From 58466a84716e084ad3339718b7f0e8196ac704bb Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Wed, 1 May 2019 17:48:12 +0200 Subject: [PATCH] Removed old UI code. Added new UI code based on LiquidMenu. --- UI.h => EEPROMAnything.h | 43 +++++----- LiquidCrystalPlus_I2C.h | 86 ------------------- MicroMDAEPiano.ino | 173 +++++++++++++++++---------------------- UI.cpp | 35 -------- UI.hpp | 57 +++++++++++++ config.h | 23 ++++-- mdaEPiano.cpp | 5 +- mdaEPiano.h | 2 +- 8 files changed, 175 insertions(+), 249 deletions(-) rename UI.h => EEPROMAnything.h (57%) delete mode 100644 LiquidCrystalPlus_I2C.h delete mode 100644 UI.cpp create mode 100644 UI.hpp diff --git a/UI.h b/EEPROMAnything.h similarity index 57% rename from UI.h rename to EEPROMAnything.h index cd3069b..8b201e1 100644 --- a/UI.h +++ b/EEPROMAnything.h @@ -21,26 +21,31 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#ifndef UI_H_INCLUDED -#define UI_H_INCLUDED + // Idea from: https://playground.arduino.cc/Code/EEPROMWriteAnything/ -/* -#include "config.h" -#include "LiquidCrystalPlus_I2C.h" -#include -#include "Encoder4.h" +#include +#include // for type definitions + +uint32_t crc32(uint8_t* calc_start, uint16_t calc_bytes); + +template 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); -class UI + *p=checksum; + + for (i = 0; i < sizeof(value); i++) + EEPROM.update(ee++, *p++); + return i; +} + +template int EEPROM_readAnything(int ee, T& value) { - public: - UI(); - ~UI(); - - private: - LiquidCrystalPlus_I2C lcd; - Encoder4 enc[2]; - int32_t enc_val[2]; - Bounce but[2]; + uint8_t* p = (uint8_t*)(void*)&value; + unsigned int i; + for (i = 0; i < sizeof(value); i++) + *p++ = EEPROM.read(ee++); + return i; } -*/ -#endif diff --git a/LiquidCrystalPlus_I2C.h b/LiquidCrystalPlus_I2C.h deleted file mode 100644 index 9aea0d0..0000000 --- a/LiquidCrystalPlus_I2C.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - MicroMDAEPiano - - MicroMDAEPiano is a port of the MDA-EPiano sound engine - (https://sourceforge.net/projects/mda-vst/) for the Teensy-3.5/3.6 with audio shield. - - (c)2019 H. Wirtz - - 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 -*/ - -#ifndef LIQUIDCRYSTALPLUS_I2C_H_INCLUDED -#define LIQUIDCRYSTALPLUS_I2C_H_INCLUDED - -#include // https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c - -#define STRING_BUF_SIZE 21 - -class LiquidCrystalPlus_I2C : public LiquidCrystal_I2C -{ - public: - - using LiquidCrystal_I2C::LiquidCrystal_I2C; - - void show(uint8_t y, uint8_t x, uint8_t fs, char *str) - { - _show(y, x, fs, str, false, false); - } - - void show(uint8_t y, uint8_t x, uint8_t fs, long num) - { - char _buf10[STRING_BUF_SIZE]; - - _show(y, x, fs, itoa(num, _buf10, 10), true, true); - } - - private: - void _show(uint8_t pos_y, uint8_t pos_x, uint8_t field_size, char *str, bool justify_right, bool fill_zero) - { - { - char tmp[STRING_BUF_SIZE]; - char *s = tmp; - uint8_t l = strlen(str); - - memset(tmp, 0, sizeof(tmp)); - if (fill_zero == true) - memset(tmp, '0', field_size); - else - memset(tmp, 0x20, field_size - 1); // blank - - if (l > field_size) - l = field_size; - - if (justify_right == true) - s += field_size - l; - - strncpy(s, str, l); - - setCursor(pos_x, pos_y); - print(tmp); - -#ifdef DEBUG - Serial.print(pos_y, DEC); - Serial.print(F("/")); - Serial.print(pos_x, DEC); - Serial.print(F(": [")); - Serial.print(tmp); - Serial.println(F("]")); -#endif - } - } -}; - -#endif diff --git a/MicroMDAEPiano.ino b/MicroMDAEPiano.ino index 441e041..31174d5 100644 --- a/MicroMDAEPiano.ino +++ b/MicroMDAEPiano.ino @@ -27,6 +27,7 @@ #include #include #include +#include "EEPROMAnything.h" #include #include "mdaEPiano.h" #ifdef USE_XFADE_DATA @@ -38,6 +39,7 @@ #include "Encoder4.h" #include #include +#include "UI.hpp" #include "midi_devices.hpp" //************************************************************************************************* @@ -102,18 +104,17 @@ float vol = VOLUME; float vol_right = 1.0; float vol_left = 1.0; elapsedMicros fill_audio_buffer; +elapsedMillis control_rate; +elapsedMillis autostore; const uint16_t audio_block_time_us = 1000000 / (SAMPLE_RATE / AUDIO_BLOCK_SAMPLES); +config_t configuration = {0xffff, 0, VOLUME, 0.5f, DEFAULT_MIDI_CHANNEL}; +bool eeprom_update_flag = false; #ifdef SHOW_CPU_LOAD_MSEC elapsedMillis cpu_mem_millis; #endif enum MDA_EP_PARAM { DECAY, RELEASE, HARDNESS, TREBLE, PAN_TREM, LFO_RATE, VELOCITY_SENSE, STEREO, MAX_POLY, TUNE, DETUNE, OVERDRIVE }; -LiquidLine welcome_line1(1, 0, "MicroMDAEPiano"); -LiquidLine welcome_line2(0, 1, "(c)parasiTstudio"); -LiquidScreen welcome_screen(welcome_line1, welcome_line2); -LiquidMenu menu(lcd); - //************************************************************************************************* //* SETUP FUNCTION //************************************************************************************************* @@ -121,17 +122,11 @@ LiquidMenu menu(lcd); void setup() { //while (!Serial) ; // wait for Arduino Serial Monitor - Serial.begin(SERIAL_SPEED); - delay(220); - - // LCD display setup - lcd.init(); - lcd.blink_off(); - lcd.cursor_off(); - lcd.backlight(); - lcd.noAutoscroll(); - menu.add_screen(welcome_screen); + menu_init(); + + Serial.begin(SERIAL_SPEED); + delay(500); // Encoder setup enc[0].write(INITIAL_ENC_L_VALUE); @@ -165,12 +160,34 @@ void setup() #ifdef TEENSY_AUDIO_BOARD sgtl5000_1.enable(); - //sgtl5000_1.dacVolumeRamp(); - sgtl5000_1.dacVolumeRampLinear(); + sgtl5000_1.dacVolumeRamp(); + sgtl5000_1.dacVolume(1.0); + //sgtl5000_1.dacVolumeRampLinear(); sgtl5000_1.unmuteHeadphone(); sgtl5000_1.unmuteLineout(); sgtl5000_1.autoVolumeDisable(); // turn off AGC - sgtl5000_1.volume(1.0, 1.0); + sgtl5000_1.unmuteHeadphone(); + sgtl5000_1.volume(0.5, 0.5); // Headphone volume + sgtl5000_1.lineOutLevel(SGTL5000_LINEOUT_LEVEL); + sgtl5000_1.audioPostProcessorEnable(); + sgtl5000_1.autoVolumeControl(1, 1, 1, 0.9, 0.01, 0.05); + sgtl5000_1.autoVolumeEnable(); + sgtl5000_1.surroundSoundEnable(); + sgtl5000_1.surroundSound(7, 3); // Configures virtual surround width from 0 (mono) to 7 (widest). select may be set to 1 (disable), 2 (mono input) or 3 (stereo input). + sgtl5000_1.enhanceBassEnable(); + sgtl5000_1.enhanceBass(1.0, 0.2, 1, 2); // Configures the bass enhancement by setting the levels of the original stereo signal and the bass-enhanced mono level which will be mixed together. The high-pass filter may be enabled (0) or bypassed (1). + /* The cutoff frequency is specified as follows: + value frequency + 0 80Hz + 1 100Hz + 2 125Hz + 3 150Hz + 4 175Hz + 5 200Hz + 6 225Hz + */ + //sgtl5000_1.eqBands(bass, mid_bass, midrange, mid_treble, treble); + Serial.println(F("Teensy-Audio-Board enabled.")); #elif defined(TGA_AUDIO_BOARD) wm8731_1.enable(); wm8731_1.volume(1.0); @@ -213,10 +230,12 @@ void setup() mixer_l.gain(1, 0.3); AudioInterrupts(); - menu.update(); Serial.println(F("")); + menu.next_screen(); + menu.update(); + #if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC) show_cpu_and_mem_usage(); cpu_mem_millis = 0; @@ -287,8 +306,18 @@ void loop() } check_midi_devices(); + + // CONTROL-RATE-EVENT-HANDLING + if (control_rate > CONTROL_RATE_MS) + { + control_rate = 0; + + + + } } + //************************************************************************************************* //* PROGRAM FUNCTIONS //************************************************************************************************* @@ -419,106 +448,60 @@ bool checkMidiChannel(byte inChannel) void set_volume(float v, float vr, float vl) { - vol = v; - vol_right = vr; - vol_left = vl; - - EEPROM.update(EEPROM_OFFSET + EEPROM_MASTER_VOLUME_ADDR, uint8_t(vol * UCHAR_MAX)); - EEPROM.update(EEPROM_OFFSET + EEPROM_VOLUME_RIGHT_ADDR, uint8_t(vol_right * UCHAR_MAX)); - EEPROM.update(EEPROM_OFFSET + EEPROM_VOLUME_LEFT_ADDR, uint8_t(vol_left * UCHAR_MAX)); - update_eeprom_checksum(); - -#ifdef DEBUG - uint8_t tmp; - Serial.print(F("Setting volume: VOL=")); - Serial.print(v, DEC); - Serial.print(F("[")); - tmp = EEPROM.read(EEPROM_OFFSET + EEPROM_MASTER_VOLUME_ADDR); - Serial.print(tmp, DEC); - Serial.print(F("/")); - Serial.print(float(tmp) / UCHAR_MAX, DEC); - Serial.print(F("] VOL_L=")); - Serial.print(vl, DEC); - Serial.print(F("[")); - tmp = EEPROM.read(EEPROM_OFFSET + EEPROM_VOLUME_LEFT_ADDR); - Serial.print(tmp, DEC); - Serial.print(F("/")); - Serial.print(float(tmp) / UCHAR_MAX, DEC); - Serial.print(F("] VOL_R=")); - Serial.print(vr, DEC); - Serial.print(F("[")); - tmp = EEPROM.read(EEPROM_OFFSET + EEPROM_VOLUME_RIGHT_ADDR); - Serial.print(tmp, DEC); - Serial.print(F("/")); - Serial.print(float(tmp) / UCHAR_MAX, DEC); - Serial.println(F("]")); -#endif - -#ifdef TEENSY_AUDIO_BOARD - sgtl5000_1.dacVolume(vol * vol_left, vol * vol_right); -#elif TGA_AUDIO_BOARD - wm8731_1.volume(vol); -#else - volume_r.gain(vr); - volume_l.gain(vl); -#endif + ; } -//************************************************************************************************* -//* EEPROM FUNCTIONS -//************************************************************************************************* +/****************************************************************************** + EEPROM HELPER + ******************************************************************************/ void initial_values_from_eeprom(void) { - uint32_t crc_eeprom = read_eeprom_checksum(); - uint32_t crc = eeprom_crc32(EEPROM_OFFSET, EEPROM_DATA_LENGTH); + uint32_t checksum; + config_t tmp_conf; + + EEPROM_readAnything(EEPROM_START_ADDRESS, tmp_conf); + checksum = crc32((byte*)&tmp_conf + 4, sizeof(tmp_conf) - 4); #ifdef DEBUG Serial.print(F("EEPROM checksum: 0x")); - Serial.print(crc_eeprom, HEX); + Serial.print(tmp_conf.checksum, HEX); Serial.print(F(" / 0x")); - Serial.print(crc, HEX); + Serial.print(checksum, HEX); #endif - if (crc_eeprom != crc) + + if (checksum != tmp_conf.checksum) { #ifdef DEBUG Serial.print(F(" - mismatch -> initializing EEPROM!")); #endif - EEPROM.update(EEPROM_OFFSET + EEPROM_MASTER_VOLUME_ADDR, uint8_t(vol * UCHAR_MAX)); - EEPROM.update(EEPROM_OFFSET + EEPROM_VOLUME_RIGHT_ADDR, uint8_t(vol_right * UCHAR_MAX)); - EEPROM.update(EEPROM_OFFSET + EEPROM_VOLUME_LEFT_ADDR, uint8_t(vol_left * UCHAR_MAX)); - update_eeprom_checksum(); + eeprom_update(); } else { - vol = float(EEPROM.read(EEPROM_OFFSET + EEPROM_MASTER_VOLUME_ADDR)) / UCHAR_MAX; - vol_right = float(EEPROM.read(EEPROM_OFFSET + EEPROM_VOLUME_RIGHT_ADDR)) / UCHAR_MAX; - vol_left = float(EEPROM.read(EEPROM_OFFSET + EEPROM_VOLUME_LEFT_ADDR)) / UCHAR_MAX; + EEPROM_readAnything(EEPROM_START_ADDRESS, configuration); + Serial.print(F(" - OK, loading!")); } #ifdef DEBUG Serial.println(); #endif } -uint32_t read_eeprom_checksum(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) +void eeprom_write(void) { - write_eeprom_checksum(eeprom_crc32(EEPROM_OFFSET, EEPROM_DATA_LENGTH)); // recalculate crc and write to eeprom + autostore = 0; + eeprom_update_flag = true; } -void write_eeprom_checksum(uint32_t crc) +void eeprom_update(void) { - EEPROM.update(EEPROM_CRC32_ADDR, (crc & 0xff000000) >> 24); - EEPROM.update(EEPROM_CRC32_ADDR + 1, (crc & 0x00ff0000) >> 16); - EEPROM.update(EEPROM_CRC32_ADDR + 2, (crc & 0x0000ff00) >> 8); - EEPROM.update(EEPROM_CRC32_ADDR + 3, crc & 0x000000ff); + 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")); } -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] = { @@ -529,20 +512,16 @@ uint32_t eeprom_crc32(uint16_t calc_start, uint16_t calc_bytes) // base code fro }; uint32_t crc = ~0L; - if (calc_start + calc_bytes > EEPROM.length()) - calc_bytes = EEPROM.length() - calc_start; - - for (uint16_t index = calc_start ; index < (calc_start + calc_bytes) ; ++index) + for (byte* index = calc_start ; index < (calc_start + calc_bytes) ; ++index) { - crc = crc_table[(crc ^ EEPROM[index]) & 0x0f] ^ (crc >> 4); - crc = crc_table[(crc ^ (EEPROM[index] >> 4)) & 0x0f] ^ (crc >> 4); + crc = crc_table[(crc ^ *index) & 0x0f] ^ (crc >> 4); + crc = crc_table[(crc ^ (*index >> 4)) & 0x0f] ^ (crc >> 4); crc = ~crc; } return (crc); } - //************************************************************************************************* //* DEBUG FUNCTIONS //************************************************************************************************* diff --git a/UI.cpp b/UI.cpp deleted file mode 100644 index 4748da6..0000000 --- a/UI.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/* - MicroMDAEPiano - - MicroMDAEPiano is a port of the MDA-EPiano sound engine - (https://sourceforge.net/projects/mda-vst/) for the Teensy-3.5/3.6 with audio shield. - - (c)2019 H. Wirtz - - 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 -*/ - -#include "config.h" -#include "UI.h" - -/* -UI::UI() -{ - LiquidCrystalPlus_I2C lcd(LCD_I2C_ADDRESS, LCD_CHARS, LCD_LINES); - enc[] = {Encoder4(ENC_L_PIN_A, ENC_L_PIN_B), Encoder4(ENC_R_PIN_A, ENC_R_PIN_B)}; - enc_val[] = {INITIAL_ENC_L_VALUE, INITIAL_ENC_R_VALUE}; - but[] = {Bounce(BUT_L_PIN, BUT_DEBOUNCE_MS), Bounce(BUT_R_PIN, BUT_DEBOUNCE_MS)}; -} -*/ diff --git a/UI.hpp b/UI.hpp new file mode 100644 index 0000000..f26bad7 --- /dev/null +++ b/UI.hpp @@ -0,0 +1,57 @@ +/* + MicroMDAEPiano + + MicroMDAEPiano is a port of the MDA-EPiano sound engine + (https://sourceforge.net/projects/mda-vst/) for the Teensy-3.5/3.6 with audio shield. + + (c)2019 H. Wirtz + + 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 +*/ + +#include +#include + +#ifndef UI_HPP_INCLUDED +#define UI_HPP_INCLUDED + +extern LiquidCrystal_I2C lcd; + +LiquidMenu menu(lcd); + +// Welcome screen +LiquidLine welcome_line1(1, 0, "MicroMDAEPiano"); +LiquidLine welcome_line2(0, 1, "(c)parasiTstudio"); +LiquidScreen welcome_screen(welcome_line1, welcome_line2); + +// Welcome screen +LiquidLine main_line1(0, 0, "Volume:"); +LiquidLine main_line2(0, 1, "Voice"); +LiquidScreen main_screen(main_line1, main_line2); + +void menu_init(void) +{ + // LCD display setup + lcd.init(); + lcd.blink_off(); + lcd.cursor_off(); + lcd.backlight(); + lcd.noAutoscroll(); + + menu.add_screen(welcome_screen); + menu.add_screen(main_screen); + menu.update(); +} +#endif diff --git a/config.h b/config.h index f542331..7524cb7 100644 --- a/config.h +++ b/config.h @@ -25,6 +25,7 @@ #define CONFIG_H_INCLUDED #include "midinotes.h" +#include // ATTENTION! For better latency you have to redefine AUDIO_BLOCK_SAMPLES from // 128 to 64 in /cores/teensy3/AudioStream.h @@ -102,19 +103,14 @@ #define LCD_LINES 2 // EEPROM address -#define EEPROM_OFFSET 0 -#define EEPROM_DATA_LENGTH 5 - -#define EEPROM_CRC32_ADDR EEPROM.length()-sizeof(uint32_t) -#define EEPROM_BANK_ADDR 0 -#define EEPROM_VOICE_ADDR 1 -#define EEPROM_MASTER_VOLUME_ADDR 2 -#define EEPROM_VOLUME_RIGHT_ADDR 3 -#define EEPROM_VOLUME_LEFT_ADDR 4 +#define EEPROM_START_ADDRESS 0 //************************************************************************************************* //* DO NO CHANGE ANYTHING BEYOND IF YOU DON'T KNOW WHAT YOU ARE DOING !!! //************************************************************************************************* + +#define CONTROL_RATE_MS 100 + // MIDI #ifdef MIDI_DEVICE_USB #define USBCON 1 @@ -134,4 +130,13 @@ #define NVOICES 32 #endif +// struct for holding the current configuration +struct config_t { + uint32_t checksum; + uint8_t voice; + float vol; + float pan; + uint8_t midi_channel; +}; + #endif diff --git a/mdaEPiano.cpp b/mdaEPiano.cpp index 7fe3abf..835e4d2 100644 --- a/mdaEPiano.cpp +++ b/mdaEPiano.cpp @@ -112,6 +112,7 @@ mdaEPiano::mdaEPiano() // mdaEPiano::mdaEPiano(audioMasterCallback audioMaster) guiUpdate = 0; + vol = VOLUME; update(); // suspend(); } @@ -239,8 +240,8 @@ void mdaEPiano::process(int16_t* outputs_r, int16_t* outputs_l) l = 1.0; else if (l < -1.0) l = -1.0; - outputs_l[frame] = static_cast(l * 0x7fff) >> REDUCE_LOUDNESS; - outputs_r[frame] = static_cast(r * 0x7fff) >> REDUCE_LOUDNESS; + outputs_l[frame] = static_cast(l * vol * 0x7fff) >> REDUCE_LOUDNESS; + outputs_r[frame] = static_cast(r * vol * 0x7fff) >> REDUCE_LOUDNESS; } if (fabs(tl) < 1.0e-10) tl = 0.0f; //anti-denormal diff --git a/mdaEPiano.h b/mdaEPiano.h index 4ea5584..3fa035b 100644 --- a/mdaEPiano.h +++ b/mdaEPiano.h @@ -108,7 +108,7 @@ class mdaEPiano float treb, tfrq, tl, tr; float tune, fine, random, stretch, overdrive; float muff, muffvel, sizevel, velsens, volume, modwhl; - + float vol; uint8_t curProgram; };