Fix for checksum calculation at SYSEX voice reading.

Small fix for using Serial and/or USB MIDI.
Surrounding of Serial.print(). You now need to define DEBUG when showing output via USB-serial.
pull/4/head
Holger Wirtz 6 years ago
parent 6bd7905dbc
commit 2c767f78f8
  1. 109
      MicroDexed.ino
  2. 19
      config.h
  3. 33
      dexed_sysex.cpp

@ -34,6 +34,21 @@
#ifdef USE_ONBOARD_USB_HOST #ifdef USE_ONBOARD_USB_HOST
#include <USBHost_t36.h> #include <USBHost_t36.h>
#endif #endif
#ifndef MASTER_KEY_MIDI // selecting sounds by encoder and display
#include <Bounce.h>
#include <Encoder.h>
#include <LiquidCrystalPlus_I2C.h>
#endif
#ifndef MASTER_KEY_MIDI
// [I2C] SCL: Pin 19, SDA: Pin 18 (https://www.pjrc.com/teensy/td_libs_Wire.html)
#define LCD_I2C_ADDRESS 0x3f
#define LCD_CHARS 20
#define LCD_LINES 4
LiquidCrystalPlus_I2C lcd(LCD_I2C_ADDRESS, LCD_CHARS, LCD_LINES);
Encoder enc1(ENC1_PIN_A, ENC1_PIN_B);
Bounce but1 = Bounce(BUT1_PIN, 10); // 10 ms debounce
#endif
// GUItool: begin automatically generated code // GUItool: begin automatically generated code
AudioPlayQueue queue1; //xy=84,294 AudioPlayQueue queue1; //xy=84,294
@ -43,7 +58,6 @@ AudioConnection patchCord3(queue1, 0, i2s1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=507,403 AudioControlSGTL5000 sgtl5000_1; //xy=507,403
// GUItool: end automatically generated code // GUItool: end automatically generated code
MIDI_CREATE_INSTANCE(HardwareSerial, MIDI_DEVICE, MIDI);
Dexed* dexed = new Dexed(SAMPLE_RATE); Dexed* dexed = new Dexed(SAMPLE_RATE);
bool sd_card_available = false; bool sd_card_available = false;
uint8_t bank = EEPROM.read(EEPROM_BANK_ADDR); uint8_t bank = EEPROM.read(EEPROM_BANK_ADDR);
@ -59,6 +73,9 @@ bool master_key_enabled = false;
IntervalTimer sched_show_cpu_usage; IntervalTimer sched_show_cpu_usage;
#endif #endif
#ifdef MIDI_DEVICE
MIDI_CREATE_INSTANCE(HardwareSerial, MIDI_DEVICE, midi_serial);
#endif
#ifdef USE_ONBOARD_USB_HOST #ifdef USE_ONBOARD_USB_HOST
USBHost usb_host; USBHost usb_host;
MIDIDevice midi_usb(usb_host); MIDIDevice midi_usb(usb_host);
@ -74,7 +91,20 @@ void setup()
{ {
//while (!Serial) ; // wait for Arduino Serial Monitor //while (!Serial) ; // wait for Arduino Serial Monitor
Serial.begin(SERIAL_SPEED); Serial.begin(SERIAL_SPEED);
delay(200);
#ifndef MASTER_KEY_MIDI
lcd.init();
lcd.blink_off();
lcd.cursor_off();
lcd.backlight();
lcd.noAutoscroll();
lcd.clear();
lcd.display();
lcd.show(0, 0, 20, "MicroDexed");
enc1.write(INITIAL_ENC1_VALUE);
#endif
Serial.println(F("MicroDexed based on https://github.com/asb2m10/dexed")); Serial.println(F("MicroDexed based on https://github.com/asb2m10/dexed"));
Serial.println(F("(c)2018 H. Wirtz <wirtz@parasitstudio.de>")); Serial.println(F("(c)2018 H. Wirtz <wirtz@parasitstudio.de>"));
Serial.println(F("<setup start>")); Serial.println(F("<setup start>"));
@ -84,8 +114,10 @@ void setup()
usb_host.begin(); usb_host.begin();
#endif #endif
// start MIDI #ifdef MIDI_DEVICE
MIDI.begin(DEFAULT_MIDI_CHANNEL); // Start serial MIDI
midi_serial.begin(DEFAULT_MIDI_CHANNEL);
#endif
// start audio card // start audio card
AudioMemory(AUDIO_MEM); AudioMemory(AUDIO_MEM);
@ -105,7 +137,7 @@ void setup()
sd_card_available = true; sd_card_available = true;
} }
#ifdef SHOW_CPU_LOAD_MSEC #if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
// Initialize processor and memory measurements // Initialize processor and memory measurements
AudioProcessorUsageMaxReset(); AudioProcessorUsageMaxReset();
AudioMemoryUsageMaxReset(); AudioMemoryUsageMaxReset();
@ -129,7 +161,9 @@ void setup()
#endif #endif
Serial.println(F("<setup end>")); Serial.println(F("<setup end>"));
#if defined (DEBUG) && defined (SHOW_CPU_LOAD_MSEC)
show_cpu_and_mem_usage(); show_cpu_and_mem_usage();
#endif
#ifdef TEST_NOTE #ifdef TEST_NOTE
//dexed->data[DEXED_VOICE_OFFSET+DEXED_LFO_PITCH_MOD_DEP] = 99; // full pitch mod depth //dexed->data[DEXED_VOICE_OFFSET+DEXED_LFO_PITCH_MOD_DEP] = 99; // full pitch mod depth
@ -152,7 +186,7 @@ void loop()
while (42 == 42) // DON'T PANIC! while (42 == 42) // DON'T PANIC!
{ {
handle_midi_input(); handle_input();
audio_buffer = queue1.getBuffer(); audio_buffer = queue1.getBuffer();
if (audio_buffer == NULL) if (audio_buffer == NULL)
@ -175,7 +209,7 @@ void loop()
} }
} }
void handle_midi_input(void) void handle_input(void)
{ {
#ifdef USE_ONBOARD_USB_HOST #ifdef USE_ONBOARD_USB_HOST
usb_host.Task(); usb_host.Task();
@ -192,19 +226,29 @@ void handle_midi_input(void)
return; return;
} }
#endif #endif
#ifdef MIDI_DEVICE
while (MIDI.read()) while (midi_serial.read())
{ {
#ifdef DEBUG #ifdef DEBUG
Serial.print(F("[MIDI-Serial] ")); Serial.print(F("[MIDI-Serial] "));
#endif #endif
if (MIDI.getType() >= 0xf0) // SYSEX if (midi_serial.getType() >= 0xf0) // SYSEX
{ {
handle_sysex_parameter(MIDI.getSysExArray(), MIDI.getSysExArrayLength()); handle_sysex_parameter(midi_serial.getSysExArray(), midi_serial.getSysExArrayLength());
} }
else if (queue_midi_event(MIDI.getType(), MIDI.getData1(), MIDI.getData2())) else if (queue_midi_event(midi_serial.getType(), midi_serial.getData1(), midi_serial.getData2()))
return; return;
} }
#endif
#ifndef MASTER_KEY_MIDI
int enc1_val = enc1.read();
if (but1.update())
;
// place handling of encoder and showing values on lcd here
#endif
} }
#ifdef TEST_NOTE #ifdef TEST_NOTE
@ -250,12 +294,15 @@ void note_off(void)
bool success = load_sysex(DEFAULT_SYSEXBANK, (++_voice_counter) - 1); bool success = load_sysex(DEFAULT_SYSEXBANK, (++_voice_counter) - 1);
if (success == false) if (success == false)
#ifdef DEBUG
Serial.println(F("E: Cannot load SYSEX data")); Serial.println(F("E: Cannot load SYSEX data"));
#endif
else else
show_patch(); show_patch();
} }
#endif #endif
#ifdef DEBUG
#ifdef SHOW_MIDI_EVENT #ifdef SHOW_MIDI_EVENT
void print_midi_event(uint8_t type, uint8_t data1, uint8_t data2) void print_midi_event(uint8_t type, uint8_t data1, uint8_t data2)
{ {
@ -274,31 +321,38 @@ void print_midi_event(uint8_t type, uint8_t data1, uint8_t data2)
Serial.println(data2, DEC); Serial.println(data2, DEC);
} }
#endif #endif
#endif
#ifdef MASTER_KEY_MIDI #ifdef MASTER_KEY_MIDI
bool handle_master_key(uint8_t data) bool handle_master_key(uint8_t data)
{ {
int8_t num = num_key_base_c(data); int8_t num = num_key_base_c(data);
#ifdef DEBUG
Serial.print(F("Master-Key: ")); Serial.print(F("Master-Key: "));
Serial.println(num, DEC); Serial.println(num, DEC);
#endif
if (num > 0) if (num > 0)
{ {
// a white key! // a white key!
if (num <= 32) if (num <= 32)
{ {
if (!load_sysex(bank, num)) if (load_sysex(bank, num))
{ {
Serial.print(F("E: cannot load voice number ")); #ifdef DEBUG
Serial.print(F("Loading voice number "));
Serial.println(num, DEC); Serial.println(num, DEC);
#endif
store_voice_number(bank, num);
} }
#ifdef DEBUG
else else
{ {
Serial.print(F("Loading voice number ")); Serial.print(F("E: cannot load voice number "));
Serial.println(num, DEC); Serial.println(num, DEC);
store_voice_number(bank, num);
} }
#endif
} }
return (true); return (true);
} }
@ -309,14 +363,18 @@ bool handle_master_key(uint8_t data)
if (num <= 10) if (num <= 10)
{ {
sgtl5000_1.volume(num * 0.1); sgtl5000_1.volume(num * 0.1);
#ifdef DEBUG
Serial.print(F("Volume changed to: ")); Serial.print(F("Volume changed to: "));
Serial.println(num * 0.1, DEC); Serial.println(num * 0.1, DEC);
#endif
} }
else if (num > 10 && num <= 20) else if (num > 10 && num <= 20)
{ {
bank = num - 10; bank = num - 10;
#ifdef DEBUG
Serial.print(F("Bank switch to: ")); Serial.print(F("Bank switch to: "));
Serial.println(bank, DEC); Serial.println(bank, DEC);
#endif
} }
} }
return (false); return (false);
@ -327,7 +385,7 @@ bool queue_midi_event(uint8_t type, uint8_t data1, uint8_t data2)
{ {
bool ret = false; bool ret = false;
#ifdef SHOW_MIDI_EVENT #if defined(DEBUG) && defined(SHOW_MIDI_EVENT)
print_midi_event(type, data1, data2); print_midi_event(type, data1, data2);
#endif #endif
@ -337,12 +395,16 @@ bool queue_midi_event(uint8_t type, uint8_t data1, uint8_t data2)
if (type == 0x80 && data1 == MASTER_KEY_MIDI) // Master key released if (type == 0x80 && data1 == MASTER_KEY_MIDI) // Master key released
{ {
master_key_enabled = false; master_key_enabled = false;
#ifdef DEBUG
Serial.println(F("Master key disabled")); Serial.println(F("Master key disabled"));
#endif
} }
else if (type == 0x90 && data1 == MASTER_KEY_MIDI) // Master key pressed else if (type == 0x90 && data1 == MASTER_KEY_MIDI) // Master key pressed
{ {
master_key_enabled = true; master_key_enabled = true;
#ifdef DEBUG
Serial.println(F("Master key enabled")); Serial.println(F("Master key enabled"));
#endif
} }
else else
{ {
@ -426,7 +488,9 @@ void handle_sysex_parameter(const uint8_t* sysex, uint8_t len)
{ {
if (sysex[1] != 0x43) // check for Yamaha sysex if (sysex[1] != 0x43) // check for Yamaha sysex
{ {
#ifdef DEBUG
Serial.println(F("E: SysEx vendor not Yamaha.")); Serial.println(F("E: SysEx vendor not Yamaha."));
#endif
return; return;
} }
@ -436,12 +500,16 @@ void handle_sysex_parameter(const uint8_t* sysex, uint8_t len)
if ((sysex[3] & 0x7c) != 0 || (sysex[3] & 0x7c) != 2) if ((sysex[3] & 0x7c) != 0 || (sysex[3] & 0x7c) != 2)
{ {
#ifdef DEBUG
Serial.println(F("E: Not a SysEx parameter or function parameter change.")); Serial.println(F("E: Not a SysEx parameter or function parameter change."));
#endif
return; return;
} }
if (sysex[6] != 0xf7) if (sysex[6] != 0xf7)
{ {
#ifdef DEBUG
Serial.println(F("E: SysEx end status byte not detected.")); Serial.println(F("E: SysEx end status byte not detected."));
#endif
return; return;
} }
if ((sysex[3] & 0x7c) == 0) if ((sysex[3] & 0x7c) == 0)
@ -465,7 +533,7 @@ void handle_sysex_parameter(const uint8_t* sysex, uint8_t len)
dexed->controllers.masterTune = (dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12); dexed->controllers.masterTune = (dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12);
dexed->controllers.refresh(); dexed->controllers.refresh();
} }
#ifdef DEBUG
Serial.print(F("SysEx")); Serial.print(F("SysEx"));
if ((sysex[3] & 0x7c) == 0) if ((sysex[3] & 0x7c) == 0)
Serial.print(F(" function")); Serial.print(F(" function"));
@ -473,12 +541,15 @@ void handle_sysex_parameter(const uint8_t* sysex, uint8_t len)
Serial.print(sysex[4], DEC); Serial.print(sysex[4], DEC);
Serial.print(F(" = ")); Serial.print(F(" = "));
Serial.println(sysex[5], DEC); Serial.println(sysex[5], DEC);
#endif
} }
#ifdef DEBUG
else else
Serial.println(F("E: SysEx parameter length wrong.")); Serial.println(F("E: SysEx parameter length wrong."));
#endif
} }
#ifdef 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)
{ {
Serial.print(F("CPU: ")); Serial.print(F("CPU: "));

@ -26,22 +26,23 @@
// Initial values // Initial values
#define MIDI_DEVICE Serial1 #define MIDI_DEVICE Serial1
//#define USE_ONBOARD_USB_HOST 1
#define VOLUME 0.5 #define VOLUME 0.5
#define SAMPLE_RATE 44100 #define SAMPLE_RATE 44100
#define DEFAULT_MIDI_CHANNEL MIDI_CHANNEL_OMNI
#define DEFAULT_SYSEXBANK 0
#define DEFAULT_SYSEXSOUND 0
//#define DEXED_ENGINE DEXED_ENGINE_MODERN //#define DEXED_ENGINE DEXED_ENGINE_MODERN
#define USE_ONBOARD_USB_HOST 1 #define AUDIO_MEM 2
#if !defined(__MK66FX1M0__) // check for Teensy-3.6 #if !defined(__MK66FX1M0__) // check for Teensy-3.6
#define MAX_NOTES 11 // No? #define MAX_NOTES 11 // No?
#else #else
#define MAX_NOTES 16 // Yes #define MAX_NOTES 16 // Yes
#endif #endif
#define AUDIO_MEM 2
#define DEFAULT_MIDI_CHANNEL MIDI_CHANNEL_OMNI
#define DEFAULT_SYSEXBANK 0
#define DEFAULT_SYSEXSOUND 0
// Master key handling (comment for disabling) // Master key handling (comment for disabling)
#define MASTER_KEY_MIDI MIDI_C6 //#define MASTER_KEY_MIDI MIDI_C6
#define MASTER_NUM1 MIDI_C1 #define MASTER_NUM1 MIDI_C1
// Debug output // Debug output
@ -71,6 +72,12 @@
//#define SDCARD_MOSI_PIN 11 // not actually used //#define SDCARD_MOSI_PIN 11 // not actually used
//#define SDCARD_SCK_PIN 13 // not actually used //#define SDCARD_SCK_PIN 13 // not actually used
// Encoder with button
#define ENC1_PIN_A 14
#define ENC1_PIN_B 15
#define BUT1_PIN 16
#define INITIAL_ENC1_VALUE 0
// EEPROM address // EEPROM address
#define EEPROM_VOICE_ADDR 0 #define EEPROM_VOICE_ADDR 0
#define EEPROM_BANK_ADDR 0 #define EEPROM_BANK_ADDR 0

@ -49,7 +49,9 @@ bool load_sysex(uint8_t bank, uint8_t voice_number)
root = SD.open(bankdir); root = SD.open(bankdir);
if (!root) if (!root)
{ {
#ifdef DEBUG
Serial.println(F("E: Cannot open main dir from SD.")); Serial.println(F("E: Cannot open main dir from SD."));
#endif
return (false); return (false);
} }
while (42 == 42) while (42 == 42)
@ -68,25 +70,31 @@ bool load_sysex(uint8_t bank, uint8_t voice_number)
found = true; found = true;
if (get_sysex_voice(bankdir, entry, voice_number, data)) if (get_sysex_voice(bankdir, entry, voice_number, data))
{ {
#ifdef DEBUG
char n[11]; char n[11];
strncpy(n, (char*)&data[118], 10); strncpy(n, (char*)&data[118], 10);
Serial.print(F("<")); Serial.print(F("<"));
Serial.print(entry.name()); Serial.print(entry.name());
Serial.print(F("|'")); Serial.print(F("|"));
Serial.print(n); Serial.print(n);
Serial.println(F("'>")); Serial.println(F(">"));
#endif
return (dexed->loadSysexVoice(data)); return (dexed->loadSysexVoice(data));
} }
else else
#ifdef DEBUG
Serial.println(F("E: Cannot load voice data")); Serial.println(F("E: Cannot load voice data"));
#endif
entry.close(); entry.close();
break; break;
} }
} }
} }
} }
#ifdef DEBUG
if (found == false) if (found == false)
Serial.println(F("E: File not found.")); Serial.println(F("E: File not found."));
#endif
return (false); return (false);
} }
@ -104,31 +112,41 @@ bool get_sysex_voice(char* dir, File sysex, uint8_t voice_number, uint8_t* data)
if (sysex.size() != 4104) // check sysex size if (sysex.size() != 4104) // check sysex size
{ {
#ifdef DEBUG
Serial.println(F("E: SysEx file size wrong.")); Serial.println(F("E: SysEx file size wrong."));
#endif
return (false); return (false);
} }
if (file = SD.open(sysex_file)) if (file = SD.open(sysex_file))
{ {
if (file.read() != 0xf0) // check sysex start-byte if (file.read() != 0xf0) // check sysex start-byte
{ {
#ifdef DEBUG
Serial.println(F("E: SysEx start byte not found.")); Serial.println(F("E: SysEx start byte not found."));
#endif
return (false); return (false);
} }
if (file.read() != 0x43) // check sysex vendor is Yamaha if (file.read() != 0x43) // check sysex vendor is Yamaha
{ {
#ifdef DEBUG
Serial.println(F("E: SysEx vendor not Yamaha.")); Serial.println(F("E: SysEx vendor not Yamaha."));
#endif
return (false); return (false);
} }
file.seek(4103); file.seek(4103);
if (file.read() != 0xf7) // check sysex end-byte if (file.read() != 0xf7) // check sysex end-byte
{ {
#ifdef DEBUG
Serial.println(F("E: SysEx end byte not found.")); Serial.println(F("E: SysEx end byte not found."));
#endif
return (false); return (false);
} }
file.seek(3); file.seek(3);
if (file.read() != 0x09) // check for sysex type (0x09=32 voices) if (file.read() != 0x09) // check for sysex type (0x09=32 voices)
{ {
#ifdef DEBUG
Serial.println(F("E: SysEx type not 32 voices.")); Serial.println(F("E: SysEx type not 32 voices."));
#endif
return (false); return (false);
} }
file.seek(6); // start of 32*128 (=4096) bytes data file.seek(6); // start of 32*128 (=4096) bytes data
@ -139,22 +157,31 @@ bool get_sysex_voice(char* dir, File sysex, uint8_t voice_number, uint8_t* data)
uint8_t d = file.read(); uint8_t d = file.read();
if (i == voice_number) if (i == voice_number)
{ {
calc_checksum += (d & 0x7F); // calculate checksum
data[n] = d; data[n] = d;
} }
calc_checksum += (d & 0x7F); // calculate checksum
} }
} }
calc_checksum = uint8_t(~calc_checksum + 1); calc_checksum = uint8_t(~calc_checksum + 1);
#ifdef DEBUG
Serial.print(F("Checksum: 0x"));
Serial.println(calc_checksum,HEX);
#endif
if (calc_checksum != uint8_t(file.read())) if (calc_checksum != uint8_t(file.read()))
{ {
#ifdef DEBUG
Serial.println(F("E: checksum mismatch.")); Serial.println(F("E: checksum mismatch."));
#endif
return (false); return (false);
} }
} }
#ifdef DEBUG
else else
{ {
Serial.print(F("Cannot open ")); Serial.print(F("Cannot open "));
Serial.println(sysex.name()); Serial.println(sysex.name());
} }
#endif
return (true); return (true);
} }

Loading…
Cancel
Save