From 6ada2aba30fef81a4b182737280208e8be2ad742 Mon Sep 17 00:00:00 2001 From: Adam Wonak Date: Sun, 10 Aug 2025 02:47:59 +0000 Subject: [PATCH] Add option to rotate the display (#27) I needed to cut the bootsplash to make room for adding this features. Reviewed-on: https://git.pinkduck.xyz/awonak/libGravity/pulls/27 --- firmware/Gravity/Gravity.ino | 59 +++++++++++++++++---------------- firmware/Gravity/app_state.h | 1 + firmware/Gravity/display.h | 30 ++++------------- firmware/Gravity/save_state.cpp | 3 +- firmware/Gravity/save_state.h | 5 +-- library.properties | 2 +- src/clock.h | 9 ++--- 7 files changed, 46 insertions(+), 63 deletions(-) diff --git a/firmware/Gravity/Gravity.ino b/firmware/Gravity/Gravity.ino index 8618f46..aef4ab8 100644 --- a/firmware/Gravity/Gravity.ino +++ b/firmware/Gravity/Gravity.ino @@ -66,10 +66,6 @@ void setup() { // Start Gravity. gravity.Init(); - // Show bootsplash when initializing firmware. - Bootsplash(); - delay(2000); - // Initialize the state manager. This will load settings from EEPROM stateManager.initialize(app); InitGravity(app); @@ -213,31 +209,34 @@ void HandleEncoderPressed() { // Check if leaving editing mode should apply a selection. if (app.editing_param) { if (app.selected_channel == 0) { // main page - // TODO: rewrite as switch - if (app.selected_param == PARAM_MAIN_ENCODER_DIR) { - app.encoder_reversed = app.selected_sub_param == 1; - gravity.encoder.SetReverseDirection(app.encoder_reversed); - } - if (app.selected_param == PARAM_MAIN_SAVE_DATA) { - 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 < StateManager::MAX_SAVE_SLOTS) { - app.selected_save_slot = app.selected_sub_param; - stateManager.loadData(app, app.selected_save_slot); - InitGravity(app); - } - } - 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); - } + switch (app.selected_param) { + case PARAM_MAIN_ENCODER_DIR: + app.encoder_reversed = app.selected_sub_param == 1; + gravity.encoder.SetReverseDirection(app.encoder_reversed); + break; + case PARAM_MAIN_ROTATE_DISP: + app.rotate_display = app.selected_sub_param == 1; + gravity.display.setFlipMode(app.rotate_display ? 1 : 0); + break; + case PARAM_MAIN_SAVE_DATA: + if (app.selected_sub_param < StateManager::MAX_SAVE_SLOTS) { + app.selected_save_slot = app.selected_sub_param; + stateManager.saveData(app); + } + break; + case PARAM_MAIN_LOAD_DATA: + 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); + } + break; + case PARAM_MAIN_FACTORY_RESET: + if (app.selected_sub_param == 0) { // Erase + stateManager.factoryReset(app); + InitGravity(app); + } + break; } } // Only mark dirty and reset selected_sub_param when leaving editing mode. @@ -313,6 +312,7 @@ void editMainParameter(int val) { } // These changes are applied upon encoder button press. case PARAM_MAIN_ENCODER_DIR: + case PARAM_MAIN_ROTATE_DISP: updateSelection(app.selected_sub_param, val, 2); break; case PARAM_MAIN_SAVE_DATA: @@ -381,6 +381,7 @@ void InitGravity(AppState& app) { gravity.clock.SetTempo(app.tempo); gravity.clock.SetSource(app.selected_source); gravity.encoder.SetReverseDirection(app.encoder_reversed); + gravity.display.setFlipMode(app.rotate_display ? 1 : 0); } void ResetOutputs() { diff --git a/firmware/Gravity/app_state.h b/firmware/Gravity/app_state.h index 0f06f02..c02f8a3 100644 --- a/firmware/Gravity/app_state.h +++ b/firmware/Gravity/app_state.h @@ -31,6 +31,7 @@ struct AppState { Clock::Pulse selected_pulse = Clock::PULSE_PPQN_24; bool editing_param = false; bool encoder_reversed = false; + bool rotate_display = false; bool refresh_screen = true; }; diff --git a/firmware/Gravity/display.h b/firmware/Gravity/display.h index faeb4d1..7c4abfa 100644 --- a/firmware/Gravity/display.h +++ b/firmware/Gravity/display.h @@ -104,6 +104,7 @@ enum ParamsMainPage : uint8_t { PARAM_MAIN_RESET, PARAM_MAIN_PULSE, PARAM_MAIN_ENCODER_DIR, + PARAM_MAIN_ROTATE_DISP, PARAM_MAIN_SAVE_DATA, PARAM_MAIN_LOAD_DATA, PARAM_MAIN_FACTORY_RESET, @@ -256,9 +257,6 @@ void DisplayMainPage() { case Clock::SOURCE_EXTERNAL_PPQN_4: subText = F("4 PPQN"); break; - case Clock::SOURCE_EXTERNAL_PPQN_2: - subText = F("2 PPQN"); - break; case Clock::SOURCE_EXTERNAL_PPQN_1: subText = F("1 PPQN"); break; @@ -316,6 +314,10 @@ void DisplayMainPage() { mainText = F("DIR"); subText = app.selected_sub_param == 0 ? F("DEFAULT") : F("REVERSED"); break; + case PARAM_MAIN_ROTATE_DISP: + mainText = F("ROT"); + subText = app.selected_sub_param == 0 ? F("DEFAULT") : F("FLIPPED"); + break; case PARAM_MAIN_SAVE_DATA: case PARAM_MAIN_LOAD_DATA: if (app.selected_sub_param == StateManager::MAX_SAVE_SLOTS) { @@ -347,7 +349,7 @@ void DisplayMainPage() { drawCenteredText(subText.c_str(), SUB_TEXT_Y, TEXT_FONT); // Draw Main Page menu items - String menu_items[PARAM_MAIN_LAST] = {F("TEMPO"), F("SOURCE"), F("CLK RUN"), F("CLK RESET"), F("PULSE OUT"), F("ENCODER DIR"), F("SAVE"), F("LOAD"), F("ERASE")}; + String menu_items[PARAM_MAIN_LAST] = {F("TEMPO"), F("SOURCE"), F("CLK RUN"), F("CLK RESET"), F("PULSE OUT"), F("ENCODER DIR"), F("ROTATE DISP"), F("SAVE"), F("LOAD"), F("ERASE")}; drawMenuItems(menu_items, PARAM_MAIN_LAST); } @@ -369,7 +371,7 @@ void DisplayChannelPage() { switch (app.selected_param) { case PARAM_CH_MOD: { - int mod_value = withCvMod ? ch.getClockModWithMod(cv1, cv2): ch.getClockMod(); + int mod_value = withCvMod ? ch.getClockModWithMod(cv1, cv2) : ch.getClockMod(); if (mod_value > 1) { mainText = F("/"); mainText += String(mod_value); @@ -497,22 +499,4 @@ void UpdateDisplay() { } while (gravity.display.nextPage()); } -void Bootsplash() { - gravity.display.firstPage(); - do { - int textWidth; - String loadingText = F("LOADING...."); - gravity.display.setFont(TEXT_FONT); - - textWidth = gravity.display.getStrWidth(StateManager::SKETCH_NAME); - gravity.display.drawStr(16 + (textWidth / 2), 20, StateManager::SKETCH_NAME); - - textWidth = gravity.display.getStrWidth(StateManager::SEMANTIC_VERSION); - gravity.display.drawStr(16 + (textWidth / 2), 32, StateManager::SEMANTIC_VERSION); - - textWidth = gravity.display.getStrWidth(loadingText.c_str()); - gravity.display.drawStr(26 + (textWidth / 2), 44, loadingText.c_str()); - } while (gravity.display.nextPage()); -} - #endif // DISPLAY_H diff --git a/firmware/Gravity/save_state.cpp b/firmware/Gravity/save_state.cpp index 4950d7e..ff00005 100644 --- a/firmware/Gravity/save_state.cpp +++ b/firmware/Gravity/save_state.cpp @@ -17,7 +17,7 @@ // Define the constants for the current firmware. const char StateManager::SKETCH_NAME[] = "ALT GRAVITY"; -const char StateManager::SEMANTIC_VERSION[] = "V2.0.0BETA4"; // NOTE: This should match the version in the library.properties file. +const char StateManager::SEMANTIC_VERSION[] = "2.0.0"; // NOTE: This should match the version in the library.properties file. // Number of available save slots. const byte StateManager::MAX_SAVE_SLOTS = 10; @@ -212,6 +212,7 @@ void StateManager::_saveMetadata(const AppState& app) { // Global user settings current_meta.selected_save_slot = app.selected_save_slot; current_meta.encoder_reversed = app.encoder_reversed; + current_meta.rotate_display = app.rotate_display; EEPROM.put(METADATA_START_ADDR, current_meta); interrupts(); diff --git a/firmware/Gravity/save_state.h b/firmware/Gravity/save_state.h index 34bfffe..29226e7 100644 --- a/firmware/Gravity/save_state.h +++ b/firmware/Gravity/save_state.h @@ -52,11 +52,12 @@ class StateManager { // This struct holds the data that identifies the firmware version. struct Metadata { - char sketch_name[16]; - char version[16]; + char sketch_name[12]; + char version[5]; // Additional global/hardware settings byte selected_save_slot; bool encoder_reversed; + bool rotate_display; }; struct ChannelState { byte base_clock_mod_index; diff --git a/library.properties b/library.properties index 1390c78..bce41dd 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=libGravity -version=2.0.0beta3 +version=2.0.0 author=Adam Wonak maintainer=awonak sentence=Hardware abstraction library for Sitka Instruments Gravity eurorack module diff --git a/src/clock.h b/src/clock.h index ea39214..9bc695c 100644 --- a/src/clock.h +++ b/src/clock.h @@ -35,7 +35,6 @@ class Clock { SOURCE_INTERNAL, SOURCE_EXTERNAL_PPQN_24, SOURCE_EXTERNAL_PPQN_4, - SOURCE_EXTERNAL_PPQN_2, SOURCE_EXTERNAL_PPQN_1, SOURCE_EXTERNAL_MIDI, SOURCE_LAST, @@ -43,9 +42,9 @@ class Clock { enum Pulse { PULSE_NONE, - PULSE_PPQN_1, - PULSE_PPQN_4, PULSE_PPQN_24, + PULSE_PPQN_4, + PULSE_PPQN_1, PULSE_LAST, }; @@ -98,10 +97,6 @@ class Clock { uClock.setClockMode(uClock.EXTERNAL_CLOCK); uClock.setInputPPQN(uClock.PPQN_4); break; - case SOURCE_EXTERNAL_PPQN_2: - uClock.setClockMode(uClock.EXTERNAL_CLOCK); - uClock.setInputPPQN(uClock.PPQN_2); - break; case SOURCE_EXTERNAL_PPQN_1: uClock.setClockMode(uClock.EXTERNAL_CLOCK); uClock.setInputPPQN(uClock.PPQN_1);