-
Notifications
You must be signed in to change notification settings - Fork 70
Custom MIDI controls
In some cases, you want more control over what kind of input is used, and what kind of MIDI messages get sent. For example, MATLAB only supports Control Change events, so normal buttons with Note On and Note Off won't work. For this application, I created a custom class for buttons that send Control Change events.
The class inherits from the MIDI_Control_Element
class, and can be used just like the other MIDI control elements (Analog
, Digital
, RotaryEncoder
...).
The code is really straightforward. First, you have to include the right header files. This is probably just MIDI_Controller.h
. Then declare a class that inherits from MIDI_Control_Element
. You have to implement the refresh method to do what you want your custom class to do. In my case, that was reading a button, and sending a CC message if the input has changed.
That's it!
#ifndef DIGITALCC_H_
#define DIGITALCC_H
#include "Arduino.h"
#include <MIDI_Outputs/MIDI_Control_Element.h>
#include <Settings/Settings.h>
#include <ExtendedInputOutput/ExtendedInputOutput.h>
class DigitalCC : public MIDI_Control_Element
{
public:
DigitalCC(pin_t pin, uint8_t controller, uint8_t channel); // Constructor
~DigitalCC(); // Destructor
void invert(); // Invert the button state
private:
void refresh(); // Check if the button state changed, and send a MIDI CC accordingly
pin_t pin;
uint8_t controller, channel;
bool prevState = HIGH, buttonState = HIGH;
unsigned long prevBounceTime = 0;
bool invertState = false;
const static unsigned long debounceTime = BUTTON_DEBOUNCE_TIME;
const static int8_t falling = LOW - HIGH;
const static int8_t rising = HIGH - LOW;
};
#endif
#include "DigitalCC.h"
#include <MIDI_Controller.h>
using namespace ExtIO;
DigitalCC::DigitalCC(pin_t pin, uint8_t controller, uint8_t channel) // Constructor
: pin(pin), controller(controller), channel(channel) {
ExtIO::pinMode(pin, INPUT_PULLUP); // Enable the internal pull-up resistor on the pin with the button/switch
}
DigitalCC::~DigitalCC() { // Destructor
ExtIO::pinMode(pin, INPUT); // make it a normal input again, without the internal pullup resistor.
}
void DigitalCC::invert() // Invert the button state
{
invertState = true;
}
void DigitalCC::refresh() { // Check if the button state changed, and send a MIDI CC accordingly
bool state = ExtIO::digitalRead(pin) ^ invertState; // read the button state and invert it if "invert" is true
if (millis() - prevBounceTime > debounceTime)
{
int8_t stateChange = state - buttonState;
if (stateChange == falling)
{ // Button is pushed
buttonState = state;
MIDI_Controller.MIDI()->send(CONTROL_CHANGE,
channel + channelOffset * channelsPerBank,
controller + addressOffset * channelsPerBank, 127);
}
if (stateChange == rising)
{ // Button is released
buttonState = state;
MIDI_Controller.MIDI()->send(CONTROL_CHANGE,
channel + channelOffset * channelsPerBank,
controller + addressOffset * channelsPerBank, 0);
}
}
if (state != prevState)
{
prevBounceTime = millis();
prevState = state;
}
}