From 54ff226694b9313ac0159cc5b84c5050064f8d8e Mon Sep 17 00:00:00 2001 From: Mitchell Marino Date: Thu, 27 Mar 2025 01:02:26 -0500 Subject: [PATCH] setup state tracking --- main/drivers/CMakeLists.txt | 1 + main/drivers/state_tracking.cpp | 87 +++++++++++++++++++++++++++++++++ main/drivers/state_tracking.h | 56 +++++++++++++++++++++ main/main.cpp | 7 +++ 4 files changed, 151 insertions(+) create mode 100644 main/drivers/state_tracking.cpp create mode 100644 main/drivers/state_tracking.h diff --git a/main/drivers/CMakeLists.txt b/main/drivers/CMakeLists.txt index fb5c43a..fa0c42f 100644 --- a/main/drivers/CMakeLists.txt +++ b/main/drivers/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES "sd.cpp" "speaker.cpp" "sseg.cpp" + "state_tracking.cpp" "tft.cpp" "wires.cpp" ) diff --git a/main/drivers/state_tracking.cpp b/main/drivers/state_tracking.cpp new file mode 100644 index 0000000..73a2a59 --- /dev/null +++ b/main/drivers/state_tracking.cpp @@ -0,0 +1,87 @@ +#include "state_tracking.h" +#include + +enum state_t { + STATE_IDLE = 0, + STATE_RECORDING = 1, + STATE_PLAYBACK = 2, +}; + +static std::vector registered_events; + +static bool should_close_recording_stream; +static FILE* recording_stream; +static uint32_t recording_start_time; + +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 = { + .name = name, + .replay_callback = replay_callback, + }; + registered_events.push_back(event); +} + +void event_occured(const char* name, const char* arg) { + if (state != STATE_RECORDING) return; + if (name == nullptr) return; + if (recording_stream == nullptr) { + ESP_LOGE("state_tracking", "We are in state recording, but recording stream is null"); + return; + } + + 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); +} + +bool set_recording_source(FILE* stream, bool should_close) { + if (state == STATE_RECORDING) return false; + + recording_stream = stream; + should_close_recording_stream = should_close; + return true; +} + +bool set_playback_source(FILE* stream, bool should_close) { + if (state == STATE_PLAYBACK) return false; + + playback_stream = stream; + should_close_playback_stream = should_close; + return true; +} + +bool start_recording() { + if (state != STATE_IDLE) return false; + if (recording_stream == nullptr) return false; + + state = STATE_RECORDING; + recording_start_time = xTaskGetTickCount(); + return true; +} + +bool stop_recording() { + if (state != STATE_RECORDING) return false; + + state = STATE_IDLE; + fflush(recording_stream); + if (should_close_recording_stream) { + fclose(recording_stream); + recording_stream = nullptr; + } + return true; +} + +bool start_playback() { + // TODO: impl + return false; +} + +bool stop_playback() { + // TODO: impl + return false; +} \ No newline at end of file diff --git a/main/drivers/state_tracking.h b/main/drivers/state_tracking.h new file mode 100644 index 0000000..049ff13 --- /dev/null +++ b/main/drivers/state_tracking.h @@ -0,0 +1,56 @@ +#ifndef STATE_TRACKING_H +#define STATE_TRACKING_H + +#include +#include "esp_vfs_fat.h" + +/// @brief An event that represents the physical bomb state moving. +struct Event { + // The name of the event. + // This should not contain whitespace or the characters ':', ',' + const char* name; + // An optional callback function for recreating the state. + // Arguments are "ticks" and the serialized argument + 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 Call this to indicate that the bomb state has transitioned. +/// @param name The name of the event that has occured. +/// @param arg The serialized data associated with the event. +/// This must not contain newline characters such as '\n' or '\r' +void event_occured(const char* name, const char* arg); + +/// @brief Sets the recording source. +/// @param stream The stream to record to. +/// @param should_close whether or not the stream should be closed when finished. +/// @return true if the source was updated. +bool set_recording_source(FILE* stream, bool should_close); + +/// @brief Sets the playback source. +/// @param stream The stream to playback from. +/// @param should_close whether or not the stream should be closed when finished. +/// @return true if the source was updated. +bool set_playback_source(FILE* stream, bool should_close); + +/// @brief Starts recording to the stream specified by `set_recording_source()`. +/// @return true if starting recording is successful. +bool start_recording(); + +/// @brief Stops recording the state. +/// @return true if stopping the recording is successful. +bool stop_recording(); + +/// @brief Starts playing back the recording specified by `set_playback_source()`. +/// @return true if starting playback is successful. +bool start_playback(); + +/// @brief Stops playing back the recording. +/// @return true if stopping the playback is successful. +bool stop_playback(); + +#endif /* STATE_TRACKING_H */ diff --git a/main/main.cpp b/main/main.cpp index 781395f..7e0a47b 100755 --- a/main/main.cpp +++ b/main/main.cpp @@ -7,6 +7,7 @@ #include "esp_rom_gpio.h" #include "drivers/all.h" +#include "drivers/state_tracking.h" #include "helper.h" @@ -32,6 +33,10 @@ extern "C" void app_main(void) { // TODO: get wires out of the drivers // TODO: generify the strike system out of wires init_wires(); + vTaskDelay(pdMS_TO_TICKS(1000)); + + set_recording_source(fopen(MOUNT_POINT "record.txt", "w"), true); + start_recording(); clean_bomb(); step0(); @@ -70,4 +75,6 @@ extern "C" void app_main(void) { play_clip_wav(MOUNT_POINT "/diffuse.wav", true, false, 3, 0); display_game_results(); + + stop_recording(); }