Removing EEPROMAnything and using EEPROM.get()/EEPROM.put() from EEPROM.h instead.

Trying to fix storing/loading of EEPROM data.
pull/15/head
Holger Wirtz 5 years ago
parent 9d72cc2a3a
commit 76768533a4
  1. 53
      EEPROMAnything.h
  2. 156
      MicroDexed.ino
  3. 12
      config.h
  4. 24
      dexed.cpp
  5. 10
      source_microdexed.h

@ -1,53 +0,0 @@
/*
MicroDexed
MicroDexed is a port of the Dexed sound engine
(https://github.com/asb2m10/dexed) for the Teensy-3.5/3.6 with audio shield.
Dexed ist heavily based on https://github.com/google/music-synthesizer-for-android
(c)2018 H. Wirtz <wirtz@parasitstudio.de>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
// Idea from: https://playground.arduino.cc/Code/EEPROMWriteAnything/
#include <EEPROM.h>
#include <Arduino.h> // for type definitions
uint32_t crc32(uint8_t* calc_start, uint16_t calc_bytes);
template <class T> int EEPROM_writeAnything(int ee, const T& value)
{
uint8_t* p = (uint8_t*)(const void*)&value;
uint16_t i;
uint32_t checksum=crc32(p+4,sizeof(value)-4);
*p=checksum;
for (i = 0; i < sizeof(value); i++)
EEPROM.update(ee++, *p++);
return i;
}
template <class T> int EEPROM_readAnything(int ee, T& value)
{
uint8_t* p = (uint8_t*)(void*)&value;
unsigned int i;
for (i = 0; i < sizeof(value); i++)
*p++ = EEPROM.read(ee++);
return i;
}

@ -30,7 +30,6 @@
#include <SD.h>
#include <MIDI.h>
#include <EEPROM.h>
#include "EEPROMAnything.h"
#include "midi_devices.hpp"
#include "dexed.h"
#include "dexed_sysex.h"
@ -117,7 +116,11 @@ AudioOutputAnalogStereo dacOut;
AudioConnection patchCord32(stereomono1, 0, dacOut, 0);
AudioConnection patchCord33(stereomono1, 1, dacOut, 1);
#endif
#ifdef USE_REVERB
AudioConnection * dynamicConnections[NUM_DEXED * 6];
#else
AudioConnection * dynamicConnections[NUM_DEXED * 5];
#endif
int nDynamic = 0;
void create_audio_connections(AudioSourceMicroDexed &d)
@ -130,10 +133,6 @@ void create_audio_connections(AudioSourceMicroDexed &d)
#if defined(USE_REVERB)
dynamicConnections[nDynamic++] = new AudioConnection(d, 0, freeverbs1, 0);
#endif
for (int i = 0; i < nDynamic; i++) {
if (dynamicConnections[i] == NULL)
Serial.printf ("Bad connection %d\n", i);
}
}
bool sd_card_available = false;
@ -195,14 +194,14 @@ void setup()
pinMode(U8X8_CS_PIN, OUTPUT);
#endif
delay(320); // necessary, because before this time no serial output is done :(
#ifdef ENABLE_LCD_UI
setup_ui();
#else
Serial.println(F("NO LCD DISPLAY ENABLED!"));
#endif
delay(220); // necessary, because before this time no serial output is done :(
Serial.println(F("MicroDexed based on https://github.com/asb2m10/dexed"));
Serial.println(F("(c)2018,2019 H. Wirtz <wirtz@parasitstudio.de>"));
Serial.println(F("https://codeberg.org/dcoredump/MicroDexed"));
@ -214,14 +213,14 @@ void setup()
for (uint8_t i = 0; i < NUM_DEXED; i++)
{
AudioSourceMicroDexed* microdexed;
Serial.print(F("Creating MicroDexed instance "));
Serial.print(i, DEC);
microdexed = new AudioSourceMicroDexed(SAMPLE_RATE);
create_audio_connections(*microdexed);
MicroDexed[i] = microdexed;
Serial.flush();
MicroDexed[i] = new AudioSourceMicroDexed(SAMPLE_RATE);
//create_audio_connections(*MicroDexed[i]);
Serial.println(F("... created"));
Serial.flush();
}
// Init EEPROM if both buttons are pressed at startup
@ -236,7 +235,7 @@ void setup()
initial_values_from_eeprom(true);
}
else*/
initial_values_from_eeprom(true);
initial_values_from_eeprom(false);
#if defined(TEENSY_AUDIO_BOARD)
sgtl5000_1.enable();
@ -281,6 +280,7 @@ void setup()
#else
Serial.println(F("Internal DAC enabled."));
#endif
Serial.flush();
// start SD card
#ifndef TEENSY4
@ -326,6 +326,7 @@ void setup()
Serial.print(F("["));
Serial.print(voice_names[instance_id][n]);
Serial.println(F("]"));
Serial.flush();
}
#endif
@ -491,19 +492,14 @@ void loop()
}
#endif
// EEPROM update handling
if (autostore >= AUTOSTORE_MS && active_voices == 0 && eeprom_update_flag == true)
{
// only store configuration data to EEPROM when AUTOSTORE_MS is reached and no voices are activated anymore
eeprom_update();
}
// MIDI input handling
check_midi_devices();
// CONTROL-RATE-EVENT-HANDLING
if (control_rate > CONTROL_RATE_MS)
{
control_rate = 0;
#ifdef ENABLE_LCD_UI
// LCD Menu
LCDML.loop();
@ -515,7 +511,14 @@ void loop()
UI_func_voice_selection(0);
}
#endif
control_rate = 0;
// EEPROM update handling
//if (autostore >= AUTOSTORE_MS && active_voices == 0 && eeprom_update_flag == true)
if (autostore >= AUTOSTORE_MS && eeprom_update_flag == true)
{
// only store configuration data to EEPROM when AUTOSTORE_MS is reached and no voices are activated anymore
eeprom_update();
}
// check for value changes and unused voices
soften_volume.tick();
@ -1135,8 +1138,8 @@ void initial_values_from_eeprom(bool init)
init_configuration();
else
{
EEPROM_readAnything(EEPROM_START_ADDRESS, tmp_conf);
checksum = crc32((byte*)&tmp_conf + 4, sizeof(tmp_conf) - 4);
EEPROM.get(EEPROM_START_ADDRESS, tmp_conf);
checksum = crc32((uint32_t*)&tmp_conf + 4, sizeof(tmp_conf) - 4);
#ifdef DEBUG
Serial.print(F("EEPROM checksum: 0x"));
@ -1154,54 +1157,54 @@ void initial_values_from_eeprom(bool init)
}
else
{
/*
configuration.instances = INSTANCES_MAX;
configuration.instance_mode = INSTANCE_MODE_MAX;
configuration.instance_splitpoint = INSTANCE_SPLITPOINT_MAX;
configuration.vol = VOLUME_MAX;
configuration.mono = MONO_MAX;
configuration.reverb_roomsize = REVERB_ROOMSIZE_MAX;
configuration.reverb_damping = REVERB_DAMPING_MAX;
configuration.chorus_frequency = CHORUS_FREQUENCY_MAX;
configuration.chorus_waveform = CHORUS_WAVEFORM_MAX;
configuration.chorus_depth = CHORUS_DEPTH_MAX;
configuration.delay_time = DELAY_TIME_MAX;
configuration.delay_feedback = DELAY_FEEDBACK_MAX; */
EEPROM.get(EEPROM_START_ADDRESS, configuration);
configuration.instances %= INSTANCES_MAX;
configuration.instance_mode %= INSTANCE_MODE_MAX;
configuration.instance_splitpoint %= INSTANCE_SPLITPOINT_MAX;
configuration.vol %= VOLUME_MAX;
configuration.mono %= MONO_MAX;
configuration.reverb_roomsize %= REVERB_ROOMSIZE_MAX;
configuration.reverb_damping %= REVERB_DAMPING_MAX;
configuration.chorus_frequency %= CHORUS_FREQUENCY_MAX;
configuration.chorus_waveform %= CHORUS_WAVEFORM_MAX;
configuration.chorus_depth %= CHORUS_DEPTH_MAX;
configuration.delay_time %= DELAY_TIME_MAX;
configuration.delay_feedback %= DELAY_FEEDBACK_MAX;
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
{
/*
configuration.dexed[instance_id].midi_channel = MIDI_CHANNEL_MAX;
configuration.dexed[instance_id].bank = MAX_BANKS;
configuration.dexed[instance_id].voice = MAX_VOICES;
configuration.dexed[instance_id].pan = PANORAMA_MAX;
configuration.dexed[instance_id].reverb_level = REVERB_LEVEL_MAX;
configuration.dexed[instance_id].chorus_level = CHORUS_LEVEL_MAX;
configuration.dexed[instance_id].delay_level = DELAY_LEVEL_MAX;
configuration.dexed[instance_id].filter_cutoff = FILTER_CUTOFF_MAX;
configuration.dexed[instance_id].filter_resonance = FILTER_RESONANCE_MAX;
configuration.dexed[instance_id].loudness = LOUDNESS_MAX;
configuration.dexed[instance_id].polyphony = POLYPHONY_MAX;
configuration.dexed[instance_id].engine = ENGINE_MAX;
configuration.dexed[instance_id].monopoly = MONOPOLY_MAX;
configuration.dexed[instance_id].pb_range = PB_RANGE_MAX;
configuration.dexed[instance_id].pb_step = PB_STEP_MAX;
configuration.dexed[instance_id].mw_range = MW_RANGE_MAX;
configuration.dexed[instance_id].mw_assign = MW_ASSIGN_MAX;
configuration.dexed[instance_id].fc_range = FC_RANGE_MAX;
configuration.dexed[instance_id].fc_assign = FC_ASSIGN_MAX;
configuration.dexed[instance_id].bc_range = BC_RANGE_MAX;
configuration.dexed[instance_id].bc_assign = BC_ASSIGN_MAX;
configuration.dexed[instance_id].at_range = AT_RANGE_MAX;
configuration.dexed[instance_id].at_assign = AT_ASSIGN_MAX;
configuration.dexed[instance_id].op_enabled = 0x3f; */
configuration.dexed[instance_id].midi_channel %= MIDI_CHANNEL_MAX;
configuration.dexed[instance_id].bank %= MAX_BANKS;
configuration.dexed[instance_id].voice %= MAX_VOICES;
configuration.dexed[instance_id].pan %= PANORAMA_MAX;
configuration.dexed[instance_id].reverb_level %= REVERB_LEVEL_MAX;
configuration.dexed[instance_id].chorus_level %= CHORUS_LEVEL_MAX;
configuration.dexed[instance_id].delay_level %= DELAY_LEVEL_MAX;
configuration.dexed[instance_id].filter_cutoff %= FILTER_CUTOFF_MAX;
configuration.dexed[instance_id].filter_resonance %= FILTER_RESONANCE_MAX;
configuration.dexed[instance_id].loudness %= LOUDNESS_MAX;
configuration.dexed[instance_id].polyphony %= POLYPHONY_MAX;
configuration.dexed[instance_id].engine %= ENGINE_MAX;
configuration.dexed[instance_id].monopoly %= MONOPOLY_MAX;
configuration.dexed[instance_id].pb_range %= PB_RANGE_MAX;
configuration.dexed[instance_id].pb_step %= PB_STEP_MAX;
configuration.dexed[instance_id].mw_range %= MW_RANGE_MAX;
configuration.dexed[instance_id].mw_assign %= MW_ASSIGN_MAX;
configuration.dexed[instance_id].fc_range %= FC_RANGE_MAX;
configuration.dexed[instance_id].fc_assign %= FC_ASSIGN_MAX;
configuration.dexed[instance_id].bc_range %= BC_RANGE_MAX;
configuration.dexed[instance_id].bc_assign %= BC_ASSIGN_MAX;
configuration.dexed[instance_id].at_range %= AT_RANGE_MAX;
configuration.dexed[instance_id].at_assign %= AT_ASSIGN_MAX;
configuration.dexed[instance_id].op_enabled %= 0x3f;
MicroDexed[instance_id]->setPBController(configuration.dexed[instance_id].pb_range, configuration.dexed[instance_id].pb_step);
MicroDexed[instance_id]->setMWController(configuration.dexed[instance_id].mw_range, configuration.dexed[instance_id].mw_assign);
MicroDexed[instance_id]->setFCController(configuration.dexed[instance_id].fc_range, configuration.dexed[instance_id].fc_assign);
MicroDexed[instance_id]->setBCController(configuration.dexed[instance_id].bc_range, configuration.dexed[instance_id].bc_assign);
MicroDexed[instance_id]->setATController(configuration.dexed[instance_id].at_range, configuration.dexed[instance_id].at_assign);
MicroDexed[instance_id]-> setOPs(configuration.dexed[instance_id].op_enabled);
MicroDexed[instance_id]->setOPs(configuration.dexed[instance_id].op_enabled);
MicroDexed[instance_id]->doRefreshVoice();
}
Serial.println(F("OK, loaded!"));
}
@ -1217,8 +1220,11 @@ void initial_values_from_eeprom(bool init)
void init_configuration(void)
{
configuration.checksum = 0xffff;
#ifdef DEBUG
Serial.print(F("Initializing configuration"));
#endif
configuration.checksum = 0xffff;
configuration.instances = INSTANCES_DEFAULT;
configuration.instance_mode = INSTANCE_MODE_DEFAULT;
configuration.instance_splitpoint = INSTANCE_SPLITPOINT_DEFAULT;
@ -1258,6 +1264,7 @@ void init_configuration(void)
configuration.dexed[instance_id].at_assign = AT_ASSIGN_DEFAULT;
configuration.dexed[instance_id].op_enabled = OP_ENABLED_DEFAULT;
}
eeprom_update();
}
void eeprom_write(void)
@ -1269,16 +1276,14 @@ void eeprom_write(void)
void eeprom_update(void)
{
eeprom_update_flag = false;
configuration.checksum = crc32((byte*)&configuration + 4, sizeof(configuration) - 4);
EEPROM_writeAnything(EEPROM_START_ADDRESS, configuration);
Serial.println(F("Updating EEPROM with configuration data:"));
#ifdef DEBUG
show_configuration();
#endif
configuration.checksum = crc32((uint32_t*)&configuration + 4, sizeof(configuration) - 4);
EEPROM.put(EEPROM_START_ADDRESS, configuration);
Serial.println(F("Updating EEPROM"));
}
uint32_t crc32(byte * calc_start, uint16_t calc_bytes) // base code from https://www.arduino.cc/en/Tutorial/EEPROMCrc
uint32_t crc32(uint32_t* calc_start, uint16_t calc_bytes) // base code from https://www.arduino.cc/en/Tutorial/EEPROMCrc
{
uint32_t* index;
const uint32_t crc_table[16] =
{
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
@ -1288,7 +1293,7 @@ uint32_t crc32(byte * calc_start, uint16_t calc_bytes) // base code from https:/
};
uint32_t crc = ~0L;
for (byte* index = calc_start ; index < (calc_start + calc_bytes) ; ++index)
for (index = calc_start ; index < (calc_start + calc_bytes) ; ++index)
{
crc = crc_table[(crc ^ *index) & 0x0f] ^ (crc >> 4);
crc = crc_table[(crc ^ (*index >> 4)) & 0x0f] ^ (crc >> 4);
@ -1337,6 +1342,7 @@ void show_cpu_and_mem_usage(void)
Serial.print(F(" ACTIVE_VOICES: "));
Serial.print(active_voices, DEC);
Serial.println();
Serial.flush();
AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset();
}
@ -1360,6 +1366,7 @@ void show_configuration(void)
Serial.print(F("Chorus Depth ")); Serial.println(configuration.chorus_depth, DEC);
Serial.print(F("Delay Time ")); Serial.println(configuration.delay_time, DEC);
Serial.print(F("Delay Feedback ")); Serial.println(configuration.delay_feedback, DEC);
Serial.flush();
for (uint8_t instance_id = 0; instance_id < NUM_DEXED; instance_id++)
{
Serial.print(F("=== DEXED INSTANCE "));
@ -1389,6 +1396,7 @@ void show_configuration(void)
Serial.print(F(" Aftertouch Range ")); Serial.println(configuration.dexed[instance_id].at_range, DEC);
Serial.print(F(" Aftertouch Assign ")); Serial.println(configuration.dexed[instance_id].at_assign, DEC);
Serial.print(F(" OP Enabled ")); Serial.println(configuration.dexed[instance_id].op_enabled, DEC);
Serial.flush();
}
Serial.println();
}
@ -1450,6 +1458,7 @@ void show_patch(uint8_t instance_id)
Serial.print(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_FREQ_FINE], DEC);
Serial.print(F(" "));
Serial.println(MicroDexed[instance_id]->data[(i * 21) + DEXED_OP_OSC_DETUNE], DEC);
Serial.flush();
}
Serial.println(F("PR1 | PR2 | PR3 | PR4 | PL1 | PL2 | PL3 | PL4"));
Serial.print(F(" "));
@ -1457,6 +1466,7 @@ void show_patch(uint8_t instance_id)
{
Serial.print(MicroDexed[instance_id]->data[DEXED_VOICE_OFFSET + i], DEC);
Serial.print(F(" "));
Serial.flush();
}
Serial.println();
Serial.print(F("ALG: "));
@ -1486,11 +1496,13 @@ void show_patch(uint8_t instance_id)
Serial.print(F("["));
Serial.print(voicename);
Serial.println(F("]"));
Serial.flush();
for (i = DEXED_GLOBAL_PARAMETER_OFFSET; i <= DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MAX_NOTES; i++)
{
Serial.print(i, DEC);
Serial.print(F(": "));
Serial.println(MicroDexed[instance_id]->data[i]);
Serial.flush();
}
Serial.println();

@ -200,7 +200,7 @@
#define VOICE_SELECTION_MS 2000
// EEPROM address
#define EEPROM_START_ADDRESS 0
#define EEPROM_START_ADDRESS 100
#define MAX_BANKS 100
#define MAX_VOICES 32 // voices per bank
@ -413,7 +413,7 @@ enum { DEXED, REVERB, DELAY, CHORUS };
#define INSTANCE_SPLITPOINT_DEFAULT MIDI_C3
//
struct dexed_t {
typedef struct {
uint8_t midi_channel;
uint8_t bank;
uint8_t voice;
@ -438,10 +438,10 @@ struct dexed_t {
uint8_t at_range;
uint8_t at_assign;
uint8_t op_enabled;
};
} dexed_t;
// struct for holding the current configuration
struct config_t {
typedef struct {
uint32_t checksum;
uint8_t instances;
uint8_t instance_mode;
@ -455,8 +455,8 @@ struct config_t {
uint8_t chorus_depth;
uint8_t delay_time;
uint8_t delay_feedback;
struct dexed_t dexed[NUM_DEXED];
};
dexed_t dexed[NUM_DEXED];
} config_t;
inline float mapfloat(float val, float in_min, float in_max, float out_min, float out_max)
{

@ -172,12 +172,12 @@ void Dexed::getSamples(uint16_t n_samples, int16_t* buffer)
fx.process(sumbuf, n_samples);
//#ifdef USE_TEENSY_DSP
//#ifdef USE_TEENSY_DSP
//arm_float_to_q15(sumbuf, buffer, AUDIO_BLOCK_SAMPLES);
//#else
//#else
for (i = 0; i < n_samples; ++i)
buffer[i] = static_cast<int16_t>(sumbuf[i] * 0x7fff);
//#endif
//#endif
}
void Dexed::keydown(uint8_t pitch, uint8_t velo) {
@ -608,12 +608,14 @@ void Dexed::setPBController(uint8_t pb_range, uint8_t pb_step)
pb_range %= PB_RANGE_MAX;
pb_step %= PB_STEP_MAX;
#ifdef DEBUG
/*
#ifdef DEBUG
Serial.print(F("pb_range="));
Serial.println(pb_range, DEC);
Serial.print(F("pb_step="));
Serial.println(pb_step, DEC);
#endif
#endif
*/
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE] = pb_range;
controllers.values_[kControllerPitchRange] = pb_range;
@ -632,12 +634,14 @@ void Dexed::setMWController(uint8_t mw_range, uint8_t mw_assign)
mw_range %= MW_RANGE_MAX;
mw_assign %= MW_ASSIGN_MAX;
#ifdef DEBUG
/*
#ifdef DEBUG
Serial.print(F("mw_range="));
Serial.println(mw_range, DEC);
Serial.print(F("mw_assign="));
Serial.println(mw_assign, DEC);
#endif
#endif
*/
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE] = mw_range;
controllers.wheel.setRange(mw_range);
@ -656,12 +660,14 @@ void Dexed::setFCController(uint8_t fc_range, uint8_t fc_assign)
fc_range %= FC_RANGE_MAX;
fc_assign %= FC_ASSIGN_MAX;
/*
#ifdef DEBUG
Serial.print(F("fc_range="));
Serial.println(fc_range, DEC);
Serial.print(F("fc_assign="));
Serial.println(fc_assign, DEC);
#endif
*/
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE] = fc_range;
controllers.foot.setRange(fc_range);
@ -680,12 +686,14 @@ void Dexed::setBCController(uint8_t bc_range, uint8_t bc_assign)
bc_range %= BC_RANGE_MAX;
bc_assign %= BC_ASSIGN_MAX;
/*
#ifdef DEBUG
Serial.print(F("bc_range="));
Serial.println(bc_range, DEC);
Serial.print(F("bc_assign="));
Serial.println(bc_assign, DEC);
#endif
*/
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE] = bc_range;
controllers.breath.setRange(bc_range);
@ -704,12 +712,14 @@ void Dexed::setATController(uint8_t at_range, uint8_t at_assign)
at_range %= AT_RANGE_MAX;
at_assign %= AT_ASSIGN_MAX;
/*
#ifdef DEBUG
Serial.print(F("at_range="));
Serial.println(at_range, DEC);
Serial.print(F("at_assign="));
Serial.println(at_assign, DEC);
#endif
*/
data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE] = at_range;
controllers.at.setRange(at_range);

@ -9,8 +9,7 @@ class AudioSourceMicroDexed : public AudioStream, public Dexed {
const uint16_t audio_block_time_us = 1000000 / (SAMPLE_RATE / AUDIO_BLOCK_SAMPLES);
uint32_t xrun = 0;
uint16_t render_time_max = 0;
AudioSourceMicroDexed(int sample_rate) : AudioStream(0, NULL), Dexed(sample_rate) {
};
AudioSourceMicroDexed(int sample_rate) : AudioStream(0, NULL), Dexed(sample_rate) { };
void update(void) {
if (in_update) {
xrun++;
@ -24,17 +23,16 @@ class AudioSourceMicroDexed : public AudioStream, public Dexed {
if (!lblock) {
in_update = false;
return;
}
getSamples(AUDIO_BLOCK_SAMPLES, lblock->data);
if (render_time > audio_block_time_us) // everything greater 2.9ms is a buffer underrun!
xrun++;
if (render_time > audio_block_time_us - (audio_block_time_us / 10)) {
/* if (render_time > audio_block_time_us - (audio_block_time_us / 10)) {
Serial.println("At CPU Limit");
uint8_t nnotes = getNumNotesPlaying();
//setMaxNotes(nnotes);
max_notes = nnotes;
}
} */
if (render_time > render_time_max)
render_time_max = render_time;
@ -43,6 +41,6 @@ class AudioSourceMicroDexed : public AudioStream, public Dexed {
release(lblock);
in_update = false;
};
private:
private:
volatile bool in_update = false;
};

Loading…
Cancel
Save