Firmware Update

Changed mapping behaveiour of seqeuncer blocks.
This commit is contained in:
2026-03-08 22:09:26 +01:00
parent 2108552078
commit 04884bc243
12 changed files with 61393 additions and 177 deletions

View File

@@ -3,13 +3,13 @@
@author: Erik Tóth
@contact: etoth@tsn.at
@date: 2025-10-26
@updated: 2025-12-06
@brief: Firmware für MCU - FIXED VERSION mit Bounds Checks
@updated: 2026-03-08
@brief: Firmware für MCU
*/
#include "FIRMWARE.h"
// ==================== Helper-Functions ====================
// Helper-Functions
bool isNotKey(Key k)
{
@@ -23,7 +23,7 @@ bool isEqualKey(Key k1, Key k2)
else return false;
}
// ==================== Keyboard ====================
// Keyboard
Keyboard::Keyboard(uint8_t nRows, uint8_t nCols, uint8_t *pinsRow, uint8_t *pinsCol)
{
@@ -178,7 +178,7 @@ void Keyboard::_removeActiveKey(uint8_t row, uint8_t col)
}
}
// ==================== CV ====================
// CV
CV::CV(Adafruit_MCP4728 *dac, TwoWire *wire, uint8_t nCV, MCP4728_channel_t *cvChannelMap, uint16_t *keyToVoltage, uint8_t row, uint8_t col)
{
@@ -209,7 +209,7 @@ void CV::setVoltage(uint8_t cvIndex, uint16_t mV)
{
if(cvIndex >= _nCV) return;
MCP4728_channel_t ch = _cvChannelMap[cvIndex];
_dac->setChannelValue(ch, map(mV, 0, 1992, 0, 2048), MCP4728_VREF_INTERNAL);
_dac->setChannelValue(ch, map(mV, 0, 2048, 0, 4095), MCP4728_VREF_INTERNAL, MCP4728_GAIN_1X);
}
void CV::setVoltage(uint8_t cvIndex, Key k)
@@ -234,7 +234,7 @@ uint8_t CV::_getKeyToVoltageIndex(Key k)
return (k.row*_col + k.col);
}
// ==================== SequencerBlock (FIXED) ====================
// SequencerBlock
/*!
* @param maxDurationMS maximum loop duration of recording in milliseconds
@@ -255,7 +255,7 @@ SequencerBlock::SequencerBlock(uint16_t maxDurationMS, uint16_t maxStepCount)
_lastStepTime = 0;
_playStartTime = 0;
_stepStartTime = 0;
_lastAddStepTime = 0; // NEU: Rate-Limiting
_lastAddStepTime = 0;
}
void SequencerBlock::startRecord()
@@ -266,7 +266,7 @@ void SequencerBlock::startRecord()
_isRecording = true;
_recordStartTime = millis();
_lastStepTime = _recordStartTime;
_lastAddStepTime = _recordStartTime; // NEU
_lastAddStepTime = _recordStartTime;
_lastVoltageCh1 = 0xFFFF;
_lastVoltageCh2 = 0xFFFF;
}
@@ -281,10 +281,8 @@ void SequencerBlock::stopRecord()
void SequencerBlock::addStep(uint16_t voltage_ch1, uint16_t voltage_ch2)
{
// KRITISCHE SICHERHEITSPRÜFUNGEN ZUERST
if(!_isRecording) return;
// Prüfe ob wir überhaupt noch Platz haben (mit Sicherheitsabstand!)
if(_stepCount >= _MAX_SEQUENCE_STEPS - 1)
{
Serial.println("\n\r[ERROR] Step limit reached! Stopping recording.");
@@ -301,19 +299,16 @@ void SequencerBlock::addStep(uint16_t voltage_ch1, uint16_t voltage_ch2)
unsigned long now = millis();
// NEU: Rate-Limiting - ignoriere zu häufige Aufrufe
if((unsigned long)(now - _lastAddStepTime) < 5)
{
return;
}
_lastAddStepTime = now;
// Hat sich die Spannung geändert?
bool voltageChanged = (voltage_ch1 != _lastVoltageCh1) || (voltage_ch2 != _lastVoltageCh2);
if(voltageChanged)
{
// WICHTIG: Prüfe nochmal ob wir Platz haben BEVOR wir schreiben!
if(_stepCount >= _MAX_SEQUENCE_STEPS - 1)
{
Serial.println("\n\r[ERROR] Array full! Stopping recording.");
@@ -321,19 +316,17 @@ void SequencerBlock::addStep(uint16_t voltage_ch1, uint16_t voltage_ch2)
return;
}
// Vorherigen Step abschließen (wenn vorhanden)
if(_stepCount > 0 && _stepCount <= _MAX_SEQUENCE_STEPS)
{
_finishCurrentStep();
}
// Neuen Step beginnen - mit Bounds Check!
if(_stepCount < _MAX_SEQUENCE_STEPS)
{
_sequence[_stepCount].voltage_ch1 = voltage_ch1;
_sequence[_stepCount].voltage_ch2 = voltage_ch2;
_sequence[_stepCount].duration = 0;
_sequence[_stepCount].active = (voltage_ch1 > 0 || voltage_ch2 > 0); // NEU: Prüfe ob Note aktiv
_sequence[_stepCount].active = (voltage_ch1 > 0 || voltage_ch2 > 0);
_stepCount++;
_lastStepTime = now;
@@ -343,8 +336,6 @@ void SequencerBlock::addStep(uint16_t voltage_ch1, uint16_t voltage_ch2)
}
else
{
// Gleiche Spannung - Duration des aktuellen Steps aktualisieren
// WICHTIG: Bounds Check!
if(_stepCount > 0 && _stepCount <= _MAX_SEQUENCE_STEPS)
{
_sequence[_stepCount - 1].duration = now - _lastStepTime;
@@ -378,7 +369,6 @@ void SequencerBlock::update()
{
if(!_isPlaying || _stepCount == 0) return;
// WICHTIG: Bounds Check BEVOR wir auf Array zugreifen!
if(_currentStep >= _stepCount || _currentStep >= _MAX_SEQUENCE_STEPS)
{
Serial.println("\n\r[ERROR] Invalid step index in update()!");
@@ -389,7 +379,6 @@ void SequencerBlock::update()
unsigned long now = millis();
unsigned long elapsed = now - _stepStartTime;
// Sicherung gegen Division durch Null / Endlosschleife
if(_sequence[_currentStep].duration == 0)
{
_currentStep++;
@@ -409,12 +398,10 @@ void SequencerBlock::update()
return;
}
// Prüfen ob aktueller Schritt abgelaufen ist
if(elapsed >= _sequence[_currentStep].duration)
{
_currentStep++;
// Sequenz-Ende erreicht?
if(_currentStep >= _stepCount)
{
if(_loop)
@@ -447,7 +434,6 @@ void SequencerBlock::clear()
_lastVoltageCh1 = 0;
_lastVoltageCh2 = 0;
// Optional: Array löschen (kann je nach Use-Case weggelassen werden)
for(uint16_t i = 0; i < _MAX_SEQUENCE_STEPS; i++)
{
_sequence[i].voltage_ch1 = 0;
@@ -500,7 +486,7 @@ uint16_t SequencerBlock::getCurrentVoltageCh2()
uint16_t SequencerBlock::getTotalDuration()
{
uint32_t total = 0; // uint32 um Overflow zu vermeiden
uint32_t total = 0;
for(uint16_t i = 0; i < _stepCount && i < _MAX_SEQUENCE_STEPS; i++)
{
total += _sequence[i].duration;
@@ -519,7 +505,7 @@ bool SequencerBlock::isCurrentStepActive()
void SequencerBlock::_finishCurrentStep()
{
if(_stepCount == 0) return;
if(_stepCount > _MAX_SEQUENCE_STEPS) return; // Sicherheitsprüfung
if(_stepCount > _MAX_SEQUENCE_STEPS) return;
unsigned long now = millis();
uint16_t duration = now - _lastStepTime;