From 9cc1a93e73c4dee3ea982b8b709814fe4eeb1efc Mon Sep 17 00:00:00 2001 From: Mitchell Marino Date: Sun, 6 Jul 2025 22:52:39 -0500 Subject: [PATCH] some bottom_half side star code work --- main/drivers/all.cpp | 3 +- main/drivers/bottom_half.cpp | 62 +++++++++++++++++++---- main/drivers/bottom_half.h | 3 ++ main/drivers/star_code.cpp | 98 ++++++++++++++++++++++++++++++++++-- main/drivers/star_code.h | 25 ++++++++- main/steps/step0.cpp | 2 +- main/steps/step5.cpp | 4 +- 7 files changed, 179 insertions(+), 18 deletions(-) diff --git a/main/drivers/all.cpp b/main/drivers/all.cpp index 2d8e03c..8fcbdb3 100644 --- a/main/drivers/all.cpp +++ b/main/drivers/all.cpp @@ -7,6 +7,7 @@ void init_drivers() { init_i2c(); // init char_lcd so we can use it to report other initialization errors. init_lcd(); + init_star_code_system(); // init the bottom half so that we can get user input. init_bottom_half(); init_sd(); @@ -18,7 +19,7 @@ void init_drivers() { init_power_board(); } -/// @brief Initializes I2C_NUM_0. +/// @brief Initializes `I2C_NUM_0`. /// /// This is hooked up the to: /// - The bottom half diff --git a/main/drivers/bottom_half.cpp b/main/drivers/bottom_half.cpp index 7644bf1..9a78cd7 100644 --- a/main/drivers/bottom_half.cpp +++ b/main/drivers/bottom_half.cpp @@ -1,9 +1,15 @@ #include "bottom_half.h" #include #include "state_tracking.h" +#include "star_code.h" static const char *TAG = "bottom_half"; +volatile bool doing_starcode = false; +static uint16_t starcode_waiting_on_release; +static char current_starcode[STARCODE_MAX_LEN + 1]; +static size_t current_starcode_idx; + static uint16_t keypad_state; static uint8_t button_state; static uint8_t switch_state; @@ -69,20 +75,23 @@ void init_bottom_half() { static uint8_t receive_delta(void) { uint8_t reg = 1; - buf[0] = 0; - ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS))); + esp_err_t result = i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 1, (100 / portTICK_PERIOD_MS)); + ESP_ERROR_CHECK_WITHOUT_ABORT(result); + if (result != ESP_OK) { + return; + } return buf[0]; } static void receive_keypad(void) { uint8_t reg = 2; - buf[0] = 0; - buf[1] = 0; - ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 2, (100 / portTICK_PERIOD_MS))); + esp_err_t result = i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 2, (100 / portTICK_PERIOD_MS)); + ESP_ERROR_CHECK_WITHOUT_ABORT(result); + if (result != ESP_OK) { + return; + } uint16_t new_keypad_state = buf[0] | (buf[1] << 8); - uint16_t just_pressed = new_keypad_state & ~keypad_state; - keypad_pressed |= just_pressed; if (is_state_tracking() && just_pressed) { char buf[6]; sprintf(buf, "%d", just_pressed); @@ -90,19 +99,54 @@ static void receive_keypad(void) { } uint16_t just_released = ~new_keypad_state & keypad_state; - keypad_released |= just_released; if (is_state_tracking() && just_released) { char buf[6]; sprintf(buf, "%d", just_released); event_occured("KP_RELEASE", buf); } + if (handling_new_starcodes && (just_pressed | (1 << KeypadKey::star))) { + current_starcode_idx = 0; + current_starcode[current_starcode_idx] = '\0'; + doing_starcode = true; + } + if (doing_starcode) { + // If we get a press while handling a starcode, we also want to capture the release of that key. + starcode_waiting_on_release |= just_pressed; + + KeypadKey key; + while (_take_key(&key, &just_pressed)) { + if (key == KeypadKey::star) { + current_starcode_idx = 0; + current_starcode[current_starcode_idx] = '\0'; + } else if (key == KeypadKey::pound) { + doing_starcode = false; + trigger_star_code(current_starcode); + } else if (current_starcode_idx < STARCODE_MAX_LEN) { + current_starcode[current_starcode_idx++] = char_of_keypad_key(key); + current_starcode[current_starcode_idx] = '\0'; + } + } + } + + // capture any releases from starcodes + uint16_t new_just_released = just_released & (~starcode_waiting_on_release); + starcode_waiting_on_release = starcode_waiting_on_release & (~just_released); + just_released = new_just_released; + + keypad_pressed |= just_pressed; + keypad_released |= just_released; keypad_state = new_keypad_state; } static void receive_button_switch(void) { uint8_t reg = 3; - ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 2, (100 / portTICK_PERIOD_MS))); + esp_err_t result = i2c_master_write_read_device(BOTTOM_I2C_NUM, BOTTOM_I2C_ADDR, ®, 1, buf, 2, (100 / portTICK_PERIOD_MS)); + ESP_ERROR_CHECK_WITHOUT_ABORT(result); + if (result != ESP_OK) { + return; + } + uint8_t new_button_state = buf[1] & 0xF; uint8_t new_switch_state = (~buf[0]) & 0xF; uint8_t new_switch_touch_state = (buf[1] >> 4) & 0xF; diff --git a/main/drivers/bottom_half.h b/main/drivers/bottom_half.h index 86f8f36..abef5af 100644 --- a/main/drivers/bottom_half.h +++ b/main/drivers/bottom_half.h @@ -12,6 +12,9 @@ #define DELTA_BIT_BUTTON_SWITCH 1 #define DELTA_BIT_TOUCH 2 +/// @brief `true` if a starcode is currently being handled. +extern volatile bool doing_starcode; + /// @brief An enum for the possible keypad buttons. typedef enum { k1 = 0, diff --git a/main/drivers/star_code.cpp b/main/drivers/star_code.cpp index 82fb197..1e80665 100644 --- a/main/drivers/star_code.cpp +++ b/main/drivers/star_code.cpp @@ -5,11 +5,94 @@ #include #include #include +#include "drivers/bottom_half.h" static const char* TAG = "star_code"; +volatile bool handling_new_starcodes = false; +static bool system_initialized = false; + +static volatile SemaphoreHandle_t star_codes_sem; static std::vector star_codes; +static TaskHandle_t task_handle; + +static void star_code_task(void* param) { + KeypadKey key; + + int current_idx = 0; + char current[STRING_MAX_LEN+1] = {0}; + + while (1) { + while (get_keypad_pressed(&key)) { + if (key == KeypadKey::star) { + current[0] = '*'; + for (int i = 1; i < STRING_MAX_LEN; i++) { + current[i] = 0; + } + current_idx = 1; + } else if (key == KeypadKey::pound) { + // submit + if (current[0] == '\0') { + continue; + } + + bool hit = false; + for (int i = 0; i < star_codes_len; i++) { + StarCodeHandler sch = star_codes[i]; + if (strcmp(current, sch.code) == 0) { + hit = true; + lcd_print(1, 2, sch.display_text); + vTaskDelay(pdMS_TO_TICKS(2000)); + if (sch.callback != nullptr) { + (sch.callback)(); + } + if (sch.should_exit) { + return; + } + break; + } + } + + if (!hit) { + lcd_print(1, 2, "Invalid Star Code"); + vTaskDelay(pdMS_TO_TICKS(2000)); + } + + // clear + for (int i = 0; i < STRING_MAX_LEN; i++) { + current[i] = 0; + } + current_idx = 0; + } else { + // out of room. skip + if (current_idx >= STRING_MAX_LEN) break; + // no code started. + if (current[0] != '*') continue; + + char c = char_of_keypad_key(key); + current[current_idx++] = c; + } + // ESP_LOGI(STEP0_TAG, "Pressed: %c", c); + + lcd_clear(); + lcd_print(1, 1, current); + } + + vTaskDelay(pdMS_TO_TICKS(10)); + } +} + +void init_star_code_system() { + star_codes_sem = xSemaphoreCreateBinary(); + xSemaphoreGive(star_codes_sem); + + xTaskCreate(star_code_task, "star_code", 2048, nullptr, 1, &task_handle); + + handling_new_starcodes = true; + system_initialized = true; +} + /// Checks if a triggered code matches an expected code. /// @return true iff the codes match, where '*'s in the expected code can match any character in the triggered code static bool check_code_match(const char* triggered, const char* expected) { @@ -29,10 +112,10 @@ static bool check_code_match(const char* triggered, const char* expected) { } bool add_star_code(StarCodeEntry code) { - if (code.code == nullptr || strlen(code.code) > 8) { + if (code.code == nullptr || strlen(code.code) > STARCODE_MAX_LEN) { return false; } - if (code.display_text != nullptr && strlen(code.display_text) > 9) { + if (code.display_text != nullptr && strlen(code.display_text) > STARCODE_MAX_LEN + 1) { return false; } @@ -108,6 +191,15 @@ bool trigger_star_code(const char* code) { return false; } - (it->callback)(); + if (it->callback != nullptr) + (it->callback)(); return true; } + +void pause_star_code_system() { + handling_new_starcodes = false; +} + +void resume_star_code_system() { + handling_new_starcodes = system_initialized; +} \ No newline at end of file diff --git a/main/drivers/star_code.h b/main/drivers/star_code.h index 285550e..31b8b55 100644 --- a/main/drivers/star_code.h +++ b/main/drivers/star_code.h @@ -1,7 +1,14 @@ #ifndef STAR_CODE_H #define STAR_CODE_H -#include +#include +#include +#include + +/// The max length of a starcode (not counting the star) +#define STARCODE_MAX_LEN 8 + +extern volatile bool handling_new_starcodes; /// @brief A handler for a specific star code struct StarCodeEntry { @@ -11,16 +18,23 @@ struct StarCodeEntry { /// /// You may include a * in the code to match on any character const char* code; - /// @brief The text to display when the star code is entered (or NULL). + /// @brief The text to display when the star code is entered (or null). /// /// This must be <= 9 characters. const char* display_text; /// @brief The number of ticks to delay when the star code is entered before calling the handler. uint32_t delay_ticks; /// @brief The function to call when the star code is entered. + /// Can be null. void (*callback)(void); + /// @brief The binary semaphore that will be given when this star code is triggered. + /// Can be null. + SemaphoreHandle_t triggered_sem; }; +/// @brief Initializes the star code system. +void init_star_code_system(); + /// @brief Adds a star code to be handled. /// @param code the star code to add /// @return true iff the star code was added @@ -57,4 +71,11 @@ void clear_star_codes(); /// @return true iff a star code was triggered bool trigger_star_code(const char* code); + +/// @brief Tempararilly stops the starcode system from handling new starcodes. +void pause_star_code_system(); + +/// @brief Resumes the starcode system to start handling new starcodes again. +void resume_star_code_system(); + #endif /* STAR_CODE_H */ \ No newline at end of file diff --git a/main/steps/step0.cpp b/main/steps/step0.cpp index b8b90b7..94f12fe 100644 --- a/main/steps/step0.cpp +++ b/main/steps/step0.cpp @@ -55,7 +55,7 @@ static const StarCodeEntry star_codes[] = { .callback = nullptr, }, { - .code = "*9861", + .code = "59862", .display_text = "Set Up Wires", .delay_ticks = pdMS_TO_TICKS(2000), .callback = setup_wires, diff --git a/main/steps/step5.cpp b/main/steps/step5.cpp index 9c05175..2ff2288 100644 --- a/main/steps/step5.cpp +++ b/main/steps/step5.cpp @@ -182,8 +182,8 @@ void step5(void) { StarCodeEntry star_code = { .code = "*2648", .display_text = "Starting...", - .should_exit = true, - .callback = nullptr, + .delay_ticks = pdMS_TO_TICKS(2000), + .callback = nullptr, // TODO }; add_star_code(star_code);