Quick hack to make NSX-39 (Poke-Miku) USB MIDI device to speak "mbed" from mbed which acts as an USB host.

Dependencies:   FatFileSystem mbed

Fork of MIDI_BlueUSB by Radio Junk Box

Description of the project

This is quick hack to control Poke-miku (NSX-39) from mbed. The mbed acts as an USB host and controls USB MIDI device NSX-39. It speaks "mbed" if you send "s¥n" from virtual USB serial (connected to PC or Mac) or push SW connected to p21. It plays MIDI file "test.mid" on local file-system if you push SW connected to p22. You can find files that I have tested at the bottom. The standard MIDI file support is still preliminary. See TestShell.cpp for the hack. This program is derived from MIDI_BlueUSB (http://mbed.org/users/radiojunkbox/code/MIDI_BlueUSB/) by Radio Junk Box.

ポケミク(NSX-39)を無改造のままmbedから鳴らせるようにしてみました。mbedがUSB hostになって、USB MIDIデバイスのポケミクを鳴らします。mbedのバーチャルシリアル(USBシリアル)にPCからs\nを送るか、p21につないだスイッチを押すとmbedとしゃべります。p22につないだスイッチを押すと、ローカルファイルシステム(.binと同じ場所)に保存した test.mid を再生します。試したファイルは下にある test1.mid と test2.mid です。MIDIファイルのサポートはまだまだ完全とはいえません。

tested MIDI files

Video: Poke-miku speaks `mbed'

Committer:
non
Date:
Tue Apr 29 06:01:52 2014 +0000
Revision:
4:cd0d8ce967d8
Parent:
1:892f8922bdc4
Fix issues when it plays a MIDI file which has multi tracks.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
radiojunkbox 0:79620c558b0c 1
radiojunkbox 0:79620c558b0c 2 /*
radiojunkbox 0:79620c558b0c 3 Copyright (c) 2012 RadioJunkBox
radiojunkbox 0:79620c558b0c 4
radiojunkbox 0:79620c558b0c 5 Permission is hereby granted, free of charge, to any person obtaining a copy
radiojunkbox 0:79620c558b0c 6 of this software and associated documentation files (the "Software"), to deal
radiojunkbox 0:79620c558b0c 7 in the Software without restriction, including without limitation the rights
radiojunkbox 0:79620c558b0c 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
radiojunkbox 0:79620c558b0c 9 copies of the Software, and to permit persons to whom the Software is
radiojunkbox 0:79620c558b0c 10 furnished to do so, subject to the following conditions:
radiojunkbox 0:79620c558b0c 11
radiojunkbox 0:79620c558b0c 12 The above copyright notice and this permission notice shall be included in
radiojunkbox 0:79620c558b0c 13 all copies or substantial portions of the Software.
radiojunkbox 0:79620c558b0c 14
radiojunkbox 0:79620c558b0c 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
radiojunkbox 0:79620c558b0c 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
radiojunkbox 0:79620c558b0c 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
radiojunkbox 0:79620c558b0c 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
radiojunkbox 0:79620c558b0c 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
radiojunkbox 0:79620c558b0c 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
radiojunkbox 0:79620c558b0c 21 THE SOFTWARE.
radiojunkbox 0:79620c558b0c 22 */
radiojunkbox 0:79620c558b0c 23
radiojunkbox 0:79620c558b0c 24 #include "mbed.h"
radiojunkbox 0:79620c558b0c 25 #include "USBHost.h"
radiojunkbox 0:79620c558b0c 26 #include "Utils.h"
radiojunkbox 0:79620c558b0c 27
radiojunkbox 0:79620c558b0c 28 #define MIDIEVT(_class,_subclass,_protocol) (((_class) << 16) | ((_subclass) << 8) | _protocol)
radiojunkbox 0:79620c558b0c 29 u8 ms_buf[255]; // MIDI Streaming Buffer
radiojunkbox 0:79620c558b0c 30
radiojunkbox 0:79620c558b0c 31 // Ring Buffer
radiojunkbox 0:79620c558b0c 32 #define BUFSIZE 32 // size of ring buffer (ex 4,8,16,32...)
radiojunkbox 0:79620c558b0c 33 int gPtr_buf_in, gPtr_buf_out;
radiojunkbox 0:79620c558b0c 34 unsigned char gRxBuf[BUFSIZE];
radiojunkbox 0:79620c558b0c 35
radiojunkbox 0:79620c558b0c 36 // Serial MIDI Port
radiojunkbox 0:79620c558b0c 37 #define MIDI_RATE 31250 // 31.25kbps
radiojunkbox 0:79620c558b0c 38 Serial gMIDI(p9,p10);
radiojunkbox 0:79620c558b0c 39 Ticker gTickerMIDI;
radiojunkbox 0:79620c558b0c 40
radiojunkbox 0:79620c558b0c 41 // Transmit to Serial MIDI Port
radiojunkbox 0:79620c558b0c 42 void TxSerialMidi()
radiojunkbox 0:79620c558b0c 43 {
radiojunkbox 0:79620c558b0c 44 unsigned char rb;
radiojunkbox 0:79620c558b0c 45
radiojunkbox 0:79620c558b0c 46 // ring buffer empty?
radiojunkbox 0:79620c558b0c 47 if(gPtr_buf_in != gPtr_buf_out)
radiojunkbox 0:79620c558b0c 48 {
radiojunkbox 0:79620c558b0c 49 // get 1byte from ring buffer
radiojunkbox 0:79620c558b0c 50 gPtr_buf_out++;
radiojunkbox 0:79620c558b0c 51 gPtr_buf_out &= (BUFSIZE - 1);
radiojunkbox 0:79620c558b0c 52 rb = gRxBuf[gPtr_buf_out];
radiojunkbox 0:79620c558b0c 53 gMIDI.putc(rb);
radiojunkbox 0:79620c558b0c 54 }
radiojunkbox 0:79620c558b0c 55 }
radiojunkbox 0:79620c558b0c 56
radiojunkbox 0:79620c558b0c 57 // Intialize Serial MIDI Port
radiojunkbox 0:79620c558b0c 58 void InitSerialMIDI()
radiojunkbox 0:79620c558b0c 59 {
radiojunkbox 0:79620c558b0c 60 gPtr_buf_in = gPtr_buf_out = 0;
radiojunkbox 0:79620c558b0c 61 gMIDI.baud(MIDI_RATE);
radiojunkbox 0:79620c558b0c 62 gTickerMIDI.attach_us(&TxSerialMidi, 500); // 500us
radiojunkbox 0:79620c558b0c 63 }
radiojunkbox 0:79620c558b0c 64
radiojunkbox 0:79620c558b0c 65 // Received MIDI Steram
radiojunkbox 0:79620c558b0c 66 void MidiEventCallback(int device, int endpoint, int status, u8* data, int len, void* userData)
radiojunkbox 0:79620c558b0c 67 {
radiojunkbox 0:79620c558b0c 68 int i;
radiojunkbox 0:79620c558b0c 69 int ptr = 0;
radiojunkbox 0:79620c558b0c 70
radiojunkbox 0:79620c558b0c 71 while((data[ptr] != 0) && (ptr < len))
radiojunkbox 0:79620c558b0c 72 {
non 1:892f8922bdc4 73 printf("MIDI %02X %02X %02X %02X", device, endpoint, status,len);
non 1:892f8922bdc4 74 printfBytes("",data,4);
radiojunkbox 0:79620c558b0c 75 for( i = 1; i<4; i++)
radiojunkbox 0:79620c558b0c 76 {
radiojunkbox 0:79620c558b0c 77 gPtr_buf_in++;
radiojunkbox 0:79620c558b0c 78 gPtr_buf_in &= (BUFSIZE - 1);
radiojunkbox 0:79620c558b0c 79 gRxBuf[gPtr_buf_in] = data[ptr+i];
radiojunkbox 0:79620c558b0c 80 }
radiojunkbox 0:79620c558b0c 81 ptr+=4;
radiojunkbox 0:79620c558b0c 82 }
radiojunkbox 0:79620c558b0c 83 USBBulkTransfer(device,endpoint,data,len,MidiEventCallback,userData);
radiojunkbox 0:79620c558b0c 84 }
radiojunkbox 0:79620c558b0c 85
radiojunkbox 0:79620c558b0c 86 // Add MIDI Interface
radiojunkbox 0:79620c558b0c 87 void AddMidiInterface(int device, InterfaceDescriptor* id, EndpointDescriptor* ed,int len)
radiojunkbox 0:79620c558b0c 88 {
radiojunkbox 0:79620c558b0c 89 if ((ed->bmAttributes & 3) != ENDPOINT_BULK || !(ed->bEndpointAddress & 0x80))
radiojunkbox 0:79620c558b0c 90 return;
radiojunkbox 0:79620c558b0c 91
radiojunkbox 0:79620c558b0c 92 // Make bulk enpoints for MIDI devices
radiojunkbox 0:79620c558b0c 93 u32 evt = MIDIEVT(id->bInterfaceClass,id->bInterfaceSubClass,id->bInterfaceProtocol);
radiojunkbox 0:79620c558b0c 94 u8* dst = ms_buf;
radiojunkbox 0:79620c558b0c 95
radiojunkbox 0:79620c558b0c 96 if(dst)
radiojunkbox 0:79620c558b0c 97 {
non 1:892f8922bdc4 98 printf("Add Midi Interface %02X %08X\r\n",ed->bEndpointAddress,evt);
radiojunkbox 0:79620c558b0c 99 USBBulkTransfer(device,ed->bEndpointAddress,dst,len,MidiEventCallback,(void*)evt);
radiojunkbox 0:79620c558b0c 100 }
radiojunkbox 0:79620c558b0c 101 }
radiojunkbox 0:79620c558b0c 102
radiojunkbox 0:79620c558b0c 103 // Detected Midi Device
radiojunkbox 0:79620c558b0c 104 int OnMidiInsert(int device)
radiojunkbox 0:79620c558b0c 105 {
radiojunkbox 0:79620c558b0c 106 u8 buffer[255];
radiojunkbox 0:79620c558b0c 107 int err = GetDescriptor(device,DESCRIPTOR_TYPE_CONFIGURATION,0,buffer,255);
radiojunkbox 0:79620c558b0c 108 if (err < 0)
radiojunkbox 0:79620c558b0c 109 return err;
radiojunkbox 0:79620c558b0c 110
radiojunkbox 0:79620c558b0c 111 int len = buffer[2] | (buffer[3] << 8);
radiojunkbox 0:79620c558b0c 112 u8* d = buffer;
radiojunkbox 0:79620c558b0c 113 u8* end = d + len;
radiojunkbox 0:79620c558b0c 114
non 1:892f8922bdc4 115 printf("OnMidiInsert %02X %02X\r\n",device,len);
radiojunkbox 0:79620c558b0c 116
radiojunkbox 0:79620c558b0c 117 while (d < end)
radiojunkbox 0:79620c558b0c 118 {
radiojunkbox 0:79620c558b0c 119 if (d[1] == DESCRIPTOR_TYPE_INTERFACE)
radiojunkbox 0:79620c558b0c 120 {
radiojunkbox 0:79620c558b0c 121 InterfaceDescriptor* id = (InterfaceDescriptor*)d;
radiojunkbox 0:79620c558b0c 122 d += d[0];
radiojunkbox 0:79620c558b0c 123 while (d < end)
radiojunkbox 0:79620c558b0c 124 {
radiojunkbox 0:79620c558b0c 125 if (d[1] == DESCRIPTOR_TYPE_ENDPOINT)
radiojunkbox 0:79620c558b0c 126 {
non 1:892f8922bdc4 127 printfBytes("MIDI Endpoint",d,d[0]);
radiojunkbox 0:79620c558b0c 128 AddMidiInterface(device,id,(EndpointDescriptor*)d,d[4]);
radiojunkbox 0:79620c558b0c 129 }
radiojunkbox 0:79620c558b0c 130 d += d[0];
radiojunkbox 0:79620c558b0c 131 }
radiojunkbox 0:79620c558b0c 132 }
radiojunkbox 0:79620c558b0c 133 d += d[0];
radiojunkbox 0:79620c558b0c 134 }
radiojunkbox 0:79620c558b0c 135 return 0;
radiojunkbox 0:79620c558b0c 136 }
non 1:892f8922bdc4 137
non 1:892f8922bdc4 138 void MIDItxHandler() {
non 1:892f8922bdc4 139 /* if (bulk_out) {
non 1:892f8922bdc4 140 if (bulk_out->getState() == USB_TYPE_IDLE) {
non 1:892f8922bdc4 141 tx.call();
non 1:892f8922bdc4 142 }
non 1:892f8922bdc4 143 } */
non 1:892f8922bdc4 144 }