Code:
#define SWITCHES 7
#define TOUCHTHRESH 2000
#define HYST 2 //HYSTERESIS AMOUNT
#include <usb_midi.h>
#include <MIDI.h>
#include "midicontrolHACK3.h"
int myMode = 0;
const int MMC = 1;
const int MIDINOTES = 2;
static int myChannel = 1;
const byte MMCSTOP [] {240, 127, 127, 6, 1, 247};
const byte MMCPLAY [] {240, 127, 127, 6, 2, 247};
const byte MMCFFWD [] {240, 127, 127, 6, 4, 247};
const byte MMCRWD [] {240, 127, 127, 6, 5, 247};
const byte MMCPUNCHIN [] {240, 127, 127, 6, 6, 247};
const byte MMCPUNCHOUT[] {240, 127, 127, 6, 7, 247};
const byte MMCPAUSE [] {240, 127, 127, 6, 9, 247};
const byte* MMCTransport [] {MMCSTOP, MMCPLAY, MMCFFWD, MMCRWD, MMCPUNCHIN, MMCPUNCHOUT, MMCPAUSE};
const uint8_t wiperPin = A4; //read fader value analog pin
const uint8_t touchPin = 1; /// capacitive touch fader
int sendSwitchesMIDINOTES [] {19, 21, 6, 1, 5, 99, 67}; // 7 random MIDI note numbers ??? could be CC ...
const uint8_t switchesPinTable [] {15, 22, 23, 9, 10, 11, 12, 16, 17};
/*
15, 22, 23 etc ... first 7 bits of C pin register
16 and 17 are first two pins of B register for encoder
*/
static int8_t enc_states[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
static uint8_t old_AB = 0;
void Fader::RW() // set up for capacitive touch
{
PositionPinRead();
touchPinRead = touchRead (touchPin);
if (touchPinRead > TOUCHTHRESH)
{
if (TOUCHSENT == false) {
usbMIDI.sendPolyPressure (127, 1, 1);
TOUCHSENT = true;
}
PINWRITE();
}
else
{
if (TOUCHSENT == true) {
usbMIDI.sendPolyPressure (127, 0, 1);
TOUCHSENT = false;
}
}
}
void Fader::PositionPinRead()
{
hystPinRead = analogRead (wiperPin);
if (currentPinRead > (hystPinRead + HYST) || hystPinRead > (currentPinRead + HYST))
{
currentPinRead = hystPinRead;
}
}
void Fader::PINWRITE ()
{
sendMSB = currentPinRead >> 3;
sendLSB = currentPinRead & 0x00F;
usbMIDI.sendControlChange (0, sendMSB, 1);
//delay(1); // 500 micros is probably better here??? is it even needed??
usbMIDI.sendControlChange (32, sendLSB, 1);
}
void Switches::RW (int choice, int channel) // could be done using bounce library, and if no noteoff's required, could be structured a bit more simply maybe
{
readMSB = GPIOC_PDIR & 0x07F;
//readLSB = GPIOD_PDIR & 0x00F;
//delay(1); is this needed..?
switch (choice)
{ case MIDINOTES:
for (int i = 0; i < SWITCHES; i++)
{
if (!(readMSB & (1 << i)))
{
if (!(mask & (1 << i) ))
{
MIDI.sendSysEx (6, MMCTransport[i], false);
usbMIDI.sendSysEx (6, MMCTransport[i]);
mask |= (1 << i);
}
}
else {
if ((mask & (1 << i)))
{
mask &= ~(1 << i);
}
}
}
break;
case MMC:
for (int i = 0; i < SWITCHES; i++)
{
if (!(readMSB & (1 << i)))
{
if (!(mask & (1 << i) ))
{
usbMIDI.sendNoteOn (sendSwitchesMIDINOTES [i], 127, channel);
MIDI.sendNoteOn (sendSwitchesMIDINOTES [i], 127, channel);
mask |= (1 << i);
}
}
else {
if ((mask & (1 << i)))
{
usbMIDI.sendNoteOff (sendSwitchesMIDINOTES [i], 0, channel);
MIDI.sendNoteOff (sendSwitchesMIDINOTES [i], 0, channel);
mask &= ~(1 << i);
}
}
}
break;
}
}
void Rotary::SET_CH (int& channel)
{
old_AB <<= 2; //remember previous state
old_AB |= (GPIOB_PDIR & 0x03 ); //add current state
RotaryRead = ( enc_states[( old_AB & 0x0F )]);
if (RotaryRead > 0)
{
channel++; if (channel > 16) {
channel = 16;
}
}
else if (RotaryRead < 0)
{
channel--; if (channel < 1) {
channel = 1;
}
}
}
void setup()
{
//MIDI.begin();
//Serial.begin (31250);
for (int i = 0; i < SWITCHES + 2; i++) // + 2 for encoder pin setup
{
pinMode(switchesPinTable [i], OUTPUT);
digitalWrite (switchesPinTable [i], LOW);
delay (1);
pinMode(switchesPinTable [i], INPUT_PULLUP );
}
}
void loop()
{
do
{
if (digitalRead (11) == LOW) {
myMode = MMC;
}
else if (digitalRead (12) == LOW) {
myMode = MIDINOTES;
}
}
while ((myMode != MMC) && (myMode != MIDINOTES));
Serial.println(String(myMode));
delay(1000);
{
Switches mySwitches;
Fader myFader;
Rotary myRotary;
while (true)
{
myRotary.SET_CH (myChannel);
myFader.RW();
mySwitches.RW (myMode, myChannel);
midithru();
}
}
}
void midithru()
{
int chnl, d1, d2, dd;
kMIDIType type;
if (MIDI.read() && MIDI.getType() < SystemExclusive) {
type = MIDI.getType();
d1 = MIDI.getData1();
d2 = MIDI.getData2();
dd = d1 + (d2 << 8);
chnl = MIDI.getChannel();
// and then send...
switch (type) {
case NoteOn:
usbMIDI.sendNoteOn(d1, d2, chnl);
break;
case NoteOff:
usbMIDI.sendNoteOff(d1, d2, chnl);
break;
case AfterTouchPoly:
usbMIDI.sendPolyPressure(d1, d2, chnl);
break;
case ControlChange:
usbMIDI.sendControlChange(d1, d2, chnl);
break;
case ProgramChange:
usbMIDI.sendProgramChange(dd, chnl);
break;
case AfterTouchChannel:
usbMIDI.sendAfterTouch(dd, chnl);
break;
case PitchBend:
usbMIDI.sendPitchBend(dd, chnl);
break;
case SystemExclusive:
// handle sysex
break;
default:
// F8 et seq.
break;
}
}
if (usbMIDI.read() && usbMIDI.getType() < SystemExclusive) {
type = (kMIDIType) usbMIDI.getType();
d1 = usbMIDI.getData1();
d2 = usbMIDI.getData2();
chnl = usbMIDI.getChannel();
// and then send...
MIDI.send(type, d1, d2, chnl);
}
}