From b9ae4d85b16769d049428822650732bacd97c61a Mon Sep 17 00:00:00 2001 From: John Edgar Park Date: Wed, 25 Apr 2018 21:03:25 -0700 Subject: [PATCH] Initial commit Feather + Trellis + DSP-G1 synthesizer --- DSP-G1_Trellis_Synth/DSP-G1_Trellis_Synth.ino | 558 ++++++++++++++++++ 1 file changed, 558 insertions(+) create mode 100644 DSP-G1_Trellis_Synth/DSP-G1_Trellis_Synth.ino diff --git a/DSP-G1_Trellis_Synth/DSP-G1_Trellis_Synth.ino b/DSP-G1_Trellis_Synth/DSP-G1_Trellis_Synth.ino new file mode 100644 index 00000000..74df2e86 --- /dev/null +++ b/DSP-G1_Trellis_Synth/DSP-G1_Trellis_Synth.ino @@ -0,0 +1,558 @@ +#include +#include "Adafruit_Trellis.h" +//use Trellis 0-11 and 16-27 as input for notes. +//use Trellis 12-15 and 28-31 for input to modes, sequencer, patches +//six potentiometers as CC value input +//rotary switch to choose banks of CC numbers for knobs + +//John Park for Adafruit Industries + +MIDI_CREATE_DEFAULT_INSTANCE(); +Adafruit_Trellis matrix0 = Adafruit_Trellis(); //left Trellis +Adafruit_Trellis matrix1 = Adafruit_Trellis(); //right Trellis +Adafruit_TrellisSet trellis = Adafruit_TrellisSet(&matrix0, &matrix1); +#define NUMTRELLIS 2 +#define numKeys (NUMTRELLIS * 16) +//#define INTPIN A2 +#define MOMENTARY 0 +#define LATCHING 1 +int holdMode = 0; +int lastHoldMode = 0; +static const unsigned LED = 13; // LED pin on the Feather + +/*********************/ +//pick scale mode here: +//0=chromatic, 1=major, 2=minor, 3=dorian, 4=mixolydian, 5=harmonic minor +int scaleMode = 0; //Dorian +/*********************/ +int octave = 1; +int transpose[6] = {0, 12, 24, 36, 48, 60}; //multiply notes depending on octave +//Trellis assignments +/* +//First three rows map to MIDI Notes, bottom row is special functions +------------------------------------------------------------------------------- + 0 1 2 3 16 17 18 19 + M16 M17 M18 M19 M20 M21 M22 M23 + + + 4 5 6 7 20 21 22 23 + M8 M9 M10 M11 M12 M13 M14 M15 + + + 8 9 10 11 24 25 26 27 + M0 M1 M2 M3 M4 M5 M6 M7 +------------------------------------------------------------------------------- + + 12 13 14 15 28 29 30 31 + seq patch pause/play rec I II III hold mode +------------------------------------------------------------------------------- +*/ + +//Map physical Trellis grids to single logical grid +int logicalPads[32] = { 0, 1, 2, 3, 8, 9, 10, 11, + 16, 17, 18, 19, 24, 25, 26, 27, + 4, 5, 6, 7, 12, 13, 14, 15, + 20, 21, 22, 23, 28, 29, 30, 31 } ; + +int padNoteMap[24] = { 16, 17, 18, 19, 20, 21, 22, 23, + 8, 9, 10, 11, 12, 13, 14, 15, + 0, 1, 2, 3, 4, 5, 6, 7}; + +int padFuncMap[8] = { //note, only hold mode is implemented currently + 0, // sequencer + 1, // patch + 2, // pause/play / recall + 3, // record / store + 4, // sequence I / patch I + 5, // seq. II / patch II + 6, // seq. III / patch III + 7 //hold mode: LATCHING or MOMENTARY + }; +//Define Scales +int scalesMatrix[6][24] = { +//Chromatic + { 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23 }, + +//Major + { 0, 2, 4, 5, 7, 9, 11, 12, + 12, 14, 16, 17, 19, 21, 23, 24, + 24, 26, 28, 29, 31, 33, 35, 36 }, + +//Minor + { 0, 2, 3, 5, 7, 8, 10, 12, + 12, 14, 15, 17, 19, 20, 22, 24, + 24, 26, 27, 29, 31, 32, 34, 36 }, + +//Dorian + { 0, 2, 3, 5, 6, 9, 10, 12, + 12, 14, 15, 17, 18, 21, 22, 24, + 24, 26, 27, 29, 30, 33, 34, 36 }, + +//Mixolydian + { 0, 2, 4, 5, 7, 9, 10, 12, + 12, 14, 16, 17, 19, 21, 22, 24, + 24, 26, 28, 29, 31, 33, 34, 36 }, + +//Harmonic Minor + { 0, 2, 3, 5, 7, 8, 11, 12, + 12, 14, 15, 17, 19, 20, 23, 24, + 24, 26, 27, 29, 31, 32, 35, 36 } +}; + +//Set up selector switch pins to read digital input pins that set the CC bank +const int CC_bankPin0 = 9; +const int CC_bankPin1 = 10; +const int CC_bankPin2 = 11; +const int CC_bankPin3 = 12; + +int CC_bankState0 = 0; +int CC_bankState1 = 0; +int CC_bankState2 = 0; +int CC_bankState3 = 0; + +//current bank per knob. assume not on 0-3 +int currentBank[6] = {4, 4, 4, 4, 4, 4}; +//last bank per knob. assume not on 0-3 +int lastBank[6] = {5, 5, 5, 5, 5, 5}; + +//Set up potentiometer pins +const int CC0_pin = A0; //potentiometer pin +int CC0_value; //store pot value +const int CC1_pin = A1; +int CC1_value; +const int CC2_pin = A2; +int CC2_value; +const int CC3_pin = A3; +int CC3_value; +const int CC4_pin = A4; +int CC4_value; +const int CC5_pin = A5; +int CC5_value; + +int CC_read[4] ; + +//Store previous values to enable hysteresis and pick-up mode for knobs +int CC_bank0_lastValue[6] = {32, 32, 32, 32, 32, 32}; +int CC_bank1_lastValue[6] = {32, 32, 32, 32, 32, 32}; +int CC_bank2_lastValue[6] = {32, 32, 32, 32, 32, 32}; +int CC_bank3_lastValue[6] = {32, 32, 32, 32, 32, 32}; + +int CC_bank0_value[6] = {0, 0, 0, 0, 0, 0}; +int CC_bank1_value[6] = {0, 0, 0, 0, 0, 0}; +int CC_bank2_value[6] = {0, 0, 0, 0, 0, 0}; +int CC_bank3_value[6] = {0, 0, 0, 0, 0, 0}; + +void setup() { + Serial.begin(115200); + pinMode(LED, OUTPUT); + digitalWrite(LED, HIGH); //turn this on as a system power indicator + pinMode(CC_bankPin0, INPUT_PULLUP); //loop this + pinMode(CC_bankPin1, INPUT_PULLUP); + pinMode(CC_bankPin2, INPUT_PULLUP); + pinMode(CC_bankPin3, INPUT_PULLUP); + + // Default Arduino I2C speed is 100 KHz, but the HT16K33 supports + // 400 KHz. We can force this for faster read & refresh, but may + // break compatibility with other I2C devices...so be prepared to + // comment this out, or save & restore value as needed. +#ifdef ARDUINO_ARCH_SAMD + Wire.setClock(400000L); +#endif +#ifdef __AVR__ + TWBR = 12; // 400 KHz I2C on 16 MHz AVR +#endif + + trellis.begin(0x70, 0x71); + for (uint8_t i=0; i 3){ //hysteresis for spinning knob too fast + Serial.print("\nCC_bank0_value for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank0_value[k]); + Serial.print("CC_bank0_lastValue for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank0_lastValue[k]); + MIDI.sendControlChange(CCNumber[k], CC_bank0_value[k], 1); + //Serial.print("CC number: "); Serial.println(CCNumber[k]); + CC_bank0_lastValue[k] = CC_bank0_value[k]; + lastBank[k] = 0; + } + } + } + } + + if(CC_bank == 1){ //second bank is selected + for(int k=0; k<6; k++){ //loop through each of six pots + if(currentBank[k] != lastBank[k]){ + //read CC values from potentiometers + CC_read[CC_bank] = analogRead(AnalogPin[k]); + CC_bank1_value[k] = map(CC_read[CC_bank], 0, 1023, 0, 127); // remap range to 0-127 + //check against last read when we were on this bank, only send CC if value + //of knob is withing a certain delta of the last value + if((abs(CC_bank1_lastValue[k] - CC_bank1_value[k])) < 3){ //hysteresis for spinning knob too fast + Serial.println("Pickup achieved."); + Serial.print("\nCC_bank1_value for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank1_value[k]); + Serial.print("CC_bank1_lastValue for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank1_lastValue[k]); + lastBank[k] = 1; + } + } + else if(currentBank[k] == lastBank[k]){ + //read CC values from potentiometers + CC_read[CC_bank] = analogRead(AnalogPin[k]); + CC_bank1_value[k] = map(CC_read[CC_bank], 0, 1023, 0, 127); // remap range to 0-127 + //check against last read, only send CC if value has changed since last read by a certain delta + if((abs(CC_bank1_lastValue[k] - CC_bank1_value[k])) > 3){ //hysteresis for spinning knob too fast + Serial.print("\nCC_bank1_value for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank1_value[k]); + Serial.print("CC_bank1_lastValue for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank1_lastValue[k]); + MIDI.sendControlChange(CCNumber[k], CC_bank1_value[k], 1); + //Serial.print("CC number: "); Serial.println(CCNumber[k]); + CC_bank1_lastValue[k] = CC_bank1_value[k]; + lastBank[k] = 1; + } + } + } + } + if(CC_bank == 2){ //third bank is selected + for(int k=0; k<6; k++){ //loop through each of six pots + if(currentBank[k] != lastBank[k]){ + //read CC values from potentiometers + CC_read[CC_bank] = analogRead(AnalogPin[k]); + CC_bank2_value[k] = map(CC_read[CC_bank], 0, 1023, 0, 127); // remap range to 0-127 + //check against last read when we were on this bank, only send CC if value + //of knob is withing a certain delta of the last value + if((abs(CC_bank2_lastValue[k] - CC_bank2_value[k])) < 3){ //hysteresis for spinning knob too fast + Serial.println("Pickup achieved."); + Serial.print("\nCC_bank2_value for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank2_value[k]); + Serial.print("CC_bank2_lastValue for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank2_lastValue[k]); + lastBank[k] = 2; + } + } + else if(currentBank[k] == lastBank[k]){ + //read CC values from potentiometers + CC_read[CC_bank] = analogRead(AnalogPin[k]); + CC_bank2_value[k] = map(CC_read[CC_bank], 0, 1023, 0, 127); // remap range to 0-127 + //check against last read, only send CC if value has changed since last read by a certain delta + if((abs(CC_bank2_lastValue[k] - CC_bank2_value[k])) > 3){ //hysteresis for spinning knob too fast + Serial.print("\nCC_bank2_value for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank2_value[k]); + Serial.print("CC_bank2_lastValue for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank2_lastValue[k]); + MIDI.sendControlChange(CCNumber[k], CC_bank2_value[k], 1); + //Serial.print("CC number: "); Serial.println(CCNumber[k]); + CC_bank2_lastValue[k] = CC_bank2_value[k]; + lastBank[k] = 2; + } + } + } + } + if(CC_bank == 3){ //fourth bank is selected + for(int k=0; k<6; k++){ //loop through each of six pots + if(currentBank[k] != lastBank[k]){ + //read CC values from potentiometers + CC_read[CC_bank] = analogRead(AnalogPin[k]); + CC_bank3_value[k] = map(CC_read[CC_bank], 0, 1023, 0, 127); // remap range to 0-127 + //check against last read when we were on this bank, only send CC if value + //of knob is withing a certain delta of the last value + if((abs(CC_bank3_lastValue[k] - CC_bank3_value[k])) < 3){ //hysteresis for spinning knob too fast + Serial.println("Pickup achieved."); + Serial.print("\nCC_bank3_value for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank3_value[k]); + Serial.print("CC_bank3_lastValue for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank3_lastValue[k]); + lastBank[k] = 3; + } + } + else if(currentBank[k] == lastBank[k]){ + //read CC values from potentiometers + CC_read[CC_bank] = analogRead(AnalogPin[k]); + CC_bank3_value[k] = map(CC_read[CC_bank], 0, 1023, 0, 127); // remap range to 0-127 + //check against last read, only send CC if value has changed since last read by a certain delta + if((abs(CC_bank3_lastValue[k] - CC_bank3_value[k])) > 3){ //hysteresis for spinning knob too fast + Serial.print("\nCC_bank3_value for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank3_value[k]); + Serial.print("CC_bank3_lastValue for knob: "); Serial.print(k); Serial.print("\t"); Serial.println(CC_bank3_lastValue[k]); + MIDI.sendControlChange(CCNumber[k], CC_bank3_value[k], 1); + //Serial.print("CC number: "); Serial.println(CCNumber[k]); + CC_bank3_lastValue[k] = CC_bank3_value[k]; + lastBank[k] = 3; + } + } + } + } +}