Skip to content

File MIDI_UART_Input.cpp

File List > examples > MIDI_UART_Input > MIDI_UART_Input.cpp

Go to the documentation of this file

Source Code

#include "daisy_seed.h"

using namespace daisy;

constexpr const bool kUseRealtimeCallback = true;

enum class Source
{
    Queue,
    RealtimeCb,
    Unknown,
};

struct SourcedMidiEvent
{
    MidiEvent message;
    Source    src;
    uint32_t  timestamp;

    SourcedMidiEvent(MidiEvent e, Source s)
    {
        message   = e;
        src       = s;
        timestamp = System::GetNow();
    }

    SourcedMidiEvent() : src(Source::Unknown), timestamp(0xffffffff) {}
};

DaisySeed       hw;
MidiUartHandler midi;

FIFO<SourcedMidiEvent, 128> event_log;


const char* GetStringForRealTimeType(SystemRealTimeType type)
{
    switch(type)
    {
        case SystemRealTimeType::TimingClock: return "Timing Clock";
        case SystemRealTimeType::SRTUndefined0: return "SRT Undefined0";
        case SystemRealTimeType::Start: return "Start";
        case SystemRealTimeType::Continue: return "Continue";
        case SystemRealTimeType::Stop: return "Stop";
        case SystemRealTimeType::SRTUndefined1: return "SRT Undefined1";
        case SystemRealTimeType::ActiveSensing: return "ActiveSensing";
        case SystemRealTimeType::Reset: return "Reset";
        default: return "Unknown Type...";
    }
}

const char* GetStringForSource(Source src)
{
    switch(src)
    {
        case Source::Queue: return "Queue";
        case Source::RealtimeCb: return "Realtime Callback";
        case Source::Unknown:
        default: return "Unknown";
    }
}

void MidiRealtimeCallback(MidiEvent& event)
{
    auto ev = SourcedMidiEvent(event, Source::RealtimeCb);
    event_log.PushBack(ev);
}

int main(void)
{
    hw.Init();

    hw.StartLog();

    MidiUartHandler::Config midi_config;
    midi.Init(midi_config);

    if(kUseRealtimeCallback)
    {
        midi.StartReceiveRt(MidiRealtimeCallback);
    }
    else
    {
        midi.StartReceive();
    }

    uint32_t now      = System::GetNow();
    uint32_t log_time = System::GetNow();

    while(1)
    {
        now = System::GetNow();

        midi.Listen();

        while(midi.HasEvents())
        {
            MidiEvent msg = midi.PopEvent();

            switch(msg.type)
            {
                case NoteOn:
                    // Do something on Note On events
                    {
                        uint8_t bytes[3] = {0x90, 0x00, 0x00};
                        bytes[1]         = msg.data[0];
                        bytes[2]         = msg.data[1];
                        midi.SendMessage(bytes, 3);
                    }
                    break;
                default: break;
            }

            auto ev = SourcedMidiEvent(msg, Source::Queue);
            event_log.PushBack(ev);
        }

        if(now - log_time > 5)
        {
            log_time = now;
            if(!event_log.IsEmpty())
            {
                auto        event = event_log.PopFront();
                auto        msg   = event.message;
                char        outstr[128];
                const char* type_str = MidiEvent::GetTypeAsString(msg);
                if(msg.type == MidiMessageType::SystemRealTime)
                {
                    const char* src_str = GetStringForSource(event.src);
                    const char* desc_str
                        = GetStringForRealTimeType(msg.srt_type);
                    sprintf(outstr,
                            "time:\t%ld\ttype: %s - %s\tsource: %s\n",
                            event.timestamp,
                            type_str,
                            desc_str,
                            src_str);
                }
                else
                {
                    // Only realtime messages are capable of hitting the realtime
                    // callback so we do not need to include the source here.
                    sprintf(outstr,
                            "time:\t%ld\ttype: %s\tChannel:  %d\tData MSB: "
                            "%d\tData LSB: %d\n",
                            event.timestamp,
                            type_str,
                            msg.channel,
                            msg.data[0],
                            msg.data[1]);
                }
                hw.PrintLine(outstr);
            }
        }
    }
}