From c7a3277b5fc9e2ae10987f3f972acb498cc9256f Mon Sep 17 00:00:00 2001 From: Adam Wonak Date: Thu, 24 Jul 2025 07:53:41 -0700 Subject: [PATCH] Memory improvements in bootsplash and StateManager --- firmware/Gravity/Gravity.ino | 7 ++++--- firmware/Gravity/app_state.h | 8 ++++---- firmware/Gravity/display.h | 23 ++++++++++++----------- firmware/Gravity/save_state.cpp | 15 +++++++++++++-- firmware/Gravity/save_state.h | 20 +++++++++----------- 5 files changed, 42 insertions(+), 31 deletions(-) diff --git a/firmware/Gravity/Gravity.ino b/firmware/Gravity/Gravity.ino index 122cbf2..18c784e 100644 --- a/firmware/Gravity/Gravity.ino +++ b/firmware/Gravity/Gravity.ino @@ -203,13 +203,13 @@ void HandleEncoderPressed() { gravity.encoder.SetReverseDirection(app.encoder_reversed); } if (app.selected_param == PARAM_MAIN_SAVE_DATA) { - if (app.selected_sub_param < MAX_SAVE_SLOTS) { + if (app.selected_sub_param < StateManager::MAX_SAVE_SLOTS) { app.selected_save_slot = app.selected_sub_param; stateManager.saveData(app); } } if (app.selected_param == PARAM_MAIN_LOAD_DATA) { - if (app.selected_sub_param < MAX_SAVE_SLOTS) { + if (app.selected_sub_param < StateManager::MAX_SAVE_SLOTS) { app.selected_save_slot = app.selected_sub_param; stateManager.loadData(app, app.selected_save_slot); InitGravity(app); @@ -223,6 +223,7 @@ void HandleEncoderPressed() { } if (app.selected_param == PARAM_MAIN_FACTORY_RESET) { if (app.selected_sub_param == 0) { // Erase + // Show bootsplash during slow erase operation. Bootsplash(); stateManager.factoryReset(app); InitGravity(app); @@ -297,7 +298,7 @@ void editMainParameter(int val) { break; case PARAM_MAIN_SAVE_DATA: case PARAM_MAIN_LOAD_DATA: - updateSelection(app.selected_sub_param, val, MAX_SAVE_SLOTS + 1); + updateSelection(app.selected_sub_param, val, StateManager::MAX_SAVE_SLOTS + 1); break; case PARAM_MAIN_RESET_STATE: updateSelection(app.selected_sub_param, val, 2); diff --git a/firmware/Gravity/app_state.h b/firmware/Gravity/app_state.h index 0ddd014..b53d314 100644 --- a/firmware/Gravity/app_state.h +++ b/firmware/Gravity/app_state.h @@ -19,9 +19,7 @@ // Global state for settings and app behavior. struct AppState { int tempo = Clock::DEFAULT_TEMPO; - bool encoder_reversed = false; - bool refresh_screen = true; - bool editing_param = false; + Channel channel[Gravity::OUTPUT_COUNT]; byte selected_param = 0; byte selected_sub_param = 0; // Temporary value for editing params. byte selected_channel = 0; // 0=tempo, 1-6=output channel @@ -29,7 +27,9 @@ struct AppState { byte selected_save_slot = 0; // The currently active save slot. Clock::Source selected_source = Clock::SOURCE_INTERNAL; Clock::Pulse selected_pulse = Clock::PULSE_PPQN_24; - Channel channel[Gravity::OUTPUT_COUNT]; + bool editing_param = false; + bool encoder_reversed = false; + bool refresh_screen = true; }; extern AppState app; diff --git a/firmware/Gravity/display.h b/firmware/Gravity/display.h index dc67447..37b900b 100644 --- a/firmware/Gravity/display.h +++ b/firmware/Gravity/display.h @@ -214,10 +214,10 @@ void swingDivisionMark() { // Human friendly display value for save slot. String displaySaveSlot(int slot) { - if (slot >= 0 && slot < MAX_SAVE_SLOTS / 2) { + if (slot >= 0 && slot < StateManager::MAX_SAVE_SLOTS / 2) { return String("A") + String(slot + 1); - } else if (slot >= MAX_SAVE_SLOTS / 2 && slot <= MAX_SAVE_SLOTS) { - return String("B") + String(slot - (MAX_SAVE_SLOTS / 2) + 1); + } else if (slot >= StateManager::MAX_SAVE_SLOTS / 2 && slot <= StateManager::MAX_SAVE_SLOTS) { + return String("B") + String(slot - (StateManager::MAX_SAVE_SLOTS / 2) + 1); } } @@ -283,7 +283,7 @@ void DisplayMainPage() { break; case PARAM_MAIN_SAVE_DATA: case PARAM_MAIN_LOAD_DATA: - if (app.selected_sub_param == MAX_SAVE_SLOTS) { + if (app.selected_sub_param == StateManager::MAX_SAVE_SLOTS) { mainText = F("x"); subText = F("BACK TO MAIN"); } else { @@ -465,7 +465,7 @@ void UpdateDisplay() { DisplayChannelPage(); } // Global channel select UI. - DisplaySelectedChannel(); + DisplaySelectedChannel(); } while (gravity.display.nextPage()); } @@ -473,16 +473,17 @@ void Bootsplash() { gravity.display.firstPage(); do { int textWidth; + String loadingText = F("LOADING...."); gravity.display.setFont(TEXT_FONT); - textWidth = gravity.display.getStrWidth(SKETCH_NAME); - gravity.display.drawStr(16 + (textWidth / 2), 20, SKETCH_NAME); + textWidth = gravity.display.getStrWidth(StateManager::SKETCH_NAME); + gravity.display.drawStr(16 + (textWidth / 2), 20, StateManager::SKETCH_NAME); - textWidth = gravity.display.getStrWidth(SEMANTIC_VERSION); - gravity.display.drawStr(16 + (textWidth / 2), 32, SEMANTIC_VERSION); + textWidth = gravity.display.getStrWidth(StateManager::SEMANTIC_VERSION); + gravity.display.drawStr(16 + (textWidth / 2), 32, StateManager::SEMANTIC_VERSION); - textWidth = gravity.display.getStrWidth("LOADING...."); - gravity.display.drawStr(26 + (textWidth / 2), 44, "LOADING...."); + textWidth = gravity.display.getStrWidth(loadingText.c_str()); + gravity.display.drawStr(26 + (textWidth / 2), 44, loadingText.c_str()); } while (gravity.display.nextPage()); } diff --git a/firmware/Gravity/save_state.cpp b/firmware/Gravity/save_state.cpp index 674115f..be4db95 100644 --- a/firmware/Gravity/save_state.cpp +++ b/firmware/Gravity/save_state.cpp @@ -15,9 +15,20 @@ #include "app_state.h" +// Define the constants for the current firmware. +const char StateManager::SKETCH_NAME[] = "ALT GRAVITY"; +const char StateManager::SEMANTIC_VERSION[] = "V2.0.0BETA2"; + +// Number of available save slots. +const byte StateManager::MAX_SAVE_SLOTS = 10; +const byte StateManager::TRANSIENT_SLOT = 10; + +// Define the minimum amount of time between EEPROM writes. +const unsigned long StateManager::SAVE_DELAY_MS = 2000; + // Calculate the starting address for EepromData, leaving space for metadata. -static const int METADATA_START_ADDR = 0; -static const int EEPROM_DATA_START_ADDR = sizeof(StateManager::Metadata); +const int StateManager::METADATA_START_ADDR = 0; +const int StateManager::EEPROM_DATA_START_ADDR = sizeof(StateManager::Metadata); StateManager::StateManager() : _isDirty(false), _lastChangeTime(0) {} diff --git a/firmware/Gravity/save_state.h b/firmware/Gravity/save_state.h index cd7fcba..b1a94d6 100644 --- a/firmware/Gravity/save_state.h +++ b/firmware/Gravity/save_state.h @@ -18,17 +18,6 @@ // Forward-declare AppState to avoid circular dependencies. struct AppState; -// Define the constants for the current firmware. -const char SKETCH_NAME[] = "ALT GRAVITY"; -const char SEMANTIC_VERSION[] = "V2.0.0BETA2"; - -// Number of available save slots. -const byte MAX_SAVE_SLOTS = 10; // Count of save slots 0 - 9 to save/load presets. -const byte TRANSIENT_SLOT = 10; // Transient slot index to persist state when powered off. - -// Define the minimum amount of time between EEPROM writes. -static const unsigned long SAVE_DELAY_MS = 2000; - /** * @brief Manages saving and loading of the application state to and from EEPROM. * The number of user slots is defined by MAX_SAVE_SLOTS, and one additional slot @@ -39,6 +28,11 @@ static const unsigned long SAVE_DELAY_MS = 2000; */ class StateManager { public: + static const char SKETCH_NAME[]; + static const char SEMANTIC_VERSION[]; + static const byte MAX_SAVE_SLOTS; + static const byte TRANSIENT_SLOT; + StateManager(); // Populate the AppState instance with values from EEPROM if they exist. @@ -92,6 +86,10 @@ class StateManager { void _saveState(const AppState& app, byte slot_index); void _loadState(AppState& app, byte slot_index); + static const unsigned long SAVE_DELAY_MS; + static const int METADATA_START_ADDR; + static const int EEPROM_DATA_START_ADDR; + bool _isDirty; unsigned long _lastChangeTime; };