Refactor code structure for improved readability and maintainability, imporved matrix read, improved SB button read

This commit is contained in:
2025-12-06 09:03:02 +01:00
parent 60950e6a0c
commit 06fa584b6d
6 changed files with 211 additions and 91 deletions

View File

@@ -3,7 +3,8 @@
@author: Erik Tóth
@contact: etoth@tsn.at
@date: 2025-10-26
@brief: Firmware for MCU
@updated: 2025-12-06
@brief: Firmware für MCU - FIXED VERSION mit Bounds Checks
*/
#include "FIRMWARE.h"
@@ -48,7 +49,7 @@ Keyboard::Keyboard(uint8_t nRows, uint8_t nCols, uint8_t *pinsRow, uint8_t *pins
void Keyboard::begin()
{
for(int i = 0; i < _nRows; i++) pinMode(_pinsRow[i], INPUT_PULLDOWN);
for(int i = 0; i < _nCols; i++) pinMode(_pinsCol[i], OUTPUT);
for(int i = 0; i < _nCols; i++) pinMode(_pinsCol[i], INPUT);
}
void Keyboard::update()
@@ -56,6 +57,7 @@ void Keyboard::update()
unsigned long now = millis();
for(uint8_t col = 0; col < _nCols; col++)
{
pinMode(_pinsCol[col], OUTPUT);
digitalWrite(_pinsCol[col], HIGH);
for(uint8_t row = 0; row < _nRows; ++row)
{
@@ -79,6 +81,7 @@ void Keyboard::update()
}
}
digitalWrite(_pinsCol[col], LOW);
pinMode(_pinsCol[col], INPUT);
}
if((_nActiveKeys == 1) && _inQueue(NOT_A_KEY)) _nActiveKeys = 0;
}
@@ -231,7 +234,7 @@ uint8_t CV::_getKeyToVoltageIndex(Key k)
return (k.row*_col + k.col);
}
// ==================== SequencerBlock ====================
// ==================== SequencerBlock (FIXED) ====================
/*!
* @param maxDurationMS maximum loop duration of recording in milliseconds
@@ -252,6 +255,7 @@ SequencerBlock::SequencerBlock(uint16_t maxDurationMS, uint16_t maxStepCount)
_lastStepTime = 0;
_playStartTime = 0;
_stepStartTime = 0;
_lastAddStepTime = 0; // NEU: Rate-Limiting
}
void SequencerBlock::startRecord()
@@ -262,7 +266,8 @@ void SequencerBlock::startRecord()
_isRecording = true;
_recordStartTime = millis();
_lastStepTime = _recordStartTime;
_lastVoltageCh1 = 0xFFFF; // Ungültiger Wert zum Triggern des ersten Steps
_lastAddStepTime = _recordStartTime; // NEU
_lastVoltageCh1 = 0xFFFF;
_lastVoltageCh2 = 0xFFFF;
}
@@ -276,28 +281,54 @@ 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.");
stopRecord();
return;
}
if(timeLimitReached())
{
Serial.println("\n\r[WARNING] Time limit reached! Stopping recording.");
stopRecord();
return;
}
unsigned long now = millis();
// NEU: Rate-Limiting - ignoriere zu häufige Aufrufe
if((now - _lastAddStepTime) < 5) // Mindestens 5ms zwischen Updates
{
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.");
stopRecord();
return;
}
// Vorherigen Step abschließen (wenn vorhanden)
if(_stepCount > 0)
if(_stepCount > 0 && _stepCount <= _MAX_SEQUENCE_STEPS)
{
_finishCurrentStep();
}
// Neuen Step beginnen
if(_canAddStep())
// Neuen Step beginnen - mit Bounds Check!
if(_stepCount < _MAX_SEQUENCE_STEPS)
{
_sequence[_stepCount].voltage_ch1 = voltage_ch1;
_sequence[_stepCount].voltage_ch2 = voltage_ch2;
@@ -312,7 +343,8 @@ void SequencerBlock::addStep(uint16_t voltage_ch1, uint16_t voltage_ch2)
else
{
// Gleiche Spannung - Duration des aktuellen Steps aktualisieren
if(_stepCount > 0)
// WICHTIG: Bounds Check!
if(_stepCount > 0 && _stepCount <= _MAX_SEQUENCE_STEPS)
{
_sequence[_stepCount - 1].duration = now - _lastStepTime;
}
@@ -345,9 +377,37 @@ 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()!");
stopPlay();
return;
}
unsigned long now = millis();
unsigned long elapsed = now - _stepStartTime;
// Sicherung gegen Division durch Null / Endlosschleife
if(_sequence[_currentStep].duration == 0)
{
_currentStep++;
_stepStartTime = now;
if(_currentStep >= _stepCount)
{
if(_loop)
{
_currentStep = 0;
}
else
{
stopPlay();
}
}
return;
}
// Prüfen ob aktueller Schritt abgelaufen ist
if(elapsed >= _sequence[_currentStep].duration)
{
@@ -386,7 +446,8 @@ void SequencerBlock::clear()
_lastVoltageCh1 = 0;
_lastVoltageCh2 = 0;
for(uint8_t i = 0; i < _MAX_SEQUENCE_STEPS; i++)
// 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;
_sequence[i].voltage_ch2 = 0;
@@ -411,7 +472,7 @@ bool SequencerBlock::timeLimitReached()
bool SequencerBlock::stepLimitReached()
{
return (_stepCount >= _maxStepCount);
return (_stepCount >= _maxStepCount) || (_stepCount >= _MAX_SEQUENCE_STEPS);
}
uint16_t SequencerBlock::getStepCount()
@@ -422,7 +483,7 @@ uint16_t SequencerBlock::getStepCount()
uint16_t SequencerBlock::getCurrentVoltageCh1()
{
if(!_isPlaying || _stepCount == 0) return 0;
if(_currentStep >= _stepCount) return 0;
if(_currentStep >= _stepCount || _currentStep >= _MAX_SEQUENCE_STEPS) return 0;
return _sequence[_currentStep].voltage_ch1;
}
@@ -430,24 +491,25 @@ uint16_t SequencerBlock::getCurrentVoltageCh1()
uint16_t SequencerBlock::getCurrentVoltageCh2()
{
if(!_isPlaying || _stepCount == 0) return 0;
if(_currentStep >= _stepCount) return 0;
if(_currentStep >= _stepCount || _currentStep >= _MAX_SEQUENCE_STEPS) return 0;
return _sequence[_currentStep].voltage_ch2;
}
uint16_t SequencerBlock::getTotalDuration()
{
uint16_t total = 0;
for(uint8_t i = 0; i < _stepCount; i++)
uint32_t total = 0; // uint32 um Overflow zu vermeiden
for(uint16_t i = 0; i < _stepCount && i < _MAX_SEQUENCE_STEPS; i++)
{
total += _sequence[i].duration;
}
return total;
return (total > 65535) ? 65535 : (uint16_t)total; // Clamp auf uint16
}
void SequencerBlock::_finishCurrentStep()
{
if(_stepCount == 0) return;
if(_stepCount > _MAX_SEQUENCE_STEPS) return; // Sicherheitsprüfung
unsigned long now = millis();
uint16_t duration = now - _lastStepTime;