Aussie_CrocHunter
Well-known member
Hi there,
I have a project on the go which is very near to completion! I have 6 switches - one of which is a momentary switch which is used for tap tempo (sends CC_Num val=127 on falling edge), but also has a mode-switching function attached to it. The mode switch triggers a single LED to flash which Bank is being selected. However, when the LED is not being used for indicating which bank is being selected, I would like it to receive the midi clock/tempo from a host such as logic pro, Mainstage, Ableton etc.
Can you please help me?
I have a project on the go which is very near to completion! I have 6 switches - one of which is a momentary switch which is used for tap tempo (sends CC_Num val=127 on falling edge), but also has a mode-switching function attached to it. The mode switch triggers a single LED to flash which Bank is being selected. However, when the LED is not being used for indicating which bank is being selected, I would like it to receive the midi clock/tempo from a host such as logic pro, Mainstage, Ableton etc.
Can you please help me?
Code:
//************LIBRARIES USED**************
// 'include the Bounce library for 'de-bouncing' switches -- removing electrical chatter as contacts settle'
#include <Bounce.h>
//'usbMIDI.h library is added automatically when code is compiled as a MIDI device'
// ******CONSTANT VALUES********
// customize code behaviour here!
const int channel = 1; // MIDI channel
const int D_PINS = 5; // number of Digital PINS
const int ON_Value = 127; // note-one velocity sent from buttons (should be 65 to 127)
// 'define the pins and notes for digital events'
const int DIGITAL_PINS[D_PINS] = {0,1,2,3,4};
const int MODE_TAP_PIN = 5;
const int MODE_TAP_LED_PIN = 21;
const int MODE_COUNT = 3;
const int RED_LED_PINS[D_PINS] = {6,19,8,10,17};
const int GREEN_LED_PINS[D_PINS] = {7,20,9,16,18};
const int BOUNCE_TIME = 30; // 5 ms is usually sufficient
const int modeThreshold = 600; // how long to hold before mode changes
const int flashOnTime = 250; // how long flashed LED is on (and OFF?)
const int flashOffTime = 250; // how long flashed LED is on (and OFF?)
//CC configuration matrix!!
const int MIDI_CC_NUMS[MODE_COUNT][D_PINS] = { //rows are banks up to MODE_COUNT
{60,61,62,63,64},
{65,66,67,68,69},
{70,71,72,73,74}
};
const int TAP_CC = 15;
//******VARIABLES***********
// a data array to remember the current state of each switch
boolean state[MODE_COUNT][D_PINS];
elapsedMillis modeTimer,flashTimer;
boolean modeSelectActive = false;
int bank = 0 ;
int flashcount;
int shiftUp; // keeps track of whether the mode change needs to be handled (true) or was (false)
int modeLED; // keeps track of whether LED is on without testing it..
//************INITIALIZE LIBRARY OBJECTS**************
// initialize the bounce objects
Bounce digital[] = {
Bounce(DIGITAL_PINS[0],BOUNCE_TIME),
Bounce(DIGITAL_PINS[1], BOUNCE_TIME),
Bounce(DIGITAL_PINS[2], BOUNCE_TIME),
Bounce(DIGITAL_PINS[3], BOUNCE_TIME),
Bounce(DIGITAL_PINS[4], BOUNCE_TIME)
};
Bounce modeTap = Bounce(MODE_TAP_PIN, BOUNCE_TIME);
//************SETUP**************
void setup() {
//'set a handle for returning control change messages'
usbMIDI.setHandleControlChange(OnControlChange);
//'loop to configure input pins and internal pullup resisters for digital section'
for (int i=0;i<D_PINS;i++){
pinMode(DIGITAL_PINS[i], INPUT_PULLUP);
pinMode(RED_LED_PINS[i], OUTPUT);
pinMode(GREEN_LED_PINS[i], OUTPUT);
}
pinMode(MODE_TAP_PIN, INPUT_PULLUP);
pinMode(MODE_TAP_LED_PIN, OUTPUT);
digitalWrite(MODE_TAP_LED_PIN, HIGH);
digitalWrite(7, HIGH); //SW1 - GREEN OFF
digitalWrite(16, HIGH); //SW2 - GREEN OFF
digitalWrite(20, HIGH); //SW3 - GREEN OFF
digitalWrite(9, HIGH); //SW4 - GREEN OFF
digitalWrite(18, HIGH); //SW5 - GREEN OFF
}
//************LOOP**************
void loop() {
getDigitalData();
getModeTap();
while (usbMIDI.read()) {
//' controllers must call .read() to keep the queue clear even if they are not responding to MIDI'
}
}
//************DIGITAL SECTION**************
void getDigitalData(){
for (int i=0;i<D_PINS;i++){
digital[i].update();
if (digital[i].fallingEdge() || digital[i].risingEdge()) {
if (state[bank][i]) {
usbMIDI.sendControlChange(MIDI_CC_NUMS[bank][i], 0, channel);
}else{
usbMIDI.sendControlChange(MIDI_CC_NUMS[bank][i], ON_Value, channel);
}
state[bank][i] = !state[bank][i] ;
digitalWrite(RED_LED_PINS[i], state[bank][i]);
digitalWrite(GREEN_LED_PINS[i], !state[bank][i]);
}
}
}
//************MODE/TAP SECTION**************
void getModeTap(){
modeTap.update();
if (modeTap.fallingEdge()) {
usbMIDI.sendControlChange(TAP_CC, ON_Value, channel); // can we send any D2 for Tap?
modeTimer = 0;
shiftUp = true;
}
if (modeTap.risingEdge()){
shiftUp = false;
}
if (modeTimer>modeThreshold && shiftUp) {
shiftUp = false;
bank++;
bank = bank%MODE_COUNT;
for (int i = 0; i < D_PINS ; i++){
digitalWrite(GREEN_LED_PINS[i], !state[bank][i]);
digitalWrite(RED_LED_PINS[i], state[bank][i]);
}
flashcount = bank + 1;
flashTimer = 0 ;
// set counter of flashes 'owed' -- count them down after main part
}
// if flashcount > 0 flash and start counter
if (flashcount){
if (flashTimer>(flashOnTime+flashOffTime)){
flashcount-- ;// decrement flashcount
flashTimer = 0;
if (modeLED == HIGH){
modeLED = LOW;
digitalWrite(MODE_TAP_LED_PIN, HIGH);
}
}else{
if (modeLED == LOW && flashTimer>flashOnTime){
modeLED = HIGH;
digitalWrite(MODE_TAP_LED_PIN, LOW);
}
}
}
}
void OnControlChange(byte channel, byte controller, byte value) {
// add channel check?
for (int i = 0; i < D_PINS ; i++){
if (MIDI_CC_NUMS[bank][i] == controller) {
if (value >= 64) {
digitalWrite(GREEN_LED_PINS[i], LOW);
digitalWrite(RED_LED_PINS[i], HIGH); //'receiving >64 turns green on and red off'
state[bank][i] = true;
}else{
digitalWrite(GREEN_LED_PINS[i], HIGH);
digitalWrite(RED_LED_PINS[i], LOW); //'receiving <64 turns red on and green off'
state[bank][i] = false;
} // 'if not the controller for i then skip this loop'
}
}
}