GPS Device
Loading...
Searching...
No Matches
menu.c
Go to the documentation of this file.
1
11
12#include "menu.h"
13#include "common.h"
14#include "init.h"
15#include "ssd1309.h"
16#include "err.h"
17#include "configuration.h"
18#include "log.h"
19#include "cmd.h"
20
34
36 char options[CONFIG_MENU_MAX_OPTIONS][SSD1309_MAX_CHARS_IN_LINE];
37
40
45 ERR_te (*get_value_fn)(uint8_t index, char **value_o);
46
49
55
58
61
64
67
69 MENU_HANDLE_ts *prev_menu[CONFIG_MENU_MAX_BUF_SIZE];
70
73
75 char name[CONFIG_MENU_MAX_NAME_LEN];
76
78 bool in_use;
79};
80
88struct internal_state_s {
90 struct menu_handle_s menus[CONFIG_MENU_MAX_OBJECTS];
91
93 uint8_t menu_num;
94
97
100
102 bool initialized;
103
105 bool started;
106};
107
109static struct internal_state_s internal_state = { 0 };
110
111/* ---- Forward declarations for internal helpers ---- */
112static ERR_te menu_selectable_run(MENU_HANDLE_ts *menu_handle);
113static ERR_te menu_dataview_run(MENU_HANDLE_ts *menu_handle);
114
115/* ---- Forward declarations for command handlers ---- */
116static ERR_te menu_cmd_info_handler(uint32_t argc, char **argv);
117static ERR_te menu_cmd_scroll_handler(uint32_t argc, char **argv);
118
127 {
128 .name = "scroll",
129 .help = "Scroll up or down, usage: menu scroll <menu> <up|down>",
130 .handler = menu_cmd_scroll_handler
131 },
132 {
133 .name = "info",
134 .help = "Shows menu information, usage: menu info",
135 .handler = menu_cmd_info_handler
136 }
137};
138
147 .cmds_ptr = menu_cmds,
148 .num_cmds = sizeof(menu_cmds) / sizeof(menu_cmds[0]),
149 .name = "menu",
150 .log_level_ptr = &internal_state.log_level
151};
152
157
160 ERR_te err = 0;
161
162 if(internal_state.initialized) {
164 }
165
166 internal_state = (struct internal_state_s){ 0 };
167
168 internal_state.log_level = LOG_LEVEL_INFO;
170 internal_state.initialized = true;
171 internal_state.started = false;
172
173 init_log();
174
176 if(err != ERR_OK) {
177 LOG_ERROR(
178 internal_state.subsys,
179 internal_state.log_level,
180 "menu_init_subsys: cmd_register error"
181 );
182
183 return err;
184 }
185 LOG_INFO(
186 internal_state.subsys,
187 internal_state.log_level,
188 "menu_init_subsys: subsys initialized"
189 );
190
191 return ERR_OK;
192}
193
196 if(internal_state.initialized && !internal_state.started) {
197 internal_state = (struct internal_state_s){ 0 };
198
200 }
201 else {
202 LOG_ERROR(
203 internal_state.subsys,
204 internal_state.log_level,
205 "menu_deinit_subsys: subsys is not initialized or not stopped"
206 );
207
209 }
210 LOG_INFO(
211 internal_state.subsys,
212 internal_state.log_level,
213 "menu_deinit_subsys: subsys deinitialized"
214 );
215
216 return ERR_OK;
217}
218
221 if(internal_state.initialized && !internal_state.started) {
222 internal_state.started = true;
223
224 LOG_INFO(
225 internal_state.subsys,
226 internal_state.log_level,
227 "menu_start_subsys: subsys started"
228 );
229 }
230 else {
231 LOG_ERROR(
232 internal_state.subsys,
233 internal_state.log_level,
234 "menu_start_subsys: subsys not initialized or already started"
235 );
236
237 return ERR_UNKNOWN;
238 }
239
240 return ERR_OK;
241}
242
245 if(internal_state.initialized && internal_state.started) {
246 internal_state.started = false;
247
248 LOG_INFO(
249 internal_state.subsys,
250 internal_state.log_level,
251 "menu_stop_subsys: subsys stopped"
252 );
253 }
254 else {
255 LOG_ERROR(
256 internal_state.subsys,
257 internal_state.log_level,
258 "menu_stop_subsys: subsys not initialized or already already stopped"
259 );
260
261 return ERR_UNKNOWN;
262 }
263
264 return ERR_OK;
265}
266
269 if(internal_state.menu_num == CONFIG_MENU_MAX_OBJECTS)
271
272 // Count number of options in the input data
273 uint8_t options_count = 0;
274 while(menu_cfg->options[options_count][0] != '\0')
275 options_count++;
276
277 if(options_count == 0)
279 else if(options_count > CONFIG_MENU_MAX_OPTIONS)
281
282 for(uint32_t i = 0; i < CONFIG_MENU_MAX_OBJECTS; i++) {
283 if(internal_state.menus[i].in_use == false) {
284 // Copy input data (menu title) to internal state
285 txt_cpy(
286 internal_state.menus[i].title,
287 menu_cfg->title,
288 get_str_len(menu_cfg->title)
289 );
290
291 // Copy input data (menu name) to internal state
292 txt_cpy(
293 internal_state.menus[i].name,
294 menu_cfg->name,
295 get_str_len(menu_cfg->name)
296 );
297
298 // Copy input data (menu options) to internal state
299 for(uint8_t j = 0; j < options_count; j++) {
300 txt_cpy(
301 internal_state.menus[i].options[j],
302 menu_cfg->options[j],
303 get_str_len(menu_cfg->options[j])
304 );
305 }
306
307 // For dataview mode, options count covers both the labels and their live values
308 if(menu_cfg->type == MENU_TYPE_DATA_VIEW) {
309 options_count *= 2;
310 }
311
312 if(options_count > 7) {
313 internal_state.menus[i].last_visible_option = 6;
314 }
315 else {
316 internal_state.menus[i].last_visible_option = options_count - 1;
317 }
318
319 internal_state.menus[i].line_to_highlight = 1;
320 internal_state.menus[i].selected_option = 0;
321 internal_state.menus[i].prev_selected_option = 0;
322 internal_state.menus[i].get_value_fn = menu_cfg->get_value_fn;
323 internal_state.menus[i].type = menu_cfg->type;
324 internal_state.menus[i].first_visible_option = 0;
325 internal_state.menus[i].options_count = options_count;
326 internal_state.menus[i].in_use = true;
327
328 *menu_handle_o = &internal_state.menus[i];
329
330 internal_state.menu_num++;
331
332 break;
333 }
334 }
335
336 return ERR_OK;
337}
338
341 ssd1309_clear_rect(1, 1, 128, 64, false);
342
343 if(menu_handle->type == MENU_TYPE_SELECTABLE) {
344 menu_selectable_run(menu_handle);
345 }
346 else if(menu_handle->type == MENU_TYPE_DATA_VIEW) {
347 menu_dataview_run(menu_handle);
348 }
349
350 ssd1309_update(false);
351
352 return ERR_OK;
353}
354
357 for(uint32_t i = 0; i < CONFIG_MENU_MAX_OBJECTS; i++) {
358 if(internal_state.menus[i].in_use == true) {
360 }
361 }
362
363 return ERR_OK;
364}
365
367ERR_te menu_get_selected_option(MENU_HANDLE_ts const *menu_handle, char *selected_option_o) {
368 ERR_te err;
369
370 if(menu_handle->type == MENU_TYPE_DATA_VIEW) {
372 }
373
374 err = str_cpy(
375 selected_option_o,
376 menu_handle->options[menu_handle->selected_option],
377 get_str_len(menu_handle->options[menu_handle->selected_option]) + 1
378 );
379 if(err != ERR_OK) {
381 }
382
383 return ERR_OK;
384}
385
388 switch(vertical_dir) {
389 case DOWN:
390 menu_handle->selected_option += 1;
391 break;
392
393 case UP:
394 menu_handle->selected_option -= 1;
395 break;
396 }
397
398 return ERR_OK;
399}
400
402ERR_te menu_get_prev_menu(MENU_HANDLE_ts *menu_handle, MENU_HANDLE_ts **prev_menu_handle_o) {
403 if(menu_handle->prev_menu_count == 0)
405
406 *prev_menu_handle_o = menu_handle->prev_menu[--menu_handle->prev_menu_count];
407
408 return ERR_OK;
409}
410
412ERR_te menu_set_prev_menu(MENU_HANDLE_ts *menu_handle, MENU_HANDLE_ts *prev_menu_handle) {
413 if(menu_handle->prev_menu_count == CONFIG_MENU_MAX_BUF_SIZE)
415
416 menu_handle->prev_menu[menu_handle->prev_menu_count++] = prev_menu_handle;
417
418 return ERR_OK;
419}
420
422
427
446 // Clamp selected item if possible boundaries exceeded
447 if(menu_handle->selected_option < 0) {
448 menu_handle->selected_option = 0;
449 }
450 else if(menu_handle->selected_option >= menu_handle->options_count) {
451 menu_handle->selected_option = menu_handle->options_count - 1;
452 }
453
454 // Items in options list is greater than 7, thus shifting of the currently showed items is needed
455 if(menu_handle->options_count > 7) {
456 // If selected item is outside (positive direction) of the currently showed items list shift
457 // the window by one in positive direction
458 if(menu_handle->selected_option > menu_handle->last_visible_option) {
459 menu_handle->first_visible_option++;
460 menu_handle->last_visible_option++;
461 }
462 // Opposite direction
463 else if (menu_handle->selected_option < menu_handle->first_visible_option) {
464 menu_handle->first_visible_option--;
465 menu_handle->last_visible_option--;
466 }
467
468 // If selection reached last visible item, shift selection in positive direction
469 if(menu_handle->selected_option == menu_handle->last_visible_option) {
470 menu_handle->line_to_highlight = 7;
471 }
472 // If selection reached first item, shift selection in negative direction
473 else if(menu_handle->selected_option == menu_handle->first_visible_option) {
474 menu_handle->line_to_highlight = 1;
475 }
476 // If selection is in-between, change selection
477 else {
478 // In positive direction
479 if(menu_handle->selected_option > menu_handle->prev_selected_option) {
480 menu_handle->line_to_highlight = menu_handle->selected_option + 1;
481 }
482 // In negative direction
483 else if(menu_handle->selected_option < menu_handle->prev_selected_option) {
484 menu_handle->line_to_highlight = 7 - (menu_handle->last_visible_option - menu_handle->selected_option);
485 }
486 }
487 menu_handle->prev_selected_option = menu_handle->selected_option;
488 }
489 // Shifting of the currently showed items is not needed
490 else {
491 // Select first item in the list
492 if(menu_handle->selected_option == menu_handle->first_visible_option) {
493 menu_handle->line_to_highlight = 1;
494 }
495 // Select next item in the list (positive direction)
496 else if(menu_handle->selected_option > menu_handle->prev_selected_option) {
497 menu_handle->line_to_highlight = menu_handle->selected_option + 1;
498 }
499 // Select next item in the list (negative direction)
500 else if(menu_handle->selected_option < menu_handle->prev_selected_option) {
501 menu_handle->line_to_highlight = menu_handle->options_count - (menu_handle->last_visible_option - menu_handle->selected_option);
502 }
503 else if(menu_handle->selected_option == menu_handle->last_visible_option) {
504 menu_handle->line_to_highlight = menu_handle->selected_option + 1;
505 }
506 menu_handle->prev_selected_option = menu_handle->selected_option;
507 }
508
509 // Draw item list on the screen
510 uint8_t line_counter = 0;
511 for(uint8_t i = menu_handle->first_visible_option; i <= menu_handle->last_visible_option; i++) {
512 line_counter++;
513 ssd1309_draw_text(menu_handle->options[i],
514 get_str_len(menu_handle->options[i]), line_counter, false);
515 }
516
517 // Simulate selection by inverting the value of pixels
518 ssd1309_invert_line(menu_handle->line_to_highlight, false);
519
520 ssd1309_draw_text(menu_handle->title, 16, 8, false);
521
522 return ERR_OK;
523}
524
541 ERR_te err;
542
543 // Clamp selected item if possible boundaries exceeded
544 if(menu_handle->selected_option < 0) {
545 menu_handle->selected_option = 0;
546 }
547 else if(menu_handle->selected_option >= menu_handle->options_count) {
548 menu_handle->selected_option = menu_handle->options_count - 1;
549 }
550
551 // Items in options list is greater than 7, thus shifting of the currently showed items is needed
552 if(menu_handle->options_count > 7) {
553 // If selected item is outside (positive direction) of the currently showed items list shift
554 // the window by one in positive direction
555 if(menu_handle->selected_option > menu_handle->last_visible_option) {
556 menu_handle->first_visible_option++;
557 menu_handle->last_visible_option++;
558 }
559 // Opposite direction
560 else if (menu_handle->selected_option < menu_handle->first_visible_option) {
561 menu_handle->first_visible_option--;
562 menu_handle->last_visible_option--;
563 }
564
565 // If selection reached last visible item, shift selection in positive direction
566 if(menu_handle->selected_option == menu_handle->last_visible_option) {
567 menu_handle->line_to_highlight = 7;
568 }
569 // If selection reached first item, shift selection in negative direction
570 else if(menu_handle->selected_option == menu_handle->first_visible_option) {
571 menu_handle->line_to_highlight = 1;
572 }
573 // If selection is in-between, change selection
574 else {
575 // In positive direction
576 if(menu_handle->selected_option > menu_handle->prev_selected_option) {
577 menu_handle->line_to_highlight = menu_handle->selected_option + 1;
578 }
579 // In negative direction
580 else if(menu_handle->selected_option < menu_handle->prev_selected_option) {
581 menu_handle->line_to_highlight = 7 - (menu_handle->last_visible_option - menu_handle->selected_option);
582 }
583 }
584 menu_handle->prev_selected_option = menu_handle->selected_option;
585 }
586 // Shifting of the currently showed items is not needed
587 else {
588 // Select first item in the list
589 if(menu_handle->selected_option == menu_handle->first_visible_option) {
590 menu_handle->line_to_highlight = 1;
591 }
592 // Select next item in the list (positive direction)
593 else if(menu_handle->selected_option > menu_handle->prev_selected_option) {
594 menu_handle->line_to_highlight = menu_handle->selected_option + 1;
595 }
596 // Select next item in the list (negative direction)
597 else if(menu_handle->selected_option < menu_handle->prev_selected_option) {
598 menu_handle->line_to_highlight = menu_handle->options_count - (menu_handle->last_visible_option - menu_handle->selected_option);
599 }
600 else if(menu_handle->selected_option == menu_handle->last_visible_option) {
601 menu_handle->line_to_highlight = menu_handle->selected_option + 1;
602 }
603 menu_handle->prev_selected_option = menu_handle->selected_option;
604 }
605
606 // Draw item list on the screen
607 uint8_t line_counter = 0;
608 uint8_t real_counter = 0;
609
610 if(menu_handle->first_visible_option > 0)
611 real_counter = menu_handle->first_visible_option / 2;
612
613 for(uint8_t i = menu_handle->first_visible_option; i <= menu_handle->last_visible_option; i++) {
614 line_counter++;
615 // Counter is at option label row
616 if(i % 2 == 0) {
617 ssd1309_draw_text(menu_handle->options[real_counter],
618 get_str_len(menu_handle->options[real_counter]), line_counter, false);
619 }
620 // Counter is at live value row
621 else {
622 char *value;
623
624 err = menu_handle->get_value_fn(real_counter, &value);
625 if(err != ERR_OK) {
627 }
628
629 ssd1309_draw_text(value,
630 get_str_len(value),
631 line_counter, false);
632
633 real_counter++;
634 }
635 }
636
637 // Simulate selection by inverting the value of pixels
638 ssd1309_invert_line(menu_handle->line_to_highlight, false);
639
640 ssd1309_draw_text(menu_handle->title, 16, 8, false);
641
642 return ERR_OK;
643}
644
646
651
665static ERR_te menu_cmd_info_handler(uint32_t argc, char **argv) {
666 if(argc != 2) {
667 LOG_ERROR(
668 internal_state.subsys,
669 internal_state.log_level,
670 "menu_cmd_info_handler: invalid arguments"
671 );
672
674 }
675
676 LOG_INFO(internal_state.subsys, internal_state.log_level, "Printing menu information:");
677
678 for(uint32_t i = 0; i < CONFIG_MENU_MAX_OBJECTS; i++) {
679 if(internal_state.menus[i].in_use == true) {
680 LOG_INFO(
681 internal_state.subsys,
682 internal_state.log_level,
683 "name: %s",
684 internal_state.menus[i].name
685 );
686 }
687 }
688
689 return ERR_OK;
690}
691
711static ERR_te menu_cmd_scroll_handler(uint32_t argc, char **argv) {
712 if(argc != 4) {
713 LOG_ERROR(
714 internal_state.subsys,
715 internal_state.log_level,
716 "menu_cmd_scroll_handler: invalid arguments"
717 );
718
720 }
721
722 for(uint32_t i = 0; i < CONFIG_MENU_MAX_OBJECTS; i++) {
723 if(str_cmp(argv[2], internal_state.menus[i].name) == true) {
724 if(str_cmp(argv[3], "up") == true) {
725 menu_scroll(&internal_state.menus[i], UP);
726 }
727 else if(str_cmp(argv[3], "down") == true) {
728 menu_scroll(&internal_state.menus[i], DOWN);
729 }
730 else {
731 LOG_ERROR(
732 internal_state.subsys,
733 internal_state.log_level,
734 "menu_cmd_scroll_handler: invalid arguments"
735 );
737 }
739
740 return ERR_OK;
741 }
742 if(i == internal_state.menu_num - 1) {
743 LOG_ERROR(
744 internal_state.subsys,
745 internal_state.log_level,
746 "menu_cmd_scroll_handler: invalid arguments"
747 );
748
750 }
751 }
752
753 return ERR_OK;
754}
755
static struct internal_state_s internal_state
Singleton instance of the SysTick driver internal state.
Command subsystem public API.
Common utility module public API.
System-wide error code definitions.
ERR_te cmd_deregister(CMD_CLIENT_INFO_ts const *cmd_client_info)
Deregisters a client from the command subsystem.
Definition cmd.c:66
ERR_te cmd_register(CMD_CLIENT_INFO_ts *cmd_client_info)
Registers a client with the command subsystem.
Definition cmd.c:51
bool str_cmp(const char *str1, const char *str2)
Compares two null-terminated strings for equality.
Definition common.c:248
int str_cpy(char *str_to, const char *str_from, uint32_t len)
Copies a null-terminated string into a destination buffer.
Definition common.c:333
uint32_t get_str_len(char const *str)
Returns the length of a string, excluding the null terminator.
Definition common.c:22
int txt_cpy(char *txt_to, const char *txt_from, uint32_t len)
Copies a fixed-length block of text into a destination buffer.
Definition common.c:350
VERTICAL_DIR_te
Represents a vertical movement direction.
Definition common.h:106
@ DOWN
Definition common.h:108
@ UP
Definition common.h:111
ERR_te
Standard return type used by all public API functions.
Definition err.h:35
@ ERR_DEINITIALIZATION_FAILURE
Definition err.h:44
@ ERR_UNKNOWN
Definition err.h:37
@ ERR_OK
Definition err.h:36
@ ERR_MODULE_ALREADY_INITIALIZED
Definition err.h:54
@ ERR_DATA_COPY_FAILURE
Definition err.h:46
@ ERR_NOT_ENOUGH_SPACE
Definition err.h:49
@ ERR_DATA_ACQUISITION_FAILURE
Definition err.h:47
@ ERR_INVALID_ARGUMENT
Definition err.h:38
ERR_te init_log(void)
Initializes the logging subsystem.
Definition init.c:25
#define LOG_ERROR(subsys, lvl, fmt,...)
Definition log.h:258
#define LOG_INFO(subsys, lvl, fmt,...)
Definition log.h:255
LOG_LEVEL_te
Log severity levels, in ascending order of severity.
Definition log.h:63
@ LOG_LEVEL_INFO
Definition log.h:64
static ERR_te menu_cmd_info_handler(uint32_t argc, char **argv)
CLI handler for the "info" command. Logs the names of all active menu handles.
Definition menu.c:665
static ERR_te menu_cmd_scroll_handler(uint32_t argc, char **argv)
CLI handler for the "scroll" command. Scrolls a named menu and re-renders it.
Definition menu.c:711
static ERR_te menu_selectable_run(MENU_HANDLE_ts *menu_handle)
Renders a MENU_TYPE_SELECTABLE menu to the display.
Definition menu.c:445
static ERR_te menu_dataview_run(MENU_HANDLE_ts *menu_handle)
Renders a MENU_TYPE_DATA_VIEW menu to the display.
Definition menu.c:540
ERR_te menu_get_prev_menu(MENU_HANDLE_ts *menu_handle, MENU_HANDLE_ts **prev_menu_handle_o)
Pops and returns the previous menu from the navigation history stack.
Definition menu.c:402
ERR_te menu_init_handle(MENU_CFG_ts *menu_cfg, MENU_HANDLE_ts **menu_handle_o)
Initializes and registers a menu handle.
Definition menu.c:268
ERR_te menu_run_handle(MENU_HANDLE_ts *menu_handle)
Renders a single menu to the display.
Definition menu.c:340
ERR_te menu_stop_subsys(void)
Stops the menu subsystem.
Definition menu.c:244
ERR_te menu_scroll(MENU_HANDLE_ts *menu_handle, VERTICAL_DIR_te vertical_dir)
Moves the menu selection cursor by one step in the given direction.
Definition menu.c:387
ERR_te menu_start_subsys(void)
Starts the menu subsystem.
Definition menu.c:220
ERR_te menu_get_selected_option(MENU_HANDLE_ts const *menu_handle, char *selected_option_o)
Retrieves the string of the currently highlighted option.
Definition menu.c:367
ERR_te menu_deinit_subsys(void)
Deinitializes the menu subsystem.
Definition menu.c:195
ERR_te menu_set_prev_menu(MENU_HANDLE_ts *menu_handle, MENU_HANDLE_ts *prev_menu_handle)
Pushes a menu onto the navigation history stack of another menu.
Definition menu.c:412
ERR_te menu_init_subsys(void)
Initializes the menu subsystem.
Definition menu.c:159
ERR_te menu_run_handle_all(void)
Renders all registered menus to the display.
Definition menu.c:356
struct menu_handle_s MENU_HANDLE_ts
Opaque handle representing a menu instance.
Definition menu.h:115
MENU_TYPE_ts
Determines the rendering and interaction mode of a menu.
Definition menu.h:59
@ MENU_TYPE_DATA_VIEW
Definition menu.h:67
@ MENU_TYPE_SELECTABLE
Definition menu.h:61
MODULES_te
Identifies a subsystem for use in logging and CLI output.
Definition modules.h:42
@ MODULES_MENU
Definition modules.h:48
ERR_te ssd1309_update(bool force)
Flushes the internal framebuffer to the display over I2C.
Definition ssd1309.c:1064
ERR_te ssd1309_invert_line(uint8_t line, bool force)
Inverts all pixels in a single display line in the framebuffer.
Definition ssd1309.c:924
ERR_te ssd1309_clear_rect(uint8_t x_src, uint8_t y_src, uint8_t x_dest, uint8_t y_dest, bool force)
Clears a rectangular region in the framebuffer (sets all pixels off).
Definition ssd1309.c:947
ERR_te ssd1309_draw_text(char const *text, uint8_t text_len, uint8_t line, bool force)
Draws a text string into the framebuffer at the specified line.
Definition ssd1309.c:806
#define SSD1309_MAX_CHARS_IN_LINE
Definition ssd1309.h:65
Common initialization public API.
Log subsystem public API.
static CMD_CLIENT_INFO_ts menu_cmd_client_info
Registration descriptor passed to the command subsystem.
Definition menu.c:146
static CMD_INFO_ts menu_cmds[]
Table of CLI commands registered by the menu subsystem.
Definition menu.c:126
Menu module public API.
SSD1309 OLED display driver public API.
Describes a subsystem client registering with the command module.
Definition cmd.h:92
Describes a single command exposed by a client.
Definition cmd.h:72
Configuration structure for initializing a menu handle.
Definition menu.h:78
MENU_TYPE_ts type
Definition menu.h:91
char title[SSD1309_MAX_CHARS_IN_LINE]
Definition menu.h:80
char options[CONFIG_MENU_MAX_OPTIONS][SSD1309_MAX_CHARS_IN_LINE]
Definition menu.h:88
ERR_te(* get_value_fn)(uint8_t index, char **value_o)
Definition menu.h:101
char name[CONFIG_MENU_MAX_NAME_LEN]
Definition menu.h:104
Internal state of the SysTick driver.
MODULES_te subsys
Definition button.c:95
struct menu_handle_s menus[CONFIG_MENU_MAX_OBJECTS]
Definition menu.c:90
LOG_LEVEL_te log_level
Definition button.c:92
uint8_t menu_num
Definition menu.c:93
Internal structure representing a single menu instance.
Definition menu.c:31
int8_t last_visible_option
Definition menu.c:66
int8_t first_visible_option
Definition menu.c:63
char title[SSD1309_MAX_CHARS_IN_LINE]
Definition menu.c:33
int8_t selected_option
Definition menu.c:57
char name[CONFIG_MENU_MAX_NAME_LEN]
Definition menu.c:75
int8_t prev_selected_option
Definition menu.c:60
ERR_te(* get_value_fn)(uint8_t index, char **value_o)
Definition menu.c:45
uint8_t options_count
Definition menu.c:54
MENU_TYPE_ts type
Definition menu.c:39
MENU_HANDLE_ts * prev_menu[CONFIG_MENU_MAX_BUF_SIZE]
Definition menu.c:69
bool in_use
Definition menu.c:78
uint8_t prev_menu_count
Definition menu.c:72
char options[CONFIG_MENU_MAX_OPTIONS][SSD1309_MAX_CHARS_IN_LINE]
Definition menu.c:36
uint8_t line_to_highlight
Definition menu.c:48