20#include "os_helpers.h"
23#include "os_io_seph_ux.h"
27ux_menu_state_t ux_menu;
28ux_turner_state_t ux_turner;
31const bagl_element_t ux_menu_elements[] = {
33 {{BAGL_RECTANGLE , 0x80, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, .text=NULL},
36 {{BAGL_ICON , 0x81, 3, 14, 7, 4, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_UP }, .text=NULL },
37 {{BAGL_ICON , 0x82, 118, 14, 7, 4, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_DOWN }, .text=NULL },
40 {{BAGL_LABELINE , 0x41, 14, 3, 100, 12, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL },
42 {{BAGL_LABELINE , 0x42, 14, 35, 100, 12, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL },
45 {{BAGL_ICON , 0x10, 14, 9, 0, 0, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, 0 }, .text=NULL },
47 {{BAGL_LABELINE , 0x20, 14, 19, 100, 12, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL },
50 {{BAGL_LABELINE , 0x21, 14, 12, 100, 12, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL },
51 {{BAGL_LABELINE , 0x22, 14, 26, 100, 12, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL },
56const ux_menu_entry_t *ux_menu_get_entry(
unsigned int entry_idx)
58 if (ux_menu.menu_iterator) {
59 return ux_menu.menu_iterator(entry_idx);
61 return &ux_menu.menu_entries[entry_idx];
64const bagl_element_t *ux_menu_element_preprocessor(
const bagl_element_t *element)
67 memmove(&
G_ux.tmp_element, element,
sizeof(bagl_element_t));
70 const ux_menu_entry_t *current_entry
71 = (
const ux_menu_entry_t *) PIC(ux_menu_get_entry(ux_menu.current_entry));
72 if (current_entry == NULL) {
75 const bagl_icon_details_t *current_entry_icon
76 = (
const bagl_icon_details_t *) PIC(current_entry->icon);
78 const ux_menu_entry_t *previous_entry = NULL;
79 if (ux_menu.current_entry) {
81 = (
const ux_menu_entry_t *) PIC(ux_menu_get_entry(ux_menu.current_entry - 1));
83 const ux_menu_entry_t *next_entry = NULL;
84 if (ux_menu.current_entry < ux_menu.menu_entries_count - 1) {
85 next_entry = (
const ux_menu_entry_t *) PIC(ux_menu_get_entry(ux_menu.current_entry + 1));
88 switch (element->component.userid) {
90 if (ux_menu.current_entry == 0) {
95 if (ux_menu.current_entry == ux_menu.menu_entries_count - 1) {
101 if (current_entry->line2 != NULL || current_entry->icon != NULL
102 || ux_menu.current_entry == 0 || ux_menu.menu_entries_count == 1 || !previous_entry
103 || previous_entry->icon != NULL || previous_entry->line2 != NULL) {
106 G_ux.tmp_element.text = previous_entry->line1;
110 if (current_entry->line2 != NULL || current_entry->icon != NULL
111 || ux_menu.current_entry == ux_menu.menu_entries_count - 1
112 || ux_menu.menu_entries_count == 1 || !next_entry || next_entry->icon != NULL) {
115 G_ux.tmp_element.text = next_entry->line1;
118 if (current_entry->icon == NULL) {
121 G_ux.tmp_element.text = (
const char *) current_entry->icon;
122 if (current_entry->icon_x) {
123 G_ux.tmp_element.component.x = current_entry->icon_x;
127 if (current_entry->line2 != NULL) {
130 G_ux.tmp_element.text = current_entry->line1;
133 if (current_entry->line2 == NULL) {
136 G_ux.tmp_element.text = current_entry->line1;
139 if (current_entry->line2 == NULL) {
142 G_ux.tmp_element.text = current_entry->line2;
144 if (current_entry_icon) {
145 G_ux.tmp_element.component.x += current_entry_icon->width;
146 G_ux.tmp_element.component.width -= current_entry_icon->width;
148 if (current_entry->text_x) {
149 G_ux.tmp_element.component.x = current_entry->text_x;
151 G_ux.tmp_element.component.font_id = BAGL_FONT_OPEN_SANS_EXTRABOLD_11px;
156 if (ux_menu.menu_entry_preprocessor) {
158 return ux_menu.menu_entry_preprocessor(current_entry, &
G_ux.tmp_element);
161 return &
G_ux.tmp_element;
164unsigned int ux_menu_elements_button(
unsigned int button_mask,
unsigned int button_mask_counter)
166 UNUSED(button_mask_counter);
168 const ux_menu_entry_t *current_entry
169 = (
const ux_menu_entry_t *) PIC(ux_menu_get_entry(ux_menu.current_entry));
170 if (current_entry == NULL) {
174 switch (button_mask) {
178 if (current_entry->menu) {
180 UX_MENU_DISPLAY(current_entry->userid,
181 (
const ux_menu_entry_t *) PIC(current_entry->menu),
182 ux_menu.menu_entry_preprocessor);
186 else if (current_entry->callback) {
187 ((ux_menu_callback_t) PIC(current_entry->callback))(current_entry->userid);
195 if (ux_menu.current_entry == 0) {
198 ux_menu.current_entry--;
204 if (ux_menu.current_entry >= ux_menu.menu_entries_count - 1) {
207 ux_menu.current_entry++;
219const ux_menu_entry_t UX_MENU_END_ENTRY = UX_MENU_END;
221void ux_menu_display(
unsigned int current_entry,
222 const ux_menu_entry_t *menu_entries,
223 ux_menu_preprocessor_t menu_entry_preprocessor)
226 ux_menu.menu_entries_count = 0;
231 if (memcmp(&menu_entries[ux_menu.menu_entries_count],
233 sizeof(ux_menu_entry_t))
237 ux_menu.menu_entries_count++;
241 if (current_entry != UX_MENU_UNCHANGED_ENTRY) {
242 ux_menu.current_entry = current_entry;
243 if (ux_menu.current_entry > ux_menu.menu_entries_count) {
244 ux_menu.current_entry = 0;
247 ux_menu.menu_entries = menu_entries;
248 ux_menu.menu_entry_preprocessor = menu_entry_preprocessor;
249 ux_menu.menu_iterator = NULL;
255 G_ux.stack[0].element_arrays[0].element_array = ux_menu_elements;
256 G_ux.stack[0].element_arrays[0].element_array_count = ARRAYLEN(ux_menu_elements);
257 G_ux.stack[0].element_arrays_count = 1;
260 G_ux.stack[0].screen_before_element_display_callback = ux_menu_element_preprocessor;
261 G_ux.stack[0].button_push_callback = ux_menu_elements_button;
266 UX_DISPLAY(ux_menu_elements, ux_menu_element_preprocessor);
271const bagl_element_t ux_turner_elements[] = {
273 {{BAGL_RECTANGLE , 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, .text=NULL},
276 {{BAGL_ICON , 0x00, 3, 12, 7, 7, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS }, .text=NULL },
277 {{BAGL_ICON , 0x00, 117, 13, 8, 6, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK }, .text=NULL },
280 {{BAGL_ICON , 0x03, 0, 9, 14, 14, 0, 0, 0 , 0xFFFFFF, 0x000000, 0, 0 }, .text=NULL },
283 {{BAGL_LABELINE , 0x04, 0, 19, 128, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL },
285 {{BAGL_LABELINE , 0x05, 0, 12, 128, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL },
286 {{BAGL_LABELINE , 0x06, 0, 26, 128, 32, 0, 0, 0 , 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px|BAGL_FONT_ALIGNMENT_CENTER, 0 }, .text=NULL },
291const bagl_element_t *ux_turner_element_preprocessor(
const bagl_element_t *element)
294 memmove(&
G_ux.tmp_element, element,
sizeof(bagl_element_t));
296 switch (element->component.userid) {
298 if (ux_turner.steps[ux_turner.current_step].icon == NULL) {
301 G_ux.tmp_element.text = (
const char *) ux_turner.steps[ux_turner.current_step].icon;
302 if (ux_turner.steps[ux_turner.current_step].icon_x) {
303 G_ux.tmp_element.component.x = ux_turner.steps[ux_turner.current_step].icon_x;
307 if (ux_turner.steps[ux_turner.current_step].line2 != NULL) {
310 if (ux_turner.steps[ux_turner.current_step].fontid1) {
311 G_ux.tmp_element.component.font_id
312 = ux_turner.steps[ux_turner.current_step].fontid1;
314 G_ux.tmp_element.text = ux_turner.steps[ux_turner.current_step].line1;
317 if (ux_turner.steps[ux_turner.current_step].line2 == NULL) {
320 if (ux_turner.steps[ux_turner.current_step].fontid1) {
321 G_ux.tmp_element.component.font_id
322 = ux_turner.steps[ux_turner.current_step].fontid1;
324 G_ux.tmp_element.text = ux_turner.steps[ux_turner.current_step].line1;
327 if (ux_turner.steps[ux_turner.current_step].line2 == NULL) {
330 if (ux_turner.steps[ux_turner.current_step].fontid2) {
331 G_ux.tmp_element.component.font_id
332 = ux_turner.steps[ux_turner.current_step].fontid2;
334 G_ux.tmp_element.text = ux_turner.steps[ux_turner.current_step].line2;
336 if (ux_turner.steps[ux_turner.current_step].text_x) {
337 G_ux.tmp_element.component.x = ux_turner.steps[ux_turner.current_step].text_x;
341 return &
G_ux.tmp_element;
344unsigned int ux_turner_elements_button(
unsigned int button_mask,
unsigned int button_mask_counter)
346 return ux_turner.button_callback(button_mask, button_mask_counter);
350unsigned int ux_turner_ticker_bolos_ux(
unsigned int ignored)
354 ux_turner.current_step = (ux_turner.current_step + 1) % ux_turner.steps_count;
356 G_ux.stack[0].ticker_value = ux_turner.steps[ux_turner.current_step].next_step_ms;
357 G_ux.stack[0].ticker_interval = ux_turner.steps[ux_turner.current_step].next_step_ms;
362void ux_turner_ticker(
unsigned int elapsed_ms)
364 ux_turner.elapsed_ms -=
MIN(ux_turner.elapsed_ms, elapsed_ms);
365 if (ux_turner.elapsed_ms == 0) {
367 ux_turner.current_step = (ux_turner.current_step + 1) % ux_turner.steps_count;
368 ux_turner.elapsed_ms = ux_turner.steps[ux_turner.current_step].next_step_ms;
369 UX_DISPLAY(ux_turner_elements, ux_turner_element_preprocessor);
374void ux_turner_display(
unsigned int current_step,
375 const ux_turner_step_t *steps,
376 unsigned int steps_count,
377 button_push_callback_t button_callback)
380 ux_turner.steps_count = steps_count;
382 if (current_step != UX_TURNER_UNCHANGED_ENTRY) {
383 ux_turner.current_step = current_step;
384 if (ux_turner.current_step > ux_turner.steps_count) {
385 ux_turner.current_step = 0;
388 ux_turner.steps = steps;
390 ux_turner.button_callback = button_callback;
396 G_ux.stack[0].element_arrays[0].element_array = ux_turner_elements;
397 G_ux.stack[0].element_arrays[0].element_array_count = ARRAYLEN(ux_turner_elements);
398 G_ux.stack[0].element_arrays_count = 1;
401 G_ux.stack[0].screen_before_element_display_callback = ux_turner_element_preprocessor;
402 G_ux.stack[0].button_push_callback = ux_turner_elements_button;
403 G_ux.stack[0].ticker_value = ux_turner.steps[ux_turner.current_step].next_step_ms;
404 G_ux.stack[0].ticker_interval = ux_turner.steps[ux_turner.current_step].next_step_ms;
405 G_ux.stack[0].ticker_callback = ux_turner_ticker_bolos_ux;
409 ux_turner.elapsed_ms = ux_turner.steps[ux_turner.current_step].next_step_ms;
411 UX_DISPLAY(ux_turner_elements, ux_turner_element_preprocessor);
418 {BAGL_RECTANGLE, 0, 0, 0, 128, 32, 0, 0, 0, 0x000000, 0x000000, 0, 0},
429 BAGL_FONT_OPEN_SANS_REGULAR_8_11PX, 0},
430 .text =
"Default printf"
ux_state_t G_ux
Global UX state instance — see ux_state_s.
const bagl_element_t clear_element
const bagl_element_t printf_element
void ux_stack_display(unsigned int stack_slot)
void ux_stack_init(unsigned int stack_slot)