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 23:9c1d09c6a2b6, committed 2014-09-17
- Comitter:
- hsgw
- Date:
- Wed Sep 17 14:29:11 2014 +0000
- Parent:
- 22:81d8c59d1070
- Child:
- 24:5281ea9f6e68
- Commit message:
- revert rev20
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/USBHostMIDI/CircBuffer.h Wed Sep 17 14:29:11 2014 +0000
@@ -0,0 +1,80 @@
+/* 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 13:51:29 2014 +0000
+++ b/USBHostMIDI/USBHostMIDI.cpp Wed Sep 17 14:29:11 2014 +0000
@@ -1,362 +1,253 @@
-/* Copyright (c) 2014 mbed.org, MIT License
- *
- * 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 "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
- switch (midi[0] & 0xf) {
- case 0: // miscellaneous function codes
- 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;
- }
- }
-
- // 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
+/* 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
--- a/USBHostMIDI/USBHostMIDI.h Wed Sep 17 13:51:29 2014 +0000
+++ b/USBHostMIDI/USBHostMIDI.h Wed Sep 17 14:29:11 2014 +0000
@@ -1,353 +1,157 @@
-/* Copyright (c) 2014 mbed.org, MIT License
- *
- * 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 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
- *
- * @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
- *
- * @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 /* USBHOST_MIDI */
-
-#endif /* USBHOSTMIDI_H */
+/* 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
