To use the node in your project you should have the e/serial-midi library installed. Use the “File → Add Library” menu item in XOD IDE if you don’t have it yet. See Using libraries for more info.
C++ implementation
// Most of the code below is taken from Arduino MIDI Library (https://github.com/FortySevenEffects/arduino_midi_library)
// and modified to work as a XOD node.
nodespace {
constexpr uint8_t PitchBend = 0xE0;
constexpr uint8_t ProgramChange = 0xC0;
constexpr uint8_t AfterTouchChannel = 0xD0;
constexpr uint8_t Clock = 0xF8;
constexpr uint8_t Start = 0xFA;
constexpr uint8_t Continue = 0xFB;
constexpr uint8_t Stop = 0xFC;
constexpr uint8_t ActiveSensing = 0xFE;
constexpr uint8_t SystemReset = 0xFF;
}
node {
void evaluate(Context ctx) {
if (!isInputDirty<input_SEND>(ctx)) return;
auto uart = getValue<input_MIDI>(ctx);
auto msg = getValue<input_MSG>(ctx);
// Then test if channel is valid
if (msg.channel >= 17 ||
msg.channel == 0 || // TODO: why?
msg.type < 0x80) {
return; // Don't send anything
}
if (msg.type <= PitchBend) { // Channel messages
// Protection: remove MSBs on data
msg.data1 &= 0x7f;
msg.data2 &= 0x7f;
const uint8_t status = msg.type | ((msg.channel - 1) & 0x0f);
uart->writeByte(status);
// Then send data
uart->writeByte(msg.data1);
if (msg.type != ProgramChange && msg.type != AfterTouchChannel) {
uart->writeByte(msg.data2);
}
emitValue<output_DONE>(ctx, 1);
} else if (msg.type >= Clock && msg.type <= SystemReset) {
switch (msg.type) {
case Clock:
case Start:
case Stop:
case Continue:
case ActiveSensing:
case SystemReset: {
uart->writeByte(msg.type);
emitValue<output_DONE>(ctx, 1);
break;
}
default:
break;
}
}
}
}