From 855fd01821a00489b30e9e31f53ec96bf0b66ea7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20T=C3=B3th?= Date: Mon, 1 Dec 2025 22:45:58 +0100 Subject: [PATCH] Firmware MCU: Update sequencer block to support dynamic step count and enhance documentation --- dev/digital/ESP32-S3/ESP32-S3.PrjPcb | 17 +++++++ .../ESP32-S3/History/ESP32-S3.~(3).PrjPcb.Zip | Bin 0 -> 5900 bytes dev/digital/Firmware_TEST/include/FIRMWARE.h | 45 ++++++++++-------- .../Firmware_TEST/include/FIRMWARE_DEF.h | 24 ++++++---- dev/digital/Firmware_TEST/src/FIRMWARE.cpp | 29 +++++------ dev/digital/Firmware_TEST/src/main.cpp | 17 ++++--- 6 files changed, 82 insertions(+), 50 deletions(-) create mode 100644 dev/digital/ESP32-S3/History/ESP32-S3.~(3).PrjPcb.Zip diff --git a/dev/digital/ESP32-S3/ESP32-S3.PrjPcb b/dev/digital/ESP32-S3/ESP32-S3.PrjPcb index 0a269a1..c8e466b 100644 --- a/dev/digital/ESP32-S3/ESP32-S3.PrjPcb +++ b/dev/digital/ESP32-S3/ESP32-S3.PrjPcb @@ -66,6 +66,23 @@ DItemRevisionGUID= GenerateClassCluster=0 DocumentUniqueId=QMXNWCKL +[Document2] +DocumentPath=ESP32-S3.Harness +AnnotationEnabled=1 +AnnotateStartValue=1 +AnnotationIndexControlEnabled=0 +AnnotateSuffix= +AnnotateScope=All +AnnotateOrder=-1 +DoLibraryUpdate=1 +DoDatabaseUpdate=1 +ClassGenCCAutoEnabled=1 +ClassGenCCAutoRoomEnabled=0 +ClassGenNCAutoScope=None +DItemRevisionGUID= +GenerateClassCluster=0 +DocumentUniqueId= + [Parameter1] Name=ProjectTitle Value=ESP32-S3 diff --git a/dev/digital/ESP32-S3/History/ESP32-S3.~(3).PrjPcb.Zip b/dev/digital/ESP32-S3/History/ESP32-S3.~(3).PrjPcb.Zip new file mode 100644 index 0000000000000000000000000000000000000000..38971f1faa693a1a5bd9ca0cfdcb40eed98af31f GIT binary patch literal 5900 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 literal 0 HcmV?d00001 diff --git a/dev/digital/Firmware_TEST/include/FIRMWARE.h b/dev/digital/Firmware_TEST/include/FIRMWARE.h index a481f88..05896fd 100644 --- a/dev/digital/Firmware_TEST/include/FIRMWARE.h +++ b/dev/digital/Firmware_TEST/include/FIRMWARE.h @@ -12,13 +12,11 @@ #ifndef FIRMWARE_H #define FIRMWARE_H -#define N_MAX_QUEUE 10 -#define N_MAX_ROWS 8 -#define N_MAX_COLS 8 -#define MS_DEBOUNCE 20 - -#define N_MAX_DAC_CH 4 -#define N_MAX_SEQUENCE_STEPS 128 +#define N_MAX_QUEUE 10 +#define N_MAX_ROWS 8 +#define N_MAX_COLS 8 +#define MS_DEBOUNCE 20 +#define N_MAX_DAC_CH 4 struct Key { @@ -94,7 +92,7 @@ class CV class SequencerBlock { public: - SequencerBlock(uint16_t maxDurationMS, uint16_t minStepDurationMS); + SequencerBlock(uint16_t maxDurationMS, uint16_t maxStepCount); // Aufnahme-Funktionen void startRecord(); @@ -105,7 +103,7 @@ class SequencerBlock // Wiedergabe-Funktionen void startPlay(); void stopPlay(); - void update(); // Muss regelmäßig aufgerufen werden + void update(); bool isPlaying(); // Sequenz-Verwaltung @@ -114,35 +112,44 @@ class SequencerBlock // Status-Abfragen bool timeLimitReached(); - uint8_t getStepCount(); + bool stepLimitReached(); + uint16_t getStepCount(); uint16_t getCurrentVoltageCh1(); uint16_t getCurrentVoltageCh2(); uint16_t getTotalDuration(); private: - // Sequenz-Speicher - DualVoltageDurationPair _sequence[N_MAX_SEQUENCE_STEPS]; - uint8_t _stepCount; - uint8_t _currentStep; + /*! + * @brief Memory limiting + * @return (uint16_t) 1024 + * @attention Increasing the value might lead to an overflow + * @note sizeOf(DualVoltageDurationPair) = 6 Byte ==> 6 Byte * 1024 = 6144 Byte + */ + const static uint16_t _MAX_SEQUENCE_STEPS = 1024; + + // Sequenz memory + DualVoltageDurationPair _sequence[_MAX_SEQUENCE_STEPS]; + uint16_t _stepCount; + uint16_t _currentStep; - // Zeitverwaltung + // Time management uint16_t _maxDurationMS; - uint16_t _minStepDurationMS; + uint16_t _maxStepCount; unsigned long _recordStartTime; unsigned long _lastStepTime; unsigned long _playStartTime; unsigned long _stepStartTime; - // Status-Flags + // Status flags bool _isRecording; bool _isPlaying; bool _loop; - // Letzte aufgenommene Spannungen + // Last recorded Voltage: at n-th step minus one uint16_t _lastVoltageCh1; uint16_t _lastVoltageCh2; - // Hilfsfunktionen + // helper functions void _finishCurrentStep(); bool _canAddStep(); }; diff --git a/dev/digital/Firmware_TEST/include/FIRMWARE_DEF.h b/dev/digital/Firmware_TEST/include/FIRMWARE_DEF.h index 8041031..f2ee7c4 100644 --- a/dev/digital/Firmware_TEST/include/FIRMWARE_DEF.h +++ b/dev/digital/Firmware_TEST/include/FIRMWARE_DEF.h @@ -11,11 +11,12 @@ #include #include // CONSTANTS DEFINITONS -#define N_KEYBOARD_ROW 4 -#define N_KEYBOARD_COL 3 +#define N_KEYBOARD_ROW 4 // for PROD. change to 5 +#define N_KEYBOARD_COL 3 // for PROD. change to 5 #define N_CV_GATES 2 #define N_SB 2 #define BAUDRATE 115200 +#define N_MAX_SEQ_STEPS 512 // PIN DEFENTITIONS // I2C PINS #define PIN_SDA 15 @@ -25,15 +26,22 @@ #define PIN_K_R1 8 #define PIN_K_R2 9 #define PIN_K_R3 10 -#define PIN_K_R4 // 11 NOT IN USE +#define PIN_K_R4 11 // DEV. not in use #define PIN_K_C0 1 #define PIN_K_C1 2 #define PIN_K_C2 4 -#define PIN_K_C3 // 5 NOT IN USE -#define PIN_K_C4 // 6 NOT IN USE +#define PIN_K_C3 5 // DEV. not in use +#define PIN_K_C4 6 // DEV. not in use // SEQUENCER BUTTON PINS -#define PIN_SB_1_REC 37 // 33 not available on dev board -#define PIN_SB_1_PLAY 38 // 34 not available on dev board +#define PIN_SB_1_REC 37 // for PROD. change to 33 / not available on dev board +#define PIN_SB_1_PLAY 38 // for PROD. change to 34 / not available on dev board #define PIN_SB_2_REC 35 -#define PIN_SB_2_PLAY 36 +#define PIN_SB_2_PLAY 36 +// MISC/INFO PINS +#define PIN_ACTIVE -1 // TODO: if any key is played return HIGH +#define PIN_REC -1 // TODO: if any sb is recording return HIGH +#define PIN_BPM -1 // TODO: get bpm through potentiometer analog value +#define PIN_B_METRONOME -1 // TODO: button activates/deactivates bpm led output +#define PIN_L_METRONOME -1 // TODO: led blinks according to bpm value + #endif \ No newline at end of file diff --git a/dev/digital/Firmware_TEST/src/FIRMWARE.cpp b/dev/digital/Firmware_TEST/src/FIRMWARE.cpp index 76a0380..f4b510b 100644 --- a/dev/digital/Firmware_TEST/src/FIRMWARE.cpp +++ b/dev/digital/Firmware_TEST/src/FIRMWARE.cpp @@ -235,12 +235,12 @@ uint8_t CV::_getKeyToVoltageIndex(Key k) /*! * @param maxDurationMS maximum loop duration of recording in milliseconds -* @param minStepDurationMS minimum duration for a step to be recorded (prevents ultra-short steps) +* @param maxStepCount maximum number of steps that can be recorded */ -SequencerBlock::SequencerBlock(uint16_t maxDurationMS, uint16_t minStepDurationMS) +SequencerBlock::SequencerBlock(uint16_t maxDurationMS, uint16_t maxStepCount) { _maxDurationMS = maxDurationMS; - _minStepDurationMS = minStepDurationMS; + _maxStepCount = maxStepCount; _stepCount = 0; _currentStep = 0; _isRecording = false; @@ -386,7 +386,7 @@ void SequencerBlock::clear() _lastVoltageCh1 = 0; _lastVoltageCh2 = 0; - for(uint8_t i = 0; i < N_MAX_SEQUENCE_STEPS; i++) + for(uint8_t i = 0; i < _MAX_SEQUENCE_STEPS; i++) { _sequence[i].voltage_ch1 = 0; _sequence[i].voltage_ch2 = 0; @@ -409,7 +409,12 @@ bool SequencerBlock::timeLimitReached() return (elapsed >= _maxDurationMS); } -uint8_t SequencerBlock::getStepCount() +bool SequencerBlock::stepLimitReached() +{ + return (_stepCount >= _maxStepCount); +} + +uint16_t SequencerBlock::getStepCount() { return _stepCount; } @@ -447,21 +452,13 @@ void SequencerBlock::_finishCurrentStep() unsigned long now = millis(); uint16_t duration = now - _lastStepTime; - // Nur Steps mit ausreichender Dauer speichern - if(duration >= _minStepDurationMS) - { - _sequence[_stepCount - 1].duration = duration; - } - else - { - // Step war zu kurz, verwerfen - _stepCount--; - } + _sequence[_stepCount - 1].duration = duration; } bool SequencerBlock::_canAddStep() { - if(_stepCount >= N_MAX_SEQUENCE_STEPS) return false; + if(_stepCount >= _maxStepCount) return false; + if(_stepCount >= _MAX_SEQUENCE_STEPS) return false; if(timeLimitReached()) return false; return true; diff --git a/dev/digital/Firmware_TEST/src/main.cpp b/dev/digital/Firmware_TEST/src/main.cpp index e1eddc4..c3d5144 100644 --- a/dev/digital/Firmware_TEST/src/main.cpp +++ b/dev/digital/Firmware_TEST/src/main.cpp @@ -1,5 +1,8 @@ /* * Example Code Three - Dual Channel Sequencer +* TODO: + - add predefined sequence of voltage (e.g. for usage as startup sound) + - implement INFO and MISC pins form file FIRMWARE_DEF.h */ #include "FIRMWARE_DEF.h" #include "FIRMWARE.h" @@ -12,17 +15,17 @@ Keyboard keyboard(N_KEYBOARD_ROW, N_KEYBOARD_COL, pins_keyboard_row, pins_keyboa Adafruit_MCP4728 MCP4728; MCP4728_channel_t cvMap[N_CV_GATES] = {MCP4728_CHANNEL_A, MCP4728_CHANNEL_B}; uint16_t keyToVoltage[N_KEYBOARD_ROW*N_KEYBOARD_COL] = { /* 83mV = 1/12V */ - 1*83, 5*83, 9*83, - 2*83, 6*83, 10*83, - 3*83, 7*83, 11*83, - 4*83, 8*83, 12*83 + 1*83, 5*83, 9*83, /* ROW 1: B D Fis */ + 2*83, 6*83, 10*83, /* ROW 2: H Dis G */ + 3*83, 7*83, 11*83, /* ROW 3: C E Gis */ + 4*83, 8*83, 12*83 /* ROW 4: Cis F A' */ }; CV cv(&MCP4728, &Wire, N_CV_GATES, cvMap, keyToVoltage, N_KEYBOARD_ROW, N_KEYBOARD_COL); -// Sequencer mit 30s max, 50ms Mindest-Step-Dauer -SequencerBlock sb1(30000, 50); -SequencerBlock sb2(30000, 50); +// Sequencer 30s max, 512 max Steps +SequencerBlock sb1(30000, N_MAX_SEQ_STEPS); +SequencerBlock sb2(30000, N_MAX_SEQ_STEPS); // Button States struct ButtonState {