From 5ade4a16a3708f8c669808b8ece1b80950b46aaf Mon Sep 17 00:00:00 2001 From: Guillaume <1017720+gwilherm@users.noreply.github.com> Date: Sun, 18 Jun 2023 10:33:51 +0200 Subject: [PATCH 1/2] Add Control-Surface submodule --- .gitmodules | 3 +++ midi-octopot/Control-Surface | 1 + 2 files changed, 4 insertions(+) create mode 160000 midi-octopot/Control-Surface diff --git a/.gitmodules b/.gitmodules index 0efc45b..b62152f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "fritzing-parts"] path = fritzing-parts url = https://github.com/htho/fritzing-parts +[submodule "midi-octopot/Control-Surface"] + path = midi-octopot/Control-Surface + url = https://github.com/tttapa/Control-Surface/ diff --git a/midi-octopot/Control-Surface b/midi-octopot/Control-Surface new file mode 160000 index 0000000..39182bb --- /dev/null +++ b/midi-octopot/Control-Surface @@ -0,0 +1 @@ +Subproject commit 39182bbab79487236c11579db3acfa336813bf54 From bbb102f6da4fd0f79074227bd282d8cffcfc7f41 Mon Sep 17 00:00:00 2001 From: Guillaume <1017720+gwilherm@users.noreply.github.com> Date: Sun, 18 Jun 2023 10:42:02 +0200 Subject: [PATCH 2/2] Use Control-Surface framework --- midi-octopot/Makefile | 6 +- midi-octopot/midi-octopot.ino | 166 ++++++++++++++++------------------ 2 files changed, 83 insertions(+), 89 deletions(-) diff --git a/midi-octopot/Makefile b/midi-octopot/Makefile index 294e967..757b038 100644 --- a/midi-octopot/Makefile +++ b/midi-octopot/Makefile @@ -1,5 +1,9 @@ BOARD_TAG = micro -ARDUINO_LIBS = MIDIUSB MIDI_Library USB-MIDI EEPROM + +# Platform libs +ARDUINO_LIBS = SPI EEPROM +# User libs +ARDUINO_LIBS+= Control-Surface MIDIUSB # Workaround for MIDIUSB with 1.8.19: 1819 < 10606 (1.6.6) ARDUINO_VERSION = 10819 diff --git a/midi-octopot/midi-octopot.ino b/midi-octopot/midi-octopot.ino index 0aa2f69..623b8c5 100644 --- a/midi-octopot/midi-octopot.ino +++ b/midi-octopot/midi-octopot.ino @@ -1,32 +1,17 @@ -#include +#include #include -USBMIDI_CREATE_DEFAULT_INSTANCE(); - -enum { - MIDI_CC_PORTAMENTO_TIME = 0x05, - MIDI_CC_VOLUME = 0x07, - MIDI_CC_PAN_MSB = 0x0A, - - MIDI_CC_SOUND_CONTROLLER_2 = 0x47, // Timbre/Harmonic Intensity - MIDI_CC_SOUND_CONTROLLER_3 = 0x48, // Release Time - MIDI_CC_SOUND_CONTROLLER_4 = 0x49, // Attack Time - MIDI_CC_SOUND_CONTROLLER_5 = 0x4A, // Brightness - MIDI_CC_EFFECTS_1_DEPTH = 0x5B, // Reverb amount - MIDI_CC_EFFECTS_4_DEPTH = 0x5F, // Detune amount -}; - -#define MIDI_CHANNEL 1 #define POT_NB 8 -byte pot_pin[] = {A10, A9, A8, A7, - A0, A1, A2, A3}; +USBMIDI_Interface midi; // Instantiate a MIDI Interface to use -byte default_pot_mcc[] = {MIDI_CC_SOUND_CONTROLLER_2, MIDI_CC_SOUND_CONTROLLER_3, MIDI_CC_PORTAMENTO_TIME, MIDI_CC_EFFECTS_1_DEPTH, - MIDI_CC_SOUND_CONTROLLER_5, MIDI_CC_SOUND_CONTROLLER_4, MIDI_CC_EFFECTS_4_DEPTH, MIDI_CC_PAN_MSB}; +uint8_t default_pot_mcc[] = {MIDI_CC::Sound_Controller_2, MIDI_CC::Sound_Controller_4, MIDI_CC::Portamento_Time, MIDI_CC::Effects_1, + MIDI_CC::Sound_Controller_5, MIDI_CC::Sound_Controller_4, MIDI_CC::Effects_4, MIDI_CC::Pan}; -byte pot_mcc[] = {0, 0, 0, 0, 0, 0, 0, 0}; -byte pot_val[] = {0, 0, 0, 0, 0, 0, 0, 0}; +CCPotentiometer pot[] = { + { A10, 0 }, { A9, 0 }, { A8, 0 }, { A7, 0 }, + { A0, 0 }, { A1, 0 }, { A2, 0 }, { A3, 0 } +}; enum { @@ -37,113 +22,118 @@ enum RESET_CMD // In: Restore default configuration }; -typedef struct +typedef union { - byte msg_idx; - byte pot_mcc[POT_NB]; -} patch_sts_t; + struct msg + { + uint8_t syx_hdr; // 0xF0 + uint8_t msg_idx; + uint8_t pot_mcc[POT_NB]; + uint8_t syx_ftr; // 0xF7 + } sts; + uint8_t array[sizeof(struct msg)]; +} patch_sts_u; + typedef struct { - byte syx_hdr; // 0xF0 - byte msg_idx; - byte pot_idx; - byte pot_mcc; - byte syx_ftr; // 0xF7 + uint8_t syx_hdr; // 0xF0 + uint8_t msg_idx; + uint8_t pot_idx; + uint8_t pot_mcc; + uint8_t syx_ftr; // 0xF7 } patch_cmd_t; void sendPatchStatus() { - patch_sts_t sts; - sts.msg_idx = PATCH_STS; - memcpy(&sts.pot_mcc, &pot_mcc, POT_NB); - MIDI.sendSysEx(sizeof(patch_sts_t), (byte*)&sts); + patch_sts_u sts; + sts.sts.syx_hdr = 0xF0; + sts.sts.syx_ftr = 0xF7; + sts.sts.msg_idx = PATCH_STS; + + for (int i = 0; i < POT_NB; i++) + sts.sts.pot_mcc[i] = pot[i].getAddress().getAddress(); + + midi.sendSysEx(sts.array); } -void updatePatch(byte* array, unsigned size) +void updatePatch(const uint8_t* array, unsigned size) { if (size == sizeof(patch_cmd_t)) { patch_cmd_t* patch = (patch_cmd_t*)array; if ((patch->pot_idx < POT_NB) && (patch->pot_mcc <= 127)) - pot_mcc[patch->pot_idx] = patch->pot_mcc; + pot[patch->pot_idx].setAddress(patch->pot_mcc); } } void saveConfig() { for (int i = 0; i < POT_NB; i++) - EEPROM.update(i, pot_mcc[i]); + EEPROM.update(i, pot[i].getAddress().getAddress()); } void restoreConfig() { for (int i = 0; i < POT_NB; i++) { - byte value = EEPROM.read(i); + uint8_t value = EEPROM.read(i); if (value <= 127) - pot_mcc[i] = value; + pot[i].setAddress(value); else - pot_mcc[i] = default_pot_mcc[i]; + pot[i].setAddress(default_pot_mcc[i]); } } void resetConfig() { for (int i = 0; i < POT_NB; i++) - pot_mcc[i] = default_pot_mcc[i]; + pot[i].setAddress(default_pot_mcc[i]); } -void handleSysEx(byte* array, unsigned size) -{ - if (size < 1) return; - switch (array[1]) - { - case PATCH_REQ: - sendPatchStatus(); - break; - case PATCH_CMD: - updatePatch(array, size); - break; - case SAVE_CMD: - saveConfig(); - break; - case RESET_CMD: - resetConfig(); - break; - default: - break; +// Custom MIDI callback that prints incoming SysEx messages. +struct MyMIDI_Callbacks : MIDI_Callbacks { + + // This callback function is called when a SysEx message is received. + void onSysExMessage(MIDI_Interface &, SysExMessage sysex) override { +#ifdef DEBUG + // Print the message + Serial << F("Received SysEx message: ") // + << AH::HexDump(sysex.data, sysex.length) // + << F(" on cable ") << sysex.cable.getOneBased() << endl; +#endif + + if (sysex.length < 1) return; + switch (sysex.data[1]) + { + case PATCH_REQ: + sendPatchStatus(); + break; + case PATCH_CMD: + updatePatch(sysex.data, sysex.length); + break; + case SAVE_CMD: + saveConfig(); + break; + case RESET_CMD: + resetConfig(); + break; + default: + break; + } } -} +} callback {}; void setup() { - Serial.begin(115200); - + restoreConfig(); - - MIDI.begin(MIDI_CHANNEL_OMNI); - MIDI.setHandleSystemExclusive(handleSysEx); + + Control_Surface.begin(); // Initialize the Control Surface + midi.begin(); + midi.setCallbacks(callback); } void loop() { - MIDI.read(); - - char serial_output[32]; - bool display_update = false; - - for (byte i = 0; i < POT_NB; i++) - { - byte val = analogRead(pot_pin[i]) / 8; - if (val != pot_val[i]) - { - display_update = true; - pot_val[i] = val; - MIDI.sendControlChange(pot_mcc[i], pot_val[i], MIDI_CHANNEL); - } - - sprintf(serial_output+3*i+i, "%03d ", (int)pot_val[i]); - } - - if (display_update) - Serial.println(serial_output); + Control_Surface.loop(); // Update the Control Surface + midi.update(); }