From 5bb6b050021e7e17fb6885d3c73721ab97661215 Mon Sep 17 00:00:00 2001 From: Mitchell Marino Date: Tue, 25 Mar 2025 19:27:20 -0500 Subject: [PATCH] updates to bottom half code and "debug switches" helper --- main/drivers/CMakeLists.txt | 1 + main/drivers/all.cpp | 5 +- main/drivers/bottom_half.cpp | 261 +++++++++++++++++++---------------- main/drivers/bottom_half.h | 10 +- main/drivers/char_lcd.cpp | 2 +- main/steps/step0.cpp | 59 ++++++-- main/steps/step3.cpp | 12 +- main/steps/wires_puzzle.cpp | 72 +++++----- main/steps/wires_puzzle.h | 12 +- 9 files changed, 243 insertions(+), 191 deletions(-) diff --git a/main/drivers/CMakeLists.txt b/main/drivers/CMakeLists.txt index b3eb6a9..fb5c43a 100644 --- a/main/drivers/CMakeLists.txt +++ b/main/drivers/CMakeLists.txt @@ -1,4 +1,5 @@ set(SOURCES + "all.cpp" "TM1640/TM16xx.cpp" "TM1640/TM1640.cpp" "SparkFunBQ27441/SparkFunBQ27441.cpp" diff --git a/main/drivers/all.cpp b/main/drivers/all.cpp index df11ed4..9c7d5fa 100644 --- a/main/drivers/all.cpp +++ b/main/drivers/all.cpp @@ -5,7 +5,7 @@ static void init_i2c(); void init_drivers() { init_i2c(); // init char_lcd so we can use it to report other initialization errors. - init_char_lcd(); + init_lcd(); // init the bottom half so that we can get user input. init_bottom_half(); init_sd(); @@ -31,7 +31,8 @@ static void init_i2c() { // .scl_pullup_en = GPIO_PULLUP_ENABLE, .master = { .clk_speed = 100*1000, - } + }, + .clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL }; ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &conf)); diff --git a/main/drivers/bottom_half.cpp b/main/drivers/bottom_half.cpp index 66b8fc3..eee9ec5 100644 --- a/main/drivers/bottom_half.cpp +++ b/main/drivers/bottom_half.cpp @@ -3,27 +3,145 @@ static const char *TAG = "bottom_half"; static uint16_t keypad_state; -static uint16_t button_state; +static uint8_t button_state; +static uint8_t switch_state; static uint8_t touch_state; static uint16_t keypad_pressed; -static uint16_t button_pressed; +static uint8_t button_pressed; +static uint8_t switch_flipped_up; static uint8_t touch_pressed; static uint16_t keypad_released; -static uint16_t button_released; +static uint8_t button_released; +static uint8_t switch_flipped_down; static uint8_t touch_released; /// read buffer static uint8_t buf[8]; +static void poll_bottom_task(void *arg); +static void receive_keypad(); +static void receive_button_switch(); +static void receive_touch(); + +// TODO: add intrupt on bottom half delta pin +// static void IRAM_ATTR gpio_isr_handler(void* arg) +// { +// // TODO: do somthing +// ESP_LOGI("BOTTOM_HALF", "Hit"); +// } + +void init_bottom_half() { + ESP_ERROR_CHECK(gpio_set_direction(BOTTOM_PIN_INTERUPT, GPIO_MODE_INPUT)); + ESP_ERROR_CHECK(gpio_set_pull_mode(BOTTOM_PIN_INTERUPT, GPIO_PULLUP_ONLY)); + + // TODO: do interupt stuff. + // ESP_ERROR_CHECK(gpio_intr_enable(BOTTOM_PIN_INTERUPT)); + // ESP_ERROR_CHECK(gpio_install_isr_service(ESP_INTR_FLAG)) + //install gpio isr service + // gpio_install_isr_service(0); + //hook isr handler for specific gpio pin + // gpio_isr_handler_add(BOTTOM_INTERUPT_PIN, gpio_isr_handler, NULL); + + receive_keypad(); + receive_button_switch(); + receive_touch(); + + xTaskCreate(poll_bottom_task, "poll_bottom", 4096, NULL, 10, NULL); +} + +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))); + 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))); + uint16_t new_keypad_state = buf[0] | (buf[1] << 8); + + uint16_t just_pressed = new_keypad_state & ~keypad_state; + keypad_pressed |= just_pressed; + + uint16_t just_released = ~new_keypad_state & keypad_state; + 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))); + uint8_t new_button_state = buf[1]; + uint8_t new_switch_state = buf[0]; + + // button + uint8_t just_pressed = new_button_state & ~button_state; + button_pressed |= just_pressed; + + uint8_t just_released = ~new_button_state & button_state; + button_released |= just_released; + + button_state = new_button_state; + + // switch + uint8_t just_flipped_down = new_switch_state & ~switch_state; + switch_flipped_down |= just_flipped_down; + + uint8_t just_flipped_up = ~new_switch_state & switch_state; + switch_flipped_up |= just_flipped_up; + + switch_state = new_switch_state; +} + +static void receive_touch(void) { + uint8_t reg = 4; + 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))); + bool new_touch_state = buf[0] != 0; + + bool just_pressed = new_touch_state & !touch_state; + touch_pressed |= just_pressed; + + bool just_released = (!new_touch_state) & touch_state; + touch_released |= just_released; + + touch_state = new_touch_state; +} + +static void poll_bottom_task(void *arg) { + // TODO: if using an interupt, switch this to use a queue + while (1) { + bool new_data = gpio_get_level(BOTTOM_PIN_INTERUPT) == 0; + if (new_data) { + uint8_t delta = receive_delta(); + // ESP_LOGI(_TAG, "delta: %d", delta); + if (delta == 0) ESP_LOGW(TAG, "delta pin was low, but delta register returned 0"); + + if (delta & (1 << DELTA_BIT_KP)) receive_keypad(); + if (delta & (1 << DELTA_BIT_BUTTON_SWITCH)) receive_button_switch(); + if (delta & (1 << DELTA_BIT_TOUCH)) receive_touch(); + } + vTaskDelay(pdMS_TO_TICKS(10)); + } + + vTaskDelete(NULL); +} + void clear_all_pressed_released(void) { keypad_pressed = 0; button_pressed = 0; + switch_flipped_up = 0; touch_pressed = 0; keypad_released = 0; button_released = 0; + switch_flipped_down = 0; touch_released = 0; } @@ -88,9 +206,12 @@ char char_of_keypad_key(KeypadKey kp) { } } -static bool _take_button(ButtonKey* button, uint16_t* button_bitfield) { +static bool _take_button(ButtonKey* button, uint8_t* button_bitfield) { + if (((*button_bitfield) & 0xF) == 0) return false; + + // scan the 4 button bits for one that is set for (int i = 0; i < 4; i++) { - int bit_selector = (1 << (i+8)); + int bit_selector = (1 << i); if ((*button_bitfield) & bit_selector) { if (button != nullptr) { *button = (ButtonKey) i; @@ -102,15 +223,18 @@ static bool _take_button(ButtonKey* button, uint16_t* button_bitfield) { } return false; } -static bool _take_switch(SwitchKey* switch_, uint16_t* button_bitfield) { +static bool _take_switch(SwitchKey* switch_, uint8_t* switch_bitfield) { + if (((*switch_bitfield) & 0xF) == 0) return false; + + // scan the 4 switch bits for one that is set for (int i = 0; i < 4; i++) { int bit_selector = (1 << i); - if ((*button_bitfield) & bit_selector) { + if ((*switch_bitfield) & bit_selector) { if (switch_ != nullptr) { *switch_ = (SwitchKey) i; } // clear bit - *button_bitfield &= ~bit_selector; + *switch_bitfield &= ~bit_selector; return true; } } @@ -123,21 +247,23 @@ bool get_pressed_button(ButtonKey* button) { bool get_released_button(ButtonKey* button) { return _take_button(button, &button_released); } - uint8_t get_button_state() { - return (uint8_t)((button_state >> 8) & 0xF); + return button_state; } bool get_flipped_up_switch(SwitchKey* switch_) { - return _take_switch(switch_, &button_released); + return _take_switch(switch_, &switch_flipped_up); } bool get_flipped_down_switch(SwitchKey* switch_) { - return _take_switch(switch_, &button_released); + return _take_switch(switch_, &switch_flipped_down); } bool get_flipped_switch(SwitchKey* switch_) { for (int i = 0; i < 4; i++) { - int bit_selector = (1 << (i+4)); - if (button_pressed & bit_selector || button_released & bit_selector) { + int bit_selector = (1 << i); + if ( + ((switch_flipped_up & bit_selector) != 0) || + ((switch_flipped_down & bit_selector) != 0) + ) { if (switch_ != nullptr) { *switch_ = (SwitchKey) i; } @@ -151,7 +277,7 @@ bool get_flipped_switch(SwitchKey* switch_) { } uint8_t get_switch_state() { - return (uint8_t)(~button_state & 0xF); + return (uint8_t)(~switch_state & 0xF); } bool get_touch_state(void) { @@ -167,108 +293,3 @@ bool get_touch_released(void) { touch_released = false; return return_; } - -static void poll_bottom_task(void *arg); -static void receive_keypad(void); -static void receive_button(void); -static void receive_touch(void); - -// TODO: add intrupt on bottom half delta pin -// static void IRAM_ATTR gpio_isr_handler(void* arg) -// { -// // TODO: do somthing -// ESP_LOGI("BOTTOM_HALF", "Hit"); -// } - -void init_bottom_half() { - gpio_config_t delta_pin_conf = {}; - // delta_pin_conf.intr_type = GPIO_INTR_LOW_LEVEL; - delta_pin_conf.mode = GPIO_MODE_INPUT; - // GPIO 0 - delta_pin_conf.pin_bit_mask = (1ULL<= 0; green_idx--) { int pos = green_pos[green_idx]; if ( - wires[pos-1] == WireColor::yellow || - wires[pos-1] == WireColor::white || - wires[pos+1] == WireColor::yellow || - wires[pos+1] == WireColor::white + wires[pos-1] == WireColor::wire_yellow || + wires[pos-1] == WireColor::wire_white || + wires[pos+1] == WireColor::wire_yellow || + wires[pos+1] == WireColor::wire_white ) { out_cut[pos] = true; if (debug) { @@ -242,7 +242,7 @@ void solve_wires(WireColor* wires, bool* out_cut) { } // 6. cut all white wires if there is a red wire in the 5th position - if (wires[4] == WireColor::red) { + if (wires[4] == WireColor::wire_red) { for (int white_idx = 0; white_idx < white_pos_len; white_idx++) { out_cut[white_pos[white_idx]] = true; if (debug) { @@ -307,8 +307,8 @@ void solve_wires(WireColor* wires, bool* out_cut) { // 12. cut any wire adjacent to both a yellow and blue wire for (int i = 0; i < NUM_WIRES-2; i++) { if ( - (wires[i] == WireColor::yellow && wires[i+2] == WireColor::blue) || - (wires[i] == WireColor::blue && wires[i+2] == WireColor::yellow) + (wires[i] == WireColor::wire_yellow && wires[i+2] == WireColor::wire_blue) || + (wires[i] == WireColor::wire_blue && wires[i+2] == WireColor::wire_yellow) ) { out_cut[i+1] = true; if (debug) { @@ -323,10 +323,10 @@ void solve_wires(WireColor* wires, bool* out_cut) { for (int i = 0; i < blue_pos_len; i++) { int pos = blue_pos[i]; if ( - wires[pos-1] == WireColor::red || - wires[pos-1] == WireColor::green || - wires[pos+1] == WireColor::red || - wires[pos+1] == WireColor::green + wires[pos-1] == WireColor::wire_red || + wires[pos-1] == WireColor::wire_green || + wires[pos+1] == WireColor::wire_red || + wires[pos+1] == WireColor::wire_green ) { out_cut[pos] = false; if (debug) { @@ -346,13 +346,13 @@ void solve_wires(WireColor* wires, bool* out_cut) { } // 3. never cut red or black wires in the 4th or 7th positions - if (wires[3] == WireColor::red || wires[3] == WireColor::black) { + if (wires[3] == WireColor::wire_red || wires[3] == WireColor::wire_black) { out_cut[3] = false; if (debug) { printf("N3. Never cutting %d\n", 3); } } - if (wires[6] == WireColor::red || wires[6] == WireColor::black) { + if (wires[6] == WireColor::wire_red || wires[6] == WireColor::wire_black) { out_cut[6] = false; if (debug) { printf("N3. Never cutting %d\n", 6); @@ -390,7 +390,7 @@ void solve_wires(WireColor* wires, bool* out_cut) { } // 6. never cut a blue or green wire in the 8th postion - if (wires[7] == WireColor::blue || wires[7] == WireColor::green) { + if (wires[7] == WireColor::wire_blue || wires[7] == WireColor::wire_green) { out_cut[7] = false; if (debug) { printf("N6. Never cutting %d\n", 7); diff --git a/main/steps/wires_puzzle.h b/main/steps/wires_puzzle.h index 836ab20..ddf2b95 100644 --- a/main/steps/wires_puzzle.h +++ b/main/steps/wires_puzzle.h @@ -10,12 +10,12 @@ #define NUM_WIRES 8 typedef enum { - red = 0, - yellow = 1, - green = 2, - blue = 3, - black = 4, - white = 5, + wire_red = 0, + wire_yellow = 1, + wire_green = 2, + wire_blue = 3, + wire_black = 4, + wire_white = 5, } WireColor; void solve_wires(WireColor* wires, bool* out_cut);