uint8_t gNumPorts = 1; // number of soft MIDI TX ports
uint8_t gTxPin[8] = {0,0,0,0, 0,0,0,0}; // MIDI Tx Pin(s) def
const uint8_t MaxBits = 64; // 64 bits (using uint64_t var)
volatile uint8_t gTxReadHead[8] = {0,0,0,0, 0,0,0,0}; // position to head in ring buffer
// test data
// NoteOn(0x90) + Ch1(0x00), Note C4(0x3C), Vel127(0x7F) => 0 0000 1001 1 - 0 0011 1100 1 - 0 1111 1110 1; LSP first
uint64_t msgBUFF[8] = {
0b0000010011000111100101111111011111111111111111111111111111111111, // C4 0x3C
0b0000010011000000010101111111011111111111111111111111111111111111, // E4 0x40
0b0000010011011000010101111111011111111111111111111111111111111111, // G4 0x43
0b0000010011000010010101111111011111111111111111111111111111111111, // C5 0x48
0b0000010011000110010101111111011111111111111111111111111111111111, // E5 0x4C
0b0000010011011110010101111111011111111111111111111111111111111111, // G5 0x4F
0b0000010011000101010101111111011111111111111111111111111111111111, // C6 0x54
0b0000010011000001100101111111011111111111111111111111111111111111 // C3 0x30
};
const uint64_t g64mask = 0x8000000000000000;
// Setup bit-bang 32usec timer tic (31250 BAUD)
IntervalTimer sMIDITx_Timer;
// ======================================================================
void setup() {
// init sMIDITx
sMIDITxPorts();
Serial.println("MIDI Bit Bang running...");
}
// ======================================================================
void loop() {
// nothing in loop - fcn BitBangPins called from timer
}
// ======================================================================
void sMIDITxPorts() { // setup the pins and interrupt timer
gNumPorts = 8; // the number of MIDI TX ports defined
gTxPin[0] = 35; // PIN used for bit banging the MIDI Tx
gTxPin[1] = 36;
gTxPin[2] = 37;
gTxPin[3] = 38;
gTxPin[4] = 39;
gTxPin[5] = 28;
gTxPin[6] = 29;
gTxPin[7] = 30;
// setup the soft MIDI Tx PINs
for (byte i=0; i<gNumPorts; i++) pinMode(gTxPin[i], OUTPUT);
//setup up Interrupt Timer
sMIDITx_Timer.priority(10); // 10 = very high priority
sMIDITx_Timer.begin(BitBangPins, 32); // 32 usec == 31250 BAUD for MIDI
} // end fcn Constructor sMIDITxPorts
// ======================================================================
void BitBangPins() { // called from interrupt timer
boolean theBit;
sMIDITx_Timer.update(32); // reset int timer tic to 32 usec
for (byte i=0; i<gNumPorts; i++) { // for each Pin...
theBit = ( g64mask & ( msgBUFF[i] << gTxReadHead[i] )); // shift the buffer left and then AND 'mask', a 1 in the MSB
digitalWriteFast( gTxPin[i], theBit); // write the bit to the pin from the buff location of the "read head"
gTxReadHead[i] = (gTxReadHead[i]+1) % MaxBits; // inc the "Read Head" of the buffer with wrapping
// used to set BPM while debugging...
if (gTxReadHead[7] == 31) sMIDITx_Timer.update(62500); // 120BMP 1/8th notes - set int timer tic to 62.5 msec
} // end for
} // end fcn _SetPins
// ======================================================================
//NOT USED YET...
void send_sMIDITxMsg(byte MSGtype, byte data1, byte data2, byte ch, byte port) {
// TODO: in bound MIDI messages must be formatted into bit streams and placed into the ring buffers (based on port)
} // end fcn send_sMsg
// ======================================================================