diff options
| author | Ralf Kistner <ralf.kistner@gmail.com> | 2013-03-18 22:10:06 +0200 |
|---|---|---|
| committer | Ralf Kistner <ralf.kistner@gmail.com> | 2013-03-18 22:10:06 +0200 |
| commit | 7fac9e38a44a65f013f5467b3d0d713bbcb2f38c (patch) | |
| tree | 3ba930bb9e3f08a3c0bee2740b8cc38ac3a49485 | |
| parent | 94cfd154d47dc9b4a8345ed9df196a7623143d9f (diff) | |
Implement MIDI read and write.
| -rw-r--r-- | avr/cores/arcore/MIDIUSB.cpp | 85 | ||||
| -rw-r--r-- | avr/cores/arcore/MIDIUSB.h | 5 | ||||
| -rw-r--r-- | avr/cores/arcore/USBAPI.h | 41 | ||||
| -rw-r--r-- | avr/cores/arcore/USBCore.cpp | 2 |
4 files changed, 132 insertions, 1 deletions
diff --git a/avr/cores/arcore/MIDIUSB.cpp b/avr/cores/arcore/MIDIUSB.cpp index 925cdf7..aeec8a7 100644 --- a/avr/cores/arcore/MIDIUSB.cpp +++ b/avr/cores/arcore/MIDIUSB.cpp @@ -2,6 +2,7 @@ #include "Platform.h" #include "USBAPI.h" #include "USBDesc.h" +#include "MIDIUSB.h" #if defined(USBCON) #ifdef MIDI_ENABLED @@ -71,5 +72,89 @@ bool WEAK MIDI_Setup(Setup& setup) return false; } +const MIDIEvent MIDI_EVENT_NONE = {0, 0, 0, 0}; + + +void MIDIUSB_::accept(void) +{ + midi_buffer *buffer = &(this->_rx_buffer); + int i = (unsigned int)(buffer->head+1) % MIDI_BUFFER_SIZE; + + // if we should be storing the received character into the location + // just before the tail (meaning that the head would advance to the + // current location of the tail), we're about to overflow the buffer + // and so we don't write the character or advance the head. + + // while we have room to store a byte + while (i != buffer->tail) { + int c = USB_Recv(CDC_RX); + if (c == -1) + break; // no more data + buffer->buffer[buffer->head] = c; + buffer->head = i; + + i = (unsigned int)(buffer->head+1) % MIDI_BUFFER_SIZE; + } +} + +int MIDIUSB_::available(void) +{ + midi_buffer *buffer = &(this->_rx_buffer); + return ((unsigned int)(MIDI_BUFFER_SIZE + buffer->head - buffer->tail) % MIDI_BUFFER_SIZE) / 4; +} + +MIDIEvent MIDIUSB_::peek(void) +{ + if(this->available() < 4) { + return MIDI_EVENT_NONE; + } else { + midi_buffer *buffer = &(this->_rx_buffer); + MIDIEvent result; + result.type = buffer->buffer[buffer->tail]; + result.m1 = buffer->buffer[(buffer->tail+1) % MIDI_BUFFER_SIZE]; + result.m2 = buffer->buffer[(buffer->tail+2) % MIDI_BUFFER_SIZE]; + result.m3 = buffer->buffer[(buffer->tail+3) % MIDI_BUFFER_SIZE]; + return result; + } +} + +MIDIEvent MIDIUSB_::read(void) +{ + MIDIEvent event = this->peek(); + midi_buffer *buffer = &(this->_rx_buffer); + buffer->tail = (unsigned int)(buffer->tail + 4) % MIDI_BUFFER_SIZE; + return event; +} + +void MIDIUSB_::flush(void) +{ + USB_Flush(MIDI_TX); +} + +size_t MIDIUSB_::write(MIDIEvent c) +{ + // TODO: only try to send bytes if the connection is open + + int r = USB_Send(MIDI_TX,&c,4); + if (r > 0) { + return r; + } else { + return 0; + } +} + +// This operator is a convenient way for a sketch to check whether the +// port has actually been configured and opened by the host (as opposed +// to just being connected to the host). It can be used, for example, in +// setup() before printing to ensure that an application on the host is +// actually ready to receive and display the data. +// This is not actually implemented yet (always returns true). +MIDIUSB_::operator bool() { + return true; +} + +MIDIUSB_ MIDIUSB; + + #endif #endif diff --git a/avr/cores/arcore/MIDIUSB.h b/avr/cores/arcore/MIDIUSB.h index e69de29..5410867 100644 --- a/avr/cores/arcore/MIDIUSB.h +++ b/avr/cores/arcore/MIDIUSB.h @@ -0,0 +1,5 @@ +#if defined(USBCON) +#ifdef MIDI_ENABLED + +#endif +#endif
\ No newline at end of file diff --git a/avr/cores/arcore/USBAPI.h b/avr/cores/arcore/USBAPI.h index f12277e..4c1852f 100644 --- a/avr/cores/arcore/USBAPI.h +++ b/avr/cores/arcore/USBAPI.h @@ -44,6 +44,47 @@ public: }; extern Serial_ Serial; + +//================================================================================ +//================================================================================ +// MIDI_USB + +#define MIDI_BUFFER_SIZE 64 + +struct midi_buffer +{ + unsigned char buffer[MIDI_BUFFER_SIZE]; + volatile int head; + volatile int tail; +}; + +typedef struct +{ + uint8_t type; + uint8_t m1; + uint8_t m2; + uint8_t m3; +} MIDIEvent; + +extern const MIDIEvent MIDI_EVENT_NONE; + +class MIDIUSB_ +{ +private: + midi_buffer _rx_buffer; +public: + + virtual int available(void); + virtual void accept(void); + virtual MIDIEvent peek(void); + virtual MIDIEvent read(void); + virtual void flush(void); + virtual size_t write(MIDIEvent); + operator bool(); +}; +extern MIDIUSB_ MIDIUSB; + + //================================================================================ //================================================================================ // Mouse diff --git a/avr/cores/arcore/USBCore.cpp b/avr/cores/arcore/USBCore.cpp index 735ca18..686a2e8 100644 --- a/avr/cores/arcore/USBCore.cpp +++ b/avr/cores/arcore/USBCore.cpp @@ -630,7 +630,7 @@ ISR(USB_GEN_vect) Serial.accept(); #endif #ifdef MIDI_ENABLED - // TODO: implement midi receive here + MIDIUSB.accept(); #endif // check whether the one-shot period has elapsed. if so, turn off the LED if (TxLEDPulse && !(--TxLEDPulse)) |
