GPS Device
Loading...
Searching...
No Matches
Menu Public API

Public functions to interact with the menu subsystem. More...

Collaboration diagram for Menu Public API:

Functions

ERR_te menu_init_subsys (void)
 Initializes the menu subsystem.
ERR_te menu_deinit_subsys (void)
 Deinitializes the menu subsystem.
ERR_te menu_start_subsys (void)
 Starts the menu subsystem.
ERR_te menu_stop_subsys (void)
 Stops the menu subsystem.
ERR_te menu_init_handle (MENU_CFG_ts *menu_cfg, MENU_HANDLE_ts **menu_handle_o)
 Initializes and registers a menu handle.
ERR_te menu_run_handle (MENU_HANDLE_ts *menu_handle)
 Renders a single menu to the display.
ERR_te menu_run_handle_all (void)
 Renders all registered menus to the display.
ERR_te menu_get_selected_option (MENU_HANDLE_ts const *menu_handle, char *selected_option_o)
 Retrieves the string of the currently highlighted option.
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.
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.
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.

Detailed Description

Public functions to interact with the menu subsystem.

Function Documentation

◆ menu_init_subsys()

ERR_te menu_init_subsys ( void )

Initializes the menu subsystem.

Resets the internal state, initializes the logging dependency, and registers the CLI commands.

Must be called before any other menu API function.

Returns
  • ERR_OK on success
  • ERR_MODULE_ALREADY_INITIALIZED if the subsystem is already initialized
  • Propagated error from cmd_register on failure
Note
Should only be called once during system startup.
See also
menu_init_subsys

Definition at line 159 of file menu.c.

159 {
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}
static struct internal_state_s internal_state
Singleton instance of the SysTick driver internal state.
ERR_te cmd_register(CMD_CLIENT_INFO_ts *cmd_client_info)
Registers a client with the command subsystem.
Definition cmd.c:51
ERR_te
Standard return type used by all public API functions.
Definition err.h:35
@ ERR_OK
Definition err.h:36
@ ERR_MODULE_ALREADY_INITIALIZED
Definition err.h:54
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_INFO
Definition log.h:64
@ MODULES_MENU
Definition modules.h:48
static CMD_CLIENT_INFO_ts menu_cmd_client_info
Registration descriptor passed to the command subsystem.
Definition menu.c:146
Internal state of the SysTick driver.
Here is the call graph for this function:
Here is the caller graph for this function:

◆ menu_deinit_subsys()

ERR_te menu_deinit_subsys ( void )

Deinitializes the menu subsystem.

Resets the internal state to zero and deregisters the CLI commands. The subsystem must be stopped before calling this function.

Returns
  • ERR_OK on success
  • ERR_DEINITIALIZATION_FAILURE if the subsystem is not initialized or still running
See also
menu_deinit_subsys

Definition at line 195 of file menu.c.

195 {
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}
ERR_te cmd_deregister(CMD_CLIENT_INFO_ts const *cmd_client_info)
Deregisters a client from the command subsystem.
Definition cmd.c:66
@ ERR_DEINITIALIZATION_FAILURE
Definition err.h:44
Here is the call graph for this function:

◆ menu_start_subsys()

ERR_te menu_start_subsys ( void )

Starts the menu subsystem.

Returns
  • ERR_OK on success
  • ERR_UNKNOWN if the subsystem is not initialized or already started
See also
menu_start_subsys

Definition at line 220 of file menu.c.

220 {
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}
@ ERR_UNKNOWN
Definition err.h:37
Here is the caller graph for this function:

◆ menu_stop_subsys()

ERR_te menu_stop_subsys ( void )

Stops the menu subsystem.

Returns
  • ERR_OK on success
  • ERR_UNKNOWN if the subsystem is not initialized or already stopped
See also
menu_stop_subsys

Definition at line 244 of file menu.c.

244 {
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}

◆ menu_init_handle()

ERR_te menu_init_handle ( MENU_CFG_ts * menu_cfg,
MENU_HANDLE_ts ** menu_handle_o )

Initializes and registers a menu handle.

Counts the number of options in menu_cfg by scanning for the first entry whose first character is ‘’\0'`, copies all configuration into the internal pool, and sets up initial scroll state.

For MENU_TYPE_DATA_VIEW menus, the internal option count is doubled to account for interleaved label and value rows.

Parameters
[in]menu_cfgPointer to the menu configuration structure.
[out]menu_handle_oPointer to a handle pointer that will be set to the allocated menu instance.
Returns
  • ERR_OK on success
  • ERR_NOT_ENOUGH_SPACE if the maximum number of handles is reached or the option count exceeds CONFIG_MENU_MAX_OPTIONS
  • ERR_INVALID_ARGUMENT if no options are found in menu_cfg
See also
menu_init_handle

Definition at line 268 of file menu.c.

268 {
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}
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
@ ERR_NOT_ENOUGH_SPACE
Definition err.h:49
@ ERR_INVALID_ARGUMENT
Definition err.h:38
@ MENU_TYPE_DATA_VIEW
Definition menu.h:67
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
Here is the call graph for this function:
Here is the caller graph for this function:

◆ menu_run_handle()

ERR_te menu_run_handle ( MENU_HANDLE_ts * menu_handle)

Renders a single menu to the display.

Clears the display area, dispatches to the appropriate internal renderer based on MENU_TYPE_ts, and triggers a display update.

Parameters
[in,out]menu_handlePointer to the menu handle to render.
Returns
  • ERR_OK always
See also
menu_run_handle

Definition at line 340 of file menu.c.

340 {
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}
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
@ MENU_TYPE_SELECTABLE
Definition menu.h:61
ERR_te ssd1309_update(bool force)
Flushes the internal framebuffer to the display over I2C.
Definition ssd1309.c:1064
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
MENU_TYPE_ts type
Definition menu.c:39
Here is the call graph for this function:
Here is the caller graph for this function:

◆ menu_run_handle_all()

ERR_te menu_run_handle_all ( void )

Renders all registered menus to the display.

Iterates over all active handles and calls menu_run_handle on each.

Returns
  • ERR_OK always
See also
menu_run_handle_all

Definition at line 356 of file menu.c.

356 {
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}
ERR_te menu_run_handle(MENU_HANDLE_ts *menu_handle)
Renders a single menu to the display.
Definition menu.c:340
Here is the call graph for this function:

◆ menu_get_selected_option()

ERR_te menu_get_selected_option ( MENU_HANDLE_ts const * menu_handle,
char * selected_option_o )

Retrieves the string of the currently highlighted option.

Only valid for MENU_TYPE_SELECTABLE menus. Returns ERR_INVALID_ARGUMENT for MENU_TYPE_DATA_VIEW menus.

Parameters
[in]menu_handlePointer to the menu handle to query.
[out]selected_option_oPointer to a buffer that will receive the selected option string (null-terminated). Must be at least SSD1309_MAX_CHARS_IN_LINE bytes.
Returns
  • ERR_OK on success
  • ERR_INVALID_ARGUMENT if the menu type is MENU_TYPE_DATA_VIEW
  • ERR_DATA_COPY_FAILURE if the string copy fails
See also
menu_get_selected_option

Definition at line 367 of file menu.c.

367 {
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}
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
@ ERR_DATA_COPY_FAILURE
Definition err.h:46
Here is the call graph for this function:
Here is the caller graph for this function:

◆ menu_scroll()

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.

Increments or decrements the internal selection index. The actual clamping to valid bounds and display update happen on the next call to menu_run_handle.

Parameters
[in,out]menu_handlePointer to the menu handle to scroll.
[in]vertical_dirUP to move the selection up, DOWN to move it down.
Returns
  • ERR_OK always
See also
menu_scroll

Definition at line 387 of file menu.c.

387 {
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}
@ DOWN
Definition common.h:108
@ UP
Definition common.h:111
int8_t selected_option
Definition menu.c:57
Here is the caller graph for this function:

◆ menu_get_prev_menu()

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.

Used to implement back-navigation. The popped handle is removed from the stack.

Parameters
[in,out]menu_handlePointer to the current menu handle.
[out]prev_menu_handle_oPointer to a handle pointer that will be set to the previous menu.
Returns
  • ERR_OK on success
  • ERR_INVALID_ARGUMENT if the navigation history stack is empty
See also
menu_get_prev_menu

Definition at line 402 of file menu.c.

402 {
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}
MENU_HANDLE_ts * prev_menu[CONFIG_MENU_MAX_BUF_SIZE]
Definition menu.c:69
uint8_t prev_menu_count
Definition menu.c:72
Here is the caller graph for this function:

◆ menu_set_prev_menu()

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.

Used to record the menu to return to when the user navigates back. Call this before transitioning to a new menu.

Parameters
[in,out]menu_handlePointer to the current menu handle whose history stack will be updated.
[in]prev_menu_handlePointer to the menu handle to push onto the history stack.
Returns
  • ERR_OK on success
  • ERR_NOT_ENOUGH_SPACE if the history stack is full
See also
menu_set_prev_menu

Definition at line 412 of file menu.c.

412 {
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}
Here is the caller graph for this function: