PicoWaveTracker/Persistence.cpp
2026-03-07 21:31:17 +01:00

220 lines
8.0 KiB
C++

#include "Persistence.h"
#include "SharedState.h"
#include "MidiDriver.h"
#include "UIManager.h"
#include "SequenceGenerator.h"
#include <EEPROM.h>
#include <Arduino.h>
void Persistence::saveSequence(bool quiet) {
midi.lock();
int addr = 0;
EEPROM.put(addr, EEPROM_MAGIC); addr += sizeof(EEPROM_MAGIC);
int channels[NUM_TRACKS];
for(int i=0; i<NUM_TRACKS; i++) channels[i] = midiChannels[i];
EEPROM.put(addr, channels); addr += sizeof(channels);
EEPROM.put(addr, melodySeeds); addr += sizeof(melodySeeds);
EEPROM.put(addr, currentStrategyIndices); addr += sizeof(currentStrategyIndices);
bool mutes[NUM_TRACKS];
for(int i=0; i<NUM_TRACKS; i++) mutes[i] = trackMute[i];
EEPROM.put(addr, mutes); addr += sizeof(mutes);
EEPROM.put(addr, (int)tempo); addr += sizeof(int);
int intensities[NUM_TRACKS];
for(int i=0; i<NUM_TRACKS; i++) intensities[i] = (int)trackIntensity[i];
EEPROM.put(addr, intensities); addr += sizeof(intensities);
int chances[NUM_TRACKS];
for(int i=0; i<NUM_TRACKS; i++) chances[i] = (int)trackChance[i];
EEPROM.put(addr, chances); addr += sizeof(chances);
int steps[NUM_TRACKS];
for(int i=0; i<NUM_TRACKS; i++) steps[i] = numSteps[i];
EEPROM.put(addr, steps); addr += sizeof(steps);
EEPROM.put(addr, globalRoot); addr += sizeof(globalRoot);
EEPROM.put(addr, currentProgression); addr += sizeof(currentProgression);
EEPROM.put(addr, progressionOrder); addr += sizeof(progressionOrder);
EEPROM.put(addr, currentScaleType); addr += sizeof(currentScaleType);
EEPROM.put(addr, numScaleNotes); addr += sizeof(numScaleNotes);
for (int i = 0; i<12; i++) {
EEPROM.put(addr, scaleNotes[i]); addr += sizeof(int);
}
EEPROM.put(addr, sequence); addr += sizeof(sequence);
midi.unlock();
EEPROM.commit();
if (!quiet) ui.showMessage("SAVED!");
}
bool Persistence::loadSequence() {
midi.lock();
int addr = 0;
uint32_t magic;
EEPROM.get(addr, magic); addr += sizeof(magic);
if (magic != EEPROM_MAGIC) {
midi.unlock();
return false;
}
int channels[NUM_TRACKS];
EEPROM.get(addr, channels); addr += sizeof(channels);
for(int i=0; i<NUM_TRACKS; i++) {
midiChannels[i] = channels[i];
if (midiChannels[i] < 1) midiChannels[i] = 1;
if (midiChannels[i] > 16) midiChannels[i] = 16;
}
EEPROM.get(addr, melodySeeds); addr += sizeof(melodySeeds);
EEPROM.get(addr, currentStrategyIndices); addr += sizeof(currentStrategyIndices);
for(int i=0; i<NUM_TRACKS; i++) {
if (currentStrategyIndices[i] < 0 || currentStrategyIndices[i] >= numStrategies) currentStrategyIndices[i] = 0;
}
bool mutes[NUM_TRACKS];
EEPROM.get(addr, mutes); addr += sizeof(mutes);
for(int i=0; i<NUM_TRACKS; i++) trackMute[i] = mutes[i];
int t;
EEPROM.get(addr, t); addr += sizeof(int);
tempo = t;
if (tempo < 40) tempo = 40;
if (tempo > 240) tempo = 240;
int intensities[NUM_TRACKS];
EEPROM.get(addr, intensities); addr += sizeof(intensities);
for(int i=0; i<NUM_TRACKS; i++) {
trackIntensity[i] = intensities[i];
if (trackIntensity[i] < 1) trackIntensity[i] = 1;
if (trackIntensity[i] > 10) trackIntensity[i] = 10;
}
int chances[NUM_TRACKS];
EEPROM.get(addr, chances); addr += sizeof(chances);
for(int i=0; i<NUM_TRACKS; i++) {
trackChance[i] = chances[i];
if (trackChance[i] < 0) trackChance[i] = 0;
if (trackChance[i] > 100) trackChance[i] = 100;
}
int steps[NUM_TRACKS];
EEPROM.get(addr, steps); addr += sizeof(steps);
for(int i=0; i<NUM_TRACKS; i++) {
numSteps[i] = steps[i];
if (numSteps[i] <= 0 || numSteps[i] > NUM_STEPS) {
numSteps[i] = NUM_STEPS;
}
}
EEPROM.get(addr, globalRoot); addr += sizeof(globalRoot);
currentRoot = globalRoot; // Sync
EEPROM.get(addr, currentProgression); addr += sizeof(currentProgression);
EEPROM.get(addr, progressionOrder); addr += sizeof(progressionOrder);
EEPROM.get(addr, currentScaleType); addr += sizeof(currentScaleType);
EEPROM.get(addr, numScaleNotes); addr += sizeof(numScaleNotes);
if (numScaleNotes < 0 || numScaleNotes > 12) numScaleNotes = 0;
for (int i = 0; i<12; i++) {
EEPROM.get(addr, scaleNotes[i]); addr += sizeof(int);
if (scaleNotes[i] < 0) scaleNotes[i] = 0;
if (scaleNotes[i] > 11) scaleNotes[i] = 11;
}
EEPROM.get(addr, sequence); addr += sizeof(sequence);
midi.unlock();
return true;
}
void Persistence::savePatch(int bank, int slot) {
int patchIndex = bank * 4 + slot;
int addr = 512 + patchIndex * 256; // Start after main save, 256 bytes per patch
midi.lock();
EEPROM.put(addr, currentRoot); addr += sizeof(currentRoot);
EEPROM.put(addr, currentScaleType); addr += sizeof(currentScaleType);
EEPROM.put(addr, numScaleNotes); addr += sizeof(numScaleNotes);
for (int i = 0; i < 12; i++) {
EEPROM.put(addr, scaleNotes[i]); addr += sizeof(int);
}
EEPROM.put(addr, currentStrategyIndices); addr += sizeof(currentStrategyIndices);
EEPROM.put(addr, melodySeeds); addr += sizeof(melodySeeds);
int steps[NUM_TRACKS];
for(int i=0; i<NUM_TRACKS; i++) steps[i] = numSteps[i];
EEPROM.put(addr, steps); addr += sizeof(steps);
bool mutes[NUM_TRACKS];
for(int i=0; i<NUM_TRACKS; i++) mutes[i] = trackMute[i];
EEPROM.put(addr, mutes); addr += sizeof(mutes);
int intensities[NUM_TRACKS];
for(int i=0; i<NUM_TRACKS; i++) intensities[i] = trackIntensity[i];
EEPROM.put(addr, intensities); addr += sizeof(intensities);
int chances[NUM_TRACKS];
for(int i=0; i<NUM_TRACKS; i++) chances[i] = trackChance[i];
EEPROM.put(addr, chances); addr += sizeof(chances);
midi.unlock();
EEPROM.commit();
ui.showMessage("SAVED!");
}
void Persistence::loadPatch(int bank, int slot, Step (*scratchBuffer)[NUM_STEPS]) {
int patchIndex = bank * 4 + slot;
int addr = 512 + patchIndex * 256;
midi.lock();
EEPROM.get(addr, currentRoot); addr += sizeof(currentRoot);
EEPROM.get(addr, currentScaleType); addr += sizeof(currentScaleType);
EEPROM.get(addr, numScaleNotes); addr += sizeof(numScaleNotes);
if (numScaleNotes < 0 || numScaleNotes > 12) numScaleNotes = 0;
for (int i = 0; i < 12; i++) {
EEPROM.get(addr, scaleNotes[i]); addr += sizeof(int);
if (scaleNotes[i] < 0) scaleNotes[i] = 0;
if (scaleNotes[i] > 11) scaleNotes[i] = 11;
}
EEPROM.get(addr, currentStrategyIndices); addr += sizeof(currentStrategyIndices);
for(int i=0; i<NUM_TRACKS; i++) {
if (currentStrategyIndices[i] < 0 || currentStrategyIndices[i] >= numStrategies) currentStrategyIndices[i] = 0;
}
EEPROM.get(addr, melodySeeds); addr += sizeof(melodySeeds);
int steps[NUM_TRACKS];
EEPROM.get(addr, steps); addr += sizeof(steps);
for(int i=0; i<NUM_TRACKS; i++) {
numSteps[i] = steps[i];
if (numSteps[i] <= 0 || numSteps[i] > NUM_STEPS) {
numSteps[i] = NUM_STEPS;
}
}
bool mutes[NUM_TRACKS];
EEPROM.get(addr, mutes); addr += sizeof(mutes);
for(int i=0; i<NUM_TRACKS; i++) trackMute[i] = mutes[i];
int intensities[NUM_TRACKS];
EEPROM.get(addr, intensities); addr += sizeof(intensities);
for(int i=0; i<NUM_TRACKS; i++) {
trackIntensity[i] = intensities[i];
if (trackIntensity[i] < 1) trackIntensity[i] = 1;
if (trackIntensity[i] > 10) trackIntensity[i] = 10;
}
int chances[NUM_TRACKS];
EEPROM.get(addr, chances); addr += sizeof(chances);
for(int i=0; i<NUM_TRACKS; i++) {
trackChance[i] = chances[i];
if (trackChance[i] < 0) trackChance[i] = 0;
if (trackChance[i] > 100) trackChance[i] = 100;
}
if (isPlaying) {
SequenceGenerator::generateSequenceData(currentThemeIndex, nextSequence);
sequenceChangeScheduled = true;
} else {
SequenceGenerator::generateSequenceData(currentThemeIndex, scratchBuffer);
memcpy(sequence, scratchBuffer, sizeof(sequence));
}
midi.unlock();
ui.showMessage("LOADED!");
}
void Persistence::factoryReset() {
ui.showMessage("RESETTING...");
for(int i=0; i<NUM_TRACKS; i++) {
trackIntensity[i] = 10;
trackChance[i] = 100;
}
uint32_t magic = 0;
EEPROM.put(0, magic);
EEPROM.commit();
delay(500);
rp2040.reboot();
}