midi_controller

Teensy simple midi controller
git clone https://git.e1e0.net/midi_controller.git
Log | Files | Refs

midi_controller.ino (2883B)


      1 #include <Bounce2.h>
      2 
      3 #define MIDI_CHANNEL 2
      4 #define MIDI_CHANGE_THRESHOLD 2
      5 
      6 #define NUM_POTS 8
      7 static const uint8_t potPins[NUM_POTS] = {A0, A1, A2, A3, A6, A7, A8, A9};
      8 static const uint8_t potCC[NUM_POTS] = {1, 2, 3, 4, 5, 6, 7, 8};
      9 int potVal[NUM_POTS] = {0, 0, 0, 0, 0, 0, 0, 0};
     10 int oldVal[NUM_POTS] = {0, 0, 0, 0, 0, 0, 0, 0};
     11 
     12 #define NUM_BUTTONS 4
     13 #define MOMENTARY 0
     14 #define LATCH 1
     15 #define TRIGGER 2
     16 static const uint8_t btnPins[NUM_BUTTONS] = {6, 7, 8, 9};
     17 static const uint8_t btnCC[NUM_BUTTONS] = {11, 12, 13, 14};
     18 uint8_t btnVal[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH};
     19 uint8_t btnOldVal[NUM_BUTTONS] = {HIGH, HIGH, HIGH, HIGH};
     20 uint8_t btnMode[NUM_BUTTONS] = {MOMENTARY, TRIGGER, TRIGGER, LATCH};
     21 Bounce *buttons = new Bounce[NUM_BUTTONS];
     22 
     23 unsigned long previousMillis = 0;
     24 
     25 // Reads all pots and sends midi CC message if it has been a change
     26 // greater than threshold (so we avoid flickering)
     27 void readPots() {
     28   uint8_t i;
     29 
     30   for (i = 0; i < NUM_POTS; i++) {
     31     potVal[i] = analogRead(potPins[i]);
     32     potVal[i] = map(potVal[i], 0, 4095, 0, 127);
     33     if (abs(potVal[i] - oldVal[i]) > MIDI_CHANGE_THRESHOLD) {
     34       usbMIDI.sendControlChange(potCC[i], potVal[i], MIDI_CHANNEL);
     35       oldVal[i] = potVal[i];
     36     }
     37   }
     38 }
     39 
     40 
     41 void setup() {
     42   analogReadResolution(12);
     43   analogReadAveraging(16);
     44   for (uint8_t i = 0; i < NUM_BUTTONS; ++i) {
     45     buttons[i].attach( btnPins[i] , INPUT_PULLUP );
     46     buttons[i].interval(10);
     47   }
     48 }
     49 
     50 void loop() {
     51   unsigned long currentMillis = millis();
     52 
     53   if(currentMillis - previousMillis > 5) { // moaaarrr stability in readings
     54     previousMillis = currentMillis;
     55     readPots();
     56   }
     57 
     58   for (uint8_t i = 0; i < NUM_BUTTONS; i++) {
     59       buttons[i].update();
     60       if (buttons[i].fell()) {
     61           if (btnOldVal[i] == HIGH) {
     62               // this is send max for momentary and latch
     63               usbMIDI.sendControlChange(btnCC[i], 127, MIDI_CHANNEL);
     64               btnOldVal[i] = LOW;
     65           } else {
     66               // if trigger mode send max again
     67               if (btnMode[i] == TRIGGER) {
     68                 // it seems vcv rack needs notes on/off for its trigger module.
     69                 usbMIDI.sendNoteOn(btnCC[i], 127, MIDI_CHANNEL);
     70                 usbMIDI.sendNoteOff(btnCC[i], 127, MIDI_CHANNEL);
     71                 // usbMIDI.sendControlChange(btnCC[i], 127, MIDI_CHANNEL);
     72               } else { // if we're here is latch mode, so we turn it off
     73                 usbMIDI.sendControlChange(btnCC[i], 0, MIDI_CHANNEL);
     74                 btnOldVal[i] = HIGH;
     75               }
     76           }
     77       }
     78       if (buttons[i].rose()) {
     79           if (btnOldVal[i] == LOW && btnMode[i] == MOMENTARY) {
     80               // button released logic goes here.
     81               // we only use this for momentary buttons.
     82               usbMIDI.sendControlChange(btnCC[i], 0, MIDI_CHANNEL);
     83               btnOldVal[i] = HIGH;
     84           }
     85       }
     86   }
     87 }