aboutsummaryrefslogtreecommitdiff
path: root/ui.c
blob: d6d75d0243bfd3c7c9c1aaa46ca32a7ea101aa53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
#include <stdio.h>
#include <stdlib.h>

#include "data_manager.h"
#include "display.h"
#include "util.h"
#include "ui.h"

static void adjust_setting(struct ui_ctx *ui, struct data_ctx *dctx, int adj)
{
	/* FIXME enforce bounds on setting - is this responsibility of data man? */
	dctx->setting += adj;
}

static void adjust_selected_category(struct ui_ctx *ui, int adj)
{
	/* FIXME */
}

static void adjust_selected_unit(struct ui_ctx *ui, int adj)
{
	/* FIXME */
}


void ui_init(struct ui_ctx *ui, struct display *display)
{
	ui->display = display;
	ui->state = UI_STATE_MAIN;
	ui->display->init();
	ui->display->clear();
}

void ui_update(struct ui_ctx *ui, struct data_ctx *dctx)
{
	char line[LCD_WIDTH+1];

	/* FIXME these are missing from the data context, dummy values to test */
	float rate_m_s = 1.2;
	char rate_sym = '\0';
	if (rate_m_s < 0) {
		rate_sym = C_DESC;
	} else if (rate_m_s == 0) {
		rate_sym = C_IDLE;
	} else {
		rate_sym = C_ASC;
	}

	/* FIXME this is only valid display for UI_STATE_MAIN. Implement the other pages */
	/* line 1 */
	snprintf(line, sizeof(line), "%.1f m %c%d m/s", dctx->altitude, rate_sym, abs(rate_m_s));
	blank_to_eol(line, sizeof(line));
	ui->display->set_cursor(0, 0);
	ui->display->write(line);


	/* line 2 */
	snprintf(line, sizeof(line), "%.2f hPa", dctx->pressure);
	blank_to_eol(line, sizeof(line));
	ui->display->set_cursor(0, 1);
	ui->display->write(line);

	/* line 3 */
	/* FIXME make nicer */
	char extra_left, extra_right;
	if (ui->state == UI_STATE_MAIN_WITH_SETTING) {
		extra_left = '>';
		extra_right = '<';
	} else {
		extra_left = ' ';
		extra_right = ' ';
	}
	snprintf(line, sizeof(line), "Set%c%.2f%chPa", extra_left, dctx->setting, extra_right);
	blank_to_eol(line, sizeof(line));
	ui->display->set_cursor(0, 2);
	ui->display->write(line);

	/* line 4 */
	snprintf(line, sizeof(line), "%.1f ""\xdf""C", 12.3f);
	blank_to_eol(line, sizeof(line));
	ui->display->set_cursor(0, 3);
	ui->display->write(line);
}

void ui_input_event(struct ui_ctx *ui, struct data_ctx *dctx, enum ui_input_event event)
{
	/* FIXME state machine */
	/* XXX menus
	    1 main display screen (alt+rate, pres, set, temp)
		  - press moves to 2
		  - hold moves to 3
		2 main display screen with setting change (alt+rate, pres, set w/icon, temp
		  - up increases setting
		  - down decreases setting
		  - timeout ?
		  - press moves to 1
		  - hold? might be useful to switch unit while changing setting?
	    3 unit adjustment screen. something like:
		  alt: m (ft)
		  rate: m/s (ft/min)
		  pressure: hPa (kPa, inHg)
		  temperature: °C (°F, K)
		  - hold moves to 1
		  - if not in change mode:
			  - press enters change mode for the selected category
			  - up selects unit category above
			  - down selects unit category below
			else:
			  - press exits change mode for the selected unit, saving selection
			  - up selects previous/left unit for category
			  - down selects next/right unit for category
		  - timeouts?
		*/
	/* state:
	 *  - selected_unit_category
	 *  - selected_unit
	 */

	switch (ui->state) {
		case UI_STATE_MAIN:
			switch (event) {
				case UI_INPUT_EVENT_PRESS:
					ui->state = UI_STATE_MAIN_WITH_SETTING;
					break;
				case UI_INPUT_EVENT_HOLD:
					ui->state = UI_STATE_CHOOSE_UNIT_CATEGORY;
					break;

				/* nops for this state: */
				case UI_INPUT_EVENT_UP:
				case UI_INPUT_EVENT_DOWN:
					/* nop */
					break;
			}
			break;
		case UI_STATE_MAIN_WITH_SETTING:
			switch (event) {
				case UI_INPUT_EVENT_PRESS:
					ui->state = UI_STATE_MAIN;
					break;
				case UI_INPUT_EVENT_UP:
					adjust_setting(ui, dctx, +1);
					break;
				case UI_INPUT_EVENT_DOWN:
					adjust_setting(ui, dctx, -1);
					break;
				/* nops for this state: */
				case UI_INPUT_EVENT_HOLD:
					/* nop */
					break;
				/* XXX timeout? */
			}
			break;
		case UI_STATE_CHOOSE_UNIT_CATEGORY:
			switch (event) {
				case UI_INPUT_EVENT_HOLD:
					ui->state = UI_STATE_MAIN;
					break;
				case UI_INPUT_EVENT_PRESS:
					ui->state = UI_STATE_CHANGE_UNIT_MODE;
					break;
				case UI_INPUT_EVENT_UP:
					adjust_selected_category(ui, -1);
					break;
				case UI_INPUT_EVENT_DOWN:
					adjust_selected_category(ui, +1);
					break;
			}
			break;
		case UI_STATE_CHANGE_UNIT_MODE:
			switch (event) {
				case UI_INPUT_EVENT_PRESS:
					ui->state = UI_STATE_CHOOSE_UNIT_CATEGORY;
					break;
				case UI_INPUT_EVENT_UP:
					adjust_selected_unit(ui, -1);
					break;
				case UI_INPUT_EVENT_DOWN:
					adjust_selected_unit(ui, +1);
					break;
				/* nops for this state: */
				case UI_INPUT_EVENT_HOLD:
					/* nop */
					break;
				/* XXX timeout? */
			}
			break;
	}
}