Advertisement
Guest User

Charlie

a guest
Aug 31st, 2024
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 12.72 KB | None | 0 0
  1. #include <MIDI.h>
  2.  
  3. MIDI_CREATE_DEFAULT_INSTANCE();
  4.  
  5. // Pin assignments
  6. const int incBtnPin = 7; // Button for increasing the program change value
  7. const int decBtnPin = 6; // Button for decreasing the program change value
  8. const int cc64BtnPin = 8; // Button for toggling Control Change 64 (Sustain) on/off
  9. const int aftertouchBtnPin = 9; // Button to toggle aftertouch transmission on/off
  10. const int potPin = A0; // Potentiometer for aftertouch value
  11. const int expression2BtnPin = 10; // Button to toggle Expression2 on/off
  12. const int expression2PotPin = A1; // Potentiometer for Expression2 value
  13. const int expression3BtnPin = 11; // Button to toggle Expression3 on/off
  14. const int expression3PotPin = A2; // Potentiometer for Expression3 value
  15. const int expression4BtnPin = 12; // Button to toggle Expression4 on/off
  16. const int expression4PotPin = A3; // Potentiometer for Expression4 value
  17. const int numBanks = 3; // How many MIDI Patch Banks does the synth have?
  18. const int maxProgramsPerBank = 128; // Maximum number of programs per bank
  19. const int maxPrograms = numBanks * maxProgramsPerBank; // Total maximum number of programs
  20.  
  21. // MIDI settings
  22. int midiChannel = 1; // Set MIDI channel for both program change and note buttons
  23. int currentBank = 3; // Initial MIDI Patch Bank
  24. int currentProgram = 63; // Initial MIDI Program (Bank 3, 65 is first User patch on Microbrute)
  25. int currentOctave = 0; // Initial Octave on Power Up
  26. int expression2MidiChannel = 2; // Set the MIDI channel for Expression2
  27. int expression3MidiChannel = 2; // Set the MIDI channel for Expression3
  28. int expression4MidiChannel = 2; // Set the MIDI channel for Expression4
  29.  
  30. // Button state tracking
  31. bool cc64ButtonState = false; // Track the state of the CC64 button (Sustain)
  32. bool secondaryFunctionEnabled = false; // Declare the secondary function state
  33. bool aftertouchEnabled = false; // State of aftertouch transmission, change to true to enable on startup
  34. bool aftertouchButtonPressed = false; // Track aftertouch button press state
  35. bool expression2Enabled = false; // State of Expression2 transmission, change to true to enable on startup
  36. bool expression2ButtonPressed = false; // Track Expression2 button press state
  37. bool expression3Enabled = false; // State of Expression3 transmission, change to true to enable on startup
  38. bool expression3ButtonPressed = false; // Track Expression3 button press state
  39. bool expression4Enabled = false; // State of Expression4 transmission, change to true to enable on startup
  40. bool expression4ButtonPressed = false; // Track Expression4 button press state
  41.  
  42. // Button assignments
  43. byte Switch0 = 41;
  44. byte Switch1 = 42;
  45. byte Switch2 = 43;
  46. byte Switch3 = 44;
  47. byte Switch4 = 45;
  48. byte Switch5 = 46;
  49. byte Switch6 = 47;
  50. byte Switch7 = 48;
  51. byte Switch8 = 49;
  52. byte Switch9 = 50;
  53. byte Switch10 = 51;
  54. byte Switch11 = 52;
  55. byte Switch12 = 53;
  56. byte MinusOctaveButton = 4;
  57. byte PlusOctaveButton = 5;
  58. byte SecondaryFunctionButton = 2; // Button to enable the secondary function
  59. byte x;
  60. byte LedPin = 13;
  61. byte note;
  62. byte velocity = 100;
  63. byte currentSwitch = 0;
  64. int startNote = 36;
  65.  
  66. byte switches[13] = {Switch0, Switch1, Switch2, Switch3, Switch4, Switch5, Switch6, Switch7, Switch8, Switch9, Switch10, Switch11, Switch12};
  67. byte switchState[13] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW};
  68. byte lastSwitchState[13] = {LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW, LOW};
  69. bool minusButtonPressed = false;
  70. bool plusButtonPressed = false;
  71. bool incButtonPressed = false;
  72. bool decButtonPressed = false;
  73. bool cc64ButtonPressed = false;
  74. unsigned long lastDebounceTime[2] = {0, 0};
  75. unsigned long debounceDelay = 50; // Debounce delay for the CC64 Sustain button
  76. unsigned long debounceDelayOctave = 140; // Debounce delay for the octave buttons
  77. unsigned long debounceDelayCC64 = 140; // Debounce delay for the CC64 Sustain button
  78.  
  79. void setup() {
  80. MIDI.begin(MIDI_CHANNEL_OFF);
  81. pinMode(incBtnPin, INPUT_PULLUP);
  82. pinMode(decBtnPin, INPUT_PULLUP);
  83. pinMode(cc64BtnPin, INPUT_PULLUP); // Set Control Change 64 button as input
  84. pinMode(aftertouchBtnPin, INPUT_PULLUP); // Set aftertouch button as input
  85. pinMode(expression2BtnPin, INPUT_PULLUP); // Set Expression2 button as input
  86. pinMode(expression3BtnPin, INPUT_PULLUP); // Set Expression3 button as input
  87. pinMode(expression4BtnPin, INPUT_PULLUP); // Set Expression4 button as input
  88. pinMode(Switch0, INPUT_PULLUP);
  89. pinMode(Switch1, INPUT_PULLUP);
  90. pinMode(Switch2, INPUT_PULLUP);
  91. pinMode(Switch3, INPUT_PULLUP);
  92. pinMode(Switch4, INPUT_PULLUP);
  93. pinMode(Switch5, INPUT_PULLUP);
  94. pinMode(Switch6, INPUT_PULLUP);
  95. pinMode(Switch7, INPUT_PULLUP);
  96. pinMode(Switch8, INPUT_PULLUP);
  97. pinMode(Switch9, INPUT_PULLUP);
  98. pinMode(Switch10, INPUT_PULLUP);
  99. pinMode(Switch11, INPUT_PULLUP);
  100. pinMode(Switch12, INPUT_PULLUP);
  101. pinMode(MinusOctaveButton, INPUT_PULLUP);
  102. pinMode(PlusOctaveButton, INPUT_PULLUP);
  103. pinMode(SecondaryFunctionButton, INPUT_PULLUP); // Set Secondary Function Button as input
  104. pinMode(LedPin, OUTPUT);
  105. pinMode(0, INPUT); // Set pin 0 as input for MIDI In (Rx)
  106.  
  107. for (x = 1; x <= 4; x++) {
  108. digitalWrite(LedPin, HIGH);
  109. delay(300);
  110. digitalWrite(LedPin, LOW);
  111. delay(300);
  112. }
  113. Serial.begin(31250); // Set baud rate for MIDI communication
  114. Serial.flush();
  115. }
  116.  
  117. void loop() {
  118. // Read MIDI data from pin 0 (Rx)
  119. while (Serial.available()) {
  120. byte incomingByte = Serial.read();
  121. MIDI.read(incomingByte);
  122. }
  123.  
  124. // Check if the Secondary Function Button is pressed
  125. if (digitalRead(SecondaryFunctionButton) == LOW) {
  126. // Enable secondary function (changing MIDI channel with octave buttons)
  127. cc64ButtonState = false; // Ensure CC64 is off when secondary function is enabled
  128. secondaryFunctionEnabled = true; // Enable the secondary function
  129. } else {
  130. secondaryFunctionEnabled = false; // Disable the secondary function
  131. }
  132.  
  133. // Handle the CC64 button press
  134. if (digitalRead(cc64BtnPin) == LOW && !cc64ButtonPressed) {
  135. cc64ButtonPressed = true;
  136. // Toggle the CC64 state
  137. cc64ButtonState = !cc64ButtonState;
  138. // Send Control Change 64 (Sustain) message
  139. MIDI.sendControlChange(64, cc64ButtonState ? 127 : 0, midiChannel);
  140. delay(debounceDelayCC64); // Debounce delay for CC64 button
  141. } else if (digitalRead(cc64BtnPin) == HIGH) {
  142. cc64ButtonPressed = false;
  143. }
  144.  
  145. // Handle the aftertouch button press
  146. if (digitalRead(aftertouchBtnPin) == LOW && !aftertouchButtonPressed) {
  147. aftertouchButtonPressed = true;
  148. aftertouchEnabled = !aftertouchEnabled; // Toggle aftertouch state
  149. delay(debounceDelay); // Debounce delay for aftertouch button
  150. } else if (digitalRead(aftertouchBtnPin) == HIGH) {
  151. aftertouchButtonPressed = false;
  152. }
  153.  
  154. // Handle the Expression2 button press
  155. if (digitalRead(expression2BtnPin) == LOW && !expression2ButtonPressed) {
  156. expression2ButtonPressed = true;
  157. expression2Enabled = !expression2Enabled; // Toggle Expression2 state
  158. delay(debounceDelay); // Debounce delay for Expression2 button
  159. } else if (digitalRead(expression2BtnPin) == HIGH) {
  160. expression2ButtonPressed = false;
  161. }
  162.  
  163. // Handle the Expression3 button press
  164. if (digitalRead(expression3BtnPin) == LOW && !expression3ButtonPressed) {
  165. expression3ButtonPressed = true;
  166. expression3Enabled = !expression3Enabled; // Toggle Expression3 state
  167. delay(debounceDelay); // Debounce delay for Expression3 button
  168. } else if (digitalRead(expression3BtnPin) == HIGH) {
  169. expression3ButtonPressed = false;
  170. }
  171.  
  172. // Handle the Expression4 button press
  173. if (digitalRead(expression4BtnPin) == LOW && !expression4ButtonPressed) {
  174. expression4ButtonPressed = true;
  175. expression4Enabled = !expression4Enabled; // Toggle Expression4 state
  176. delay(debounceDelay); // Debounce delay for Expression4 button
  177. } else if (digitalRead(expression4BtnPin) == HIGH) {
  178. expression4ButtonPressed = false;
  179. }
  180.  
  181. // Read the potentiometer value and send aftertouch message if enabled
  182. if (aftertouchEnabled) {
  183. int potValue = analogRead(potPin);
  184. int aftertouchValue = map(potValue, 0, 1023, 0, 127); // 0,1023 are the analog pot range
  185. MIDI.sendAfterTouch(aftertouchValue, midiChannel);
  186. }
  187.  
  188. // Read the potentiometer value and send Expression2 message if enabled
  189. if (expression2Enabled) {
  190. int potValue = analogRead(expression2PotPin);
  191. int expression2Value = map(potValue, 0, 1023, 0, 127); // 0,1023 are the analog pot range
  192. MIDI.sendControlChange(23, expression2Value, expression2MidiChannel); // CC number 23
  193. }
  194.  
  195. // Read the potentiometer value and send Expression3 message if enabled
  196. if (expression3Enabled) {
  197. int potValue = analogRead(expression3PotPin);
  198. int expression3Value = map(potValue, 0, 1023, 0, 127); // 0,1023 are the analog pot range
  199. MIDI.sendControlChange(83, expression3Value, expression3MidiChannel); // CC number 83
  200. }
  201.  
  202. // Read the potentiometer value and send Expression4 message if enabled
  203. if (expression4Enabled) {
  204. int potValue = analogRead(expression4PotPin);
  205. int expression4Value = map(potValue, 0, 1023, 0, 127); // 0,1023 are the analog pot range
  206. MIDI.sendControlChange(106, expression4Value, expression4MidiChannel); // CC number 106
  207. }
  208.  
  209. // Handle note buttons
  210. for (int n = 0; n < 13; n++) {
  211. currentSwitch = digitalRead(switches[n]);
  212. if (currentSwitch == LOW && lastSwitchState[n] == HIGH) {
  213. note = n;
  214. // Send note-on message with the adjusted MIDI channel or octave
  215. if (secondaryFunctionEnabled) {
  216. MIDI.sendNoteOn(note + startNote, velocity, adjustMIDIChannel(midiChannel));
  217. } else {
  218. MIDI.sendNoteOn(note + startNote + (currentOctave * 12), velocity, midiChannel);
  219. }
  220. }
  221. if (currentSwitch == HIGH && lastSwitchState[n] == LOW) {
  222. note = n;
  223. // Send note-off message with the adjusted MIDI channel or octave
  224. if (secondaryFunctionEnabled) {
  225. MIDI.sendNoteOff(note + startNote, 0, adjustMIDIChannel(midiChannel));
  226. } else {
  227. MIDI.sendNoteOff(note + startNote + (currentOctave * 12), 0, midiChannel);
  228. }
  229. }
  230. lastSwitchState[n] = currentSwitch;
  231. }
  232.  
  233. // Handle Minus Octave Button
  234. if (digitalRead(MinusOctaveButton) == LOW && !minusButtonPressed) {
  235. if (secondaryFunctionEnabled) {
  236. midiChannel = adjustMIDIChannel(midiChannel - 1);
  237. } else {
  238. if (currentOctave > -3) { // Set the lower bound for the octave
  239. currentOctave--;
  240. }
  241. }
  242. minusButtonPressed = true;
  243. delay(debounceDelayOctave); // Debounce delay for MinusOctaveButton
  244. }
  245. if (digitalRead(MinusOctaveButton) == HIGH) {
  246. minusButtonPressed = false;
  247. }
  248.  
  249. // Handle Plus Octave Button
  250. if (digitalRead(PlusOctaveButton) == LOW && !plusButtonPressed) {
  251. if (secondaryFunctionEnabled) {
  252. midiChannel = adjustMIDIChannel(midiChannel + 1);
  253. } else {
  254. if (currentOctave < 7) { // Set the upper bound for the octave
  255. currentOctave++;
  256. }
  257. }
  258. plusButtonPressed = true;
  259. delay(debounceDelayOctave); // Debounce delay for PlusOctaveButton
  260. }
  261. if (digitalRead(PlusOctaveButton) == HIGH) {
  262. plusButtonPressed = false;
  263. }
  264.  
  265. // Handle program change buttons
  266. int incButtonState = digitalRead(incBtnPin);
  267. int decButtonState = digitalRead(decBtnPin);
  268.  
  269. if (incButtonState == LOW && !incButtonPressed) {
  270. currentProgram++;
  271. if (currentProgram >= maxPrograms) {
  272. currentProgram = 0;
  273. currentBank++;
  274. if (currentBank > numBanks) {
  275. currentBank = 1;
  276. }
  277. }
  278. MIDI.sendControlChange(0, currentBank - 1, midiChannel);
  279. MIDI.sendProgramChange(currentProgram, midiChannel);
  280. incButtonPressed = true;
  281. delay(debounceDelay);
  282. }
  283. if (incButtonState == HIGH) {
  284. incButtonPressed = false;
  285. }
  286.  
  287. if (decButtonState == LOW && !decButtonPressed) {
  288. currentProgram--;
  289. if (currentProgram < 0) {
  290. currentProgram = maxPrograms - 1;
  291. currentBank--;
  292. if (currentBank < 1) {
  293. currentBank = numBanks;
  294. }
  295. }
  296. MIDI.sendControlChange(0, currentBank - 1, midiChannel);
  297. MIDI.sendProgramChange(currentProgram, midiChannel);
  298. decButtonPressed = true;
  299. delay(debounceDelay);
  300. }
  301. if (decButtonState == HIGH) {
  302. decButtonPressed = false;
  303. }
  304. }
  305.  
  306. // Function to adjust MIDI channel and ensure it wraps around
  307. int adjustMIDIChannel(int channel) {
  308. if (channel < 1) {
  309. return 16;
  310. } else if (channel > 16) {
  311. return 1;
  312. } else {
  313. return channel;
  314. }
  315. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement