141 lines
3.6 KiB
Arduino
141 lines
3.6 KiB
Arduino
|
||
// include libraries
|
||
#include <Adafruit_MCP23X17.h>
|
||
#include <MIDI.h>
|
||
|
||
// Instantiate libraries
|
||
Adafruit_MCP23X17 mcp1; // First MCP23017
|
||
Adafruit_MCP23X17 mcp2; // Second MCP23017
|
||
// Default hardware MIDI. SoftwareSerial is too slow...
|
||
MIDI_CREATE_DEFAULT_INSTANCE();
|
||
// A7 A6 A5 A4 A3 A2 A1 A0 <-- GPIO A
|
||
// MCP pins 28 27 26 25 24 23 22 21 20 19 18 17 16 15
|
||
// 8 = pin 1 ╔══════════════════════════════════════════╗
|
||
// 9 = pin 2 ╠ MCP23017 ║
|
||
// 10 = pin 3 ╚══════════════════════════════════════════╝
|
||
// 01 02 03 04 05 06 07 08 9 10 11 12 13 14
|
||
// B0 B1 B2 B3 B4 B5 B6 B7 <-- GPIO B
|
||
|
||
// Default MIDI channel
|
||
byte currentMidiChannel = 8; // Default MIDI channel
|
||
|
||
// Struct for 2 MCP chips.
|
||
struct MCPOutput {
|
||
uint8_t chip; // 0 = mcp1, 1 = mcp2
|
||
uint8_t pin; // 0–15
|
||
};
|
||
|
||
// LED shows MIDI activity
|
||
unsigned long ledOnTime = 0;
|
||
bool ledActive = false;
|
||
const unsigned long ledDuration = 50; // flash for 50ms
|
||
|
||
// Note to pin mapping. {chip, pin}
|
||
// One would be able to add up to 8 MCPs, but 2 is plenty for a Meowsic.
|
||
MCPOutput noteToMCP[32] = {
|
||
// MCP1 – MIDI 57 to 72
|
||
{0, 0}, // 57 A3
|
||
{0, 1}, // 58 A#3
|
||
{0, 2}, // 59 B3
|
||
{0, 3}, // 60 C4
|
||
{0, 4}, // 61 C#4
|
||
{0, 5}, // 62 D4
|
||
{0, 6}, // 63 D#4
|
||
{0, 7}, // 64 E4
|
||
{0, 8}, // 65 F4
|
||
{0, 9}, // 66 F#4
|
||
{0, 10}, // 67 G4
|
||
{0, 11}, // 68 G#4
|
||
{0, 12}, // 69 A4
|
||
{0, 13}, // 70 A#4
|
||
{0, 14}, // 71 B4
|
||
{0, 15}, // 72 C5
|
||
|
||
// MCP2 – MIDI 73 to 88
|
||
{1, 0}, // 73 C#5
|
||
{1, 1}, // 74 D5
|
||
{1, 2}, // 75 D#5
|
||
{1, 3}, // 76 E5
|
||
{1, 4}, // 77 F5
|
||
{1, 5}, // 78 F#5
|
||
{1, 6}, // 79 G5
|
||
{1, 7}, // 80 G#5
|
||
{1, 8}, // 81 A5
|
||
{1, 9}, // 82 A#5
|
||
{1, 10}, // 83 B5
|
||
{1, 11}, // 84 C6
|
||
{1, 12}, // 85 C#6
|
||
{1, 13}, // 86 D6
|
||
{1, 14}, // 87 D#6
|
||
{1, 15} // 88 E6
|
||
};
|
||
|
||
|
||
void setup() {
|
||
// LED debug
|
||
pinMode(LED_BUILTIN, OUTPUT);
|
||
|
||
// Initialize MCP23017s
|
||
mcp1.begin_I2C(0x20);
|
||
mcp2.begin_I2C(0x21);
|
||
// Initialize MIDI
|
||
MIDI.begin(MIDI_CHANNEL_OMNI);
|
||
MIDI.setHandleNoteOn(handleNoteOn);
|
||
MIDI.setHandleNoteOff(handleNoteOff);
|
||
|
||
for (int i = 0; i < 16; i++) {
|
||
mcp1.pinMode(i, OUTPUT);
|
||
mcp1.digitalWrite(i, LOW);
|
||
|
||
mcp2.pinMode(i, OUTPUT);
|
||
mcp2.digitalWrite(i, LOW);
|
||
}
|
||
}
|
||
|
||
void loop() {
|
||
MIDI.read();
|
||
|
||
// LED feedback
|
||
if (ledActive && millis() - ledOnTime >= ledDuration) {
|
||
digitalWrite(LED_BUILTIN, LOW);
|
||
ledActive = false;
|
||
}
|
||
// if (MIDI.read()) {
|
||
// digitalWrite(LED_BUILTIN, HIGH);
|
||
// delay(50);
|
||
// digitalWrite(LED_BUILTIN, LOW);
|
||
|
||
// }
|
||
}
|
||
|
||
void handleNoteOn(byte channel, byte pitch, byte velocity) {
|
||
if (channel == currentMidiChannel) {
|
||
|
||
if (pitch >= 57 && pitch <= 88) {
|
||
MCPOutput out = noteToMCP[pitch - 57];
|
||
if (out.chip == 0) {
|
||
mcp1.digitalWrite(out.pin, HIGH);
|
||
} else if (out.chip == 1) {
|
||
mcp2.digitalWrite(out.pin, HIGH);
|
||
}
|
||
}
|
||
}
|
||
|
||
// Flash LED on any valid Note On
|
||
digitalWrite(LED_BUILTIN, HIGH);
|
||
ledOnTime = millis();
|
||
ledActive = true;
|
||
}
|
||
|
||
void handleNoteOff(byte channel, byte pitch, byte velocity) {
|
||
if (channel == currentMidiChannel) {
|
||
if (pitch >= 57 && pitch <= 88) {
|
||
MCPOutput out = noteToMCP[pitch - 57];
|
||
if (out.chip == 0) {
|
||
mcp1.digitalWrite(out.pin, LOW);
|
||
} else if (out.chip == 1) {
|
||
mcp2.digitalWrite(out.pin, LOW);
|
||
}
|
||
}
|
||
}
|
||
} |