Added a configuration struct for holding parameters which should be

stored in EEPROM. So I dropped most old EEPROM code.
Also added storing to EEPROM only when AUTOSTORE_MS is reached and no
voices are active.
pull/4/head
Holger Wirtz 6 years ago
parent 0ebc87a157
commit 1b965c0975
  1. 53
      EEPROMAnything.h
  2. 224
      MicroDexed.ino
  3. 76
      UI.cpp
  4. 8
      UI.h
  5. 26
      config.h

@ -0,0 +1,53 @@
/*
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;
}

@ -29,6 +29,7 @@
#include <SD.h> #include <SD.h>
#include <MIDI.h> #include <MIDI.h>
#include <EEPROM.h> #include <EEPROM.h>
#include "EEPROMAnything.h"
#include "midi_devices.hpp" #include "midi_devices.hpp"
#include <limits.h> #include <limits.h>
#include "dexed.h" #include "dexed.h"
@ -94,16 +95,11 @@ AudioConnection patchCord15(volume_l, 0, pt8211_1, 1);
Dexed* dexed = new Dexed(SAMPLE_RATE); Dexed* dexed = new Dexed(SAMPLE_RATE);
bool sd_card_available = false; bool sd_card_available = false;
uint8_t midi_channel = DEFAULT_MIDI_CHANNEL;
uint32_t xrun = 0; uint32_t xrun = 0;
uint32_t overload = 0; uint32_t overload = 0;
uint32_t peak = 0; uint32_t peak = 0;
uint16_t render_time_max = 0; uint16_t render_time_max = 0;
uint8_t bank = 0;
uint8_t max_loaded_banks = 0; uint8_t max_loaded_banks = 0;
uint8_t voice = 0;
float vol = VOLUME;
float pan = 0.5f;
char bank_name[BANK_NAME_LEN]; char bank_name[BANK_NAME_LEN];
char voice_name[VOICE_NAME_LEN]; char voice_name[VOICE_NAME_LEN];
char bank_names[MAX_BANKS][BANK_NAME_LEN]; char bank_names[MAX_BANKS][BANK_NAME_LEN];
@ -125,16 +121,10 @@ bool effect_delay_sync = 0;
elapsedMicros fill_audio_buffer; elapsedMicros fill_audio_buffer;
elapsedMillis control_rate; elapsedMillis control_rate;
uint8_t active_voices = 0; uint8_t active_voices = 0;
#ifdef SHOW_CPU_LOAD_MSEC #ifdef SHOW_CPU_LOAD_MSEC
elapsedMillis cpu_mem_millis; elapsedMillis cpu_mem_millis;
#endif #endif
config_t configuration = {0xffff, 0, 0, VOLUME, 0.5f, DEFAULT_MIDI_CHANNEL};
#ifdef TEST_NOTE
IntervalTimer sched_note_on;
IntervalTimer sched_note_off;
uint8_t _voice_counter = 0;
#endif
void setup() void setup()
{ {
@ -194,7 +184,7 @@ void setup()
Serial.println(F("PT8211 enabled.")); Serial.println(F("PT8211 enabled."));
#endif #endif
set_volume(vol, pan); set_volume(configuration.vol, configuration.pan);
// start SD card // start SD card
SPI.setMOSI(SDCARD_MOSI_PIN); SPI.setMOSI(SDCARD_MOSI_PIN);
@ -212,13 +202,13 @@ void setup()
// read all bank names // read all bank names
max_loaded_banks = get_bank_names(); max_loaded_banks = get_bank_names();
strip_extension(bank_names[bank], bank_name); strip_extension(bank_names[configuration.bank], bank_name);
// read all voice name for actual bank // read all voice name for actual bank
get_voice_names_from_bank(bank); get_voice_names_from_bank(configuration.bank);
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Bank [")); Serial.print(F("Bank ["));
Serial.print(bank_names[bank]); Serial.print(bank_names[configuration.bank]);
Serial.print(F("/")); Serial.print(F("/"));
Serial.print(bank_name); Serial.print(bank_name);
Serial.println(F("]")); Serial.println(F("]"));
@ -251,13 +241,13 @@ void setup()
mixer2.gain(2, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // only delayed signal (without feedback) mixer2.gain(2, mapfloat(effect_delay_volume, 0, ENC_DELAY_VOLUME_STEPS, 0.0, 1.0)); // only delayed signal (without feedback)
// load default SYSEX data // load default SYSEX data
load_sysex(bank, voice); load_sysex(configuration.bank, configuration.voice);
} }
#ifdef I2C_DISPLAY #ifdef I2C_DISPLAY
enc[0].write(map(vol * 100, 0, 100, 0, ENC_VOL_STEPS)); enc[0].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[0] = enc[0].read(); enc_val[0] = enc[0].read();
enc[1].write(voice); enc[1].write(configuration.voice);
enc_val[1] = enc[1].read(); enc_val[1] = enc[1].read();
but[0].update(); but[0].update();
but[1].update(); but[1].update();
@ -271,9 +261,9 @@ void setup()
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Bank/Voice from EEPROM [")); Serial.print(F("Bank/Voice from EEPROM ["));
Serial.print(EEPROM.read(EEPROM_OFFSET + EEPROM_BANK_ADDR), DEC); Serial.print(configuration.bank, DEC);
Serial.print(F("/")); Serial.print(F("/"));
Serial.print(EEPROM.read(EEPROM_OFFSET + EEPROM_VOICE_ADDR), DEC); Serial.print(configuration.voice, DEC);
Serial.println(F("]")); Serial.println(F("]"));
show_patch(); show_patch();
#endif #endif
@ -322,15 +312,15 @@ void loop()
} }
#ifndef TEENSY_AUDIO_BOARD #ifndef TEENSY_AUDIO_BOARD
for (uint8_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++) for (uint8_t i = 0; i < AUDIO_BLOCK_SAMPLES; i++)
audio_buffer[i] *= vol; audio_buffer[i] *= configuration.vol;
#endif #endif
queue1.playBuffer(); queue1.playBuffer();
} }
// EEPROM update handling // EEPROM update handling
if (eeprom_update_status > 0 && autostore >= autostore_value) if (autostore >= AUTOSTORE_MS && active_voices == 0)
{ {
autostore = 0; // only store configuration data to EEPROM when AUTOSTORE_MS is reached and no voices are activated anymore
eeprom_update(); eeprom_update();
} }
@ -397,7 +387,7 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
case 0: case 0:
if (inValue < MAX_BANKS) if (inValue < MAX_BANKS)
{ {
bank = inValue; configuration.bank = inValue;
handle_ui(); handle_ui();
} }
break; break;
@ -414,15 +404,15 @@ void handleControlChange(byte inChannel, byte inCtrl, byte inValue)
dexed->controllers.refresh(); dexed->controllers.refresh();
break; break;
case 7: // Volume case 7: // Volume
vol = float(inValue) / 0x7f; configuration.vol = float(inValue) / 0x7f;
set_volume(vol, pan); set_volume(configuration.vol, configuration.pan);
break; break;
case 10: // Pan case 10: // Pan
pan = float(inValue) / 128; configuration.pan = float(inValue) / 128;
set_volume(vol, pan); set_volume(configuration.vol, configuration.pan);
break; break;
case 32: // BankSelect LSB case 32: // BankSelect LSB
bank = inValue; configuration.bank = inValue;
break; break;
case 64: case 64:
dexed->setSustain(inValue > 63); dexed->setSustain(inValue > 63);
@ -511,12 +501,12 @@ void handleProgramChange(byte inChannel, byte inProgram)
{ {
if (inProgram < MAX_VOICES) if (inProgram < MAX_VOICES)
{ {
load_sysex(bank, inProgram); load_sysex(configuration.bank, inProgram);
handle_ui(); handle_ui();
} }
} }
void handleSystemExclusive(byte *sysex, uint len) void handleSystemExclusive(byte * sysex, uint len)
{ {
/* /*
SYSEX MESSAGE: Parameter Change SYSEX MESSAGE: Parameter Change
@ -705,23 +695,23 @@ void handleSystemReset(void)
} }
/****************************************************************************** /******************************************************************************
END OF MIDI MESSAGE HANDLER MIDI HELPER
******************************************************************************/ ******************************************************************************/
bool checkMidiChannel(byte inChannel) bool checkMidiChannel(byte inChannel)
{ {
// check for MIDI channel // check for MIDI channel
if (midi_channel == MIDI_CHANNEL_OMNI) if (configuration.midi_channel == MIDI_CHANNEL_OMNI)
{ {
return (true); return (true);
} }
else if (inChannel != midi_channel) else if (inChannel != configuration.midi_channel)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("Ignoring MIDI data on channel ")); Serial.print(F("Ignoring MIDI data on channel "));
Serial.print(inChannel); Serial.print(inChannel);
Serial.print(F("(listening on ")); Serial.print(F("(listening on "));
Serial.print(midi_channel); Serial.print(configuration.midi_channel);
Serial.println(F(")")); Serial.println(F(")"));
#endif #endif
return (false); return (false);
@ -729,30 +719,27 @@ bool checkMidiChannel(byte inChannel)
return (true); return (true);
} }
/******************************************************************************
VOLUME HELPER
******************************************************************************/
void set_volume(float v, float p) void set_volume(float v, float p)
{ {
vol = v; configuration.vol = v;
pan = p; configuration.pan = p;
#ifdef DEBUG #ifdef DEBUG
uint8_t tmp;
Serial.print(F("Setting volume: VOL=")); Serial.print(F("Setting volume: VOL="));
Serial.print(v, DEC); Serial.print(v, DEC);
Serial.print(F("[")); Serial.print(F("["));
tmp = EEPROM.read(EEPROM_OFFSET + EEPROM_MASTER_VOLUME_ADDR); Serial.print(configuration.vol, DEC);
Serial.print(tmp, DEC);
Serial.print(F("/"));
Serial.print(float(tmp) / UCHAR_MAX, DEC);
Serial.print(F("] PAN=")); Serial.print(F("] PAN="));
Serial.print(F("[")); Serial.print(F("["));
tmp = EEPROM.read(EEPROM_OFFSET + EEPROM_PAN_ADDR); Serial.print(configuration.pan, DEC);
Serial.print(tmp, DEC);
Serial.print(F("/"));
Serial.print(float(tmp) / SCHAR_MAX, DEC);
Serial.print(F("] ")); Serial.print(F("] "));
Serial.print(pow(v * sinf(p * PI / 2), VOLUME_CURVE), 3); Serial.print(pow(configuration.vol * sinf(configuration.pan * PI / 2), VOLUME_CURVE), 3);
Serial.print(F("/")); Serial.print(F("/"));
Serial.println(pow(v * cosf(p * PI / 2), VOLUME_CURVE), 3); Serial.println(pow(configuration.vol * cosf( configuration.pan * PI / 2), VOLUME_CURVE), 3);
#endif #endif
// http://files.csound-tutorial.net/floss_manual/Release03/Cs_FM_03_ScrapBook/b-panning-and-spatialization.html // http://files.csound-tutorial.net/floss_manual/Release03/Cs_FM_03_ScrapBook/b-panning-and-spatialization.html
@ -771,58 +758,49 @@ inline float logvol(float x)
return (0.001 * expf(6.908 * x)); return (0.001 * expf(6.908 * x));
} }
/******************************************************************************
EEPROM HELPER
******************************************************************************/
void initial_values_from_eeprom(void) void initial_values_from_eeprom(void)
{ {
uint32_t crc_eeprom = read_eeprom_checksum(); uint32_t checksum;
uint32_t crc = eeprom_crc32(EEPROM_OFFSET, EEPROM_DATA_LENGTH);
EEPROM_readAnything(EEPROM_START_ADDRESS, configuration);
checksum = crc32((byte*)&configuration + 4, sizeof(configuration) - 4);
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("EEPROM checksum: 0x")); Serial.print(F("EEPROM checksum: 0x"));
Serial.print(crc_eeprom, HEX); Serial.print(configuration.checksum, HEX);
Serial.print(F(" / 0x")); Serial.print(F(" / 0x"));
Serial.print(crc, HEX); Serial.print(checksum, HEX);
#endif #endif
if (crc_eeprom != crc)
if (checksum != configuration.checksum)
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.print(F(" - mismatch -> initializing EEPROM!")); Serial.print(F(" - mismatch -> initializing EEPROM!"));
#endif #endif
eeprom_write(EEPROM_UPDATE_BANK + EEPROM_UPDATE_VOICE + EEPROM_UPDATE_VOL + EEPROM_UPDATE_PAN + EEPROM_UPDATE_MIDICHANNEL); eeprom_update();
}
else
{
bank = EEPROM.read(EEPROM_OFFSET + EEPROM_BANK_ADDR);
voice = EEPROM.read(EEPROM_OFFSET + EEPROM_VOICE_ADDR);
vol = float(EEPROM.read(EEPROM_OFFSET + EEPROM_MASTER_VOLUME_ADDR)) / UCHAR_MAX;
pan = float(EEPROM.read(EEPROM_OFFSET + EEPROM_PAN_ADDR)) / SCHAR_MAX;
midi_channel = EEPROM.read(EEPROM_OFFSET + EEPROM_MIDICHANNEL_ADDR);
if (midi_channel > 16)
midi_channel = MIDI_CHANNEL_OMNI;
} }
#ifdef DEBUG #ifdef DEBUG
Serial.println(); Serial.println();
#endif #endif
} }
uint32_t read_eeprom_checksum(void) void eeprom_write(void)
{
return (EEPROM.read(EEPROM_CRC32_ADDR) << 24 | EEPROM.read(EEPROM_CRC32_ADDR + 1) << 16 | EEPROM.read(EEPROM_CRC32_ADDR + 2) << 8 | EEPROM.read(EEPROM_CRC32_ADDR + 3));
}
void update_eeprom_checksum(void)
{ {
write_eeprom_checksum(eeprom_crc32(EEPROM_OFFSET, EEPROM_DATA_LENGTH)); // recalculate crc and write to eeprom autostore = 0;
} }
void write_eeprom_checksum(uint32_t crc) void eeprom_update(void)
{ {
EEPROM.update(EEPROM_CRC32_ADDR, (crc & 0xff000000) >> 24); autostore = 0;
EEPROM.update(EEPROM_CRC32_ADDR + 1, (crc & 0x00ff0000) >> 16); EEPROM_writeAnything(EEPROM_START_ADDRESS, configuration);
EEPROM.update(EEPROM_CRC32_ADDR + 2, (crc & 0x0000ff00) >> 8);
EEPROM.update(EEPROM_CRC32_ADDR + 3, crc & 0x000000ff);
} }
uint32_t eeprom_crc32(uint16_t calc_start, uint16_t calc_bytes) // base code from https://www.arduino.cc/en/Tutorial/EEPROMCrc uint32_t crc32(byte * calc_start, uint16_t calc_bytes) // base code from https://www.arduino.cc/en/Tutorial/EEPROMCrc
{ {
const uint32_t crc_table[16] = const uint32_t crc_table[16] =
{ {
@ -833,97 +811,19 @@ uint32_t eeprom_crc32(uint16_t calc_start, uint16_t calc_bytes) // base code fro
}; };
uint32_t crc = ~0L; uint32_t crc = ~0L;
if (calc_start + calc_bytes > EEPROM.length()) for (byte* index = calc_start ; index < (calc_start + calc_bytes) ; ++index)
calc_bytes = EEPROM.length() - calc_start;
for (uint16_t index = calc_start ; index < (calc_start + calc_bytes) ; ++index)
{ {
crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4); crc = crc_table[(crc ^ *index) & 0x0f] ^ (crc >> 4);
crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4); crc = crc_table[(crc ^ (*index >> 4)) & 0x0f] ^ (crc >> 4);
crc = ~crc; crc = ~crc;
} }
return (crc); return (crc);
} }
void eeprom_write(uint8_t status) /******************************************************************************
{ DEBUG HELPER
eeprom_update_status |= status; ******************************************************************************/
if (eeprom_update_status != 0)
autostore = 0;
#ifdef DEBUG
Serial.print(F("Updating EEPROM state to: "));
Serial.println(eeprom_update_status, DEC);
#endif
}
void eeprom_update(void)
{
autostore_value = AUTOSTORE_FAST_MS;
if (eeprom_update_status & EEPROM_UPDATE_BANK)
{
EEPROM.update(EEPROM_OFFSET + EEPROM_BANK_ADDR, bank);
#ifdef DEBUG
Serial.println(F("Bank written to EEPROM"));
#endif
eeprom_update_status &= ~EEPROM_UPDATE_BANK;
}
else if (eeprom_update_status & EEPROM_UPDATE_VOICE)
{
EEPROM.update(EEPROM_OFFSET + EEPROM_VOICE_ADDR, voice);
#ifdef DEBUG
Serial.println(F("Voice written to EEPROM"));
#endif
eeprom_update_status &= ~EEPROM_UPDATE_VOICE;
}
else if (eeprom_update_status & EEPROM_UPDATE_VOL)
{
EEPROM.update(EEPROM_OFFSET + EEPROM_MASTER_VOLUME_ADDR, uint8_t(vol * UCHAR_MAX));
#ifdef DEBUG
Serial.println(F("Volume written to EEPROM"));
#endif
eeprom_update_status &= ~EEPROM_UPDATE_VOL;
}
else if (eeprom_update_status & EEPROM_UPDATE_PAN)
{
EEPROM.update(EEPROM_OFFSET + EEPROM_PAN_ADDR, uint8_t(pan * SCHAR_MAX));
#ifdef DEBUG
Serial.println(F("Panorama written to EEPROM"));
#endif
eeprom_update_status &= ~EEPROM_UPDATE_PAN;
}
else if (eeprom_update_status & EEPROM_UPDATE_MIDICHANNEL )
{
EEPROM.update(EEPROM_OFFSET + EEPROM_MIDICHANNEL_ADDR, midi_channel);
update_eeprom_checksum();
#ifdef DEBUG
Serial.println(F("MIDI channel written to EEPROM"));
#endif
eeprom_update_status &= ~EEPROM_UPDATE_MIDICHANNEL;
}
else if (eeprom_update_status & EEPROM_UPDATE_CHECKSUM)
{
update_eeprom_checksum();
#ifdef DEBUG
Serial.println(F("Checksum written to EEPROM"));
#endif
eeprom_update_status &= ~EEPROM_UPDATE_CHECKSUM;
autostore_value = AUTOSTORE_MS;
return;
}
if (eeprom_update_status == 0)
eeprom_update_status |= EEPROM_UPDATE_CHECKSUM;
}
void init_eeprom(void)
{
for (uint8_t i = 0; i < EEPROM_DATA_LENGTH; i++)
{
EEPROM.update(EEPROM_OFFSET + i, 0);
}
}
#if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC) #if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
void show_cpu_and_mem_usage(void) void show_cpu_and_mem_usage(void)

@ -38,7 +38,7 @@ void handle_ui(void)
{ {
if (ui_back_to_main >= UI_AUTO_BACK_MS && (ui_state != UI_MAIN && ui_state != UI_EFFECTS_FILTER && ui_state != UI_EFFECTS_DELAY)) if (ui_back_to_main >= UI_AUTO_BACK_MS && (ui_state != UI_MAIN && ui_state != UI_EFFECTS_FILTER && ui_state != UI_EFFECTS_DELAY))
{ {
enc[0].write(map(vol * 100, 0, 100, 0, ENC_VOL_STEPS)); enc[0].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[0] = enc[0].read(); enc_val[0] = enc[0].read();
ui_show_main(); ui_show_main();
} }
@ -97,7 +97,7 @@ void handle_ui(void)
break; break;
case UI_EFFECTS_DELAY: case UI_EFFECTS_DELAY:
ui_main_state = UI_MAIN_VOICE; ui_main_state = UI_MAIN_VOICE;
enc[i].write(voice); enc[i].write(configuration.voice);
enc_val[i] = enc[i].read(); enc_val[i] = enc[i].read();
ui_show_main(); ui_show_main();
break; break;
@ -114,17 +114,17 @@ void handle_ui(void)
switch (ui_state) switch (ui_state)
{ {
case UI_MAIN: case UI_MAIN:
enc[i].write(map(vol * 100, 0, 100, 0, ENC_VOL_STEPS)); enc[i].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[i] = enc[i].read(); enc_val[i] = enc[i].read();
ui_show_volume(); ui_show_volume();
break; break;
case UI_VOLUME: case UI_VOLUME:
enc[i].write(midi_channel); enc[i].write(configuration.midi_channel);
enc_val[i] = enc[i].read(); enc_val[i] = enc[i].read();
ui_show_midichannel(); ui_show_midichannel();
break; break;
case UI_MIDICHANNEL: case UI_MIDICHANNEL:
enc[i].write(map(vol * 100, 0, 100, 0, ENC_VOL_STEPS)); enc[i].write(map(configuration.vol * 100, 0, 100, 0, ENC_VOL_STEPS));
enc_val[i] = enc[i].read(); enc_val[i] = enc[i].read();
ui_show_main(); ui_show_main();
break; break;
@ -139,13 +139,13 @@ void handle_ui(void)
case UI_MAIN_BANK: case UI_MAIN_BANK:
case UI_MAIN_BANK_SELECTED: case UI_MAIN_BANK_SELECTED:
ui_main_state = UI_MAIN_VOICE; ui_main_state = UI_MAIN_VOICE;
enc[i].write(voice); enc[i].write(configuration.voice);
enc_val[i] = enc[i].read(); enc_val[i] = enc[i].read();
break; break;
case UI_MAIN_VOICE: case UI_MAIN_VOICE:
case UI_MAIN_VOICE_SELECTED: case UI_MAIN_VOICE_SELECTED:
ui_main_state = UI_MAIN_BANK; ui_main_state = UI_MAIN_BANK;
enc[i].write(bank); enc[i].write(configuration.bank);
enc_val[i] = enc[i].read(); enc_val[i] = enc[i].read();
break; break;
} }
@ -217,8 +217,8 @@ void handle_ui(void)
enc[i].write(0); enc[i].write(0);
else if (enc[i].read() >= ENC_VOL_STEPS) else if (enc[i].read() >= ENC_VOL_STEPS)
enc[i].write(ENC_VOL_STEPS); enc[i].write(ENC_VOL_STEPS);
set_volume(float(map(enc[i].read(), 0, ENC_VOL_STEPS, 0, 100)) / 100, pan); set_volume(float(map(enc[i].read(), 0, ENC_VOL_STEPS, 0, 100)) / 100, configuration.pan);
eeprom_write(EEPROM_UPDATE_VOL); eeprom_write();
ui_show_volume(); ui_show_volume();
break; break;
case UI_MIDICHANNEL: case UI_MIDICHANNEL:
@ -226,8 +226,8 @@ void handle_ui(void)
enc[i].write(0); enc[i].write(0);
else if (enc[i].read() >= 16) else if (enc[i].read() >= 16)
enc[i].write(16); enc[i].write(16);
midi_channel = enc[i].read(); configuration.midi_channel = enc[i].read();
eeprom_write(EEPROM_UPDATE_MIDICHANNEL); eeprom_write();
ui_show_midichannel(); ui_show_midichannel();
break; break;
} }
@ -238,7 +238,7 @@ void handle_ui(void)
case UI_VOLUME: case UI_VOLUME:
ui_state = UI_MAIN; ui_state = UI_MAIN;
lcd.clear(); lcd.clear();
enc[1].write(voice); enc[1].write(configuration.voice);
ui_show_main(); ui_show_main();
break; break;
case UI_MAIN: case UI_MAIN:
@ -251,39 +251,39 @@ void handle_ui(void)
enc[i].write(0); enc[i].write(0);
else if (enc[i].read() > max_loaded_banks - 1) else if (enc[i].read() > max_loaded_banks - 1)
enc[i].write(max_loaded_banks - 1); enc[i].write(max_loaded_banks - 1);
bank = enc[i].read(); configuration.bank = enc[i].read();
get_voice_names_from_bank(bank); get_voice_names_from_bank(configuration.bank);
load_sysex(bank, voice); load_sysex(configuration.bank, configuration.voice);
eeprom_write(EEPROM_UPDATE_BANK); eeprom_write();
break; break;
case UI_MAIN_VOICE: case UI_MAIN_VOICE:
ui_main_state = UI_MAIN_VOICE_SELECTED; ui_main_state = UI_MAIN_VOICE_SELECTED;
case UI_MAIN_VOICE_SELECTED: case UI_MAIN_VOICE_SELECTED:
if (enc[i].read() <= 0) if (enc[i].read() <= 0)
{ {
if (bank > 0) if (configuration.bank > 0)
{ {
enc[i].write(MAX_VOICES - 1); enc[i].write(MAX_VOICES - 1);
bank--; configuration.bank--;
get_voice_names_from_bank(bank); get_voice_names_from_bank(configuration.bank);
} }
else else
enc[i].write(0); enc[i].write(0);
} }
else if (enc[i].read() > MAX_VOICES - 1) else if (enc[i].read() > MAX_VOICES - 1)
{ {
if (bank < MAX_BANKS - 1) if (configuration.bank < MAX_BANKS - 1)
{ {
enc[i].write(0); enc[i].write(0);
bank++; configuration.bank++;
get_voice_names_from_bank(bank); get_voice_names_from_bank(configuration.bank);
} }
else else
enc[i].write(MAX_VOICES - 1); enc[i].write(MAX_VOICES - 1);
} }
voice = enc[i].read(); configuration.voice = enc[i].read();
load_sysex(bank, voice); load_sysex(configuration.bank, configuration.voice);
eeprom_write(EEPROM_UPDATE_VOICE); eeprom_write();
break; break;
} }
ui_show_main(); ui_show_main();
@ -411,9 +411,9 @@ void ui_show_main(void)
lcd.clear(); lcd.clear();
} }
lcd.show(0, 0, 2, bank); lcd.show(0, 0, 2, configuration.bank);
lcd.show(0, 2, 1, " "); lcd.show(0, 2, 1, " ");
strip_extension(bank_names[bank], bank_name); strip_extension(bank_names[configuration.bank], bank_name);
if (ui_main_state == UI_MAIN_BANK || ui_main_state == UI_MAIN_BANK_SELECTED) if (ui_main_state == UI_MAIN_BANK || ui_main_state == UI_MAIN_BANK_SELECTED)
{ {
@ -428,18 +428,18 @@ void ui_show_main(void)
lcd.show(0, 11, 1, " "); lcd.show(0, 11, 1, " ");
} }
lcd.show(1, 0, 2, voice + 1); lcd.show(1, 0, 2, configuration.voice + 1);
lcd.show(1, 2, 1, " "); lcd.show(1, 2, 1, " ");
if (ui_main_state == UI_MAIN_VOICE || ui_main_state == UI_MAIN_VOICE_SELECTED) if (ui_main_state == UI_MAIN_VOICE || ui_main_state == UI_MAIN_VOICE_SELECTED)
{ {
lcd.show(1, 2, 1, "["); lcd.show(1, 2, 1, "[");
lcd.show(1, 3, 10, voice_names[voice]); lcd.show(1, 3, 10, voice_names[configuration.voice]);
lcd.show(1, 14, 1, "]"); lcd.show(1, 14, 1, "]");
} }
else else
{ {
lcd.show(1, 2, 1, " "); lcd.show(1, 2, 1, " ");
lcd.show(1, 3, 10, voice_names[voice]); lcd.show(1, 3, 10, voice_names[configuration.voice]);
lcd.show(1, 14, 1, " "); lcd.show(1, 14, 1, " ");
} }
@ -456,18 +456,18 @@ void ui_show_volume(void)
lcd.show(0, 0, LCD_CHARS, "Volume"); lcd.show(0, 0, LCD_CHARS, "Volume");
} }
lcd.show(0, LCD_CHARS - 3, 3, vol * 100); lcd.show(0, LCD_CHARS - 3, 3, configuration.vol * 100);
if (vol == 0.0) if (configuration.vol == 0.0)
lcd.show(1, 0, LCD_CHARS , " "); lcd.show(1, 0, LCD_CHARS , " ");
else else
{ {
if (vol < (float(LCD_CHARS) / 100)) if (configuration.vol < (float(LCD_CHARS) / 100))
lcd.show(1, 0, LCD_CHARS, "*"); lcd.show(1, 0, LCD_CHARS, "*");
else else
{ {
for (uint8_t i = 0; i < map(vol * 100, 0, 100, 0, LCD_CHARS); i++) for (uint8_t i = 0; i < map(configuration.vol * 100, 0, 100, 0, LCD_CHARS); i++)
lcd.show(1, i, 1, "*"); lcd.show(1, i, 1, "*");
for (uint8_t i = map(vol * 100, 0, 100, 0, LCD_CHARS); i < LCD_CHARS; i++) for (uint8_t i = map(configuration.vol * 100, 0, 100, 0, LCD_CHARS); i < LCD_CHARS; i++)
lcd.show(1, i, 1, " "); lcd.show(1, i, 1, " ");
} }
} }
@ -485,12 +485,12 @@ void ui_show_midichannel(void)
lcd.show(0, 0, LCD_CHARS, "MIDI Channel"); lcd.show(0, 0, LCD_CHARS, "MIDI Channel");
} }
if (midi_channel == MIDI_CHANNEL_OMNI) if (configuration.midi_channel == MIDI_CHANNEL_OMNI)
lcd.show(1, 0, 4, "OMNI"); lcd.show(1, 0, 4, "OMNI");
else else
{ {
lcd.show(1, 0, 2, midi_channel); lcd.show(1, 0, 2, configuration.midi_channel);
if (midi_channel == 1) if (configuration.midi_channel == 1)
lcd.show(1, 2, 2, " "); lcd.show(1, 2, 2, " ");
} }

@ -36,18 +36,14 @@
extern Encoder4 enc[2]; extern Encoder4 enc[2];
extern int32_t enc_val[2]; extern int32_t enc_val[2];
extern Bounce but[2]; extern Bounce but[2];
extern float vol;
extern float pan;
extern LiquidCrystalPlus_I2C lcd; extern LiquidCrystalPlus_I2C lcd;
extern uint8_t bank; extern config_t configuration;
extern uint8_t max_loaded_banks; extern uint8_t max_loaded_banks;
extern uint8_t voice;
extern char bank_name[BANK_NAME_LEN]; extern char bank_name[BANK_NAME_LEN];
extern char voice_name[VOICE_NAME_LEN]; extern char voice_name[VOICE_NAME_LEN];
extern uint8_t ui_state; extern uint8_t ui_state;
extern uint8_t ui_main_state; extern uint8_t ui_main_state;
extern uint8_t midi_channel; extern void eeprom_write(void);
extern void eeprom_write(uint8_t status);
extern void set_volume(float v, float pan); extern void set_volume(float v, float pan);
extern elapsedMillis autostore; extern elapsedMillis autostore;
extern elapsedMillis long_button_pressed; extern elapsedMillis long_button_pressed;

@ -145,22 +145,7 @@
#define AUTOSTORE_FAST_MS 50 #define AUTOSTORE_FAST_MS 50
// EEPROM address // EEPROM address
#define EEPROM_OFFSET 0 #define EEPROM_START_ADDRESS 0
#define EEPROM_DATA_LENGTH 5
#define EEPROM_CRC32_ADDR EEPROM.length()-sizeof(uint32_t)-33
#define EEPROM_BANK_ADDR 0
#define EEPROM_VOICE_ADDR 1
#define EEPROM_MASTER_VOLUME_ADDR 2
#define EEPROM_PAN_ADDR 3
#define EEPROM_MIDICHANNEL_ADDR 4
#define EEPROM_UPDATE_BANK (1<<0)
#define EEPROM_UPDATE_VOICE (1<<1)
#define EEPROM_UPDATE_VOL (1<<2)
#define EEPROM_UPDATE_PAN (1<<3)
#define EEPROM_UPDATE_MIDICHANNEL (1<<4)
#define EEPROM_UPDATE_CHECKSUM (1<<7)
#define MAX_BANKS 100 #define MAX_BANKS 100
#define MAX_VOICES 32 // voices per bank #define MAX_VOICES 32 // voices per bank
@ -194,4 +179,13 @@
#define USE_TEENSY_DSP 1 #define USE_TEENSY_DSP 1
#define SUM_UP_AS_INT 1 #define SUM_UP_AS_INT 1
// struct for holding the current configuration
struct config_t {
uint32_t checksum;
uint8_t bank;
uint8_t voice;
float vol;
float pan;
uint8_t midi_channel;
};
#endif // CONFIG_H_INCLUDED #endif // CONFIG_H_INCLUDED

Loading…
Cancel
Save