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 {
 | 
			
		||||
	int16_t rotary_encoder_delta;
 | 
			
		||||
	enum button_state push_button;
 | 
			
		||||
	bool button_ready;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
bool menu_get_button_ready_state(const struct lcd_menu *menu);
 | 
			
		||||
 | 
			
		||||
void menu_list_compute_count(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 *my_parent;
 | 
			
		||||
	static bool button_ready;
 | 
			
		||||
	static int page = 0;
 | 
			
		||||
	static int last_page = -1;
 | 
			
		||||
	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;
 | 
			
		||||
	uint32_t ser1, ser2, ser3;
 | 
			
		||||
	enum button_state push_button;
 | 
			
		||||
	bool button_ready;
 | 
			
		||||
 | 
			
		||||
	if (entry_type == MENU_ENTRY_FIRST_ENTER) {
 | 
			
		||||
		uptime_secs = 0ULL;
 | 
			
		||||
		page = 0;
 | 
			
		||||
		last_page = -1;
 | 
			
		||||
		my_parent = parent;
 | 
			
		||||
		button_ready = false;
 | 
			
		||||
		menu_display_clear(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");
 | 
			
		||||
		break;
 | 
			
		||||
	case 4:
 | 
			
		||||
		last_page = 4;
 | 
			
		||||
		systick_get_uptime_from_tick(&uptime_days, &uptime_hours, &uptime_mins, &new_uptime_secs);
 | 
			
		||||
		if (new_uptime_secs != 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);
 | 
			
		||||
	button_ready = menu_get_button_ready_state(menu);
 | 
			
		||||
 | 
			
		||||
	if (push_button == BUTTON_IDLE)
 | 
			
		||||
		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)
 | 
			
		||||
{
 | 
			
		||||
	(void)parent;
 | 
			
		||||
	static struct menu_list list;
 | 
			
		||||
	static bool button_valid;
 | 
			
		||||
	bool menu_changed = false;
 | 
			
		||||
	static const char * const root_entry_names[] = {
 | 
			
		||||
		"About",
 | 
			
		||||
		"Monitoring",
 | 
			
		||||
		"Error Flags",
 | 
			
		||||
		NULL
 | 
			
		||||
	};
 | 
			
		||||
	static const menu_func_t root_entry_funcs[] = {
 | 
			
		||||
		reflow_menu_about,
 | 
			
		||||
		reflow_menu_monitor
 | 
			
		||||
		reflow_menu_monitor,
 | 
			
		||||
		reflow_menu_err_flags,
 | 
			
		||||
	};
 | 
			
		||||
	enum button_state push_button;
 | 
			
		||||
	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");
 | 
			
		||||
		menu_ack_rotary_delta(menu);
 | 
			
		||||
		if (entry_type == MENU_ENTRY_FIRST_ENTER) {
 | 
			
		||||
			button_valid = false;
 | 
			
		||||
			list.entry_names = root_entry_names;
 | 
			
		||||
			list.submenu_list = root_entry_funcs;
 | 
			
		||||
			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);
 | 
			
		||||
	rot_delta = menu_get_rotary_delta(menu);
 | 
			
		||||
 | 
			
		||||
	if (push_button == BUTTON_IDLE) {
 | 
			
		||||
		button_valid = true;
 | 
			
		||||
	} else if (button_valid && push_button == BUTTON_SHORT_RELEASED) {
 | 
			
		||||
	if (menu_get_button_ready_state(menu) && push_button == BUTTON_SHORT_RELEASED) {
 | 
			
		||||
		/* Enter currently selected menu_entry */
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	if (!menu)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
@@ -38,6 +39,9 @@ void menu_handle(struct lcd_menu *menu, int16_t rotary_encoder_delta, enum butto
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
		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) {
 | 
			
		||||
		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))
 | 
			
		||||
@@ -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->init_parent = NULL;
 | 
			
		||||
	menu->inputs.push_button = BUTTON_IDLE;
 | 
			
		||||
	menu->inputs.button_ready = false;
 | 
			
		||||
	menu->inputs.rotary_encoder_delta = 0;
 | 
			
		||||
	menu->active_entry_type = MENU_ENTRY_FIRST_ENTER;
 | 
			
		||||
	menu->update_display = display_update;
 | 
			
		||||
@@ -243,6 +251,16 @@ enum button_state menu_get_button_state(const struct lcd_menu *menu)
 | 
			
		||||
	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)
 | 
			
		||||
{
 | 
			
		||||
	uint8_t i;
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user