Components and supplies
Toggle Switch, SPDT
MIDI 5 pins connector DIN 41524
Arduino Mega 2560
Metal Enclosure, Electrical / Industrial
Rotary Encoder with Push-Button
Stereo jack socket
3PDT STOMP FOOT / PEDAL SWITCH
Tools and machines
Soldering iron (generic)
Solder Wire, Lead Free
Apps and platforms
Arduino IDE
Project description
Code
MIDI merger v1.11.1
arduino
1/* 2MIDI Merger v1.11.1 32022-10-16 4*/ 5 6/* MIDI and ShiftIn libraries */ 7#include <MIDI.h> 8#include <ShiftIn.h> 9ShiftIn<2> shift; // Two shift registers 10 11 12/* A MIDI instance is created for each of the two serial ports used */ 13MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, M1); 14MIDI_CREATE_INSTANCE(HardwareSerial, Serial3, M2); 15 16 17 18/* Shift registers variables */ 19int num; 20int incoming; 21int newRegRead; 22 23/* Switches state. The variable contains: switch number, first and second pin state */ 24int s1[3] = {0,0,0}; int s1Old[3] = {0,0,0}; 25int s2[3] = {1,0,0}; int s2Old[3] = {1,0,0}; 26int s3[2] = {2,0}; int s3Old[2] = {2,0}; 27 28int s4[3] = {3,0,0}; int s4Old[3] = {3,0,0}; 29int s5[3] = {4,0,0}; int s5Old[3] = {4,0,0}; 30int s6[2] = {5,0}; int s6Old[2] = {5,0}; 31 32/* Encoder and stomps state */ 33int e[4] = {6,0,0,0}; int eOld[4] = {6,0,0,0}; 34int f[4] = {7,0,0,0}; int fOld[4] = {7,0,0,0}; 35 36/* Leds */ 37const int ledR = 43; 38const int ledG = 45; 39const int ledB = 41; 40const int ledPow = 39; 41int ledList[4] = {ledB, ledR, ledG, ledPow}; 42 43/* Pedals variables */ 44const int p[2] = {3,2}; 45const int p2A = A4; 46int susVal[2]; 47int susValOld[2]; 48int ccVal[2]; 49int sPedal[5] = {0,0,0,0,0}; 50 51int expVal[2]; 52int expValOld[2]; 53int expcc[2]; 54int expccOld[2]; 55 56int button = 0; int buttonOld = 0; 57 58/* Settings list */ 59/* 0. MIDI channel pedal 1, Digital - Default: ch8 60 1. MIDI channel pedal 2, Digital - Default: ch8 61 2. MIDI channel pedal 2, Analog - Default: ch8 62 3. CC pedal 1, Digital - Default: sustain 63 4. CC pedal 2, Digital - Default: sustain 64 5. CC pedal 2, Analog - Default: volume 65*/ 66int setting[6] = {8, 8, 8, 1, 1, 2}; 67/* The settings are: 0.midi channel for pedal 1; 68 1. midi channel for pedal 2, digital 69 2. midi channel for pedal 2, analog 70 3. index for listcc, cc destination of pedal 1 71 4. index for listcc, cc destination of pedal 2, digital 72 5. index for listcc, cc destination of pedal 2, analog*/ 73/* Control change number to be selected for expression pedal */ 74const int listCC[12] = {64, 7, 74, 71, 11, 1, 5, 73, 91, 93, 72, 10}; 75 76 77 78 79void setup() { 80 /* turn on the "power on led" */ 81 pinMode(ledPow, OUTPUT); 82 digitalWrite(ledPow, HIGH); 83 84 M1.begin(MIDI_CHANNEL_OMNI); 85 M2.begin(MIDI_CHANNEL_OMNI); 86 Serial.begin(9600); 87 88 /* Shift registers setup */ 89 shift.begin(4, 5, 6, 7); 90 if(shift.update()) 91 incoming = readShiftReg(); 92 saveShiftReg(); 93 e[1] = 0; 94 95 /* LEDs pins */ 96 pinMode(ledR, OUTPUT); 97 pinMode(ledG, OUTPUT); 98 pinMode(ledB, OUTPUT); 99 100 101 /* pedals */ 102 pinMode(p2A, INPUT_PULLUP); 103 pinMode(p[0], INPUT_PULLUP); 104 105 /* Defines digital/analog pedal behaviour */ 106 /* Digital */ 107 if (s3[1] == 0) { 108 pinMode(p[1], INPUT_PULLUP); 109 } 110 /* Analog */ 111 if (s3[1] == 1) { 112 pinMode(p[1], OUTPUT); 113 digitalWrite(p[1], HIGH); 114 } 115 116 /* Blink the leds after setup is done */ 117 for (int ii=0; ii<=2; ii++) { 118 digitalWrite(ledList[ii],HIGH); 119 delay(250); 120 digitalWrite(ledList[ii],LOW); 121 } 122} 123 124 125 126 127void loop() { 128 129 shiftReg(); 130 131 merger(); 132 merger(); 133 merger(); 134 135 pedals(); 136 137 merger(); 138 merger(); 139 merger(); 140 141} 142 143 144 145 146 147void shiftReg() { 148 149 if(shift.update()) {newRegRead = 1;} else {newRegRead = 0;} 150 incoming = readShiftReg(); 151 152 if(newRegRead){ 153 saveShiftReg(); 154 } 155} 156 157int readShiftReg() { 158 159 for(int i = 0; i < shift.getDataWidth(); i++){ 160 bitWrite(num, i, shift.state(i)); 161 } 162 163 int incomingNumber = 0; 164 for (int bitNumber = 8; bitNumber <= 15; bitNumber++) { 165 bitWrite(incoming, incomingNumber, bitRead(num,bitNumber)); 166 incomingNumber++; 167 } 168 for (int bitNumber = 0; bitNumber <= 7; bitNumber++) { 169 bitWrite(incoming, incomingNumber, bitRead(num,bitNumber)); 170 incomingNumber++; 171 } 172 merger(); 173 return incoming; 174} 175 176 177 178void saveShiftReg() { 179 /* Assign shift register values to variables */ 180 e[1] = bitRead(incoming,0); 181 e[2] = bitRead(incoming,1); 182 e[3] = bitRead(incoming,2); 183 f[1] = bitRead(incoming,3); 184 f[3] = bitRead(incoming,4); 185 f[2] = bitRead(incoming,5); 186 s3[1] = bitRead(incoming,6); 187 s6[1] = bitRead(incoming,7); 188 189 merger(); 190 191 s2[2] = bitRead(incoming,8); 192 s2[1] = bitRead(incoming,9); 193 s1[2] = bitRead(incoming,10); 194 s1[1] = bitRead(incoming,11); 195 s4[2] = bitRead(incoming,12); 196 s4[1] = bitRead(incoming,13); 197 s5[2] = bitRead(incoming,14); 198 s5[1] = bitRead(incoming,15); 199 200 sPedal[1] = s4[2]; 201 sPedal[2] = s4[1]; 202 sPedal[3] = s5[2]; 203 sPedal[4] = s5[1]; 204 205 206 if (s1[1] == 1) { 207 M1.turnThruOn(); 208 } 209 if (s1[2] == 1) { 210 M1.turnThruOff(); 211 } 212 if (s1[1] == 0 && s1[2] == 0) { 213 M1.turnThruOn(); 214 } 215 if (s2[2] == 1) { 216 M2.turnThruOn(); 217 } 218 if (s2[1] == 1) { 219 M2.turnThruOff(); 220 } 221 if (s2[1] == 0 && s2[2] == 0) { 222 M2.turnThruOff(); 223 } 224 merger(); 225} 226 227 228 229void merger() { 230 /* Manages the MIDI routing */ 231 if (M1.read()) { 232 if (s1[2] == 1) { 233 M2.send(M1.getType(), M1.getData1(), M1.getData2(), M1.getChannel()); 234 } 235 if (s1[1] == 0 && s1[2] == 0) { 236 M2.send(M1.getType(), M1.getData1(), M1.getData2(), M1.getChannel()); 237 } 238 } 239 240 if (M2.read()) { 241 if (s2[1] == 1) { 242 M1.send(M2.getType(), M2.getData1(), M2.getData2(), M2.getChannel()); 243 } 244 } 245 switchLed(); 246} 247 248 249 250void switchLed() { 251 /* LED color based on the MIDI message type */ 252 switch(M1.getType()) { 253 case midi::NoteOn: 254 ledOn(ledG); 255 break; 256 case midi::NoteOff: 257 ledOn(ledR); 258 break; 259 case midi::PitchBend: 260 ledOn(ledB); 261 break; 262 case midi::ControlChange: 263 ledOn(ledR); 264 break; 265 } 266 switch(M2.getType()) { 267 case midi::NoteOn: 268 ledOn(ledG); 269 break; 270 case midi::NoteOff: 271 ledOn(ledR); 272 break; 273 case midi::PitchBend: 274 ledOn(ledB); 275 break; 276 case midi::ControlChange: 277 ledOn(ledR); 278 break; 279 } 280 281} 282 283 284 285void ledOn(int ledPin) { 286 /* Turns on the led having pin number equal to the argument of the function. 287 Otherwise, it turns the LED off */ 288 for (int ii = ledList[0]; ii <= ledList[2]+2; ii = ii+2) { 289 if (ledPin == ii) { 290 digitalWrite(ledPin, HIGH); 291 } else { 292 digitalWrite(ledPin, LOW); 293 } 294 } 295} 296 297 298 299void pedals() { 300 /* Manages the pedals */ 301 302 if (s3[1] != s3Old[1]) { 303 if (s3[1] == 1) { 304 pinMode(p[1], INPUT_PULLUP); 305 } else if (s3[1] == 0) { 306 pinMode(p[1], OUTPUT); 307 digitalWrite(p[1], HIGH); 308 } 309 s3Old[1] = s3[1]; 310 } 311 312 for (int ii = 0; ii <= 1; ii++) { 313 314 /* Always proceed with pedal 1 */ 315 /* Proceed with pedal two if it is set on digital/switch */ 316 if (ii == 0 || ((s3[1] == 1) && (ii == 1))) { 317 susVal[ii] = digitalRead(p[ii]); 318 if (susVal[ii] != susValOld[ii]) { 319 if (susVal[ii] == 1) { 320 ccVal[ii] = 127; 321 } 322 if (susVal[ii] == 0) { 323 ccVal[ii] = 0; 324 } 325 326 if (sPedal[ii*2+1] == 1) { 327 M1.sendControlChange(listCC[setting[ii+3]],ccVal[ii],setting[ii]); 328 } 329 if (sPedal[ii*2+2] == 1) { 330 M2.sendControlChange(listCC[setting[ii+3]],ccVal[ii],setting[ii]); 331 } 332 if (sPedal[ii*2+1] == 0 && sPedal[ii*2+2] == 0) { 333 M1.sendControlChange(listCC[setting[ii+3]],ccVal[ii],setting[ii]); 334 M2.sendControlChange(listCC[setting[ii+3]],ccVal[ii],setting[ii]); 335 } 336 337 susValOld[ii] = susVal[ii]; 338 merger(); 339 } 340 } 341 342 if (ii == 1 && s3[1] == 0) { 343 expVal[1] = analogRead(p2A); 344 expcc[1] = map(expVal[1],30,1023,0,127); 345 346 if (expcc[1] != expccOld[1] && abs(expccOld[1]-expcc[1])>= 5) { 347 if (s5[1] == 1) { 348 M1.sendControlChange(listCC[setting[2+3]],expcc[1],setting[2]); 349 } 350 if (s5[2] == 1) { 351 M2.sendControlChange(listCC[setting[2+3]],expcc[1],setting[2]); 352 } 353 if (s5[1] == 0 && s5[2] == 0) { 354 M1.sendControlChange(listCC[setting[2+3]],expcc[1],setting[2]); 355 M2.sendControlChange(listCC[setting[2+3]],expcc[1],setting[2]); 356 } 357 358 359 expccOld[1] = expcc[1]; 360 } 361 } 362 merger(); 363 364 } 365 366}
Downloadable files
MIDI ports on serial3
MIDI ports on serial3
MIDI ports on serial2
MIDI ports on serial2
Pedals
This scheme represents the wiring and setting of the interchangable digital/analog port. A switch is used to change between these two modes.
Pedals
Shift registers
A single switch position is represented as an example for the connection that is repeated for all the 8 central pins of each shift register. The central pin of a switch is connected to 5V, the two remaining pins are connected to the shift registers as indicated in the example.
Shift registers
Comments
Only logged in users can leave comments