From a9e44145f068af71d8dfc8be113ceb9f84bd2cc1 Mon Sep 17 00:00:00 2001 From: Mitchell Marino Date: Thu, 17 Jul 2025 17:02:31 -0500 Subject: [PATCH] more LCD Header work --- main/drivers/all.cpp | 2 + main/drivers/char_lcd.cpp | 59 ++++++++++++++++++++++++------ main/drivers/char_lcd.h | 5 ++- main/drivers/game_info.cpp | 5 ++- main/drivers/game_info.h | 2 +- main/drivers/i2c_lcd_pcf8574.c | 2 +- main/drivers/i2c_lcd_pcf8574.h | 2 +- main/drivers/power.cpp | 6 +-- main/drivers/power.h | 2 +- main/drivers/star_code.cpp | 67 ++++++++++++++++++++-------------- main/drivers/star_code.h | 2 +- main/helper.cpp | 3 +- main/main.cpp | 1 + main/steps/step0.cpp | 37 +++++++++---------- 14 files changed, 123 insertions(+), 72 deletions(-) diff --git a/main/drivers/all.cpp b/main/drivers/all.cpp index 3f2c41f..3e38868 100644 --- a/main/drivers/all.cpp +++ b/main/drivers/all.cpp @@ -14,4 +14,6 @@ void init_drivers() { init_tft(); init_leds(); init_power_board(); + + set_lcd_header_enabled(true); } diff --git a/main/drivers/char_lcd.cpp b/main/drivers/char_lcd.cpp index 0aa9818..cc4a74f 100644 --- a/main/drivers/char_lcd.cpp +++ b/main/drivers/char_lcd.cpp @@ -8,14 +8,22 @@ i2c_lcd_pcf8574_handle_t lcd; -static volatile bool header_enabled; +static volatile bool header_enabled = false; static const char *TAG = "char_lcd"; static const char* EMPTY_ROW = " "; -static const char* EMPTY_ROW3 = " "; static char buf[65]; +static void monitor_battery_task(void* _arg) { + (void) _arg; + + while (true) { + vTaskDelay(pdMS_TO_TICKS(1'000)); + lcd_print_header_bat(); + } +} + static bool replay_handler(const char* event, char* arg) { if (strcmp(event, "LCD_CLEAR") == 0) { lcd_clear(); @@ -97,6 +105,8 @@ void init_lcd() { register_replay_fn(replay_handler); + xTaskCreate(monitor_battery_task, "bat_monitor", 1024*2, nullptr, 0, nullptr); + ESP_LOGI(TAG, "LCD initialized!"); } @@ -108,14 +118,18 @@ void lcd_clear() { event_occured("LCD_CLEAR", NULL); } } else { - lcd_print(1, 2, EMPTY_ROW3); + lcd_print(0, 1, EMPTY_ROW); + lcd_print(0, 2, EMPTY_ROW); + lcd_print(0, 3, EMPTY_ROW); } } +// TODO: rm void lcd_cursor_home() { lcd_set_cursor_pos(0, 0); } +// TODO: with print requiring you to set a pos every time, this function is not helpful void lcd_set_cursor_pos(uint8_t col, uint8_t row) { lcd_set_cursor(&lcd, col, row); @@ -212,7 +226,7 @@ void lcd_set_backlight(bool backlight) { } } -void lcd_create_char(uint8_t location, uint8_t* charmap) { +void lcd_create_char(uint8_t location, const uint8_t charmap[]) { lcd_create_char(&lcd, location, charmap); if (is_state_tracking()) { @@ -236,14 +250,15 @@ void lcd_print(uint8_t col, uint8_t row, const char* str) { } void set_lcd_header_enabled(bool enable) { - if (!header_enabled && enable) { - // enabling header - lcd_print_header(); - } else if (header_enabled && !enable) { - // disabling header - lcd_print(1, 1, EMPTY_ROW); - } + bool old_header_enabled = header_enabled; header_enabled = enable; + + // update header in response to enabling/disabling the header + if (enable && !old_header_enabled) { + lcd_print_header(); + } else if (!enable && old_header_enabled) { + lcd_print(0, 0, EMPTY_ROW); + } } bool lcd_header_enabled() { @@ -256,4 +271,24 @@ void lcd_print_header() { lcd_print_header_bat(); } -// TODO: add task to continoususly print the battery header. +void lcd_do_splash() { + const uint8_t custom_char[6][8] = { + { 0x01, 0x01, 0x02, 0x02, 0x07, 0x07, 0x0F, 0x0D }, + { 0x10, 0x10, 0x18, 0x18, 0x1C, 0x0C, 0x0E, 0x06 }, + { 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x07, 0x07 }, + { 0x19, 0x1B, 0x13, 0x17, 0x07, 0x0F, 0x0F, 0x1F }, + { 0x13, 0x1B, 0x1F, 0x1F, 0x00, 0x1F, 0x1F, 0x1F }, + { 0x00, 0x00, 0x10, 0x10, 0x00, 0x18, 0x1C, 0x1C }, + }; + + // TODO: make the lcd_lib somehow support the custom character 0 which would otherwise be a null terminator + lcd_create_char(1, custom_char[0]); + lcd_create_char(2, custom_char[1]); + lcd_create_char(3, custom_char[2]); + lcd_create_char(4, custom_char[3]); + lcd_create_char(5, custom_char[4]); + lcd_create_char(6, custom_char[5]); + + lcd_print(6, 1, "\x01\x02Marino"); + lcd_print(5, 2, "\x03\x04\x05\x06""DEV"); +} \ No newline at end of file diff --git a/main/drivers/char_lcd.h b/main/drivers/char_lcd.h index 3f3e63c..51eaa50 100644 --- a/main/drivers/char_lcd.h +++ b/main/drivers/char_lcd.h @@ -47,7 +47,7 @@ void lcd_set_autoscroll(bool autoscroll); void lcd_set_backlight(bool backlight); // Create a custom character -void lcd_create_char(uint8_t location, uint8_t charmap[]); +void lcd_create_char(uint8_t location, const uint8_t charmap[]); /// @brief Print a string to the LCD at a given pos. /// @param col the column to print the string at. @@ -75,4 +75,7 @@ void lcd_print_header_step(); /// @brief Prints the battery section of the LCD header. void lcd_print_header_bat(); +/// @brief Prints the splash screen for the BLK_BOX. +void lcd_do_splash(); + #endif /* CHAR_LCD_H */ \ No newline at end of file diff --git a/main/drivers/game_info.cpp b/main/drivers/game_info.cpp index 3dfa616..3eca2f7 100644 --- a/main/drivers/game_info.cpp +++ b/main/drivers/game_info.cpp @@ -2,7 +2,8 @@ #include #include "char_lcd.h" -static char game_state[GAME_STATE_MAX_LEN+1] = " "; +// static char game_state[GAME_STATE_MAX_LEN+1] = " "; +static char game_state[GAME_STATE_MAX_LEN+1] = "MENU "; void set_game_state(char* new_state) { snprintf(game_state, sizeof(game_state), "%-5s", new_state); @@ -18,5 +19,5 @@ void reset_game_state() { void lcd_print_header_step() { if (!lcd_header_enabled()) return; - lcd_print(11, 1, game_state); + lcd_print(10, 0, game_state); } diff --git a/main/drivers/game_info.h b/main/drivers/game_info.h index bf135be..2f10d72 100644 --- a/main/drivers/game_info.h +++ b/main/drivers/game_info.h @@ -11,7 +11,7 @@ void set_game_state(char* new_state); /// @brief Resets the game state to be blank. void reset_game_state(); -/// @brief Prints the game state section of the header to the char_lcd. (row 1, columns 11-15) +/// @brief Prints the game state section of the header to the char_lcd. (row 0, columns 10-14) void lcd_print_header_step(); #endif /* GAME_INFO_H */ \ No newline at end of file diff --git a/main/drivers/i2c_lcd_pcf8574.c b/main/drivers/i2c_lcd_pcf8574.c index 18312bc..992cee9 100644 --- a/main/drivers/i2c_lcd_pcf8574.c +++ b/main/drivers/i2c_lcd_pcf8574.c @@ -241,7 +241,7 @@ void lcd_set_backlight(i2c_lcd_pcf8574_handle_t* lcd, uint8_t brightness) { } // lcd_set_backlight() // Custom character creation: allows us to create up to 8 custom characters in the CGRAM locations -void lcd_create_char(i2c_lcd_pcf8574_handle_t* lcd, uint8_t location, uint8_t charmap[]) { +void lcd_create_char(i2c_lcd_pcf8574_handle_t* lcd, uint8_t location, const uint8_t charmap[]) { location &= 0x7; // Only 8 locations are available // Set the CGRAM address lcd_send(lcd, 0x40 | (location << 3), false); diff --git a/main/drivers/i2c_lcd_pcf8574.h b/main/drivers/i2c_lcd_pcf8574.h index b31a87c..230711c 100644 --- a/main/drivers/i2c_lcd_pcf8574.h +++ b/main/drivers/i2c_lcd_pcf8574.h @@ -94,7 +94,7 @@ void lcd_no_autoscroll(i2c_lcd_pcf8574_handle_t* lcd); void lcd_set_backlight(i2c_lcd_pcf8574_handle_t* lcd, uint8_t brightness); // Create a custom character -void lcd_create_char(i2c_lcd_pcf8574_handle_t* lcd, uint8_t location, uint8_t charmap[]); +void lcd_create_char(i2c_lcd_pcf8574_handle_t* lcd, uint8_t location, const uint8_t charmap[]); // Write a character to the LCD void lcd_write(i2c_lcd_pcf8574_handle_t* lcd, uint8_t value); diff --git a/main/drivers/power.cpp b/main/drivers/power.cpp index 0a4312a..1db6e99 100644 --- a/main/drivers/power.cpp +++ b/main/drivers/power.cpp @@ -65,9 +65,9 @@ void lcd_print_header_bat() { snprintf(buf, sizeof(buf), "%3d%%", soc); } - if (lipo.chgFlag()) { - buf[4] = '+'; + if (lipo.current() > 0) { + buf[3] = '+'; } - lcd_print(17, 1, buf); + lcd_print(16, 0, buf); } diff --git a/main/drivers/power.h b/main/drivers/power.h index 2ec8174..2150547 100644 --- a/main/drivers/power.h +++ b/main/drivers/power.h @@ -14,7 +14,7 @@ void init_power_board(); /// @return battery voltage in mV. uint16_t get_bat_voltage(); -/// @brief Prints the battery section of the header to the char_lcd. (row 1, columns 17-20) +/// @brief Prints the battery section of the header to the char_lcd. (row 0, columns 16-19) void lcd_print_header_bat(); #endif /* POWER_H */ diff --git a/main/drivers/star_code.cpp b/main/drivers/star_code.cpp index 65b7664..c33e5da 100644 --- a/main/drivers/star_code.cpp +++ b/main/drivers/star_code.cpp @@ -20,7 +20,8 @@ static std::vector star_codes; static const char EMPTY_STAR_CODE_HEADER[] = " "; esp_timer_handle_t starcode_delay_timer; -static volatile StarCodeEntry* processing_starcode = nullptr; +static volatile bool processing_starcode; +static volatile StarCodeEntry* current_starcode = nullptr; static volatile bool doing_starcode = false; static uint16_t starcode_waiting_on_release; static char current[STARCODE_MAX_LEN + 1]; @@ -29,19 +30,24 @@ static size_t current_idx; static void starcode_trigger_cb(void* arg) { (void) arg; - if (processing_starcode->triggered_sem != nullptr) - xSemaphoreGive(processing_starcode->triggered_sem); - if (processing_starcode->callback != nullptr) - (processing_starcode->callback)(); + processing_starcode = false; + + if (current_starcode != nullptr) { + if (current_starcode->triggered_sem != nullptr) + xSemaphoreGive(current_starcode->triggered_sem); + if (current_starcode->callback != nullptr) + (current_starcode->callback)(); + + current_starcode = nullptr; + } - processing_starcode = nullptr; // TODO: rename star code everywhere to starcode lcd_print_header_star_code(); } void star_code_handle_keypad(uint16_t* just_pressed, uint16_t* just_released) { - if ((processing_starcode == nullptr) && handling_new_starcodes && (*just_pressed | (1 << KeypadKey::star))) { + if ((!processing_starcode) && handling_new_starcodes && (*just_pressed & (1 << KeypadKey::star))) { current_idx = 0; current[current_idx] = '\0'; doing_starcode = true; @@ -57,7 +63,6 @@ void star_code_handle_keypad(uint16_t* just_pressed, uint16_t* just_released) { current[current_idx] = '\0'; } else if (key == KeypadKey::pound) { doing_starcode = false; - lcd_print_header_star_code(); if (current_idx != 0) { trigger_star_code(current); } @@ -72,8 +77,8 @@ void star_code_handle_keypad(uint16_t* just_pressed, uint16_t* just_released) { // append the character current[current_idx++] = char_of_keypad_key(key); current[current_idx] = '\0'; - lcd_print_header_star_code(); } + lcd_print_header_star_code(); } } @@ -95,7 +100,7 @@ void init_star_code_system() { .skip_unhandled_events = false, }; - esp_timer_create(&timer_args, &starcode_delay_timer); + ESP_ERROR_CHECK(esp_timer_create(&timer_args, &starcode_delay_timer)); handling_new_starcodes = true; system_initialized = true; @@ -191,24 +196,26 @@ void clear_star_codes() { } bool trigger_star_code(const char* code) { + ESP_LOGI(TAG, "Star codes to checK:"); + for (const auto& entry : star_codes) { + ESP_LOGI(TAG, "%s", entry.code); + } + + auto it = std::find_if(star_codes.begin(), star_codes.end(), [&](const StarCodeEntry& other) { return check_code_match(code, other.code); }); - if (it == star_codes.end()) { - return false; + uint64_t delay_us = 2'000'000; + processing_starcode = true; + if (it != star_codes.end()) { + current_starcode = &*it; + delay_us = current_starcode->delay_us; } - processing_starcode = &*it; + ESP_ERROR_CHECK(esp_timer_start_once(starcode_delay_timer, delay_us)); - // print display text - if (processing_starcode->display_text != nullptr) { - lcd_print_header_star_code(); - } - - esp_timer_start_once(starcode_delay_timer, processing_starcode->delay_us); - - return true; + return current_starcode != nullptr; } void pause_star_code_system() { @@ -223,19 +230,23 @@ void resume_star_code_system() { void lcd_print_header_star_code() { if (!lcd_header_enabled()) return; - if (processing_starcode != nullptr) { - if (processing_starcode->display_text != nullptr) { + // TODO: consider upping the display text size to be able to overwrite the game_state area. + if (processing_starcode) { + if (current_starcode == nullptr) { + lcd_print(0, 0, "Invalid "); + } else if (current_starcode->display_text != nullptr) { char buf[STARCODE_MAX_LEN + 2]; - snprintf(buf, sizeof(buf), "%s", processing_starcode->display_text); - lcd_print(1, 1, processing_starcode->display_text); + snprintf(buf, sizeof(buf), "%s", current_starcode->display_text); + lcd_print(0, 0, buf); } else { - lcd_print(1, 1, EMPTY_STAR_CODE_HEADER); + lcd_print(0, 0, EMPTY_STAR_CODE_HEADER); } + } else if (doing_starcode) { char buf[STARCODE_MAX_LEN + 2]; snprintf(buf, sizeof(buf), "*%-8s", current); - lcd_print(1, 1, buf); + lcd_print(0, 0, buf); } else { - lcd_print(1, 1, EMPTY_STAR_CODE_HEADER); + lcd_print(0, 0, EMPTY_STAR_CODE_HEADER); } } diff --git a/main/drivers/star_code.h b/main/drivers/star_code.h index 409ed6f..f58babe 100644 --- a/main/drivers/star_code.h +++ b/main/drivers/star_code.h @@ -81,7 +81,7 @@ void set_star_code_sys_enabled(bool enable); /// @return `true` if the star code system is handling star codes. bool star_code_sys_enabled(); -/// @brief Prints the star code section of the header to the char_lcd. (row 1, columns 1-10) +/// @brief Prints the star code section of the header to the char_lcd. (row 0, columns 0-9) void lcd_print_header_star_code(); #endif /* STAR_CODE_H */ \ No newline at end of file diff --git a/main/helper.cpp b/main/helper.cpp index 1d55bec..1afd254 100644 --- a/main/helper.cpp +++ b/main/helper.cpp @@ -17,9 +17,8 @@ void clean_bomb(void) { set_module_sseg_raw(clear); // clear char lcd - lcd_clear(); lcd_set_cursor_vis(false); - lcd_cursor_home(); + lcd_clear(); // TODO: add stuff for starcode system } diff --git a/main/main.cpp b/main/main.cpp index 625e877..76b923e 100755 --- a/main/main.cpp +++ b/main/main.cpp @@ -37,6 +37,7 @@ extern "C" void app_main(void) { vTaskDelay(pdMS_TO_TICKS(1000)); clean_bomb(); + lcd_do_splash(); step0(); // set_recording_source(stdout, false); diff --git a/main/steps/step0.cpp b/main/steps/step0.cpp index 75d54fb..314778f 100644 --- a/main/steps/step0.cpp +++ b/main/steps/step0.cpp @@ -47,18 +47,27 @@ static void replay_last() { void step0() { + led_set(IndicatorLED::LED_SPEAKER, LEDColor::LED_COLOR_BLUE); + leds_flush(); + + SemaphoreHandle_t continue_sem = xSemaphoreCreateBinary(); + if (continue_sem == nullptr) { + ESP_LOGE(TAG, "could not create semaphore"); + return; + } + StarCodeEntry star_codes[] = { { .code = "9819", .display_text = "Defusal Initiated", .delay_us = 2'000'000, .callback = nullptr, - .triggered_sem = nullptr, + .triggered_sem = continue_sem, }, { .code = "59862", .display_text = "Set Up Wires", - .delay_us = 2'000'000, + .delay_us = 10'000'000, .callback = setup_wires, .triggered_sem = nullptr, }, @@ -130,42 +139,42 @@ void step0() { .display_text = "Skip To Step 1", .delay_us = 2'000'000, .callback = skip_to_step1, - .triggered_sem = nullptr, + .triggered_sem = continue_sem, }, { .code = "59882", .display_text = "Skip To Step 2", .delay_us = 2'000'000, .callback = skip_to_step2, - .triggered_sem = nullptr, + .triggered_sem = continue_sem, }, { .code = "59883", .display_text = "Skip To Step 3", .delay_us = 2'000'000, .callback = skip_to_step3, - .triggered_sem = nullptr, + .triggered_sem = continue_sem, }, { .code = "59884", .display_text = "Skip To Step 4", .delay_us = 2'000'000, .callback = skip_to_step4, - .triggered_sem = nullptr, + .triggered_sem = continue_sem, }, { .code = "59885", .display_text = "Skip To Step 5", .delay_us = 2'000'000, .callback = skip_to_step5, - .triggered_sem = nullptr, + .triggered_sem = continue_sem, }, { .code = "59886", .display_text = "Skip To Step 6", .delay_us = 2'000'000, .callback = skip_to_step6, - .triggered_sem = nullptr, + .triggered_sem = continue_sem, }, { .code = "1111", @@ -186,21 +195,11 @@ void step0() { .display_text = "replay_last", .delay_us = 2'000'000, .callback = replay_last, - .triggered_sem = nullptr, + .triggered_sem = continue_sem, }, }; size_t len = sizeof(star_codes)/sizeof(star_codes[0]); - - SemaphoreHandle_t continue_sem = xSemaphoreCreateBinary(); - if (continue_sem == nullptr) { - ESP_LOGE(TAG, "could not create semaphore"); - return; - } - - led_set(IndicatorLED::LED_SPEAKER, LEDColor::LED_COLOR_BLUE); - leds_flush(); - add_star_codes(star_codes, len); xSemaphoreTake(continue_sem, portMAX_DELAY); rm_star_codes(star_codes, len);