#include "step1.h" static const char *STEP1_TAG = "step1"; static char* COLOR_NAMES[] = { "green", "red", "yellow", "purple" }; static char* NUM_NAMES[] = { "one", "two", "three", "four" }; static uint8_t NEOPIXEL_COLORS[4][3] = { {0, 20, 0}, {20, 0, 0}, {20, 20, 0}, {15, 0, 20}, }; static std::random_device my_rd; static std::mt19937 my_gen(my_rd()); static std::uniform_int_distribution<> zero_to_one(0, 1); static std::uniform_int_distribution<> zero_to_two(0, 2); static std::uniform_int_distribution<> zero_to_three(0, 3); static lv_obj_t *scr; static lv_obj_t *text = NULL; static lv_style_t style_screen; static lv_style_t green_text; static lv_style_t red_text; static lv_style_t yellow_text; static lv_style_t purple_text; static int switch_leds[] = {0, 0, 0, 0}; static lv_style_t* color_styles[] = { &green_text, &red_text, &yellow_text, &purple_text }; static void init_step(void) { scr = lv_disp_get_scr_act(NULL); // Set the background color of the display to black. lv_style_init(&style_screen); lv_style_set_bg_color(&style_screen, lv_color_black()); lv_style_set_text_font(&style_screen, &lv_font_montserrat_32); lv_obj_add_style(lv_scr_act(), &style_screen, LV_STATE_DEFAULT); // rgb565 lv_color_t green; green.full = 0x27e0; lv_color_t red; red.full = 0xf800; lv_color_t yellow; yellow.full = 0xffa9; lv_color_t purple; purple.full = 0x881f; lv_style_init(&green_text); lv_style_set_text_color(&green_text, green); lv_style_init(&red_text); lv_style_set_text_color(&red_text, red); lv_style_init(&yellow_text); lv_style_set_text_color(&yellow_text, yellow); lv_style_init(&purple_text); lv_style_set_text_color(&purple_text, purple); text = lv_label_create(scr); } static void clean_up_step(void) { lv_obj_clean(text); lv_obj_clean(scr); } static void generate_switch_leds(void) { int colors[4] = {0, 1, 2, 3}; int idx = zero_to_three(my_gen); switch_leds[0] = colors[idx]; colors[idx] = colors[3]; idx = zero_to_two(my_gen); switch_leds[1] = colors[idx]; colors[idx] = colors[2]; idx = zero_to_one(my_gen); switch_leds[2] = colors[idx]; colors[idx] = colors[1]; switch_leds[3] = colors[0]; ESP_LOGI(STEP1_TAG, "%d, %d, %d, %d", switch_leds[0], switch_leds[1], switch_leds[2], switch_leds[3]); for (int i = 0; i < 4; i++) { uint8_t* rgb = NEOPIXEL_COLORS[switch_leds[i]]; led_strip_set_pixel(leds, Led::switch1 - i, rgb[0], rgb[1], rgb[2]); } led_strip_refresh(leds); } static int generate_part_a(void) { int text_color = zero_to_three(my_gen); int text_idx = zero_to_three(my_gen); char* text_string = COLOR_NAMES[text_idx]; lv_label_set_text(text, text_string); lv_obj_center(text); lv_obj_add_style(text, color_styles[text_color], LV_STATE_DEFAULT); generate_switch_leds(); // the correct answer is the text color return text_color; } static int generate_part_b(void) { int is_color = zero_to_one(my_gen) == 0; if (is_color) { return generate_part_a(); } int text_color = zero_to_three(my_gen); int text_number = zero_to_three(my_gen); char* text_string = NUM_NAMES[text_number]; lv_label_set_text(text, text_string); lv_obj_center(text); lv_obj_add_style(text, color_styles[text_color], LV_STATE_DEFAULT); generate_switch_leds(); // the correct answer is the number return text_number; } static int generate_part_c(void) { int type = zero_to_two(my_gen); if (type != 0) { return generate_part_b(); } int text_color = zero_to_three(my_gen); char* text_string = "switch"; lv_label_set_text(text, text_string); lv_obj_center(text); lv_obj_add_style(text, color_styles[text_color], LV_STATE_DEFAULT); generate_switch_leds(); // the correct answer is the switch return text_color + 4; } static void part_a(void) { stop_module_timer(); set_module_time(30); lcd_clear(&lcd); lcd_set_cursor(&lcd, 1, 1); lcd_print(&lcd, "COLOR"); ESP_ERROR_CHECK(led_strip_set_pixel(leds, Led::char_lcd, 20, 0, 20)); ESP_ERROR_CHECK(led_strip_refresh(leds)); int times = 0; int correct = generate_part_a(); ButtonKey button; SwitchKey switch_; while (times < 15) { while (get_pressed_button(&button)) { start_module_timer(); if ((int)(button) == correct) { times++; if (times >= 15) break; correct = generate_part_a(); } else { strike("Incorrect color action"); } } while (get_flipped_switch(&switch_)) { strike("Incorrect color action"); } vTaskDelay(pdMS_TO_TICKS(10)); } lv_label_set_text(text, ""); vTaskDelay(pdMS_TO_TICKS(80)); play_raw(MOUNT_POINT "/correct.pcm"); } static void part_b(void) { stop_module_timer(); set_module_time(25); lcd_clear(&lcd); lcd_set_cursor(&lcd, 1, 1); lcd_print(&lcd, "NUMBER"); ESP_ERROR_CHECK(led_strip_set_pixel(leds, Led::char_lcd, 0, 0, 30)); ESP_ERROR_CHECK(led_strip_refresh(leds)); int times = 0; int correct = generate_part_b(); ButtonKey button; SwitchKey switch_; while (times < 15) { while (get_pressed_button(&button)) { start_module_timer(); if ((int)(button) == correct) { times++; if (times >= 15) break; correct = generate_part_b(); } else { strike("Incorrect color action"); } } while (get_flipped_switch(&switch_)) { strike("Incorrect color action"); } vTaskDelay(pdMS_TO_TICKS(10)); } lv_label_set_text(text, ""); vTaskDelay(pdMS_TO_TICKS(80)); play_raw(MOUNT_POINT "/correct.pcm"); } static void part_c(void) { stop_module_timer(); set_module_time(20); lcd_clear(&lcd); lcd_set_cursor(&lcd, 1, 1); lcd_print(&lcd, "SWITCH"); ESP_ERROR_CHECK(led_strip_set_pixel(leds, Led::char_lcd, 20, 20, 0)); ESP_ERROR_CHECK(led_strip_refresh(leds)); int times = 0; int correct = generate_part_c(); ButtonKey button; SwitchKey switch_; while (times < 15) { while (get_pressed_button(&button)) { start_module_timer(); if ((int)(button) == correct) { times++; if (times >= 15) break; correct = generate_part_c(); } else { strike("Incorrect color action"); } } while (get_flipped_switch(&switch_)) { start_module_timer(); if (switch_leds[(int)(switch_)] + 4 == correct) { times++; if (times >= 10) break; correct = generate_part_c(); } else { strike("Incorrect color action"); } } vTaskDelay(pdMS_TO_TICKS(10)); } lv_label_set_text(text, ""); vTaskDelay(pdMS_TO_TICKS(80)); play_raw(MOUNT_POINT "/correct.pcm"); } void step1(void) { SwitchKey switch_; while (get_flipped_switch(&switch_)); init_step(); part_a(); part_b(); part_c(); clean_up_step(); }