Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: F401RE-USBHostMIDI_RecieveExample
Fork of F401RE-USBHost by
Revision 24:5281ea9f6e68, committed 2014-09-18
- Comitter:
- hsgw
- Date:
- Thu Sep 18 10:50:22 2014 +0000
- Parent:
- 23:9c1d09c6a2b6
- Child:
- 25:c4fdd0b4e643
- Commit message:
- add other midi status. ; but miscellaneous function and cable event has been disabled.
Changed in this revision
--- a/USBHostMIDI/CircBuffer.h Wed Sep 17 14:29:11 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,80 +0,0 @@
-/* USBHostMidi library
- * Originaled by k.shoji
- * porting by Takuya Urakawa
- */
-
-/* mbed USBHost Library
- * Copyright (c) 2006-2013 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef CIRCBUFFER_H
-#define CIRCBUFFER_H
-
-#include "stdint.h"
-
-//circular buffer
-template<typename T, int size>
-class CircBuffer {
-public:
-
- CircBuffer() {
- write = 0;
- read = 0;
- }
-
- bool isFull() {
- bool r = (((write + 1) % size) == read);
- return r;
- }
-
- bool isEmpty() {
- bool r = (read == write);
- return r;
- }
-
- void flush() {
- write = 0;
- read = 0;
- }
-
- void queue(T k) {
- while (((write + 1) % size) == read) {
- wait_ms(10);
- }
- buf[write++] = k;
- write %= size;
- }
-
- uint16_t available() {
- uint16_t a = (write >= read) ? (write - read) : (size - read + write);
- return a;
- }
-
- bool dequeue(T * c) {
- bool empty = (read == write);
- if (!empty) {
- *c = buf[read++];
- read %= size;
- }
- return (!empty);
- }
-
-private:
- volatile uint16_t write;
- volatile uint16_t read;
- volatile T buf[size];
-};
-
-#endif
--- a/USBHostMIDI/USBHostMIDI.cpp Wed Sep 17 14:29:11 2014 +0000
+++ b/USBHostMIDI/USBHostMIDI.cpp Thu Sep 18 10:50:22 2014 +0000
@@ -1,253 +1,366 @@
-/* USBHostMidi library
- * Originaled by k.shoji
- * porting by Takuya Urakawa
- */
-
-/* mbed USBHost Library
- * Copyright (c) 2006-2013 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "USBHostMIDI.h"
-
-#if USBHOST_MIDI
-
-#include "dbg.h"
-
-#define SET_LINE_CODING 0x20
-
-USBHostMIDI::USBHostMIDI(): circ_buf() {
- host = USBHost::getHostInst();
- size_bulk_in = 0;
- size_bulk_out = 0;
- init();
-}
-
-void USBHostMIDI::init() {
- dev = NULL;
- bulk_in = NULL;
- bulk_out = NULL;
- dev_connected = false;
- midi_intf = -1;
- midi_device_found = false;
- circ_buf.flush();
-}
-
-bool USBHostMIDI::connected()
-{
- return dev_connected;
-}
-
-bool USBHostMIDI::connect() {
-
- if (dev_connected) {
- return true;
- }
- for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
- if ((dev = host->getDevice(i)) != NULL) {
-
- USB_DBG("Trying to connect MIDI device\r\n");
-
- if(host->enumerate(dev, this))
- break;
-
- if (midi_device_found) {
- bulk_in = dev->getEndpoint(midi_intf, BULK_ENDPOINT, IN);
- bulk_out = dev->getEndpoint(midi_intf, BULK_ENDPOINT, OUT);
-
- if (!bulk_in || !bulk_out)
- break;
-
- USB_INFO("New MIDI device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, midi_intf);
- dev->setName("MIDI", midi_intf);
- host->registerDriver(dev, midi_intf, this, &USBHostMIDI::init);
-
- size_bulk_in = bulk_in->getSize();
- size_bulk_out = bulk_out->getSize();
-
- bulk_in->attach(this, &USBHostMIDI::rxHandler);
-
- host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
- dev_connected = true;
- return true;
- }
- }
- }
- init();
- return false;
-}
-
-void USBHostMIDI::rxHandler() {
- uint8_t pos = 0;
- uint8_t midi[4];
- if (bulk_in) {
- int len = bulk_in->getLengthTransferred();
- if (bulk_in->getState() == USB_TYPE_IDLE || bulk_in->getState() == USB_TYPE_FREE) {
- for (int i = 0; i < len; i++) {
- circ_buf.queue(buf[i]);
- }
-
- // MIDI event handling
- while (!circ_buf.isEmpty()) {
- // read each four bytes
- circ_buf.dequeue(&midi[pos++]);
- if (pos == 4) {
- pos = 0;
-
- // process MIDI message
- // switch by code index number
- switch (midi[0] & 0xf) {
- case 8:
- noteOff(midi[1] & 0xf, midi[2], midi[3]);
- break;
- case 9:
- if (midi[3]) {
- noteOn(midi[1] & 0xf, midi[2], midi[3]);
- } else {
- noteOff(midi[1] & 0xf, midi[2], midi[3]);
- }
- break;
- case 11:
- controlChange(midi[1] & 0xf, midi[2], midi[3]);
- break;
- case 12:
- programChange(midi[1] & 0xf, midi[2]);
- break;
- case 14:
- pitchBend(midi[1] & 0xf, midi[2] | (midi[3] << 7));
- break;
- default:
- break;
- }
- }
- }
-
- host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
- }
- }
-}
-
-int USBHostMIDI::sendNoteOn(unsigned char channel, unsigned char note, unsigned char velocity) {
- uint8_t midi[4];
-
- if (bulk_out) {
- midi[0] = 9;
- midi[1] = channel & 0xf;
- midi[2] = note & 0x7f;
- midi[3] = velocity & 0x7f;
- if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
- return 1;
- }
- }
- return -1;
-}
-
-int USBHostMIDI::sendNoteOff(unsigned char channel, unsigned char note, unsigned char velocity) {
- uint8_t midi[4];
-
- if (bulk_out) {
- midi[0] = 8;
- midi[1] = channel & 0xf;
- midi[2] = note & 0x7f;
- midi[3] = velocity & 0x7f;
- if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
- return 1;
- }
- }
- return -1;
-}
-
-int USBHostMIDI::sendControlChange(unsigned char channel, unsigned char key, unsigned char value) {
- uint8_t midi[4];
-
- if (bulk_out) {
- midi[0] = 11;
- midi[1] = channel & 0xf;
- midi[2] = key & 0x7f;
- midi[3] = value & 0x7f;
- if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
- return 1;
- }
- }
- return -1;
-}
-
-int USBHostMIDI::sendProgramChange(unsigned char channel, unsigned char program) {
- uint8_t midi[4];
-
- if (bulk_out) {
- midi[0] = 12;
- midi[1] = channel & 0xf;
- midi[2] = program & 0x7f;
- midi[3] = 0;
- if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
- return 1;
- }
- }
- return -1;
-}
-
-int USBHostMIDI::sendPitchBend(unsigned char channel, unsigned int value) {
- uint8_t midi[4];
-
- if (bulk_out) {
- midi[0] = 14;
- midi[1] = channel & 0xf;
- midi[2] = value & 0x7f;
- midi[3] = (value >> 7) & 0x7f;
- if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
- return 1;
- }
- }
- return -1;
-}
-
-/*virtual*/ void USBHostMIDI::setVidPid(uint16_t vid, uint16_t pid)
-{
- // we don't check VID/PID for this driver
-}
-
-/*virtual*/ bool USBHostMIDI::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
-{
- // USB MIDI class/subclass
- if ((midi_intf == -1) &&
- (intf_class == AUDIO_CLASS) &&
- (intf_subclass == 0x03)) {
- midi_intf = intf_nb;
- return true;
- }
-
- // vendor specific device
- if ((midi_intf == -1) &&
- (intf_class == 0xff) &&
- (intf_subclass == 0x03)) {
- midi_intf = intf_nb;
- return true;
- }
-
- return false;
-}
-
-/*virtual*/ bool USBHostMIDI::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
-{
- if (intf_nb == midi_intf) {
- if (type == BULK_ENDPOINT) {
- midi_device_found = true;
- return true;
- }
- }
- return false;
-}
-
-#endif
+/* USBHostMidi library
+ * Originaled by k.shoji
+ * porting by Takuya Urakawa
+ */
+
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "USBHostMIDI.h"
+
+#if USBHOST_MIDI
+
+#include "dbg.h"
+
+#define SET_LINE_CODING 0x20
+
+USBHostMIDI::USBHostMIDI() {
+ host = USBHost::getHostInst();
+ size_bulk_in = 0;
+ size_bulk_out = 0;
+ init();
+}
+
+void USBHostMIDI::init() {
+ dev = NULL;
+ bulk_in = NULL;
+ bulk_out = NULL;
+ dev_connected = false;
+ midi_intf = -1;
+ midi_device_found = false;
+ sysExBufferPos = 0;
+}
+
+bool USBHostMIDI::connected()
+{
+ return dev_connected;
+}
+
+bool USBHostMIDI::connect() {
+
+ if (dev_connected) {
+ return true;
+ }
+ for (uint8_t i = 0; i < MAX_DEVICE_CONNECTED; i++) {
+ if ((dev = host->getDevice(i)) != NULL) {
+
+ USB_DBG("Trying to connect MIDI device\r\n");
+
+ if(host->enumerate(dev, this))
+ break;
+
+ if (midi_device_found) {
+ bulk_in = dev->getEndpoint(midi_intf, BULK_ENDPOINT, IN);
+ bulk_out = dev->getEndpoint(midi_intf, BULK_ENDPOINT, OUT);
+
+ if (!bulk_in || !bulk_out)
+ break;
+
+ USB_INFO("New MIDI device: VID:%04x PID:%04x [dev: %p - intf: %d]", dev->getVid(), dev->getPid(), dev, midi_intf);
+ dev->setName("MIDI", midi_intf);
+ host->registerDriver(dev, midi_intf, this, &USBHostMIDI::init);
+
+ size_bulk_in = bulk_in->getSize();
+ size_bulk_out = bulk_out->getSize();
+
+ bulk_in->attach(this, &USBHostMIDI::rxHandler);
+
+ host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
+ dev_connected = true;
+ return true;
+ }
+ }
+ }
+ init();
+ return false;
+}
+
+void USBHostMIDI::rxHandler() {
+ uint8_t *midi;
+ if (bulk_in) {
+ int length = bulk_in->getLengthTransferred();
+ if (bulk_in->getState() == USB_TYPE_IDLE || bulk_in->getState() == USB_TYPE_FREE) {
+ // MIDI event handling
+ for (int i = 0; i < length; i += 4) {
+ if (i + 4 > length) {
+ // length shortage, ignored.
+ break;
+ }
+
+ // read each four bytes
+ midi = &buf[i];
+ // process MIDI message
+ // switch by code index number
+ USB_DBG("midi: %d, %d, %d, %d", midi[0]&0xf, midi[1], midi[2], midi[3]);
+ switch (midi[0] & 0xf) {
+ case 0: // miscellaneous function codes
+ //if(midi[1] == 0) break;
+ //miscellaneousFunctionCode(midi[1], midi[2], midi[3]);
+ break;
+ case 1: // cable events
+ //cableEvent(midi[1], midi[2], midi[3]);
+ break;
+ case 2: // two bytes system common messages
+ systemCommonTwoBytes(midi[1], midi[2]);
+ break;
+ case 3: // three bytes system common messages
+ systemCommonThreeBytes(midi[1], midi[2], midi[3]);
+ break;
+ case 4: // SysEx starts or continues
+ sysExBuffer[sysExBufferPos++] = midi[1];
+ if (sysExBufferPos >= 64) {
+ systemExclusive(sysExBuffer, sysExBufferPos, true);
+ sysExBufferPos = 0;
+ }
+ sysExBuffer[sysExBufferPos++] = midi[2];
+ if (sysExBufferPos >= 64) {
+ systemExclusive(sysExBuffer, sysExBufferPos, true);
+ sysExBufferPos = 0;
+ }
+ sysExBuffer[sysExBufferPos++] = midi[3];
+ // SysEx continues. don't send
+ break;
+ case 5: // SysEx ends with single byte
+ sysExBuffer[sysExBufferPos++] = midi[1];
+ systemExclusive(sysExBuffer, sysExBufferPos, false);
+ sysExBufferPos = 0;
+ break;
+ case 6: // SysEx ends with two bytes
+ sysExBuffer[sysExBufferPos++] = midi[1];
+ if (sysExBufferPos >= 64) {
+ systemExclusive(sysExBuffer, sysExBufferPos, true);
+ sysExBufferPos = 0;
+ }
+ sysExBuffer[sysExBufferPos++] = midi[2];
+ systemExclusive(sysExBuffer, sysExBufferPos, false);
+ sysExBufferPos = 0;
+ break;
+ case 7: // SysEx ends with three bytes
+ sysExBuffer[sysExBufferPos++] = midi[1];
+ if (sysExBufferPos >= 64) {
+ systemExclusive(sysExBuffer, sysExBufferPos, true);
+ sysExBufferPos = 0;
+ }
+ sysExBuffer[sysExBufferPos++] = midi[2];
+ if (sysExBufferPos >= 64) {
+ systemExclusive(sysExBuffer, sysExBufferPos, true);
+ sysExBufferPos = 0;
+ }
+ sysExBuffer[sysExBufferPos++] = midi[3];
+ systemExclusive(sysExBuffer, sysExBufferPos, false);
+ sysExBufferPos = 0;
+ break;
+ case 8:
+ noteOff(midi[1] & 0xf, midi[2], midi[3]);
+ break;
+ case 9:
+ if (midi[3]) {
+ noteOn(midi[1] & 0xf, midi[2], midi[3]);
+ } else {
+ noteOff(midi[1] & 0xf, midi[2], midi[3]);
+ }
+ break;
+ case 10:
+ polyKeyPress(midi[1] & 0xf, midi[2], midi[3]);
+ break;
+ case 11:
+ controlChange(midi[1] & 0xf, midi[2], midi[3]);
+ break;
+ case 12:
+ programChange(midi[1] & 0xf, midi[2]);
+ break;
+ case 13:
+ channelPressure(midi[1] & 0xf, midi[2]);
+ break;
+ case 14:
+ pitchBend(midi[1] & 0xf, midi[2] | (midi[3] << 7));
+ break;
+ case 15:
+ singleByte(midi[1]);
+ break;
+ default: break;
+ }
+ }
+
+ // read another message
+ host->bulkRead(dev, bulk_in, buf, size_bulk_in, false);
+ }
+ }
+}
+
+bool USBHostMIDI::sendMidiBuffer(uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3) {
+ if (bulk_out) {
+ uint8_t midi[4];
+
+ midi[0] = data0;
+ midi[1] = data1;
+ midi[2] = data2;
+ midi[3] = data3;
+ if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, 4) == USB_TYPE_OK) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool USBHostMIDI::sendMiscellaneousFunctionCode(uint8_t data1, uint8_t data2, uint8_t data3) {
+ return sendMidiBuffer(0, data1, data2, data3);
+}
+
+bool USBHostMIDI::sendCableEvent(uint8_t data1, uint8_t data2, uint8_t data3) {
+ return sendMidiBuffer(1, data1, data2, data3);
+}
+
+bool USBHostMIDI::sendSystemCommmonTwoBytes(uint8_t data1, uint8_t data2) {
+ return sendMidiBuffer(2, data1, data2, 0);
+}
+
+bool USBHostMIDI::sendSystemCommmonThreeBytes(uint8_t data1, uint8_t data2, uint8_t data3) {
+ return sendMidiBuffer(3, data1, data2, 0);
+}
+
+bool USBHostMIDI::sendSystemExclusive(uint8_t *buffer, int length) {
+ uint8_t midi[64];
+ int midiLength;
+ int midiPos;
+ if (bulk_out) {
+ for (int i = 0; i < length; i += 48) {
+ if (i + 48 >= length) {
+ // contains last data
+ midiLength = (((length - i) + 2) / 3) * 4;
+ for (int pos = i; pos < length; pos += 3) {
+ midiPos = (pos + 2) / 3 * 4;
+ if (pos + 3 >= length) {
+ // last data
+ switch (pos % 3) {
+ case 0:
+ midi[midiPos ] = 7;
+ midi[midiPos + 1] = buffer[pos ];
+ midi[midiPos + 2] = buffer[pos + 1];
+ midi[midiPos + 3] = buffer[pos + 2];
+ break;
+ case 1:
+ midi[midiPos ] = 5;
+ midi[midiPos + 1] = buffer[pos ];
+ midi[midiPos + 2] = 0;
+ midi[midiPos + 3] = 0;
+ break;
+ case 2:
+ midi[midiPos ] = 6;
+ midi[midiPos + 1] = buffer[pos ];
+ midi[midiPos + 2] = buffer[pos + 1];
+ midi[midiPos + 3] = 0;
+ break;
+ }
+ } else {
+ // has more data
+ midi[midiPos ] = 4;
+ midi[midiPos + 1] = buffer[pos ];
+ midi[midiPos + 2] = buffer[pos + 1];
+ midi[midiPos + 3] = buffer[pos + 2];
+ }
+ }
+ } else {
+ // has more data
+ midiLength = 64;
+ for (int pos = i; pos < length; pos += 3) {
+ midiPos = (pos + 2) / 3 * 4;
+ midi[midiPos ] = 4;
+ midi[midiPos + 1] = buffer[pos ];
+ midi[midiPos + 2] = buffer[pos + 1];
+ midi[midiPos + 3] = buffer[pos + 2];
+ }
+ }
+
+ if (host->bulkWrite(dev, bulk_out, (uint8_t *)midi, midiLength) != USB_TYPE_OK) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+bool USBHostMIDI::sendNoteOff(uint8_t channel, uint8_t note, uint8_t velocity) {
+ return sendMidiBuffer(8, channel & 0xf | 0x80, note & 0x7f, velocity & 0x7f);
+}
+
+bool USBHostMIDI::sendNoteOn(uint8_t channel, uint8_t note, uint8_t velocity) {
+ return sendMidiBuffer(9, channel & 0xf | 0x90, note & 0x7f, velocity & 0x7f);
+}
+
+bool USBHostMIDI::sendPolyKeyPress(uint8_t channel, uint8_t note, uint8_t pressure) {
+ return sendMidiBuffer(10, channel & 0xf | 0xa0, note & 0x7f, pressure & 0x7f);
+}
+
+bool USBHostMIDI::sendControlChange(uint8_t channel, uint8_t key, uint8_t value) {
+ return sendMidiBuffer(11, channel & 0xf | 0xb0, key & 0x7f, value & 0x7f);
+}
+
+bool USBHostMIDI::sendProgramChange(uint8_t channel, uint8_t program) {
+ return sendMidiBuffer(12, channel & 0xf | 0xc0, program & 0x7f, 0);
+}
+
+bool USBHostMIDI::sendChannelPressure(uint8_t channel, uint8_t pressure) {
+ return sendMidiBuffer(13, channel & 0xf | 0xd0, pressure & 0x7f, 0);
+}
+
+bool USBHostMIDI::sendPitchBend(uint8_t channel, uint16_t value) {
+ return sendMidiBuffer(14, channel & 0xf | 0xe0, value & 0x7f, (value >> 7) & 0x7f);
+}
+
+bool USBHostMIDI::sendSingleByte(uint8_t data) {
+ return sendMidiBuffer(15, data, 0, 0);
+}
+
+/*virtual*/ void USBHostMIDI::setVidPid(uint16_t vid, uint16_t pid)
+{
+ // we don't check VID/PID for this driver
+}
+
+/*virtual*/ bool USBHostMIDI::parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol) //Must return true if the interface should be parsed
+{
+ // USB MIDI class/subclass
+ if ((midi_intf == -1) &&
+ (intf_class == AUDIO_CLASS) &&
+ (intf_subclass == 0x03)) {
+ midi_intf = intf_nb;
+ return true;
+ }
+
+ // vendor specific device
+ if ((midi_intf == -1) &&
+ (intf_class == 0xff) &&
+ (intf_subclass == 0x03)) {
+ midi_intf = intf_nb;
+ return true;
+ }
+
+ return false;
+}
+
+/*virtual*/ bool USBHostMIDI::useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir) //Must return true if the endpoint will be used
+{
+ if (intf_nb == midi_intf) {
+ if (type == BULK_ENDPOINT) {
+ midi_device_found = true;
+ return true;
+ }
+ }
+ return false;
+}
+
+#endif
--- a/USBHostMIDI/USBHostMIDI.h Wed Sep 17 14:29:11 2014 +0000
+++ b/USBHostMIDI/USBHostMIDI.h Thu Sep 18 10:50:22 2014 +0000
@@ -1,157 +1,358 @@
-/* USBHostMidi library
- * Originaled by k.shoji
- * porting by Takuya Urakawa
- */
-
-/* mbed USBHost Library
- * Copyright (c) 2006-2013 ARM Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef USBHOSTMIDI_H
-#define USBHOSTMIDI_H
-
-#include "USBHostConf.h"
-
-#if USBHOST_MIDI
-
-#include "USBHost.h"
-
-// STM nucleo boards do not support mbed-rtos
-//#include "MtxCircBuffer.h"
-#include "CircBuffer.h"
-
-/**
- * A class to communicate a USB MIDI device
- */
-class USBHostMIDI : public IUSBEnumerator {
-public:
- /**
- * Constructor
- */
- USBHostMIDI();
-
- /**
- * Check if a USB MIDI device is connected
- *
- * @returns true if a midi device is connected
- */
- bool connected();
-
- /**
- * Try to connect a midi device
- *
- * @return true if connection was successful
- */
- bool connect();
-
- /**
- * Attach a callback called when note on is received
- *
- * @param ptr function pointer
- */
- inline void attachNoteOn(void (*fn)(unsigned char, unsigned char, unsigned char)) {
- if (fn != NULL) {
- noteOn = fn;
- }
- }
-
- /**
- * Attach a callback called when note off is received
- *
- * @param ptr function pointer
- */
- inline void attachNoteOff(void (*fn)(unsigned char, unsigned char, unsigned char)) {
- if (fn != NULL) {
- noteOff = fn;
- }
- }
-
- /**
- * Attach a callback called when control change is received
- *
- * @param ptr function pointer
- */
- inline void attachControlChange(void (*fn)(unsigned char, unsigned char, unsigned char)) {
- if (fn != NULL) {
- controlChange = fn;
- }
- }
-
- /**
- * Attach a callback called when program change is received
- *
- * @param ptr function pointer
- */
- inline void attachProgramChange(void (*fn)(unsigned char, unsigned char)) {
- if (fn != NULL) {
- programChange = fn;
- }
- }
-
- /**
- * Attach a callback called when pitch bend is received
- *
- * @param ptr function pointer
- */
- inline void attachPitchBend(void (*fn)(unsigned char, unsigned int)) {
- if (fn != NULL) {
- pitchBend = fn;
- }
- }
-
- int sendNoteOn(unsigned char channel, unsigned char note, unsigned char velocity);
- int sendNoteOff(unsigned char channel, unsigned char note, unsigned char velocity);
- int sendControlChange(unsigned char channel, unsigned char key, unsigned char value);
- int sendProgramChange(unsigned char channel, unsigned char program);
- int sendPitchBend(unsigned char channel, unsigned int value);
-
-protected:
- //From IUSBEnumerator
- virtual void setVidPid(uint16_t vid, uint16_t pid);
- virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
- virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
-
-private:
- USBHost * host;
- USBDeviceConnected * dev;
- USBEndpoint * bulk_in;
- USBEndpoint * bulk_out;
- uint32_t size_bulk_in;
- uint32_t size_bulk_out;
-
- bool dev_connected;
-
- void init();
-
- CircBuffer<uint8_t, 128> circ_buf;
-
- uint8_t buf[128];
-
- void rxHandler();
-
- void (*noteOn)(unsigned char, unsigned char, unsigned char);
- void (*noteOff)(unsigned char, unsigned char, unsigned char);
- void (*controlChange)(unsigned char, unsigned char, unsigned char);
- void (*programChange)(unsigned char, unsigned char);
- void (*pitchBend)(unsigned char, unsigned int);
-
- int midi_intf;
- bool midi_device_found;
-
-};
-
-#endif
-
-#endif
+/* USBHostMidi library
+ * Originaled by k.shoji
+ * porting by Takuya Urakawa
+ */
+
+/* mbed USBHost Library
+ * Copyright (c) 2006-2013 ARM Limited
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef USBHOSTMIDI_H
+#define USBHOSTMIDI_H
+
+#include "USBHostConf.h"
+
+#if USBHOST_MIDI
+
+#include "USBHost.h"
+
+/**
+ * A class to communicate a USB MIDI device
+ */
+class USBHostMIDI : public IUSBEnumerator {
+public:
+ /**
+ * Constructor
+ */
+ USBHostMIDI();
+
+ /**
+ * Check if a USB MIDI device is connected
+ *
+ * @returns true if a midi device is connected
+ */
+ bool connected();
+
+ /**
+ * Try to connect a midi device
+ *
+ * @return true if connection was successful
+ */
+ bool connect();
+
+ /**
+ * Attach a callback called when miscellaneous function code is received
+ * @warning DISABLED
+ *
+ * @param ptr function pointer
+ * prototype: void onMiscellaneousFunctionCode(uint8_t data1, uint8_t data2, uint8_t data3);
+ */
+ inline void attachMiscellaneousFunctionCode(void (*fn)(uint8_t, uint8_t, uint8_t)) {
+ miscellaneousFunctionCode = fn;
+ }
+
+ /**
+ * Attach a callback called when cable event is received
+ * @warning DISABLED
+ *
+ * @param ptr function pointer
+ * prototype: void onCableEvent(uint8_t data1, uint8_t data2, uint8_t data3);
+ */
+ inline void attachCableEvent(void (*fn)(uint8_t, uint8_t, uint8_t)) {
+ cableEvent = fn;
+ }
+
+ /**
+ * Attach a callback called when system exclusive is received
+ *
+ * @param ptr function pointer
+ * prototype: void onSystemCommonTwoBytes(uint8_t data1, uint8_t data2);
+ */
+ inline void attachSystemCommonTwoBytes(void (*fn)(uint8_t, uint8_t)) {
+ systemCommonTwoBytes = fn;
+ }
+
+ /**
+ * Attach a callback called when system exclusive is received
+ *
+ * @param ptr function pointer
+ * prototype: void onSystemCommonThreeBytes(uint8_t data1, uint8_t data2, uint8_t data3);
+ */
+ inline void attachSystemCommonThreeBytes(void (*fn)(uint8_t, uint8_t, uint8_t)) {
+ systemCommonThreeBytes = fn;
+ }
+
+ /**
+ * Attach a callback called when system exclusive is received
+ *
+ * @param ptr function pointer
+ * prototype: void onSystemExclusive(uint8_t *data, uint16_t length, bool hasNextData);
+ */
+ inline void attachSystemExclusive(void (*fn)(uint8_t *, uint16_t, bool)) {
+ systemExclusive = fn;
+ }
+
+ /**
+ * Attach a callback called when note on is received
+ *
+ * @param ptr function pointer
+ * prototype: void onNoteOn(uint8_t channel, uint8_t note, uint8_t velocity);
+ */
+ inline void attachNoteOn(void (*fn)(uint8_t, uint8_t, uint8_t)) {
+ noteOn = fn;
+ }
+
+ /**
+ * Attach a callback called when note off is received
+ *
+ * @param ptr function pointer
+ * prototype: void onNoteOff(uint8_t channel, uint8_t note, uint8_t velocity);
+ */
+ inline void attachNoteOff(void (*fn)(uint8_t, uint8_t, uint8_t)) {
+ noteOff = fn;
+ }
+
+ /**
+ * Attach a callback called when poly keypress is received
+ *
+ * @param ptr function pointer
+ * prototype: void onPolyKeyPress(uint8_t channel, uint8_t note, uint8_t pressure);
+ */
+ inline void attachPolyKeyPress(void (*fn)(uint8_t, uint8_t, uint8_t)) {
+ polyKeyPress = fn;
+ }
+
+ /**
+ * Attach a callback called when control change is received
+ *
+ * @param ptr function pointer
+ * prototype: void onControlChange(uint8_t channel, uint8_t key, uint8_t value);
+ */
+ inline void attachControlChange(void (*fn)(uint8_t, uint8_t, uint8_t)) {
+ controlChange = fn;
+ }
+
+ /**
+ * Attach a callback called when program change is received
+ *
+ * @param ptr function pointer
+ * prototype: void onProgramChange(uint8_t channel, uint8_t program);
+ */
+ inline void attachProgramChange(void (*fn)(uint8_t, uint8_t)) {
+ programChange = fn;
+ }
+
+ /**
+ * Attach a callback called when channel pressure is received
+ *
+ * @param ptr function pointer
+ * prototype: void onChannelPressure(uint8_t channel, uint8_t pressure);
+ */
+ inline void attachChannelPressure(void (*fn)(uint8_t, uint8_t)) {
+ channelPressure = fn;
+ }
+
+ /**
+ * Attach a callback called when pitch bend is received
+ *
+ * @param ptr function pointer
+ * prototype: void onPitchBend(uint8_t channel, uint16_t value);
+ */
+ inline void attachPitchBend(void (*fn)(uint8_t, uint16_t)) {
+ pitchBend = fn;
+ }
+
+ /**
+ * Attach a callback called when single byte is received
+ *
+ * @param ptr function pointer
+ * prototype: void onSingleByte(uint8_t value);
+ */
+ inline void attachSingleByte(void (*fn)(uint8_t)) {
+ singleByte = fn;
+ }
+
+ /**
+ * Send a cable event with 3 bytes event
+ *
+ * @param data1 0-255
+ * @param data2 0-255
+ * @param data3 0-255
+ * @return true if message sent successfully
+ */
+ bool sendMiscellaneousFunctionCode(uint8_t data1, uint8_t data2, uint8_t data3);
+
+ /**
+ * Send a cable event with 3 bytes event
+ *
+ * @param data1 0-255
+ * @param data2 0-255
+ * @param data3 0-255
+ * @return true if message sent successfully
+ */
+ bool sendCableEvent(uint8_t data1, uint8_t data2, uint8_t data3);
+
+ /**
+ * Send a system common message with 2 bytes event
+ *
+ * @param data1 0-255
+ * @param data2 0-255
+ * @return true if message sent successfully
+ */
+ bool sendSystemCommmonTwoBytes(uint8_t data1, uint8_t data2);
+
+ /**
+ * Send a system common message with 3 bytes event
+ *
+ * @param data1 0-255
+ * @param data2 0-255
+ * @param data3 0-255
+ * @return true if message sent successfully
+ */
+ bool sendSystemCommmonThreeBytes(uint8_t data1, uint8_t data2, uint8_t data3);
+
+ /**
+ * Send a system exclusive event
+ *
+ * @param buffer, starts with 0xF0, and end with 0xf7
+ * @param length
+ * @return true if message sent successfully
+ */
+ bool sendSystemExclusive(uint8_t *buffer, int length);
+
+ /**
+ * Send a note off event
+ *
+ * @param channel 0-15
+ * @param note 0-127
+ * @param velocity 0-127
+ * @return true if message sent successfully
+ */
+ bool sendNoteOff(uint8_t channel, uint8_t note, uint8_t velocity);
+
+ /**
+ * Send a note on event
+ *
+ * @param channel 0-15
+ * @param note 0-127
+ * @param velocity 0-127 (0 means note off)
+ * @return true if message sent successfully
+ */
+ bool sendNoteOn(uint8_t channel, uint8_t note, uint8_t velocity);
+
+ /**
+ * Send a poly keypress event
+ *
+ * @param channel 0-15
+ * @param note 0-127
+ * @param pressure 0-127
+ * @return true if message sent successfully
+ */
+ bool sendPolyKeyPress(uint8_t channel, uint8_t note, uint8_t pressure);
+
+ /**
+ * Send a control change event
+ *
+ * @param channel 0-15
+ * @param key 0-127
+ * @param value 0-127
+ * @return true if message sent successfully
+ */
+ bool sendControlChange(uint8_t channel, uint8_t key, uint8_t value);
+
+ /**
+ * Send a program change event
+ *
+ * @param channel 0-15
+ * @param program 0-127
+ * @return true if message sent successfully
+ */
+ bool sendProgramChange(uint8_t channel, uint8_t program);
+
+ /**
+ * Send a channel pressure event
+ *
+ * @param channel 0-15
+ * @param pressure 0-127
+ * @return true if message sent successfully
+ */
+ bool sendChannelPressure(uint8_t channel, uint8_t pressure);
+
+ /**
+ * Send a control change event
+ *
+ * @param channel 0-15
+ * @param key 0(lower)-8191(center)-16383(higher)
+ * @return true if message sent successfully
+ */
+ bool sendPitchBend(uint8_t channel, uint16_t value);
+
+ /**
+ * Send a single byte event
+ *
+ * @param data 0-255
+ * @return true if message sent successfully
+ */
+ bool sendSingleByte(uint8_t data);
+
+protected:
+ //From IUSBEnumerator
+ virtual void setVidPid(uint16_t vid, uint16_t pid);
+ virtual bool parseInterface(uint8_t intf_nb, uint8_t intf_class, uint8_t intf_subclass, uint8_t intf_protocol); //Must return true if the interface should be parsed
+ virtual bool useEndpoint(uint8_t intf_nb, ENDPOINT_TYPE type, ENDPOINT_DIRECTION dir); //Must return true if the endpoint will be used
+
+private:
+ USBHost * host;
+ USBDeviceConnected * dev;
+ USBEndpoint * bulk_in;
+ USBEndpoint * bulk_out;
+ uint32_t size_bulk_in;
+ uint32_t size_bulk_out;
+
+ bool dev_connected;
+
+ void init();
+
+ uint8_t buf[64];
+
+ void rxHandler();
+
+uint16_t sysExBufferPos;
+ uint8_t sysExBuffer[64];
+
+ void (*miscellaneousFunctionCode)(uint8_t, uint8_t, uint8_t);
+ void (*cableEvent)(uint8_t, uint8_t, uint8_t);
+ void (*systemCommonTwoBytes)(uint8_t, uint8_t);
+ void (*systemCommonThreeBytes)(uint8_t, uint8_t, uint8_t);
+ void (*systemExclusive)(uint8_t *, uint16_t, bool);
+ void (*noteOff)(uint8_t, uint8_t, uint8_t);
+ void (*noteOn)(uint8_t, uint8_t, uint8_t);
+ void (*polyKeyPress)(uint8_t, uint8_t, uint8_t);
+ void (*controlChange)(uint8_t, uint8_t, uint8_t);
+ void (*programChange)(uint8_t, uint8_t);
+ void (*channelPressure)(uint8_t, uint8_t);
+ void (*pitchBend)(uint8_t, uint16_t);
+ void (*singleByte)(uint8_t);
+
+ bool sendMidiBuffer(uint8_t data0, uint8_t data1, uint8_t data2, uint8_t data3);
+
+ int midi_intf;
+ bool midi_device_found;
+
+};
+
+#endif
+
+#endif
