Issue #6: Improve LCD menu and implement function to see safety flags
This commit is contained in:
		@@ -35,6 +35,7 @@ typedef void (*menu_func_t)(struct lcd_menu *menu, enum menu_entry_func_entry en
 | 
				
			|||||||
struct menu_inputs {
 | 
					struct menu_inputs {
 | 
				
			||||||
	int16_t rotary_encoder_delta;
 | 
						int16_t rotary_encoder_delta;
 | 
				
			||||||
	enum button_state push_button;
 | 
						enum button_state push_button;
 | 
				
			||||||
 | 
						bool button_ready;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct lcd_menu {
 | 
					struct lcd_menu {
 | 
				
			||||||
@@ -76,6 +77,8 @@ int16_t menu_get_rotary_delta(const struct lcd_menu *menu);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
enum button_state menu_get_button_state(const struct lcd_menu *menu);
 | 
					enum button_state menu_get_button_state(const struct lcd_menu *menu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool menu_get_button_ready_state(const struct lcd_menu *menu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void menu_list_compute_count(struct menu_list *list);
 | 
					void menu_list_compute_count(struct menu_list *list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void menu_list_scroll_down(struct menu_list *list);
 | 
					void menu_list_scroll_down(struct menu_list *list);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,7 +107,6 @@ static void reflow_menu_monitor(struct lcd_menu *menu, enum menu_entry_func_entr
 | 
				
			|||||||
static void reflow_menu_about(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
 | 
					static void reflow_menu_about(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	static void *my_parent;
 | 
						static void *my_parent;
 | 
				
			||||||
	static bool button_ready;
 | 
					 | 
				
			||||||
	static int page = 0;
 | 
						static int page = 0;
 | 
				
			||||||
	static int last_page = -1;
 | 
						static int last_page = -1;
 | 
				
			||||||
	static uint32_t uptime_secs;
 | 
						static uint32_t uptime_secs;
 | 
				
			||||||
@@ -118,13 +117,13 @@ static void reflow_menu_about(struct lcd_menu *menu, enum menu_entry_func_entry
 | 
				
			|||||||
	int16_t rot_delta;
 | 
						int16_t rot_delta;
 | 
				
			||||||
	uint32_t ser1, ser2, ser3;
 | 
						uint32_t ser1, ser2, ser3;
 | 
				
			||||||
	enum button_state push_button;
 | 
						enum button_state push_button;
 | 
				
			||||||
 | 
						bool button_ready;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (entry_type == MENU_ENTRY_FIRST_ENTER) {
 | 
						if (entry_type == MENU_ENTRY_FIRST_ENTER) {
 | 
				
			||||||
		uptime_secs = 0ULL;
 | 
							uptime_secs = 0ULL;
 | 
				
			||||||
		page = 0;
 | 
							page = 0;
 | 
				
			||||||
		last_page = -1;
 | 
							last_page = -1;
 | 
				
			||||||
		my_parent = parent;
 | 
							my_parent = parent;
 | 
				
			||||||
		button_ready = false;
 | 
					 | 
				
			||||||
		menu_display_clear(menu);
 | 
							menu_display_clear(menu);
 | 
				
			||||||
		menu_ack_rotary_delta(menu);
 | 
							menu_ack_rotary_delta(menu);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -190,6 +189,7 @@ static void reflow_menu_about(struct lcd_menu *menu, enum menu_entry_func_entry
 | 
				
			|||||||
		menu_lcd_output(menu, 3, "Page 4/5");
 | 
							menu_lcd_output(menu, 3, "Page 4/5");
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case 4:
 | 
						case 4:
 | 
				
			||||||
 | 
							last_page = 4;
 | 
				
			||||||
		systick_get_uptime_from_tick(&uptime_days, &uptime_hours, &uptime_mins, &new_uptime_secs);
 | 
							systick_get_uptime_from_tick(&uptime_days, &uptime_hours, &uptime_mins, &new_uptime_secs);
 | 
				
			||||||
		if (new_uptime_secs != uptime_secs) {
 | 
							if (new_uptime_secs != uptime_secs) {
 | 
				
			||||||
			uptime_secs = new_uptime_secs;
 | 
								uptime_secs = new_uptime_secs;
 | 
				
			||||||
@@ -206,6 +206,7 @@ static void reflow_menu_about(struct lcd_menu *menu, enum menu_entry_func_entry
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	push_button = menu_get_button_state(menu);
 | 
						push_button = menu_get_button_state(menu);
 | 
				
			||||||
 | 
						button_ready = menu_get_button_ready_state(menu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (push_button == BUTTON_IDLE)
 | 
						if (push_button == BUTTON_IDLE)
 | 
				
			||||||
		button_ready = true;
 | 
							button_ready = true;
 | 
				
			||||||
@@ -216,20 +217,93 @@ static void reflow_menu_about(struct lcd_menu *menu, enum menu_entry_func_entry
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void reflow_menu_err_flags(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						static void *my_parent = NULL;
 | 
				
			||||||
 | 
						static uint8_t offset;
 | 
				
			||||||
 | 
						static uint64_t timestamp;
 | 
				
			||||||
 | 
						bool state;
 | 
				
			||||||
 | 
						enum button_state push_button;
 | 
				
			||||||
 | 
						int16_t rot;
 | 
				
			||||||
 | 
						uint32_t i;
 | 
				
			||||||
 | 
						char name[64];
 | 
				
			||||||
 | 
						int32_t line_counter;
 | 
				
			||||||
 | 
						bool skip_err_flag_prefix;
 | 
				
			||||||
 | 
						bool try_ack = false;
 | 
				
			||||||
 | 
						enum safety_flag flag;
 | 
				
			||||||
 | 
						bool button_ready;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						push_button = menu_get_button_state(menu);
 | 
				
			||||||
 | 
						rot = menu_get_rotary_delta(menu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (entry_type != MENU_ENTRY_CONTINUE) {
 | 
				
			||||||
 | 
							if (entry_type == MENU_ENTRY_FIRST_ENTER) {
 | 
				
			||||||
 | 
								my_parent = parent;
 | 
				
			||||||
 | 
								offset = 0;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if (push_button == BUTTON_IDLE && rot == 0) {
 | 
				
			||||||
 | 
								if (!systick_ticks_have_passed(timestamp, 150))
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						button_ready = menu_get_button_ready_state(menu);
 | 
				
			||||||
 | 
						if (push_button == BUTTON_SHORT_RELEASED && button_ready) {
 | 
				
			||||||
 | 
							menu_entry_dropback(menu, my_parent);
 | 
				
			||||||
 | 
						} if (push_button == BUTTON_LONG && button_ready) {
 | 
				
			||||||
 | 
							try_ack = true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (rot >= 4 || rot <= -4) {
 | 
				
			||||||
 | 
							menu_ack_rotary_delta(menu);
 | 
				
			||||||
 | 
							if (rot > 0) {
 | 
				
			||||||
 | 
								offset++;
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								if (offset > 0)
 | 
				
			||||||
 | 
									offset--;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						menu_display_clear(menu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						line_counter = -offset;
 | 
				
			||||||
 | 
						for (i = 0; i < safety_controller_get_flag_count(); i++) {
 | 
				
			||||||
 | 
							(void)safety_controller_get_flag_by_index(i, &state, &flag);
 | 
				
			||||||
 | 
							if (try_ack)
 | 
				
			||||||
 | 
								safety_controller_ack_flag(flag);
 | 
				
			||||||
 | 
							if (state) {
 | 
				
			||||||
 | 
								if (line_counter >= 0 && line_counter < 4) {
 | 
				
			||||||
 | 
									safety_controller_get_flag_name_by_index(i, name, sizeof(name));
 | 
				
			||||||
 | 
									if (!strncmp(name, "ERR_FLAG_", 9)) {
 | 
				
			||||||
 | 
										skip_err_flag_prefix = true;
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										skip_err_flag_prefix = false;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									menu_lcd_outputf(menu, line_counter, "%s", (skip_err_flag_prefix ? &name[9] : name));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								line_counter++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						timestamp = systick_get_global_tick();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void reflow_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
 | 
					static void reflow_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_entry entry_type, void *parent)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	(void)parent;
 | 
						(void)parent;
 | 
				
			||||||
	static struct menu_list list;
 | 
						static struct menu_list list;
 | 
				
			||||||
	static bool button_valid;
 | 
					 | 
				
			||||||
	bool menu_changed = false;
 | 
						bool menu_changed = false;
 | 
				
			||||||
	static const char * const root_entry_names[] = {
 | 
						static const char * const root_entry_names[] = {
 | 
				
			||||||
		"About",
 | 
							"About",
 | 
				
			||||||
		"Monitoring",
 | 
							"Monitoring",
 | 
				
			||||||
 | 
							"Error Flags",
 | 
				
			||||||
		NULL
 | 
							NULL
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	static const menu_func_t root_entry_funcs[] = {
 | 
						static const menu_func_t root_entry_funcs[] = {
 | 
				
			||||||
		reflow_menu_about,
 | 
							reflow_menu_about,
 | 
				
			||||||
		reflow_menu_monitor
 | 
							reflow_menu_monitor,
 | 
				
			||||||
 | 
							reflow_menu_err_flags,
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
	enum button_state push_button;
 | 
						enum button_state push_button;
 | 
				
			||||||
	int16_t rot_delta;
 | 
						int16_t rot_delta;
 | 
				
			||||||
@@ -240,7 +314,6 @@ static void reflow_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_e
 | 
				
			|||||||
		update_display_buffer(0, "Main Menu");
 | 
							update_display_buffer(0, "Main Menu");
 | 
				
			||||||
		menu_ack_rotary_delta(menu);
 | 
							menu_ack_rotary_delta(menu);
 | 
				
			||||||
		if (entry_type == MENU_ENTRY_FIRST_ENTER) {
 | 
							if (entry_type == MENU_ENTRY_FIRST_ENTER) {
 | 
				
			||||||
			button_valid = false;
 | 
					 | 
				
			||||||
			list.entry_names = root_entry_names;
 | 
								list.entry_names = root_entry_names;
 | 
				
			||||||
			list.submenu_list = root_entry_funcs;
 | 
								list.submenu_list = root_entry_funcs;
 | 
				
			||||||
			list.update_display = menu->update_display;
 | 
								list.update_display = menu->update_display;
 | 
				
			||||||
@@ -252,9 +325,7 @@ static void reflow_menu_root_entry(struct lcd_menu *menu, enum menu_entry_func_e
 | 
				
			|||||||
	push_button = menu_get_button_state(menu);
 | 
						push_button = menu_get_button_state(menu);
 | 
				
			||||||
	rot_delta = menu_get_rotary_delta(menu);
 | 
						rot_delta = menu_get_rotary_delta(menu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (push_button == BUTTON_IDLE) {
 | 
						if (menu_get_button_ready_state(menu) && push_button == BUTTON_SHORT_RELEASED) {
 | 
				
			||||||
		button_valid = true;
 | 
					 | 
				
			||||||
	} else if (button_valid && push_button == BUTTON_SHORT_RELEASED) {
 | 
					 | 
				
			||||||
		/* Enter currently selected menu_entry */
 | 
							/* Enter currently selected menu_entry */
 | 
				
			||||||
		menu_list_enter_selected_entry(&list, menu);
 | 
							menu_list_enter_selected_entry(&list, menu);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -27,6 +27,7 @@ void menu_handle(struct lcd_menu *menu, int16_t rotary_encoder_delta, enum butto
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
	menu_func_t tmp;
 | 
						menu_func_t tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!menu)
 | 
						if (!menu)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -38,6 +39,9 @@ void menu_handle(struct lcd_menu *menu, int16_t rotary_encoder_delta, enum butto
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	tmp = menu->active_entry;
 | 
						tmp = menu->active_entry;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (menu->active_entry_type == MENU_ENTRY_FIRST_ENTER && push_button != BUTTON_IDLE) {
 | 
				
			||||||
 | 
							menu->inputs.button_ready = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (menu->active_entry_type == MENU_ENTRY_FIRST_ENTER) {
 | 
						if (menu->active_entry_type == MENU_ENTRY_FIRST_ENTER) {
 | 
				
			||||||
		menu->active_entry(menu, menu->active_entry_type, menu->init_parent);
 | 
							menu->active_entry(menu, menu->active_entry_type, menu->init_parent);
 | 
				
			||||||
@@ -48,6 +52,9 @@ void menu_handle(struct lcd_menu *menu, int16_t rotary_encoder_delta, enum butto
 | 
				
			|||||||
	if (menu->active_entry_type != MENU_ENTRY_CONTINUE && tmp == menu->active_entry) {
 | 
						if (menu->active_entry_type != MENU_ENTRY_CONTINUE && tmp == menu->active_entry) {
 | 
				
			||||||
		menu->active_entry_type = MENU_ENTRY_CONTINUE;
 | 
							menu->active_entry_type = MENU_ENTRY_CONTINUE;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (push_button == BUTTON_IDLE)
 | 
				
			||||||
 | 
							menu->inputs.button_ready = true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void menu_init(struct lcd_menu *menu, menu_func_t root_node, void (*display_update)(uint8_t row, const char *data))
 | 
					void menu_init(struct lcd_menu *menu, menu_func_t root_node, void (*display_update)(uint8_t row, const char *data))
 | 
				
			||||||
@@ -59,6 +66,7 @@ void menu_init(struct lcd_menu *menu, menu_func_t root_node, void (*display_upda
 | 
				
			|||||||
	menu->active_entry = root_node;
 | 
						menu->active_entry = root_node;
 | 
				
			||||||
	menu->init_parent = NULL;
 | 
						menu->init_parent = NULL;
 | 
				
			||||||
	menu->inputs.push_button = BUTTON_IDLE;
 | 
						menu->inputs.push_button = BUTTON_IDLE;
 | 
				
			||||||
 | 
						menu->inputs.button_ready = false;
 | 
				
			||||||
	menu->inputs.rotary_encoder_delta = 0;
 | 
						menu->inputs.rotary_encoder_delta = 0;
 | 
				
			||||||
	menu->active_entry_type = MENU_ENTRY_FIRST_ENTER;
 | 
						menu->active_entry_type = MENU_ENTRY_FIRST_ENTER;
 | 
				
			||||||
	menu->update_display = display_update;
 | 
						menu->update_display = display_update;
 | 
				
			||||||
@@ -243,6 +251,16 @@ enum button_state menu_get_button_state(const struct lcd_menu *menu)
 | 
				
			|||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool menu_get_button_ready_state(const struct lcd_menu *menu)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						bool ret = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (menu)
 | 
				
			||||||
 | 
							ret = menu->inputs.button_ready;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void menu_display_clear(struct lcd_menu *menu)
 | 
					void menu_display_clear(struct lcd_menu *menu)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	uint8_t i;
 | 
						uint8_t i;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user