diff --git a/main/drivers/char_lcd.cpp b/main/drivers/char_lcd.cpp index 4472e0d..d427bae 100644 --- a/main/drivers/char_lcd.cpp +++ b/main/drivers/char_lcd.cpp @@ -2,11 +2,14 @@ #include "./i2c_lcd_pcf8574.h" #include +#include "state_tracking.h" i2c_lcd_pcf8574_handle_t lcd; static const char *TAG = "char_lcd"; +static char buf[65]; + void init_lcd() { ESP_LOGI(TAG, "Initializing LCD..."); @@ -18,17 +21,29 @@ void init_lcd() { ESP_LOGI(TAG, "LCD initialized!"); } - void lcd_clear() { lcd_clear(&lcd); + + if (is_state_tracking()) { + event_occured("LCD_CLEAR", NULL); + } } void lcd_cursor_home() { lcd_home(&lcd); + + if (is_state_tracking()) { + event_occured("LCD_CURSOR", "0,0"); + } } void lcd_set_cursor_pos(uint8_t col, uint8_t row) { lcd_set_cursor(&lcd, col, row); + + if (is_state_tracking()) { + sprintf(buf, "%d,%d", col, row); + event_occured("LCD_CURSOR", buf); + } } void lcd_set_display(bool display) { @@ -37,6 +52,10 @@ void lcd_set_display(bool display) { } else { lcd_no_display(&lcd); } + + if (is_state_tracking()) { + event_occured("LCD_SET_DISPLAY", display ? "true" : "false"); + } } void lcd_set_cursor_vis(bool cursor) { @@ -45,6 +64,10 @@ void lcd_set_cursor_vis(bool cursor) { } else { lcd_no_cursor(&lcd); } + + if (is_state_tracking()) { + event_occured("LCD_CURSOR_VIS", cursor ? "true" : "false"); + } } void lcd_set_cursor_blink(bool blink) { @@ -53,20 +76,40 @@ void lcd_set_cursor_blink(bool blink) { } else { lcd_no_blink(&lcd); } + + if (is_state_tracking()) { + event_occured("LCD_CURSOR_BLINK", blink ? "true" : "false"); + } } void lcd_scroll_display_left() { lcd_scroll_display_left(&lcd); + + if (is_state_tracking()) { + event_occured("LCD_SCROLL_DISPLAY_LEFT", NULL); + } } void lcd_scroll_display_right() { lcd_scroll_display_right(&lcd); + + if (is_state_tracking()) { + event_occured("LCD_SCROLL_DISPLAY_RIGHT", NULL); + } } void lcd_left_to_right() { lcd_left_to_right(&lcd); + + if (is_state_tracking()) { + event_occured("LCD_SCROLL_LEFT_TO_RIGHT", NULL); + } } void lcd_right_to_left() { lcd_right_to_left(&lcd); + + if (is_state_tracking()) { + event_occured("LCD_SCROLL_RIGHT_TO_LEFT", NULL); + } } void lcd_set_autoscroll(bool autoscroll) { @@ -75,25 +118,51 @@ void lcd_set_autoscroll(bool autoscroll) { } else { lcd_no_autoscroll(&lcd); } + + if (is_state_tracking()) { + event_occured("LCD_AUTOSCROLL", autoscroll ? "true" : "false"); + } } void lcd_set_backlight(uint8_t brightness) { lcd_set_backlight(&lcd, brightness); + + if (is_state_tracking()) { + sprintf(buf, "%d", brightness); + event_occured("LCD_BACKLIGHT", buf); + } } -void lcd_create_char(uint8_t location, uint8_t charmap[]) { +void lcd_create_char(uint8_t location, uint8_t* charmap) { lcd_create_char(&lcd, location, charmap); + + if (is_state_tracking()) { + snprintf(buf, 65, + "%d,%d,%d,%d,%d,%d,%d,%d,%d", location, + charmap[0], charmap[1], charmap[2], charmap[3], charmap[4], charmap[5], charmap[6], charmap[7] + ); + event_occured("LCD_CREATE_CHAR", buf); + } } void lcd_write(uint8_t value) { lcd_write(&lcd, value); + + if (is_state_tracking()) { + sprintf(buf, "%d", value); + event_occured("LCD_WRITE", buf); + } } void lcd_print(const char* str) { lcd_print(&lcd, str); + + if (is_state_tracking()) { + event_occured("LCD_PRINT", str); + } } void lcd_print(uint8_t col, uint8_t row, const char* str) { lcd_set_cursor_pos(col, row); - lcd_print(&lcd, str); -} \ No newline at end of file + lcd_print(str); +} diff --git a/main/drivers/state_tracking.cpp b/main/drivers/state_tracking.cpp index 73a2a59..409a29b 100644 --- a/main/drivers/state_tracking.cpp +++ b/main/drivers/state_tracking.cpp @@ -1,4 +1,5 @@ #include "state_tracking.h" +#include #include enum state_t { @@ -7,7 +8,7 @@ enum state_t { STATE_PLAYBACK = 2, }; -static std::vector registered_events; +static std::vector event_cbs; static bool should_close_recording_stream; static FILE* recording_stream; @@ -17,12 +18,12 @@ static bool should_close_playback_stream; static FILE* playback_stream; static state_t state = STATE_IDLE; -void register_event(const char* name, void (*replay_callback)(uint32_t, const char*)) { - Event event = { +void register_event_cb(const char* name, void (*replay_callback)(uint32_t, const char*)) { + EventCB event = { .name = name, .replay_callback = replay_callback, }; - registered_events.push_back(event); + event_cbs.push_back(event); } void event_occured(const char* name, const char* arg) { @@ -36,7 +37,13 @@ void event_occured(const char* name, const char* arg) { arg = (arg == nullptr) ? "" : arg; uint32_t ticks = xTaskGetTickCount() - recording_start_time; fprintf(recording_stream, "%ld,%s:%s\n", ticks, name, (arg == nullptr) ? "" : arg); + fflush(recording_stream); + + int fd = fileno(recording_stream); + if (fd != -1) { + fsync(fd); + } } bool set_recording_source(FILE* stream, bool should_close) { @@ -84,4 +91,8 @@ bool start_playback() { bool stop_playback() { // TODO: impl return false; -} \ No newline at end of file +} + +bool is_state_tracking() { + return state == STATE_RECORDING; +} diff --git a/main/drivers/state_tracking.h b/main/drivers/state_tracking.h index 049ff13..4326f20 100644 --- a/main/drivers/state_tracking.h +++ b/main/drivers/state_tracking.h @@ -5,7 +5,7 @@ #include "esp_vfs_fat.h" /// @brief An event that represents the physical bomb state moving. -struct Event { +struct EventCB { // The name of the event. // This should not contain whitespace or the characters ':', ',' const char* name; @@ -14,10 +14,12 @@ struct Event { void (*replay_callback)(uint32_t, const char*); }; -/// @brief Registers an event to be tracked. -/// @param name The name of the event that has occured. -/// @param replay_callback A function to call to recreate this state transition. -void register_event(const char* name, void (*replay_callback)(uint32_t, const char*)); +/// @brief Registers a callback for a certain event to be called on replay. +/// @param name The name of the event to respond to. +/// @param replay_callback A function to call to playback this state transition. +void register_event_cb(const char* name, void (*replay_callback)(uint32_t, const char*)); + +// TODO: add one for generically responding to all events. /// @brief Call this to indicate that the bomb state has transitioned. /// @param name The name of the event that has occured. @@ -53,4 +55,10 @@ bool start_playback(); /// @return true if stopping the playback is successful. bool stop_playback(); +/// @brief Gets weather or not we are tracking the state +/// This can be helpful to conditionally do extra computation only +/// when we are tracking the state. +/// @return +bool is_state_tracking(); + #endif /* STATE_TRACKING_H */ diff --git a/main/main.cpp b/main/main.cpp index 7e0a47b..498c617 100755 --- a/main/main.cpp +++ b/main/main.cpp @@ -35,11 +35,19 @@ extern "C" void app_main(void) { init_wires(); vTaskDelay(pdMS_TO_TICKS(1000)); - set_recording_source(fopen(MOUNT_POINT "record.txt", "w"), true); + // set_recording_source(stdout, false); + FILE* record_file = fopen(MOUNT_POINT "/record.txt", "w"); + if (record_file == nullptr) { + ESP_LOGE("main", "failed to open record.txt"); + } + set_recording_source(record_file, true); start_recording(); clean_bomb(); step0(); + + stop_recording(); + set_game_time(initial_game_time); start_game_timer(); total_strikes = 0; @@ -76,5 +84,4 @@ extern "C" void app_main(void) { display_game_results(); - stop_recording(); } diff --git a/main/steps/step0.cpp b/main/steps/step0.cpp index f345425..cc909a3 100644 --- a/main/steps/step0.cpp +++ b/main/steps/step0.cpp @@ -42,7 +42,7 @@ void step0() { StarCodeHandler star_codes[] = { { .code = "*9819", - .display_text = "Diffusal Initiated", + .display_text = "Defusal Initiated", .should_exit = true, .callback = nullptr, },