This commit is contained in:
aZholtikov committed 2026-10-28 15:47:41 +03:00
1 parent b57a9eac15
commit c884a61f6e
2 files changed
+115 -124

No files matched your search

+78 -97
View File
@@ -1,6 +1,5 @@
#include "zh_sim_race_button_box.h"
// Хэндлы - функции - переменные
// #define ENCODER_NUMBER 0x01
// #define LCD_VIEWPORT_ROWS 3
@@ -8,13 +7,13 @@
// #define LCD_TOTAL_ROWS 4
#define BOOT_SPLASH_MS 5000
#define MAIN_SCREEN_COUNT 5
#define LOAD_SCREEN_COUNT 5
// #define MAIN_SCREEN_COUNT 5
// #define LOAD_SCREEN_COUNT 5
// #define NVS_NAMESPACE "sim_race_box" /* NEW */
// #define NVS_KEY_SETTINGS "settings" /* NEW */
static const char *TAG = "sim_race_box";
// static const char *TAG = "sim_race_box";
/* ============================================================
* Данные main-экранов (idle)
@@ -25,21 +24,7 @@ int16_t main_times_data[VIEW_CELLS] = {1234, 1201, 1250, -49, 0};
int16_t main_debug_data[VIEW_CELLS] = {45, -42, 152, 12, 0};
int16_t main_blank_data[VIEW_CELLS] = {0, 0, 0, 0, 0};
/* ---------- Дескрипторы экранов ---------- */
// typedef struct
// {
// const char *name;
// const char *const labels[VIEW_ROWS];
// int16_t *data;
// } main_screen_desc_t;
// typedef struct
// {
// const char *name;
// const char *const lines[VIEW_ROWS];
// } load_screen_desc_t;
static const zh_main_screen_description_t main_screens[MAIN_SCREEN_COUNT] = {
static const zh_main_screen_description_t main_screens[] = {
{"Race", {"SPD", "RPM", "GER", "LAP"}, main_race_data},
{"Engine", {"OIL", "WTR", "BAT", "FUL"}, main_engine_data},
{"Times", {"LAP", "BST", "LST", "DLT"}, main_times_data},
@@ -47,29 +32,18 @@ static const zh_main_screen_description_t main_screens[MAIN_SCREEN_COUNT] = {
{"Blank", {"---", "---", "---", "---"}, main_blank_data},
};
static const zh_boot_screen_description_t load_screens[LOAD_SCREEN_COUNT] = {
{"Boot", {"Booting...", "RAM: OK", "I2C: OK", "Starting..."}},
{"Version", {"FW v1.0", "Build 2025-10", "ESP-IDF v5.4", "zh_menu v1.2"}},
{"Diag", {"I2C: OK", "LCD: OK", "ENC: OK", "All: OK"}},
{"Ready", {"System ready", "Ready for race", "Let's go", ""}},
{"Blank", {"", "", "", ""}},
};
/* ---------- Пользовательский выбор ---------- */
static int _boot_screen = 0;
static int _main_screen = 0;
static bool _boot_done = false;
static bool _prev_selected = false; /* NEW: для детекции выхода из edit */
/* ---------- Динамические буферы меток ---------- */
char lbl_boot_screen[MENU_LABEL_LEN] = "B:Boot";
char lbl_main_screen[MENU_LABEL_LEN] = "M:Race";
char lbl_temp_on[MENU_LABEL_LEN] = "Temp ON 15C";
char lbl_temp_off[MENU_LABEL_LEN] = "Temp OFF 35C";
char lbl_pw_ch_1[MENU_LABEL_LEN] = "PW CH 1 100%";
char lbl_pw_ch_2[MENU_LABEL_LEN] = "PW CH 2 100%";
char lbl_pw_ch_3[MENU_LABEL_LEN] = "PW CH 3 100%";
char lbl_pw_ch_4[MENU_LABEL_LEN] = "PW CH 4 100%";
// char lbl_boot_screen[LCD_TOTAL_COLS + 1] = "B:Boot";
// char lbl_main_screen[LCD_TOTAL_COLS + 1] = "M:Race";
// char lbl_temp_on[LCD_TOTAL_COLS + 1] = "Temp ON 15C";
// char lbl_temp_off[LCD_TOTAL_COLS + 1] = "Temp OFF 35C";
// char lbl_pw_ch_1[LCD_TOTAL_COLS + 1] = "PW CH 1 100%";
// char lbl_pw_ch_2[LCD_TOTAL_COLS + 1] = "PW CH 2 100%";
// char lbl_pw_ch_3[LCD_TOTAL_COLS + 1] = "PW CH 3 100%";
// char lbl_pw_ch_4[LCD_TOTAL_COLS + 1] = "PW CH 4 100%";
/* ---------- Handle'ы ---------- */
zh_encoder_handle_t *encoder_handle = NULL;
@@ -85,6 +59,14 @@ static void zh_save_settings(void);
void zh_encoder_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data);
void zh_menu_enter_main_menu_callback(void *arg);
void zh_menu_exit_main_menu_callback(void *arg);
void zh_menu_change_menu_callback(zh_menu_node_t *current_node, uint8_t current_index);
void zh_menu_selectable_item_callback(void *arg);
void zh_menu_back_command_callback(void *arg);
void zh_menu_boot_screen_callback(void *arg);
void zh_menu_main_screen_callback(void *arg);
/* ---------- Состояние меню ---------- */
static zh_menu_node_t *last_node = NULL;
static uint8_t last_index = 0;
@@ -150,15 +132,15 @@ static void zh_save_settings(void)
}
/* ---------- Утилиты ---------- */
static inline int16_t _clamp_i16(int16_t v, int16_t lo, int16_t hi)
{
return v < lo ? lo : (v > hi ? hi : v);
}
// static inline int16_t _clamp_i16(int16_t v, int16_t lo, int16_t hi)
// {
// return v < lo ? lo : (v > hi ? hi : v);
// }
static inline uint8_t _clamp_u8(int16_t v, uint8_t lo, uint8_t hi)
{
return v < lo ? lo : (v > hi ? hi : v);
}
// static inline uint8_t _clamp_u8(int16_t v, uint8_t lo, uint8_t hi)
// {
// return v < lo ? lo : (v > hi ? hi : v);
// }
static void _invalidaterow_cache(void)
{
@@ -166,8 +148,7 @@ static void _invalidaterow_cache(void)
}
/* ---------- Форматирование ---------- */
static void _format_row(char *buf, const char *label, bool selected, bool edit,
bool arrow_up, bool arrow_down)
static void _format_row(char *buf, const char *label, bool selected, bool edit, bool arrow_up, bool arrow_down)
{
memset(buf, ' ', LCD_TOTAL_COLS);
buf[LCD_TOTAL_COLS] = '\0';
@@ -211,8 +192,9 @@ static void _format_load_row(char *buf, const char *line)
static void _lcd_put_row(uint8_t row, const char *text)
{
if (row_valid[row] && memcmp(row_cache[row], text, LCD_TOTAL_COLS) == 0)
{
return;
}
zh_160x_set_cursor(&lcd_handle, row, 0);
zh_160x_print_char(&lcd_handle, text);
memcpy(row_cache[row], text, LCD_TOTAL_COLS);
@@ -255,11 +237,11 @@ static void _refresh_dynamic_labels(zh_menu_node_t *node)
}
else if (lbl == lbl_boot_screen)
{
snprintf(lbl_boot_screen, sizeof(lbl_boot_screen), "B:%s", load_screens[_boot_screen].name);
snprintf(lbl_boot_screen, sizeof(lbl_boot_screen), "B:%s", boot_screens[boot_screen_number].name);
}
else if (lbl == lbl_main_screen)
{
snprintf(lbl_main_screen, sizeof(lbl_main_screen), "M:%s", main_screens[_main_screen].name);
snprintf(lbl_main_screen, sizeof(lbl_main_screen), "M:%s", main_screens[main_screen_number].name);
}
}
}
@@ -267,7 +249,7 @@ static void _refresh_dynamic_labels(zh_menu_node_t *node)
/* ---------- Отрисовка экранов ---------- */
static void _draw_main_screen(void)
{
const zh_main_screen_description_t *s = &main_screens[_main_screen];
const zh_main_screen_description_t *s = &main_screens[main_screen_number];
for (uint8_t i = 0; i < LCD_TOTAL_ROWS; ++i)
{
char buf[LCD_TOTAL_COLS + 1];
@@ -278,7 +260,7 @@ static void _draw_main_screen(void)
static void _draw_load_screen(void)
{
const zh_boot_screen_description_t *s = &load_screens[_boot_screen];
const zh_boot_screen_description_t *s = &boot_screens[boot_screen_number];
for (uint8_t i = 0; i < LCD_TOTAL_ROWS; ++i)
{
char buf[LCD_TOTAL_COLS + 1];
@@ -451,7 +433,7 @@ void zh_encoder_event_handler(void *arg, esp_event_base_t event_base, int32_t ev
case ZH_BUTTON_EVENT:
{
zh_encoder_button_event_on_isr_t *button_event = event_data;
if (button_event->button_status == true)
if (button_event->button_status == ENCODER_BUTTON_RELEASED)
{
menu_status.is_active == false ? zh_menu_set(&menu_handle, ZH_MENU_ENTER, NULL, 0) : menu_status.is_selected == false ? zh_menu_set(&menu_handle, ZH_MENU_SELECT, NULL, 0)
: zh_menu_set(&menu_handle, ZH_MENU_BACK, NULL, 0);
@@ -531,60 +513,58 @@ void zh_menu_change_menu_callback(zh_menu_node_t *current_node, uint8_t current_
void zh_menu_selectable_item_callback(void *arg)
{
if (last_node == NULL || last_node->submenu == NULL)
{
return;
}
if (last_index >= last_node->item_numbers)
{
return;
}
zh_menu_node_t *item = &last_node->submenu[last_index];
if (arg == NULL)
{
zh_menu_set(&menu_handle, ZH_MENU_SHOW, NULL, 0);
return;
}
zh_encoder_event_on_isr_t *enc = arg;
int8_t dir = enc->encoder_status ? +1 : -1;
zh_encoder_event_on_isr_t *encoder = arg;
int8_t dir = encoder->encoder_status ? +1 : -1;
bool changed = false;
if (item->label == lbl_temp_on)
{
air_condition_temp_on = _clamp_i16(air_condition_temp_on + dir, 15, 30);
air_condition_temp_on = VALUE_CLAMP(air_condition_temp_on + dir, 15, 30);
changed = true;
}
else if (item->label == lbl_temp_off)
{
air_condition_temp_off = _clamp_i16(air_condition_temp_off + dir, 15, 30);
air_condition_temp_off = VALUE_CLAMP(air_condition_temp_off + dir, 15, 30);
changed = true;
}
else if (item->label == lbl_pw_ch_1)
{
exit_channel_power[0] = _clamp_u8(exit_channel_power[0] + dir * 5, 0, 100);
exit_channel_power[0] = VALUE_CLAMP(exit_channel_power[0] + dir * 5, 0, 100);
changed = true;
}
else if (item->label == lbl_pw_ch_2)
{
exit_channel_power[1] = _clamp_u8(exit_channel_power[1] + dir * 5, 0, 100);
exit_channel_power[1] = VALUE_CLAMP(exit_channel_power[1] + dir * 5, 0, 100);
changed = true;
}
else if (item->label == lbl_pw_ch_3)
{
exit_channel_power[2] = _clamp_u8(exit_channel_power[2] + dir * 5, 0, 100);
exit_channel_power[2] = VALUE_CLAMP(exit_channel_power[2] + dir * 5, 0, 100);
changed = true;
}
else if (item->label == lbl_pw_ch_4)
{
exit_channel_power[3] = _clamp_u8(exit_channel_power[3] + dir * 5, 0, 100);
exit_channel_power[3] = VALUE_CLAMP(exit_channel_power[3] + dir * 5, 0, 100);
changed = true;
}
if (changed)
if (changed == true)
{
zh_menu_set(&menu_handle, ZH_MENU_SHOW, NULL, 0);
}
}
/* ---------- Selectable: выбор load-экрана ---------- */
void zh_menu_boot_screen_callback(void *arg)
{
if (arg == NULL)
@@ -592,24 +572,24 @@ void zh_menu_boot_screen_callback(void *arg)
zh_menu_set(&menu_handle, ZH_MENU_SHOW, NULL, 0);
return;
}
zh_encoder_event_on_isr_t *enc = arg;
int8_t dir = enc->encoder_status ? +1 : -1;
int next = _boot_screen + dir;
zh_encoder_event_on_isr_t *encoder = arg;
int8_t dir = encoder->encoder_status == true ? +1 : -1;
int next = boot_screen_number + dir;
if (next < 0)
next = LOAD_SCREEN_COUNT - 1;
if (next >= LOAD_SCREEN_COUNT)
next = 0;
if (next != _boot_screen)
{
_boot_screen = next;
next = ARRAY_SIZE(boot_screens) - 1;
}
if (next >= ARRAY_SIZE(boot_screens))
{
next = 0;
}
if (next != boot_screen_number)
{
boot_screen_number = next;
zh_menu_set(&menu_handle, ZH_MENU_SHOW, NULL, 0);
}
}
/* ---------- Selectable: выбор main-экрана ---------- */
void zh_menu_main_screen_callback(void *arg)
{
if (arg == NULL)
@@ -617,28 +597,29 @@ void zh_menu_main_screen_callback(void *arg)
zh_menu_set(&menu_handle, ZH_MENU_SHOW, NULL, 0);
return;
}
zh_encoder_event_on_isr_t *enc = arg;
int8_t dir = enc->encoder_status ? +1 : -1;
int next = _main_screen + dir;
zh_encoder_event_on_isr_t *encoder = arg;
int8_t dir = encoder->encoder_status == true ? +1 : -1;
int next = main_screen_number + dir;
if (next < 0)
next = MAIN_SCREEN_COUNT - 1;
if (next >= MAIN_SCREEN_COUNT)
next = 0;
if (next != _main_screen)
{
_main_screen = next;
next = ARRAY_SIZE(main_screens) - 1;
}
if (next >= ARRAY_SIZE(main_screens))
{
next = 0;
}
if (next != main_screen_number)
{
main_screen_number = next;
zh_menu_set(&menu_handle, ZH_MENU_SHOW, NULL, 0);
}
}
void zh_menu_simple_item_callback(void *arg)
{
(void)arg;
ESP_LOGI(TAG, "Simple item callback performed");
}
// void zh_menu_simple_item_callback(void *arg)
// {
// (void)arg;
// ESP_LOGI(TAG, "Simple item callback performed");
// }
void zh_menu_back_command_callback(void *arg)
{
+37 -27
View File
@@ -7,17 +7,30 @@
#include "zh_encoder.h"
#include "zh_ota_server.h"
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
#define VALUE_CLAMP(v, lo, hi) ((v) < (lo) ? (lo) : ((v) > (hi) ? (hi) : (v)))
#define ENCODER_NUMBER 1
#define LCD_TOTAL_ROWS 4
#define LCD_TOTAL_COLS 16
#define STATS_TASK_PRIORITY tskIDLE_PRIORITY /*!< Priority of the statistics/monitoring task */
#define STATS_TASK_STACK_SIZE configMINIMAL_STACK_SIZE + 1280 /*!< Stack size of the statistics/monitoring task */
#define EXPANDER_TASK_PRIORITY tskIDLE_PRIORITY + 5 /*!< Priority of the PCF8574 expander polling task */
#define EXPANDER_TASK_STACK_SIZE configMINIMAL_STACK_SIZE /*!< Stack size of the expander polling task */
#define ENCODER_TASK_PRIORITY tskIDLE_PRIORITY + 4 /*!< Priority of the encoder reading task */
#define ENCODER_TASK_STACK_SIZE configMINIMAL_STACK_SIZE /*!< Stack size of the encoder task */
// #define LCD_VIEWPORT_ROWS (LCD_TOTAL_ROWS - 1)
#define MENU_LABEL_LEN 17
#define ENCODER_BUTTON_RELEASED true /*!< State: encoder button released */
#define ENCODER_BUTTON_PRESSED false /*!< State: encoder button pressed */
// #define LCD_TOTAL_COLS+1 17
/* ---------- Размеры view ---------- */
#define VIEW_CELLS 5 /* ячеек в массиве данных (main) */
#define VIEW_ROWS 4 /* строк отрисовывается на LCD */
// #define VIEW_ROWS 4 /* строк отрисовывается на LCD */
#define NVS_NAMESPACE "sim_race_box" /* NEW */
#define NVS_KEY_SETTINGS "settings" /* NEW */
@@ -29,36 +42,25 @@ extern int16_t main_times_data[VIEW_CELLS];
extern int16_t main_debug_data[VIEW_CELLS];
extern int16_t main_blank_data[VIEW_CELLS];
/* ---------- Динамические буферы меток ---------- */
extern char lbl_temp_on[MENU_LABEL_LEN];
extern char lbl_temp_off[MENU_LABEL_LEN];
extern char lbl_pw_ch_1[MENU_LABEL_LEN];
extern char lbl_pw_ch_2[MENU_LABEL_LEN];
extern char lbl_pw_ch_3[MENU_LABEL_LEN];
extern char lbl_pw_ch_4[MENU_LABEL_LEN];
extern char lbl_boot_screen[MENU_LABEL_LEN]; /* "B: <имя load-экрана>" */
extern char lbl_main_screen[MENU_LABEL_LEN]; /* "M: <имя main-экрана>" */
/* ---------- Переменные значений ---------- */
// extern int16_t g_temp_on;
// extern int16_t g_temp_off;
// extern uint8_t g_pw_ch[4];
/* ---------- Callbacks ---------- */
void zh_menu_enter_main_menu_callback(void *arg);
void zh_menu_exit_main_menu_callback(void *arg);
void zh_menu_change_menu_callback(zh_menu_node_t *current_node, uint8_t current_index);
void zh_menu_selectable_item_callback(void *arg);
void zh_menu_simple_item_callback(void *args);
void zh_menu_back_command_callback(void *arg);
void zh_menu_boot_screen_callback(void *arg);
void zh_menu_main_screen_callback(void *arg);
#ifdef __cplusplus
extern "C"
{
#endif
extern void zh_menu_selectable_item_callback(void *arg);
extern void zh_menu_back_command_callback(void *arg);
extern void zh_menu_boot_screen_callback(void *arg);
extern void zh_menu_main_screen_callback(void *arg);
static char lbl_boot_screen[LCD_TOTAL_COLS + 1] = "B:Boot";
static char lbl_main_screen[LCD_TOTAL_COLS + 1] = "M:Race";
static char lbl_temp_on[LCD_TOTAL_COLS + 1] = "Temp ON 15C";
static char lbl_temp_off[LCD_TOTAL_COLS + 1] = "Temp OFF 35C";
static char lbl_pw_ch_1[LCD_TOTAL_COLS + 1] = "PW CH 1 100%";
static char lbl_pw_ch_2[LCD_TOTAL_COLS + 1] = "PW CH 2 100%";
static char lbl_pw_ch_3[LCD_TOTAL_COLS + 1] = "PW CH 3 100%";
static char lbl_pw_ch_4[LCD_TOTAL_COLS + 1] = "PW CH 4 100%";
typedef struct
{
uint8_t air_condition_temp_on;
@@ -82,6 +84,14 @@ extern "C"
const char *const lines[LCD_TOTAL_ROWS];
} zh_boot_screen_description_t;
static const zh_boot_screen_description_t boot_screens[] = {
{"Boot", {"Booting...", "RAM: OK", "I2C: OK", "Starting..."}},
{"Version", {"FW v1.0", "Build 2025-10", "ESP-IDF v5.4", ""}},
{"Diag", {"I2C: OK", "LCD: OK", "ENC: OK", "All: OK"}},
{"Ready", {"System ready", "Ready for race", "Let's go", ""}},
{"Blank", {"---", "---", "---", "---"}},
};
zh_menu_node_t main_menu = {
.label = "Settings",
.submenu = (zh_menu_node_t[]){