From e29471056645e135e44a6774013f71e34021a960 Mon Sep 17 00:00:00 2001 From: Holger Wirtz Date: Mon, 4 Jun 2018 13:19:09 +0200 Subject: [PATCH] Hopefully fixed controller handling. Added master key support for voice selection (32 white keys started from C1) and volume handling (10 keys started from C#1). --- MicroDexed.ino | 193 ++++++++++++++++++++++++++++++++++--------------- config.h | 5 +- dexed.cpp | 23 ++++-- 3 files changed, 156 insertions(+), 65 deletions(-) diff --git a/MicroDexed.ino b/MicroDexed.ino index 907176b..2bf6592 100644 --- a/MicroDexed.ino +++ b/MicroDexed.ino @@ -44,19 +44,19 @@ AudioControlSGTL5000 sgtl5000_1; //xy=507,403 MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, MIDI); Dexed* dexed = new Dexed(SAMPLE_RATE); - IntervalTimer sched_master_key_auto_disable; +bool sd_card_available = false; +bool master_key_enabled = false; #ifdef SHOW_CPU_LOAD_MSEC IntervalTimer sched_show_cpu_usage; #endif + #ifdef USE_ONBOARD_USB_HOST USBHost usb_host; MIDIDevice midi_usb(usb_host); #endif -bool sd_card_available = false; -bool master_key_enabled = false; #ifdef TEST_MIDI IntervalTimer sched_note_on; IntervalTimer sched_note_off; @@ -72,7 +72,7 @@ void setup() Serial.println(F("(c)2018 H. Wirtz")); Serial.println(F("setup start")); - // strat up USB host + // start up USB host #ifdef USE_ONBOARD_USB_HOST usb_host.begin(); #endif @@ -105,15 +105,12 @@ void setup() sched_show_cpu_usage.begin(show_cpu_and_mem_usage, SHOW_CPU_LOAD_MSEC * 1000); #endif - load_sysex("ROM1A.SYX", 17); + load_sysex("ROM1A.SYX", 1); + #ifdef DEBUG show_patch(); #endif - //dexed->activate(); - //dexed->setMaxNotes(MAX_NOTES); - //dexed->setEngineType(DEXED_ENGINE); - Serial.print(F("AUDIO_BLOCK_SAMPLES=")); Serial.println(AUDIO_BLOCK_SAMPLES); @@ -144,47 +141,17 @@ void setup() void loop() { int16_t* audio_buffer; // pointer to 128 * int16_t (=256 bytes!) - bool break_for_calculation = false; while (42 == 42) // DON'T PANIC! { -#ifdef USE_ONBOARD_USB_HOST - usb_host.Task(); -#endif + handle_midi_input(); + audio_buffer = queue1.getBuffer(); if (audio_buffer == NULL) { Serial.println(F("E: audio_buffer allocation problems!")); } -#ifdef USE_ONBOARD_USB_HOST - while (midi_usb.read()) - { - break_for_calculation = queue_midi_event(midi_usb.getType(), midi_usb.getData1(), midi_usb.getData2()); - if (break_for_calculation == true) - break; - } - - if (!break_for_calculation) - { -#endif - while (MIDI.read()) - { - if (MIDI.getType() == 0xF0) // SysEX - { - handle_sysex_parameter(MIDI.getSysExArray(), MIDI.getSysExArrayLength()); - } - else - { - break_for_calculation = queue_midi_event(MIDI.getType(), MIDI.getData1(), MIDI.getData2()); - if (break_for_calculation == true) - break; - } - } -#ifdef USE_ONBOARD_USB_HOST - } -#endif - if (!queue1.available()) continue; @@ -205,6 +172,35 @@ void loop() } } +void handle_midi_input(void) +{ +#ifdef USE_ONBOARD_USB_HOST + usb_host.Task(); + while (midi_usb.read()) + { + if (MIDI.getType() == 0xF0) // SysEX + { + handle_sysex_parameter(MIDI.getSysExArray(), MIDI.getSysExArrayLength()); + } + else if (queue_midi_event(midi_usb.getType(), midi_usb.getData1(), midi_usb.getData2())) + return; + } +#endif + + while (MIDI.read()) + { + if (MIDI.getType() == 0xF0) // SysEX + { + handle_sysex_parameter(MIDI.getSysExArray(), MIDI.getSysExArrayLength()); + } + else + { + if (queue_midi_event(MIDI.getType(), MIDI.getData1(), MIDI.getData2())) + return; + } + } +} + #ifdef TEST_MIDI void note_on(void) { @@ -260,6 +256,34 @@ void note_off(void) } #endif +bool handle_master_key(uint8_t data) +{ + int8_t num = num_key_base_c(data); + + if (num > 0) + { + // a white key! + num = num - 1 + (((data - MASTER_NUM1) / 12) * 7); + if (num <= 32) + { + if (!load_sysex("RITCH0~1.SYX", num)) + { + Serial.print("E: cannot load voice number "); + Serial.println(num, DEC); + } + } + return (true); + } + else + { + // a black key! + num = abs(num) + (((data - MASTER_NUM1) / 12) * 7); + if (num <= 10) + sgtl5000_1.volume(num * 0.1); + } + return (false); +} + bool queue_midi_event(uint8_t type, uint8_t data1, uint8_t data2) { #ifdef SHOW_MIDI_EVENT @@ -273,16 +297,10 @@ bool queue_midi_event(uint8_t type, uint8_t data1, uint8_t data2) if (master_key_enabled == true) { - if (data1 >= 24 && data1 <= 56) - { - if (!load_sysex("RITCH0~1.SYX", data1 - 24)) - { - Serial.print("E: cannot load voice number "); - Serial.println(data1 - 24, DEC); - } - } - master_key_enabled = false; - Serial.println("Master key disabled"); + master_key_enabled = handle_master_key(data1); + + if (master_key_enabled == false) + Serial.println("Master key disabled"); } else { @@ -300,6 +318,39 @@ bool queue_midi_event(uint8_t type, uint8_t data1, uint8_t data2) return (false); } +int8_t num_key_base_c(uint8_t midi_note) +{ + switch (midi_note % 12) + { + // positive numbers are white keys, negative black ones + case 0: + return (1); + case 1: + return (-1); + case 2: + return (2); + case 3: + return (-2); + case 4: + return (3); + case 5: + return (4); + case 6: + return (-3); + case 7: + return (5); + case 8: + return (-4); + case 9: + return (6); + case 10: + return (-5); + case 11: + return (7); + } + return (0); +} + void handle_sysex_parameter(const uint8_t* sysex, uint8_t len) { // parse parameter change @@ -307,27 +358,51 @@ void handle_sysex_parameter(const uint8_t* sysex, uint8_t len) { if (sysex[1] != 0x43) // check for Yamaha sysex { - Serial.println("E: SysEx vendor not Yamaha."); + Serial.println(F("E: SysEx vendor not Yamaha.")); return; } - if ((sysex[3] & 0x7c) != 0) + if ((sysex[3] & 0x7c) != 0 || (sysex[3] & 0x7c) != 2) { - Serial.println("E: Not a SysEx parameter change."); + Serial.println(F("E: Not a SysEx parameter or function parameter change.")); return; } if (sysex[6] != 0xf7) { - Serial.println("E: SysEx end status byte not detected."); + Serial.println(F("E: SysEx end status byte not detected.")); return; } - dexed->data[sysex[4]] = sysex[5]; // set parameter - Serial.print("SysEx parameter "); + if ((sysex[3] & 0x7c) == 0) + { + dexed->data[sysex[4]] = sysex[5]; // set parameter + dexed->doRefreshVoice(); + } + else + { + dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET - 63 + sysex[4]] = sysex[5]; // set functionparameter + dexed->controllers.values_[kControllerPitchRange] = dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE]; + dexed->controllers.values_[kControllerPitchStep] = dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP]; + dexed->controllers.wheel.setRange(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE]); + dexed->controllers.wheel.setTarget(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN]); + dexed->controllers.foot.setRange(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE]); + dexed->controllers.foot.setTarget(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN]); + dexed->controllers.breath.setRange(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE]); + dexed->controllers.breath.setTarget(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN]); + dexed->controllers.at.setRange(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE]); + dexed->controllers.at.setTarget(dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN]); + dexed->controllers.masterTune = (dexed->data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12); + dexed->controllers.refresh(); + } + + Serial.print(F("SysEx")); + if ((sysex[3] & 0x7c) == 0) + Serial.print(F(" function")); + Serial.print(F(" parameter ")); Serial.print(sysex[4], DEC); - Serial.print("="); + Serial.print(F("=")); Serial.println(sysex[5], DEC); } else - Serial.println("E: SysEx parameter length wrong."); + Serial.println(F("E: SysEx parameter length wrong.")); } void master_key_auto_disable(void) diff --git a/config.h b/config.h index f96ea54..3a357aa 100644 --- a/config.h +++ b/config.h @@ -39,8 +39,11 @@ #define SHOW_CPU_LOAD_MSEC 5000 #define MAX_NOTES 16 #define AUDIO_MEM 2 -#define MASTER_KEY_MIDI 108 + +#define MASTER_KEY_MIDI 84 #define MASTER_KEY_AUTO_DISABLE_MSEC 5000 +#define MASTER_NUM1 24 +#define MASTER_BANK_SELECT 83 // Use these with the Teensy Audio Shield #define SDCARD_CS_PIN 10 diff --git a/dexed.cpp b/dexed.cpp index 4e72373..a8e0eb2 100644 --- a/dexed.cpp +++ b/dexed.cpp @@ -555,15 +555,15 @@ bool Dexed::loadSysexVoice(uint8_t* new_data) *(p_data + DEXED_VOICE_OFFSET + DEXED_TRANSPOSE) = new_data[117]; memcpy(&data[DEXED_VOICE_OFFSET + DEXED_NAME], &new_data[118], 10); *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE) = 1; - *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP) = 0; + *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP) = 1; *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE) = 99; - *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN) = 0; + *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN) = 7; *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE) = 99; - *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN) = 0; + *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN) = 7; *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE) = 99; - *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN) = 0; + *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN) = 7; *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE) = 99; - *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN) = 0; + *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN) = 7; *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE) = 0; *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP1_ENABLE) = 1; *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP2_ENABLE) = 1; @@ -573,6 +573,19 @@ bool Dexed::loadSysexVoice(uint8_t* new_data) *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP6_ENABLE) = 1; *(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MAX_NOTES) = MAX_NOTES; + controllers.values_[kControllerPitchRange] = data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_RANGE]; + controllers.values_[kControllerPitchStep] = data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_PITCHBEND_STEP]; + controllers.wheel.setRange(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_RANGE]); + controllers.wheel.setTarget(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MODWHEEL_ASSIGN]); + controllers.foot.setRange(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_RANGE]); + controllers.foot.setTarget(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_FOOTCTRL_ASSIGN]); + controllers.breath.setRange(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_RANGE]); + controllers.breath.setTarget(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_BREATHCTRL_ASSIGN]); + controllers.at.setRange(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_RANGE]); + controllers.at.setTarget(data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_AT_ASSIGN]); + controllers.masterTune = (data[DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_MASTER_TUNE] * 0x4000 << 11) * (1.0 / 12); + controllers.refresh(); + setOPs((*(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP1_ENABLE) << 5) | (*(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP2_ENABLE) << 4) | (*(p_data + DEXED_GLOBAL_PARAMETER_OFFSET + DEXED_OP3_ENABLE) << 3) |