send(uart)

e/serial-midi/send(uart)

No description
send(uart)
@/send(uart)
MIDIxod/uart/uart
MSGe/midi/message
SENDpulse
send(uart)
MIDI
MSG
SEND
DONE
DONEpulse
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;
            }
        }
    }
}