You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
145 lines
3.9 KiB
145 lines
3.9 KiB
/** 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<MidiEvent, 128> 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|