From 68b8f980df03293abbfcddb2d5437d99cca92b4a Mon Sep 17 00:00:00 2001 From: Mitchell M Date: Sun, 11 Aug 2024 16:46:58 -0500 Subject: [PATCH] fix up step 4 --- main/drivers/leds.cpp | 6 +- main/drivers/leds.h | 2 +- main/drivers/wires.cpp | 2 + main/drivers/wires.h | 1 + main/helper.h | 3 + main/main.cpp | 2 +- main/steps/step2.cpp | 4 +- main/steps/step4.cpp | 360 +++++++++++++++++++++++++++++++++++++---- main/steps/step4.h | 3 + 9 files changed, 342 insertions(+), 41 deletions(-) diff --git a/main/drivers/leds.cpp b/main/drivers/leds.cpp index 6518a07..4b19535 100644 --- a/main/drivers/leds.cpp +++ b/main/drivers/leds.cpp @@ -5,7 +5,7 @@ led_strip_handle_t leds; void init_leds(void) { led_strip_config_t strip_config = { .strip_gpio_num = NEOPIXEL_PIN, - .max_leds = PIXEL_COUNT, + .max_leds = LED_COUNT, .led_pixel_format = LED_PIXEL_FORMAT_GRB, .led_model = LED_MODEL_WS2812 }; @@ -20,8 +20,8 @@ void init_leds(void) { } void example_leds(void) { - for (int i = 0; i < PIXEL_COUNT; i++) { - ESP_ERROR_CHECK(led_strip_set_pixel(leds, i, i, PIXEL_COUNT-i, 0)); + for (int i = 0; i < LED_COUNT; i++) { + ESP_ERROR_CHECK(led_strip_set_pixel(leds, i, i, LED_COUNT-i, 0)); } ESP_ERROR_CHECK(led_strip_refresh(leds)); } \ No newline at end of file diff --git a/main/drivers/leds.h b/main/drivers/leds.h index 82f2443..1dc0366 100644 --- a/main/drivers/leds.h +++ b/main/drivers/leds.h @@ -3,7 +3,7 @@ #include "led_strip.h" -#define PIXEL_COUNT 21 +#define LED_COUNT 21 #define NEOPIXEL_PIN GPIO_NUM_7 // 10MHz resolution, 1 tick = 0.1us (led strip needs a high resolution) #define LED_STRIP_RMT_RES_HZ (10 * 1000 * 1000) diff --git a/main/drivers/wires.cpp b/main/drivers/wires.cpp index 6d37e00..43fe524 100644 --- a/main/drivers/wires.cpp +++ b/main/drivers/wires.cpp @@ -77,6 +77,8 @@ void clear_wires_pressed_released_cut(void) { void strike(char* reason) { ESP_LOGW("strike!", "%s", reason); + lcd_set_cursor(&lcd, 0, 3); + lcd_print(&lcd, reason); uint8_t reg = 6; ESP_ERROR_CHECK_WITHOUT_ABORT(i2c_master_write_to_device(WIRES_I2C_NUM, WIRES_I2C_ADDR, ®, 1, (100 / portTICK_PERIOD_MS))); } diff --git a/main/drivers/wires.h b/main/drivers/wires.h index c12d3d2..065bc69 100644 --- a/main/drivers/wires.h +++ b/main/drivers/wires.h @@ -5,6 +5,7 @@ #include #include #include +#include "drivers/char_lcd.h" #define WIRES_PIN_DELTA GPIO_NUM_2 #define WIRES_I2C_NUM I2C_NUM_1 diff --git a/main/helper.h b/main/helper.h index 916e560..aa28ba3 100644 --- a/main/helper.h +++ b/main/helper.h @@ -16,6 +16,9 @@ struct StarCodeHandler { void (*callback)(void); }; +// TODO: add something for RNG. +// TODO: add something for colors, to make everything consistant. + /// Clears most persistant bomb state void clean_bomb(void); void poster_child_task(void* arg); diff --git a/main/main.cpp b/main/main.cpp index cdbe28e..3eb56c2 100755 --- a/main/main.cpp +++ b/main/main.cpp @@ -42,7 +42,7 @@ extern "C" void app_main(void) { clean_bomb(); step0(); - set_game_time(30*60*1000 + 1000); + set_game_time(60*60*1000 + 1000); start_game_timer(); clean_bomb(); step1(); diff --git a/main/steps/step2.cpp b/main/steps/step2.cpp index 4467802..3e7661f 100644 --- a/main/steps/step2.cpp +++ b/main/steps/step2.cpp @@ -170,7 +170,7 @@ static void init_screen(void) { xSemaphoreGive(xGuiSemaphore); - // xTaskCreate(music_task, "music", 4096, NULL, 5, &music_handle); + xTaskCreate(music_task, "music", 4096, NULL, 5, &music_handle); } static void deinit_screen(void) { @@ -179,7 +179,7 @@ static void deinit_screen(void) { lv_obj_clean(lv_scr_act()); xSemaphoreGive(xGuiSemaphore); - // vTaskDelete(music_handle); + vTaskDelete(music_handle); } bool play_game(int time, int required_score) { diff --git a/main/steps/step4.cpp b/main/steps/step4.cpp index 32f1766..cbc1879 100644 --- a/main/steps/step4.cpp +++ b/main/steps/step4.cpp @@ -1,53 +1,97 @@ #include "step4.h" +#define ONE_SECOND_TIME 60'000 +#define THREE_SECOND_TIME 60'000 +#define SIX_SECOND_TIME 60'000 + static const char *TAG = "step4"; static int tone = 0; static int times = 0; +static const char* TONE_FILES[] = { + MOUNT_POINT "/low-1.pcm", + MOUNT_POINT "/low-3.pcm", + MOUNT_POINT "/low-6.pcm", + MOUNT_POINT "/high-1.pcm", + MOUNT_POINT "/high-3.pcm", + MOUNT_POINT "/high-6.pcm", +}; + +static const char* LCD_STRINGS[] = { + "something", + "nothing", + "", + "a word", + "not something", + "what?", + "LCD", + "display", +}; + +static int indicator_led_idxs[LED_COUNT] = {0}; + +static bool contains_coconut = false; +static char* COCONUT = "coconut"; +static char lcd_random_char_set[] = "aeiou tnsrhldm"; +static char random_lcd_text[21] = {0}; + static std::random_device rd; static std::mt19937 gen(rd()); static std::uniform_int_distribution<> tone_dist(0, 5); -static std::uniform_int_distribution<> color_dist(0, 5); +static std::uniform_int_distribution<> color_dist(0, 6); +static std::uniform_int_distribution<> lcd_string_dist(0, 7); +static std::uniform_int_distribution<> lcd_number_dist(0, 15); +static std::uniform_int_distribution<> lcd_rand_char_dist(0, sizeof(lcd_random_char_set)-2); +static std::uniform_int_distribution<> has_coconut_dist(0, 2); +static std::uniform_int_distribution<> coconut_position_dist(0, 13); -static uint8_t NEOPIXEL_COLORS[6][3] = { +static uint8_t NEOPIXEL_COLORS[7][3] = { {20, 0, 0}, // red {20, 10, 0}, // orange {20, 20, 0}, // yellow {0, 20, 0}, // green {0, 0, 20}, // blue {20, 0, 20}, // purple + {0, 0, 0}, // off }; -static void play_tone(); static bool one_second(); static bool three_second(); static bool six_second(); void step4(void) { // start counting down module timer immediatly - set_module_time(10*1000); + set_module_time(20'000); start_module_timer(); while (get_module_time() > 0) vTaskDelay(pdMS_TO_TICKS(100)); while (times < 4) { tone = tone_dist(gen); - play_tone(); + // tone = 2; + play_raw(TONE_FILES[tone]); + switch (tone % 3) { case 0: if (one_second()) { times++; + clean_bomb(); + play_raw(MOUNT_POINT "/correct.pcm"); } break; case 1: if (three_second()) { times++; + clean_bomb(); + play_raw(MOUNT_POINT "/correct.pcm"); } break; case 2: if (six_second()) { times++; + clean_bomb(); + play_raw(MOUNT_POINT "/correct.pcm"); } break; } @@ -55,46 +99,294 @@ void step4(void) { } } +static void generate_random_lcd_text(void) { + for (int i = 0; i < 20; i++) { + int char_idx = lcd_rand_char_dist(gen); + random_lcd_text[i] = lcd_random_char_set[char_idx]; + } + contains_coconut = (has_coconut_dist(gen) == 0); + if (contains_coconut) { + int idx = coconut_position_dist(gen); + for (int i = 0; i < 7; i++) { + random_lcd_text[idx+i] = COCONUT[i]; + // ESP_LOGI(TAG, "Writing idx %d to %c. Is %c", idx+i, COCONUT[i], random_lcd_text[idx+i]); + } + // ESP_LOGI(TAG, "Now: %s", random_lcd_text); + } +} + +/// Sets the leds to random values. +/// +/// This does not flush the leds. +static void rng_leds() { + for (int i = 0; i < LED_COUNT; i++) { + indicator_led_idxs[i] = color_dist(gen); + } +} + +static void write_leds() { + // update all the leds + for (int i = 0; i < LED_COUNT; i++) { + auto colors = NEOPIXEL_COLORS[indicator_led_idxs[i]]; + led_strip_set_pixel(leds, i, colors[0], colors[1], colors[2]); + } + led_strip_refresh(leds); +} + +static uint8_t four_bit_flag(bool b0, bool b1, bool b2, bool b3) { + return + (b0 << 0) | + (b1 << 1) | + (b2 << 2) | + (b3 << 3) + ; +} + +static void print_bin(char* out_str, uint8_t n) { + out_str[0] = ((n & 0b1000) ? '1' : '0'); + out_str[1] = ((n & 0b0100) ? '1' : '0'); + out_str[2] = ((n & 0b0010) ? '1' : '0'); + out_str[3] = ((n & 0b0001) ? '1' : '0'); + out_str[4] = ' '; + out_str[5] = 'i'; + out_str[6] = 'n'; + out_str[7] = ' '; + out_str[8] = 'o'; + out_str[9] = 'r'; + out_str[10] = 'd'; + out_str[11] = 'e'; + out_str[12] = 'r'; + out_str[13] = ':'; + out_str[14] = ' '; + out_str[15] = ((n & 0b0001) ? '1' : '0'); + out_str[16] = ((n & 0b0010) ? '1' : '0'); + out_str[17] = ((n & 0b0100) ? '1' : '0'); + out_str[18] = ((n & 0b1000) ? '1' : '0'); +} + +static void debug_correct_values(uint8_t correct_buttons, uint8_t button_mask, uint8_t correct_switches) { + char buf[20] = {0}; + print_bin(buf, correct_switches); + ESP_LOGI(TAG, "Expected Switch State: 0b%s", buf); + print_bin(buf, correct_buttons); + ESP_LOGI(TAG, "Expected Button State: 0b%s", buf); + print_bin(buf, button_mask); + ESP_LOGI(TAG, "Button Mask: 0b%s", buf); +} + +static void debug_actual_values(uint8_t buttons, uint8_t switch_) { + char buf[20] = {0}; + print_bin(buf, switch_); + ESP_LOGI(TAG, "Actual Switch State: 0b%s", buf); + print_bin(buf, buttons); + ESP_LOGI(TAG, "Actual Button State: 0b%s", buf); + ESP_LOGI(TAG, ""); +} + static bool one_second() { - set_module_time(30*1000); + clean_bomb(); + set_module_time(ONE_SECOND_TIME); start_module_timer(); - int speaker_indicator_color = color_dist(gen); + rng_leds(); + int speaker_color = indicator_led_idxs[Led::speaker]; + int lcd_string_idx = lcd_string_dist(gen); + bool was_high = (tone / 3) == 1; + write_leds(); + lcd_clear(&lcd); + lcd_set_cursor(&lcd, 1, 1); + lcd_print(&lcd, LCD_STRINGS[lcd_string_idx]); - while (get_module_time() > 0) { - + int red_led_count = 0; + int blue_led_count = 0; + for (int i = 0; i < LED_COUNT; i++) { + if (indicator_led_idxs[i] == 0) { + red_led_count++; + } else if (indicator_led_idxs[i] == 4) { + blue_led_count++; + } } -return false; + uint8_t correct_switches = four_bit_flag( + speaker_color == 0 || speaker_color == 1 || speaker_color == 2, + lcd_string_idx == 0 || lcd_string_idx == 1, + was_high, + !was_high + ); + + uint8_t correct_button_mask = 0b1011; + uint8_t correct_buttons = four_bit_flag( + indicator_led_idxs[Led::char_lcd] != 6, // green + red_led_count > blue_led_count, // red + 0, // yellow UNCHECKED + indicator_led_idxs[Led::rfid] == 4 || indicator_led_idxs[Led::rfid] == 6 // blue + ); + + debug_correct_values(correct_buttons, correct_button_mask, correct_switches); + + // wait for timer + while (get_module_time() > 0) { + vTaskDelay(pdMS_TO_TICKS(100)); + } + + debug_actual_values(get_button_state(), get_switch_state()); + + if (get_switch_state() != correct_switches) { + clean_bomb(); + strike("Incorrect Switches"); + return false; + } + if ((get_button_state() & correct_button_mask) != correct_buttons) { + clean_bomb(); + strike("Incorrect Buttons"); + return false; + } + + return true; } static bool three_second() { - return false; + clean_bomb(); + set_module_time(THREE_SECOND_TIME); + start_module_timer(); + + int lcd_number = lcd_number_dist(gen); + char lcd_number_string[9] = {0}; + sprintf(lcd_number_string, "%d", lcd_number); + lcd_set_cursor(&lcd, 1, 1); + lcd_print(&lcd, lcd_number_string); + + bool was_high = (tone / 3) == 1; + + rng_leds(); + write_leds(); + int red_led_count = 0; + int blue_led_count = 0; + for (int i = 0; i < LED_COUNT; i++) { + if (indicator_led_idxs[i] == 0) { + red_led_count++; + } else if (indicator_led_idxs[i] == 4) { + blue_led_count++; + } + } + + // reverse the ordering of the bits + uint8_t correct_switches = four_bit_flag( + (lcd_number >> 3) & 1, + (lcd_number >> 2) & 1, + (lcd_number >> 1) & 1, + (lcd_number >> 0) & 1 + ); + + uint8_t correct_button_mask = 0b1110; + uint8_t correct_buttons = four_bit_flag( + 0, // green UNCHECKED + was_high, // red + (lcd_number % 2) == 0, // yellow + blue_led_count > red_led_count // blue + ); + + debug_correct_values(correct_buttons, correct_button_mask, correct_switches); + + // wait for timer + while (get_module_time() > 0) { + vTaskDelay(pdMS_TO_TICKS(100)); + } + + debug_actual_values(get_button_state(), get_switch_state()); + + if (get_switch_state() != correct_switches) { + clean_bomb(); + strike("Incorrect Switches"); + return false; + } + if ((get_button_state() & correct_button_mask) != correct_buttons) { + clean_bomb(); + strike("Incorrect Buttons"); + return false; + } + + return true; } static bool six_second() { - return false; + clean_bomb(); + set_module_time(SIX_SECOND_TIME); + start_module_timer(); + + generate_random_lcd_text(); + vTaskDelay(pdMS_TO_TICKS(10)); + lcd_set_cursor(&lcd, 0, 0); + lcd_print(&lcd, random_lcd_text); + + int vowels = 0; + for (int i = 0; i < 20; i++) { + char c = random_lcd_text[i]; + if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') { + vowels++; + } + } + + bool was_high = (tone / 3) == 1; + + bool second_switch_correct_state = (indicator_led_idxs[Led::switch2] == 0) || (indicator_led_idxs[Led::switch2] == 6); + second_switch_correct_state = second_switch_correct_state || was_high; + + rng_leds(); + write_leds(); + + int green_led_count = 0; + int blue_led_count = 0; + for (int i = 0; i < LED_COUNT; i++) { + if (indicator_led_idxs[i] == 4) { + blue_led_count++; + } else if (indicator_led_idxs[i] == 3) { + green_led_count++; + } + } + + int purple_led_on_bottom_count = 0; + for (int i = Led::rfid; i < LED_COUNT; i++) { + if (indicator_led_idxs[i] == 5) { + purple_led_on_bottom_count++; + } + } + + uint8_t correct_switches = four_bit_flag( + vowels > 7, + second_switch_correct_state, + true, + !(purple_led_on_bottom_count > 1) + ); + + uint8_t correct_button_mask = 0b1101; + uint8_t correct_buttons = four_bit_flag( + (!was_high) || (green_led_count >= 2) || indicator_led_idxs[Led::keypad] == 4, // green + 0, // red UNCHECKED + blue_led_count >= 3, // yellow + contains_coconut // blue + ); + + debug_correct_values(correct_buttons, correct_button_mask, correct_switches); + + // wait for timer + while (get_module_time() > 0) { + vTaskDelay(pdMS_TO_TICKS(100)); + } + + debug_actual_values(get_button_state(), get_switch_state()); + + if (get_switch_state() != correct_switches) { + clean_bomb(); + strike("Incorrect Switches"); + return false; + } + if ((get_button_state() & correct_button_mask) != correct_buttons) { + clean_bomb(); + strike("Incorrect Buttons"); + return false; + } + + return true; } -static void play_tone() { - switch (tone) { - case 0: - play_raw(MOUNT_POINT "/low-1.pcm"); - break; - case 1: - play_raw(MOUNT_POINT "/low-3.pcm"); - break; - case 2: - play_raw(MOUNT_POINT "/low-6.pcm"); - break; - case 3: - play_raw(MOUNT_POINT "/high-1.pcm"); - break; - case 4: - play_raw(MOUNT_POINT "/high-3.pcm"); - break; - case 5: - play_raw(MOUNT_POINT "/high-6.pcm"); - break; - } -} diff --git a/main/steps/step4.h b/main/steps/step4.h index 2177a70..358a540 100644 --- a/main/steps/step4.h +++ b/main/steps/step4.h @@ -5,7 +5,10 @@ #include "../drivers/bottom_half.h" #include "../drivers/wires.h" #include "../drivers/speaker.h" +#include "../drivers/leds.h" +#include "../drivers/char_lcd.h" #include "../drivers/game_timer.h" +#include "../helper.h" void step4(void);