From 7b8e38844a5767c3fbba9659f78153be7f7d7f8b Mon Sep 17 00:00:00 2001 From: Mitchell M Date: Wed, 14 Aug 2024 18:29:51 -0500 Subject: [PATCH] speaker updates and tweaks --- main/drivers/game_timer.cpp | 28 ++++++++++++++----- main/drivers/game_timer.h | 3 +++ main/drivers/speaker.cpp | 54 +++++++++++++++++++++++++++++++++++++ main/drivers/speaker.h | 6 +++++ main/drivers/wires.cpp | 5 +++- main/drivers/wires.h | 2 ++ main/main.cpp | 34 +++++++++++++++++++++++ main/steps/step4.cpp | 24 ++++++++++++++--- main/steps/step5.cpp | 2 +- 9 files changed, 146 insertions(+), 12 deletions(-) diff --git a/main/drivers/game_timer.cpp b/main/drivers/game_timer.cpp index ac4f107..dc86955 100644 --- a/main/drivers/game_timer.cpp +++ b/main/drivers/game_timer.cpp @@ -1,11 +1,10 @@ -#ifndef GAME_TIMER_HPP -#define GAME_TIMER_HPP - #include "game_timer.h" static bool is_module_playing; static bool is_game_playing; +static bool game_time_count_up; + // in ms static uint32_t game_time_left; static uint32_t module_time_left; @@ -70,6 +69,18 @@ uint32_t get_module_time() { return module_time_left; } +/// Issues a time penalty to the game time +void time_penalty(uint32_t penalty) { + if (game_time_count_up) { + game_time_left += penalty; + } else { + game_time_left = sat_sub(game_time_left, penalty); + if (game_time_left == 0) { + game_time_count_up = true; + } + } +} + static void game_timer_task(void *arg) { TickType_t lastWakeTime = xTaskGetTickCount(); @@ -78,7 +89,14 @@ static void game_timer_task(void *arg) while (1) { vTaskDelayUntil( &lastWakeTime, pdMS_TO_TICKS(frequency)); if (is_game_playing) { - game_time_left = sat_sub(game_time_left, frequency); + if (game_time_count_up) { + game_time_left += frequency; + } else { + game_time_left = sat_sub(game_time_left, frequency); + if (game_time_left == 0) { + game_time_count_up = true; + } + } write_game_time(game_time_left); } if (is_module_playing) { @@ -96,5 +114,3 @@ static uint32_t sat_sub(uint32_t x, uint32_t y) res &= -(res <= x); return res; } - -#endif /* GAME_TIMER_HPP */ \ No newline at end of file diff --git a/main/drivers/game_timer.h b/main/drivers/game_timer.h index 5729772..c0913d7 100644 --- a/main/drivers/game_timer.h +++ b/main/drivers/game_timer.h @@ -22,6 +22,9 @@ void set_game_time(uint32_t new_time); /// Gets the current game time in ms uint32_t get_game_time(); +/// Gets the current game time in ms +void time_penalty(uint32_t penalty); + /// Sets the module time in ms void set_module_time(uint32_t new_time); /// Gets the current module time in ms diff --git a/main/drivers/speaker.cpp b/main/drivers/speaker.cpp index d1807d4..37dc90d 100644 --- a/main/drivers/speaker.cpp +++ b/main/drivers/speaker.cpp @@ -4,6 +4,60 @@ i2s_chan_handle_t tx_chan; static const char *TAG = "speaker_driver"; +esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle) { + FILE *fh = fopen(fp, "rb"); + if (fh == NULL) + { + ESP_LOGE(TAG, "Failed to open file"); + return ESP_ERR_INVALID_ARG; + } + + // create a writer buffer + uint8_t *read_buf = (uint8_t*) calloc(AUDIO_BUFFER, sizeof(uint8_t)); + uint16_t *write_buf = (uint16_t*) calloc(AUDIO_BUFFER, sizeof(uint16_t)); + size_t bytes_read = 0; + size_t bytes_written = 0; + + esp_err_t channel_enable_result = i2s_channel_enable(tx_chan); + ESP_ERROR_CHECK_WITHOUT_ABORT(channel_enable_result); + if (channel_enable_result != ESP_OK) { + return channel_enable_result; + } + + bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh); + for (int i = 0; i < bytes_read; i++) { + write_buf[i] = read_buf[i] << 4; + } + +// i2s_channel_enable(tx_handle); + + while (bytes_read > 0) { + // write the buffer to the i2s + // ESP_LOGI(TAG, "Writing: "); + // for (int i = 0; i < words_read; i++) { + // int16_t val = buf[i]; + // printf("%s0x%04X ", (val < 0 ? "-" : "+"), (val < 0 ? -val : val)); + // }> + i2s_channel_write(tx_chan, write_buf, bytes_read * sizeof(int16_t), &bytes_written, portMAX_DELAY); + bytes_read = fread(read_buf, sizeof(uint8_t), AUDIO_BUFFER, fh); + for (int i = 0; i < bytes_read; i++) { + write_buf[i] = read_buf[i] << 4; + } + uint8_t recv = 0; + if (xQueueReceive(stop_handle, &recv, 0)) { + break; + } + vTaskDelay(pdMS_TO_TICKS(10)); + } + + i2s_channel_disable(tx_chan); + free(read_buf); + free(write_buf); + fclose(fh); + + return ESP_OK; +} + esp_err_t play_raw(const char *fp) { FILE *fh = fopen(fp, "rb"); if (fh == NULL) diff --git a/main/drivers/speaker.h b/main/drivers/speaker.h index 0231b25..795bc41 100644 --- a/main/drivers/speaker.h +++ b/main/drivers/speaker.h @@ -4,6 +4,7 @@ #include #include #include "freertos/FreeRTOS.h" +#include "freertos/queue.h" #include "freertos/task.h" #include "driver/i2s_std.h" #include "driver/gpio.h" @@ -19,7 +20,12 @@ extern i2s_chan_handle_t tx_chan; +/// Plays a audio file stopping when something is received on `stop_handle` +/// +/// `stop_handle` should be of size `uint8_t`. +esp_err_t play_raw_stop_queue(const char *fp, QueueHandle_t stop_handle); esp_err_t play_raw(const char *fp); + void init_speaker(void); void play_example(); diff --git a/main/drivers/wires.cpp b/main/drivers/wires.cpp index bc775e2..9c9da69 100644 --- a/main/drivers/wires.cpp +++ b/main/drivers/wires.cpp @@ -1,5 +1,7 @@ #include "wires.h" +uint32_t total_strikes; + static const char *TAG = "wires"; static const uint32_t STRIKE_TIME_PENALTY = 30'000; @@ -81,7 +83,8 @@ void strike(char* reason) { ESP_LOGW("strike!", "%s", reason); lcd_set_cursor(&lcd, 0, 3); lcd_print(&lcd, reason); - set_game_time(get_game_time() - STRIKE_TIME_PENALTY); + time_penalty(STRIKE_TIME_PENALTY); + total_strikes += 1; 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 67531d5..03474f0 100644 --- a/main/drivers/wires.h +++ b/main/drivers/wires.h @@ -15,6 +15,8 @@ #define DELTA_BIT_WIRES 0 #define DELTA_BIT_BUTTON 1 +extern uint32_t total_strikes; + void init_wires(void); uint8_t get_wires(void); uint8_t get_cut_wires(void); diff --git a/main/main.cpp b/main/main.cpp index 67fb6b3..902a081 100755 --- a/main/main.cpp +++ b/main/main.cpp @@ -28,6 +28,38 @@ static const char *TAG = "main"; uint32_t initial_game_time = 60*60*1000; uint32_t skip_to_step = 0; +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'); +} + +static void debug_switches() { + uint8_t switch_state = 0; + uint8_t button_state = 0; + + char buff[5] = {0}; + + while (1) { + uint8_t new_button_state = get_button_state(); + if (new_button_state != button_state) { + button_state = new_button_state; + print_bin(buff, button_state); + ESP_LOGI("main", "b: 0b%s", buff); + } + + uint8_t new_switch_state = get_switch_state(); + if (new_switch_state != switch_state) { + switch_state = new_switch_state; + print_bin(buff, switch_state); + ESP_LOGI("main", "s: 0b%s", buff); + } + + vTaskDelay(pdMS_TO_TICKS(10)); + } +} + extern "C" void app_main(void) { printf("app_main\n"); @@ -42,6 +74,8 @@ extern "C" void app_main(void) { init_bottom_half(); init_char_lcd(); + // debug_switches(); + clean_bomb(); step0(); set_game_time(initial_game_time + 1000); diff --git a/main/steps/step4.cpp b/main/steps/step4.cpp index a6f2340..37a5cb7 100644 --- a/main/steps/step4.cpp +++ b/main/steps/step4.cpp @@ -24,6 +24,9 @@ static const void* BACKGROUND_SRC = (void*)"A:/sdcard/bg.bin"; // LV_IMG_DECLARE(background); // static const void* BACKGROUND_SRC = (void*)&background; +static QueueHandle_t stop_music; +static bool playing_music = true; + static const char* PIECE_IMG_SRC[] = { NULL, "A:/sdcard/lb.bin", @@ -127,9 +130,17 @@ static int bdca(int i) { // [0,1,2,3] -> [ 0,+2,+1,-1] } static void music_task(void* arg) { - while (1) { - play_raw(MOUNT_POINT "/tetris.pcm"); + stop_music = xQueueCreate(2, sizeof (uint8_t)); + if (stop_music == 0) { + ESP_LOGW(TAG, "Could not create stop_music queue!"); + vTaskDelete(NULL); } + + while (playing_music) { + play_raw_stop_queue(MOUNT_POINT "/tetris.pcm", stop_music); + } + + vTaskDelete(NULL); } static void init_screen(void) { @@ -170,7 +181,7 @@ static void init_screen(void) { xSemaphoreGive(xGuiSemaphore); - xTaskCreate(music_task, "music", 4096, NULL, 5, &music_handle); + xTaskCreate(music_task, "music", 4096, NULL, 5, NULL); } static void deinit_screen(void) { @@ -179,7 +190,11 @@ static void deinit_screen(void) { lv_obj_clean(lv_scr_act()); xSemaphoreGive(xGuiSemaphore); - vTaskDelete(music_handle); + playing_music = false; + uint8_t value = 0; + if (!xQueueSend(stop_music, &value, pdMS_TO_TICKS(1000))) { + ESP_LOGE(TAG, "Faild to send stop queue"); + } } bool play_game(int time, int required_score) { @@ -330,6 +345,7 @@ void step4(void) { complete(); while (!play_game(6*60*1000, 8)) fail(); complete(); + // vTaskDelay(pdMS_TO_TICKS(3000)); deinit_screen(); } diff --git a/main/steps/step5.cpp b/main/steps/step5.cpp index 99b6008..f3f862a 100644 --- a/main/steps/step5.cpp +++ b/main/steps/step5.cpp @@ -80,7 +80,7 @@ void step5(void) { clean_bomb(); int solved_puzzles = 0; - while (solved_puzzles < ) { + while (solved_puzzles < TIMES_TO_SOLVE) { lcd_set_cursor(&lcd, 1, 1); int puzzle = puzzle_dist(gen);