aboutsummaryrefslogtreecommitdiff
path: root/Software
diff options
context:
space:
mode:
authorDonald Delmar Davis <don@suspectdevices.com>2012-11-19 11:57:28 -0800
committerDonald Delmar Davis <don@suspectdevices.com>2012-11-19 11:57:28 -0800
commitb6381c14a669f5d1da0e3a3a9d67cb6b372fe8b4 (patch)
treebf9b23ed074301b763808b3e964b3ea4163192dd /Software
parent92ac5f0423edeabbc978b59a6c0dc2f62f843124 (diff)
Add PacketMidi and MidiSpec files.HEADmaster
Diffstat (limited to 'Software')
-rwxr-xr-xSoftware/LGL/MM2.c1
-rwxr-xr-xSoftware/LGL/MM2.h8
-rw-r--r--Software/LGL/MidiSpecs.h132
-rwxr-xr-xSoftware/LGL/PacketMidi.c313
-rwxr-xr-xSoftware/LGL/PacketMidi.h58
5 files changed, 503 insertions, 9 deletions
diff --git a/Software/LGL/MM2.c b/Software/LGL/MM2.c
index 4fb74f3..2682f36 100755
--- a/Software/LGL/MM2.c
+++ b/Software/LGL/MM2.c
@@ -118,7 +118,6 @@ int main(void)
/** ISR to handle the reloading of the PWM timer with the next sample. */
ISR(TIMER0_COMPA_vect, ISR_BLOCK)
{
- uint16_t MixedSample = 0;
/* Sum together all the active notes to form a single sample */
for (uint8_t i = 0; i < MAX_SIMULTANEOUS_NOTES; i++)
diff --git a/Software/LGL/MM2.h b/Software/LGL/MM2.h
index b0de95c..1fb5246 100755
--- a/Software/LGL/MM2.h
+++ b/Software/LGL/MM2.h
@@ -84,14 +84,6 @@
/** Sample table increments per period for the base MIDI note frequency */
#define BASE_INCREMENT (((F_CPU / VIRTUAL_SAMPLE_TABLE_SIZE / 2) / BASE_FREQUENCY))
- /* Type Defines: */
- typedef struct
- {
- uint8_t LRUAge;
- uint8_t Pitch;
- uint32_t TableIncrement;
- uint32_t TablePosition;
- } DDSNoteData;
/* Function Prototypes: */
void SetupHardware(void);
diff --git a/Software/LGL/MidiSpecs.h b/Software/LGL/MidiSpecs.h
new file mode 100644
index 0000000..008f460
--- /dev/null
+++ b/Software/LGL/MidiSpecs.h
@@ -0,0 +1,132 @@
+/*--------------------------------------------------------------------------MidiSpecs.h
+ *
+ * These defines are based on specs created by the USB and MMA standards organizations.
+ * There are not a lot of other ways to code them so liscensing this is rather ludicrous.
+ * However, in order to be able to embed this in client projects, and avoid the stupidity
+ * of enforced open everything I will declare the following about this file.
+ *
+ * Copyright (c) 2011 Donald Delmar Davis, Suspect Devices
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+/*
+ * USB midi commands from
+ * MIDI10.pdf "Universal Serial Bus Device Class Definition for MIDI Devices"
+ * REV 1. (1999)
+ * http://www.usb.org/developers/devclass_docs/midi10.pdf
+ *
+ */
+
+#ifndef __LETS_MIDI_SPECS_H__
+#define __LETS_MIDI_SPECS_H__
+#include <stdint.h>
+#include <stdbool.h>
+
+#if defined(__GNUC__)
+typedef struct
+{
+ unsigned cable : 4;
+ unsigned cin : 4; // this is the low nibble.
+ uint8_t midi0;
+ uint8_t midi1;
+ uint8_t midi2;
+} __attribute__ ((__packed__)) MIDI_EVENT_PACKET_t ;
+#else
+typedef struct // may need to be adjusted for other compilers and bitfield order...
+{
+ unsigned cable : 4;
+ unsigned cin : 4;
+ uint8_t midi0;
+ uint8_t midi1;
+ uint8_t midi2;
+} MIDI_EVENT_PACKET_t ;
+#endif
+
+
+#define CIN_MISC_FUNCTION 0x00 /* Reserved for future extension. */
+#define CIN_CABLE_EVENT 0x01 /* Reserved for future extension. */
+#define CIN_2BYTE_SYS_COMMON 0x02 /* 2Bytes -- MTC, SongSelect, etc. */
+#define CIN_3BYTE_SYS_COMMON 0x03 /* 3Bytes -- SPP, etc. */
+#define CIN_SYSEX 0x04 /* 3Bytes */
+#define CIN_SYSEX_ENDS_IN_1 0x05 /* 1Bytes */
+#define CIN_SYSEX_ENDS_IN_2 0x06 /* 2Bytes */
+#define CIN_SYSEX_ENDS_IN_3 0x07 /* 3Bytes */
+#define CIN_NOTE_OFF 0x08 /* 3Bytes */
+#define CIN_NOTE_ON 0x09 /* 3Bytes */
+#define CIN_AFTER_TOUCH 0x0A /* 3Bytes */
+#define CIN_CONTROL_CHANGE 0x0B /* 3Bytes */
+#define CIN_PROGRAM_CHANGE 0x0C /* 2Bytes */
+#define CIN_CHANNEL_PRESSURE 0x0D /* 2Bytes */
+#define CIN_PITCH_WHEEL 0x0E /* 3Bytes */
+#define CIN_1BYTE 0x0F /* 1Bytes */
+//#define CIN_IS_SYSEX(cin) ((cin == CIN_SYSEX)||(cin == CIN_SYSEX_ENDS_IN_1)||(cin == CIN_SYSEX_ENDS_IN_2)||(cin == CIN_SYSEX_ENDS_IN_3))
+#define CIN_IS_SYSEX(cin) ( ((cin) & ~(0x08)) && ((cin) &0x04) )
+
+/*
+ * MIDI V1 message definitions these are from the MMA document
+ * http://www.midi.org/techspecs/midimessages.php
+ */
+#define MIDIv1_BAUD_RATE 31250
+
+/*
+ * parse midi (v1) message macros
+ */
+#define MIDIv1_IS_STATUS(b) ((b) & 0x80)
+#define MIDIv1_IS_VOICE(b) ((b) <= 0xEF)
+#define MIDIv1_VOICE_COMMAND(b) ((b) & 0xF0)
+#define MIDIv1_VOICE_CHANNEL(b) ((b) & 0x0F)
+#define MIDIv1_IS_SYSCOMMON(b) (((b) >= 0xF0) & ((b) < 0xF8))
+#define MIDIv1_IS_REALTIME(b) ((b) >= 0xF8)
+
+/*
+ * Voice category messages
+ */
+#define MIDIv1_NOTE_OFF 0x80 /* 2 bytes data -- CIN_NOTE_OFF */
+#define MIDIv1_NOTE_ON 0x90 /* 2 bytes data -- CIN_NOTE_ON */
+#define MIDIv1_AFTER_TOUCH 0xA0 /* 2 bytes data -- CIN_AFTER_TOUCH */
+#define MIDIv1_CONTROL_CHANGE 0xB0 /* 2 bytes data -- CIN_CONTROL_CHANGE */
+#define MIDIv1_PROGRAM_CHANGE 0xC0 /* 1 byte data -- CIN_PROGRAM_CHANGE */
+#define MIDIv1_CHANNEL_PRESSURE 0xD0 /* 1 byte data -- CIN_CHANNEL_PRESSURE */
+#define MIDIv1_PITCH_WHEEL 0xE0 /* 2 bytes data -- CIN_PITCH_WHEEL */
+
+/*
+ * System common category messages
+ */
+#define MIDIv1_SYSEX_START 0xF0
+#define MIDIv1_SYSEX_END 0xF7
+#define MIDIv1_MTC_QUARTER_FRAME 0xF1 /* 1 byte data -- CIN_2BYTE_SYS_COMMON */
+#define MIDIv1_SONG_POSITION_PTR 0xF2 /* 2 bytes data -- CIN_3BYTE_SYS_COMMON */
+#define MIDIv1_SONG_SELECT 0xF3 /* 1 byte data -- CIN_2BYTE_SYS_COMMON */
+#define MIDIv1_TUNE_REQUEST 0xF6 /* no data -- CIN_1BYTE */
+
+/*
+ * Realtime category messages, can be sent anytime
+ */
+#define MIDIv1_CLOCK 0xF8 /* no data -- CIN_1BYTE */
+#define MIDIv1_TICK 0xF9 /* no data -- CIN_1BYTE */
+#define MIDIv1_START 0xFA /* no data -- CIN_1BYTE */
+#define MIDIv1_CONTINUE 0xFB /* no data -- CIN_1BYTE */
+#define MIDIv1_STOP 0xFC /* no data -- CIN_1BYTE */
+#define MIDIv1_ACTIVE_SENSE 0xFE /* no data -- CIN_1BYTE */
+#define MIDIv1_RESET 0xFF /* no data -- CIN_1BYTE */
+
+#endif
+
+
diff --git a/Software/LGL/PacketMidi.c b/Software/LGL/PacketMidi.c
new file mode 100755
index 0000000..b29f5bf
--- /dev/null
+++ b/Software/LGL/PacketMidi.c
@@ -0,0 +1,313 @@
+/*-------------------------------------------------------------------------------------PacketMidi.c
+ *
+ * Draft of Suspect Devices "PacketMidi" midi library.
+ * I started this because I needed a library that I could embed in client projects
+ * Some of the better libraries are gpl only and therefor could not be used where
+ * the client wanted control over their end product and code. This library is there
+ * for bsd liscensed.
+ *
+ * The philosophy of PacketMidi is based on the model presented in the usb spec
+ * where all midi events are 4 bytes long, serialization (sic) and deserialialization
+ * is handled by the uart interupts and uart output routines.
+ * events are queued and handled in the main loop.
+ *
+ *
+ * Created by Donald D Davis on 9/9/11.
+ *
+ * Copyright (c) 2011 Donald Delmar Davis, Suspect Devices
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "PacketMidi.h"
+// should use fancy use if __AVR_ATMEGA168__
+#if defined(__AVR_ATmega328__) || defined(__AVR_ATmega168__)
+#define MIDI_USES_UART0 1
+#endif
+
+#ifndef DEFAULT_MIDI_CHANNEL
+#define DEFAULT_MIDI_CHANNEL 0
+#define DEFAULT_MIDI_CABLE_NO 0
+#endif
+
+
+volatile uint8_t Channel = DEFAULT_MIDI_CHANNEL;
+
+
+
+/*---------------------------------------dispatchMidiEvent(MIDI_EVENT_PACKET_t e)
+ *
+ */
+
+
+void dispatchMidiEvent(MIDI_EVENT_PACKET_t e) {
+
+ if (CIN_IS_SYSEX(e.cin)) {
+ sysexInterpreter(e);
+ } else {
+ doLocalMidiEvent(e);
+ routeToUart(e);
+ }
+}
+
+
+#define MAX_EVENT_QUEUE_LENGTH 16
+/*------------------------------------------------------------------------------
+ * uart event queue routines.
+ * these are brutally rudimentary at the moment.
+ *----------------------------------------------------------------------------*/
+
+MIDI_EVENT_PACKET_t UARTMIDIEventQueue[MAX_EVENT_QUEUE_LENGTH];
+uint8_t UARTMIDIEventQueueHead=0;
+uint8_t UARTMIDIEventQueueTail=0;
+/*------------------------------------------queueMidiEvent(MIDI_EVENT_PACKET_t e)
+ * add packet to queue
+ */
+
+void queueMidiEvent(MIDI_EVENT_PACKET_t e) {
+ UARTMIDIEventQueue[UARTMIDIEventQueueTail]=e;
+ if (++UARTMIDIEventQueueTail>=MAX_EVENT_QUEUE_LENGTH) {
+ UARTMIDIEventQueueTail=0;
+ } // some bounds checking should be here!!!
+}
+/*------------------------------------------------------------midiEventInQueue()
+ *
+ */
+
+bool midiEventInQueue() {
+ return (UARTMIDIEventQueueHead!=UARTMIDIEventQueueTail);
+}
+
+/*------------------------------------------------------------------------------
+ * uart event queue routines.
+ *----------------------------------------------------------------------------*/
+MIDI_EVENT_PACKET_t nextMidiEvent() {
+ // some bounds checking should be here!!!
+ MIDI_EVENT_PACKET_t e = UARTMIDIEventQueue[UARTMIDIEventQueueHead];
+ if (++UARTMIDIEventQueueHead>=MAX_EVENT_QUEUE_LENGTH) {
+ UARTMIDIEventQueueHead=0;
+ }
+ return (e);
+}
+
+/*------------------------------------------------------------------------------
+ * uart setup and handling
+ *----------------------------------------------------------------------------*/
+
+/*------------------------------------------------ISR(USARTx_RX_vect, ISR_BLOCK)
+ * parse incoming bytes into midi Events.
+ */
+
+#ifndef MIDI_USES_UART0
+ISR(USART1_RX_vect, ISR_BLOCK)
+{
+ uint8_t b = UDR1;
+#else
+ISR(USART_RX_vect, ISR_BLOCK)
+{
+ uint8_t b = UDR0;
+#endif
+
+ static uint8_t needBytes;
+ static uint8_t bytesIndex;
+ static bool inSysex;
+ static MIDI_EVENT_PACKET_t realTimeEvent;
+ static MIDI_EVENT_PACKET_t pendingEvent;
+
+ if (inSysex) {
+ if (b == MIDIv1_SYSEX_END){
+ inSysex=0;
+ if (bytesIndex==3) {
+ pendingEvent.cin=CIN_SYSEX_ENDS_IN_3;
+ pendingEvent.midi2=b;
+ } else if (bytesIndex==2) {
+ pendingEvent.cin=CIN_SYSEX_ENDS_IN_2;
+ pendingEvent.midi1=b;
+ } else {
+ pendingEvent.cin=CIN_SYSEX_ENDS_IN_1;
+ pendingEvent.midi0=b;
+ }
+ bytesIndex=0;
+ needBytes=0;
+ queueMidiEvent(pendingEvent);
+
+ } else {
+ if (bytesIndex==1){
+ pendingEvent.midi0=b;
+ bytesIndex++;
+ } else if (bytesIndex==2) {
+ pendingEvent.midi1=b;
+ bytesIndex++;
+ } else {
+ pendingEvent.midi2=b;
+ queueMidiEvent(pendingEvent);
+ pendingEvent.cin=CIN_SYSEX;
+ bytesIndex=1;
+ }
+
+ }
+ return;
+ }
+
+ if (needBytes) { // if still parsing last command.
+ if (bytesIndex==1){
+ pendingEvent.midi0=b;
+ bytesIndex++;
+ } else if (bytesIndex==2) {
+ pendingEvent.midi1=b;
+ bytesIndex++;
+ } else {
+ pendingEvent.midi2=b;
+ }
+ needBytes--;
+ if (needBytes < 1) { // if that was the last Byte
+ needBytes=0;
+ queueMidiEvent(pendingEvent);
+ }
+ return;
+ }
+
+
+ if (MIDIv1_IS_REALTIME(b)){
+ realTimeEvent.cable=DEFAULT_MIDI_CABLE_NO;
+ realTimeEvent.cin=CIN_1BYTE;
+ realTimeEvent.midi0=b;
+ queueMidiEvent(realTimeEvent);
+ return ;
+ }
+ if (MIDIv1_IS_VOICE(b)){
+
+ pendingEvent.cable = DEFAULT_MIDI_CABLE_NO;
+ pendingEvent.cin = (b>>4)&0x0f;
+ pendingEvent.midi0 = b;
+ if((MIDIv1_VOICE_COMMAND(b) == MIDIv1_PROGRAM_CHANGE)
+ || (MIDIv1_VOICE_COMMAND(b) == MIDIv1_CHANNEL_PRESSURE)
+ ) {
+ needBytes = 1;
+ } else {
+ needBytes = 2;
+ }
+ bytesIndex = 2;
+ return;
+ }
+ if (MIDIv1_IS_SYSCOMMON(b)){
+ pendingEvent.cable = DEFAULT_MIDI_CABLE_NO;
+ switch (b) {
+ case MIDIv1_SYSEX_START :
+ inSysex = 1;
+ needBytes = 2;
+ bytesIndex = 2;
+ pendingEvent.cin = CIN_SYSEX;
+ pendingEvent.midi0 = b;
+ break;
+ case MIDIv1_SONG_POSITION_PTR :
+ pendingEvent.cin = CIN_3BYTE_SYS_COMMON;
+ pendingEvent.midi0 = b;
+ needBytes=2;
+ bytesIndex=2;
+ break;
+ case MIDIv1_TUNE_REQUEST :
+ pendingEvent.cin = CIN_1BYTE;
+ pendingEvent.midi0 = b;
+ queueMidiEvent(pendingEvent);
+ break;
+ case MIDIv1_MTC_QUARTER_FRAME :
+ case MIDIv1_SONG_SELECT :
+ pendingEvent.cin = CIN_2BYTE_SYS_COMMON;
+ pendingEvent.midi0 = b;
+ needBytes = 1;
+ bytesIndex = 2;
+ break;
+ // case MIDIv1_SYSEX_END handled up top
+ }
+ return;
+ }
+
+}
+
+/*---------------------------------------------routeToUart(MIDI_EVENT_PACKET_t E)
+ *
+ */
+void routeToUart(MIDI_EVENT_PACKET_t E) {
+ // we will handle these when they are defined in the standard.
+ // if (E.cin<CIN_2BYTE_SYS_COMMON ) {
+ // return;
+ // }
+ sendUartMidiByte(E.midi0); // we always send at least data1
+ if ((E.cin==CIN_1BYTE)
+ ||(E.cin==CIN_SYSEX_ENDS_IN_1)
+ ) {
+ return;
+ }
+ sendUartMidiByte(E.midi1); // we sometimes send data2
+ if ((E.cin==CIN_2BYTE_SYS_COMMON)
+ || (E.cin==CIN_SYSEX_ENDS_IN_2)
+ || (E.cin==CIN_PROGRAM_CHANGE)
+ || (E.cin==CIN_CHANNEL_PRESSURE)
+ ) {
+ return;
+ }
+ sendUartMidiByte(E.midi2); // the rest of the time we send data3
+}
+
+/*---------------------------------------------------sendUartMidiByte(uint8_t b)
+ *
+ */
+void sendUartMidiByte(uint8_t b) {
+#ifndef MIDI_USES_UART0
+ while (!(UCSR1A & (1 << UDRE1)));
+ UDR1 = b;
+#else
+ while (!(UCSR0A & (1 << UDRE0)));
+ UDR0 = b;
+#endif
+}
+
+/*---------------------------------------------------------------setupMidiUart()
+ *
+ */
+#define UART_USE_u2x 1
+
+void setupMidiUart() {
+ uint16_t baud;
+#ifndef MIDI_USES_UART0
+#ifdef UART_USE_u2x
+ UCSR1A = _BV(U2X1);
+ baud = (F_CPU / 4 / MIDIv1_BAUD_RATE - 1) / 2;
+#else
+ UCSR1A = 0;
+ baud = (F_CPU / 8 / MIDIv1_BAUD_RATE - 1) / 2;
+#endif
+ UBRR1 = baud;
+ UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1));
+#else
+#ifdef UART_USE_u2x
+ UCSR0A = _BV(U2X0);
+ baud = (F_CPU / 4 / MIDIv1_BAUD_RATE - 1) / 2;
+#else
+ UCSR0A = 0;
+ baud = (F_CPU / 8 / MIDIv1_BAUD_RATE - 1) / 2;
+#endif
+ UBRR0 = baud;
+ UCSR0B = ((1 << RXCIE0) | (1 << TXEN0) | (1 << RXEN0));
+#endif
+}
+
+
diff --git a/Software/LGL/PacketMidi.h b/Software/LGL/PacketMidi.h
new file mode 100755
index 0000000..91cbe3f
--- /dev/null
+++ b/Software/LGL/PacketMidi.h
@@ -0,0 +1,58 @@
+/*-------------------------------------------------------------------------------------PacketMidi.h
+ *
+ * Draft of Suspect Devices "PacketMidi" midi library.
+ * I started this because I needed a library that I could embed in client projects
+ * Some of the better libraries are gpl only and therefor could not be used where
+ * the client wanted control over their end product and code. This library is there
+ * for bsd liscensed.
+ *
+ * The philosophy of PacketMidi is based on the model presented in the usb spec
+ * where all midi events are 4 bytes long, serialization (sic) and deserialialization
+ * is handled by the uart interupts and uart output routines.
+ * events are queued and handled in the main loop.
+ *
+ *
+ * Created by Donald D Davis on 9/9/11.
+ *
+ * Copyright (c) 2011 Donald Delmar Davis, Suspect Devices
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of this
+ * software and associated documentation files (the "Software"), to deal in the Software
+ * without restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to the following
+ * conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all copies
+ * or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+ * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+#ifndef __LETS_PACKET_MIDI_H__
+#define __LETS_PACKET_MIDI_H__
+
+#include "MidiSpecs.h"
+
+void setupMidiUart(void);
+void routeToUart(MIDI_EVENT_PACKET_t e);
+void dispatchMidiEvent(MIDI_EVENT_PACKET_t e);
+void queueMidiEvent(MIDI_EVENT_PACKET_t e);
+bool midiEventInQueue(void);
+MIDI_EVENT_PACKET_t nextMidiEvent(void);
+void sendUartMidiByte(uint8_t b);
+
+// user supplied ....
+void doLocalMidiEvent(MIDI_EVENT_PACKET_t e);
+void getLocalMidiEvents(void);
+void sysexInterpreter(MIDI_EVENT_PACKET_t e);
+
+#endif
+
+
+