aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRalf Kistner <ralf.kistner@gmail.com>2013-03-18 22:10:06 +0200
committerRalf Kistner <ralf.kistner@gmail.com>2013-03-18 22:10:06 +0200
commit7fac9e38a44a65f013f5467b3d0d713bbcb2f38c (patch)
tree3ba930bb9e3f08a3c0bee2740b8cc38ac3a49485
parent94cfd154d47dc9b4a8345ed9df196a7623143d9f (diff)
Implement MIDI read and write.
-rw-r--r--avr/cores/arcore/MIDIUSB.cpp85
-rw-r--r--avr/cores/arcore/MIDIUSB.h5
-rw-r--r--avr/cores/arcore/USBAPI.h41
-rw-r--r--avr/cores/arcore/USBCore.cpp2
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))