/** Example of setting reading MIDI Input via USB Host * * * This requires a USB-A connector * * This example will also log incoming messages to the serial port for general MIDI troubleshooting */ #include "daisy_seed.h" #include "usbh_midi.h" /** This prevents us from having to type "daisy::" in front of a lot of things. */ using namespace daisy; /** Global Hardware access */ DaisySeed hw; MidiUsbHandler midi; USBHostHandle usbHost; /** FIFO to hold messages as we're ready to print them */ FIFO event_log; void USBH_Connect(void* data) { hw.PrintLine("device connected"); } void USBH_Disconnect(void* data) { hw.PrintLine("device disconnected"); } void USBH_ClassActive(void* data) { if(usbHost.IsActiveClass(USBH_MIDI_CLASS)) { hw.PrintLine("MIDI device class active"); MidiUsbHandler::Config midi_config; midi_config.transport_config.periph = MidiUsbTransport::Config::Periph::HOST; midi.Init(midi_config); midi.StartReceive(); } } void USBH_Error(void* data) { hw.PrintLine("USB device error"); } int main(void) { /** Initialize our hardware */ hw.Init(); hw.StartLog(true); hw.PrintLine("MIDI USB Host start"); /** Configure USB host */ USBHostHandle::Config usbhConfig; usbhConfig.connect_callback = USBH_Connect, usbhConfig.disconnect_callback = USBH_Disconnect, usbhConfig.class_active_callback = USBH_ClassActive, usbhConfig.error_callback = USBH_Error, usbHost.Init(usbhConfig); usbHost.RegisterClass(USBH_MIDI_CLASS); uint32_t now = System::GetNow(); uint32_t log_time = System::GetNow(); uint32_t blink_time = 0; bool ledState = false; hw.PrintLine("MIDI USB Host initialized"); /** Infinite Loop */ while(1) { now = System::GetNow(); if (now > blink_time) { hw.SetLed(ledState); ledState = !ledState; if (usbHost.GetPresent()) blink_time = now + 400; else blink_time = now + 80; } /** Run USB host process */ usbHost.Process(); if(usbHost.IsActiveClass(USBH_MIDI_CLASS) && midi.RxActive()) { /** Process MIDI in the background */ midi.Listen(); /** Loop through any MIDI Events */ while(midi.HasEvents()) { MidiEvent msg = midi.PopEvent(); /** Handle messages as they come in * See DaisyExamples for some examples of this */ 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; } /** Regardless of message, let's add the message data to our queue to output */ event_log.PushBack(msg); } /** Now separately, every 5ms we'll print the top message in our queue if there is one */ if(now - log_time > 5) { log_time = now; if(!event_log.IsEmpty()) { auto msg = event_log.PopFront(); char outstr[128]; const char* type_str = MidiEvent::GetTypeAsString(msg); sprintf(outstr, "time:\t%ld\ttype: %s\tChannel: %d\tData MSB: " "%d\tData LSB: %d\n", now, type_str, msg.channel, msg.data[0], msg.data[1]); hw.PrintLine(outstr); } } } } }