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:
Sun Apr 27 07:40:40 2014 +0000
Revision:
3:31fbce33c25b
Parent:
2:7576d1327cf1
Child:
4:cd0d8ce967d8
Support standard MIDI file (preliminary)

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) 2010 Peter Barrett
non 3:31fbce33c25b 4 Copyright (c) 2014 Noriaki Mitsunaga (SMF part)
radiojunkbox 0:79620c558b0c 5
radiojunkbox 0:79620c558b0c 6 Permission is hereby granted, free of charge, to any person obtaining a copy
radiojunkbox 0:79620c558b0c 7 of this software and associated documentation files (the "Software"), to deal
radiojunkbox 0:79620c558b0c 8 in the Software without restriction, including without limitation the rights
radiojunkbox 0:79620c558b0c 9 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
radiojunkbox 0:79620c558b0c 10 copies of the Software, and to permit persons to whom the Software is
radiojunkbox 0:79620c558b0c 11 furnished to do so, subject to the following conditions:
radiojunkbox 0:79620c558b0c 12
radiojunkbox 0:79620c558b0c 13 The above copyright notice and this permission notice shall be included in
radiojunkbox 0:79620c558b0c 14 all copies or substantial portions of the Software.
radiojunkbox 0:79620c558b0c 15
radiojunkbox 0:79620c558b0c 16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
radiojunkbox 0:79620c558b0c 17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
radiojunkbox 0:79620c558b0c 18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
radiojunkbox 0:79620c558b0c 19 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
radiojunkbox 0:79620c558b0c 20 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
radiojunkbox 0:79620c558b0c 21 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
radiojunkbox 0:79620c558b0c 22 THE SOFTWARE.
radiojunkbox 0:79620c558b0c 23 */
radiojunkbox 0:79620c558b0c 24
radiojunkbox 0:79620c558b0c 25 #include <stdio.h>
radiojunkbox 0:79620c558b0c 26 #include <stdlib.h>
radiojunkbox 0:79620c558b0c 27 #include <stdio.h>
radiojunkbox 0:79620c558b0c 28 #include <string.h>
radiojunkbox 0:79620c558b0c 29
non 1:892f8922bdc4 30 #include "mbed.h"
radiojunkbox 0:79620c558b0c 31 #include "Utils.h"
radiojunkbox 0:79620c558b0c 32 #include "USBHost.h"
radiojunkbox 0:79620c558b0c 33 #include "hci.h"
radiojunkbox 0:79620c558b0c 34
non 2:7576d1327cf1 35 #include "common.h"
non 2:7576d1327cf1 36 #include "TestShell.h"
non 2:7576d1327cf1 37
non 2:7576d1327cf1 38 static DigitalOut myLED1(LED1);
non 3:31fbce33c25b 39 static DigitalIn mySW1(SW1pin);
non 3:31fbce33c25b 40 static DigitalIn mySW2(SW2pin);
non 3:31fbce33c25b 41 int PlaySMF(char *fname);
non 2:7576d1327cf1 42
radiojunkbox 0:79620c558b0c 43 void printf(const BD_ADDR* addr)
radiojunkbox 0:79620c558b0c 44 {
radiojunkbox 0:79620c558b0c 45 const u8* a = addr->addr;
radiojunkbox 0:79620c558b0c 46 printf("%02X:%02X:%02X:%02X:%02X:%02X",a[5],a[4],a[3],a[2],a[1],a[0]);
radiojunkbox 0:79620c558b0c 47 }
radiojunkbox 0:79620c558b0c 48
radiojunkbox 0:79620c558b0c 49 #define MAX_HCL_SIZE 260
radiojunkbox 0:79620c558b0c 50 #define MAX_ACL_SIZE 400
radiojunkbox 0:79620c558b0c 51
radiojunkbox 0:79620c558b0c 52 class HCITransportUSB : public HCITransport
radiojunkbox 0:79620c558b0c 53 {
radiojunkbox 0:79620c558b0c 54 int _device;
radiojunkbox 0:79620c558b0c 55 u8* _hciBuffer;
radiojunkbox 0:79620c558b0c 56 u8* _aclBuffer;
radiojunkbox 0:79620c558b0c 57
non 3:31fbce33c25b 58 public:
non 3:31fbce33c25b 59 void Open(int device, u8* hciBuffer, u8* aclBuffer) {
radiojunkbox 0:79620c558b0c 60 _device = device;
radiojunkbox 0:79620c558b0c 61 _hciBuffer = hciBuffer;
radiojunkbox 0:79620c558b0c 62 _aclBuffer = aclBuffer;
radiojunkbox 0:79620c558b0c 63 USBInterruptTransfer(_device,0x81,_hciBuffer,MAX_HCL_SIZE,HciCallback,this);
radiojunkbox 0:79620c558b0c 64 USBBulkTransfer(_device,0x82,_aclBuffer,MAX_ACL_SIZE,AclCallback,this);
radiojunkbox 0:79620c558b0c 65 }
radiojunkbox 0:79620c558b0c 66
non 3:31fbce33c25b 67 static void HciCallback(int device, int endpoint, int status, u8* data, int len, void* userData) {
radiojunkbox 0:79620c558b0c 68 HCI* t = ((HCITransportUSB*)userData)->_target;
radiojunkbox 0:79620c558b0c 69 if (t)
radiojunkbox 0:79620c558b0c 70 t->HCIRecv(data,len);
radiojunkbox 0:79620c558b0c 71 USBInterruptTransfer(device,0x81,data,MAX_HCL_SIZE,HciCallback,userData);
radiojunkbox 0:79620c558b0c 72 }
radiojunkbox 0:79620c558b0c 73
non 3:31fbce33c25b 74 static void AclCallback(int device, int endpoint, int status, u8* data, int len, void* userData) {
radiojunkbox 0:79620c558b0c 75 HCI* t = ((HCITransportUSB*)userData)->_target;
radiojunkbox 0:79620c558b0c 76 if (t)
radiojunkbox 0:79620c558b0c 77 t->ACLRecv(data,len);
radiojunkbox 0:79620c558b0c 78 USBBulkTransfer(device,0x82,data,MAX_ACL_SIZE,AclCallback,userData);
radiojunkbox 0:79620c558b0c 79 }
radiojunkbox 0:79620c558b0c 80
non 3:31fbce33c25b 81 virtual void HCISend(const u8* data, int len) {
radiojunkbox 0:79620c558b0c 82 USBControlTransfer(_device,REQUEST_TYPE_CLASS, 0, 0, 0,(u8*)data,len);
radiojunkbox 0:79620c558b0c 83 }
radiojunkbox 0:79620c558b0c 84
non 3:31fbce33c25b 85 virtual void ACLSend(const u8* data, int len) {
radiojunkbox 0:79620c558b0c 86 USBBulkTransfer(_device,0x02,(u8*)data,len);
radiojunkbox 0:79620c558b0c 87 }
radiojunkbox 0:79620c558b0c 88 };
radiojunkbox 0:79620c558b0c 89
radiojunkbox 0:79620c558b0c 90
radiojunkbox 0:79620c558b0c 91 #define WII_REMOTE 0x042500
radiojunkbox 0:79620c558b0c 92
non 2:7576d1327cf1 93 #define NSX39_device 1
non 2:7576d1327cf1 94 #define NSX39_endpoint 2
non 2:7576d1327cf1 95
non 1:892f8922bdc4 96 void NoteOn(u8 ch, u8 note, u8 velocity)
non 1:892f8922bdc4 97 {
non 1:892f8922bdc4 98 static u8 d[64] = {0x09};
non 1:892f8922bdc4 99 d[1] = 0x90 | (ch & 0x7f);
non 1:892f8922bdc4 100 d[2] = note & 0x7f;
non 1:892f8922bdc4 101 d[3] = velocity & 0x7f;
non 2:7576d1327cf1 102 USBBulkTransfer(NSX39_device, NSX39_endpoint, d, 4, NULL, NULL);
non 1:892f8922bdc4 103 }
non 1:892f8922bdc4 104
non 1:892f8922bdc4 105 void NoteOff(u8 ch, u8 note, u8 velocity)
non 1:892f8922bdc4 106 {
non 1:892f8922bdc4 107 static u8 d[64] = {0x08};
non 1:892f8922bdc4 108 d[1] = 0x80 | (ch & 0xf);
non 1:892f8922bdc4 109 d[2] = note & 0x7f;
non 1:892f8922bdc4 110 d[3] = velocity & 0x7f;
non 2:7576d1327cf1 111 USBBulkTransfer(NSX39_device, NSX39_endpoint, d, 4, NULL, NULL);
non 1:892f8922bdc4 112 }
non 1:892f8922bdc4 113
non 1:892f8922bdc4 114 void Miku(u8 chr)
non 1:892f8922bdc4 115 {
non 1:892f8922bdc4 116 static u8 d[64] = {0x04, 0xf0, 0x43, 0x79,
non 3:31fbce33c25b 117 0x04, 0x09, 0x11, 0x0a,
non 3:31fbce33c25b 118 0x07, 0x00, 0x00, 0xf7
non 3:31fbce33c25b 119 };
non 1:892f8922bdc4 120 d[10] = chr;
non 2:7576d1327cf1 121 USBBulkTransfer(NSX39_device, NSX39_endpoint, d, 12, NULL, NULL);
non 1:892f8922bdc4 122 }
non 1:892f8922bdc4 123
non 1:892f8922bdc4 124
radiojunkbox 0:79620c558b0c 125 class HIDBluetooth
radiojunkbox 0:79620c558b0c 126 {
radiojunkbox 0:79620c558b0c 127 int _control; // Sockets for control (out) and interrupt (in)
radiojunkbox 0:79620c558b0c 128 int _interrupt;
radiojunkbox 0:79620c558b0c 129 int _devClass;
radiojunkbox 0:79620c558b0c 130 BD_ADDR _addr;
radiojunkbox 0:79620c558b0c 131 u8 _pad[2]; // Struct align
non 3:31fbce33c25b 132
radiojunkbox 0:79620c558b0c 133 public:
radiojunkbox 0:79620c558b0c 134 HIDBluetooth() : _control(0),_interrupt(0),_devClass(0) {};
radiojunkbox 0:79620c558b0c 135
non 3:31fbce33c25b 136 bool InUse() {
radiojunkbox 0:79620c558b0c 137 return _control != 0;
radiojunkbox 0:79620c558b0c 138 }
radiojunkbox 0:79620c558b0c 139
non 3:31fbce33c25b 140 static void OnHidInterrupt(int socket, SocketState state, const u8* data, int len, void* userData) {
radiojunkbox 0:79620c558b0c 141 HIDBluetooth* t = (HIDBluetooth*)userData;
non 3:31fbce33c25b 142 if (data) {
non 3:31fbce33c25b 143 if (t->_devClass == WII_REMOTE && data[1] == 0x30) {
radiojunkbox 0:79620c558b0c 144 printf("================wii====================\n");
radiojunkbox 0:79620c558b0c 145 t->Led();
radiojunkbox 0:79620c558b0c 146 t->Hid(); // ask for accelerometer
radiojunkbox 0:79620c558b0c 147 t->_devClass = 0;
radiojunkbox 0:79620c558b0c 148 }
radiojunkbox 0:79620c558b0c 149
radiojunkbox 0:79620c558b0c 150 const u8* d = data;
non 3:31fbce33c25b 151 switch (d[1]) {
non 3:31fbce33c25b 152 case 0x02: {
radiojunkbox 0:79620c558b0c 153 int x = (signed char)d[3];
radiojunkbox 0:79620c558b0c 154 int y = (signed char)d[4];
radiojunkbox 0:79620c558b0c 155 printf("Mouse %2X dx:%d dy:%d\n",d[2],x,y);
radiojunkbox 0:79620c558b0c 156 }
radiojunkbox 0:79620c558b0c 157 break;
radiojunkbox 0:79620c558b0c 158
non 3:31fbce33c25b 159 case 0x37: { // Accelerometer http://wiki.wiimoteproject.com/Reports
radiojunkbox 0:79620c558b0c 160 int pad = (d[2] & 0x9F) | ((d[3] & 0x9F) << 8);
radiojunkbox 0:79620c558b0c 161 int x = (d[2] & 0x60) >> 5 | d[4] << 2;
radiojunkbox 0:79620c558b0c 162 int y = (d[3] & 0x20) >> 4 | d[5] << 2;
radiojunkbox 0:79620c558b0c 163 int z = (d[3] & 0x40) >> 5 | d[6] << 2;
radiojunkbox 0:79620c558b0c 164 printf("WII %04X %d %d %d\n",pad,x,y,z);
radiojunkbox 0:79620c558b0c 165 }
radiojunkbox 0:79620c558b0c 166 break;
radiojunkbox 0:79620c558b0c 167 default:
radiojunkbox 0:79620c558b0c 168 printHex(data,len);
radiojunkbox 0:79620c558b0c 169 }
radiojunkbox 0:79620c558b0c 170 }
radiojunkbox 0:79620c558b0c 171 }
radiojunkbox 0:79620c558b0c 172
non 3:31fbce33c25b 173 static void OnHidControl(int socket, SocketState state, const u8* data, int len, void* userData) {
radiojunkbox 0:79620c558b0c 174 printf("OnHidControl\n");
radiojunkbox 0:79620c558b0c 175 if (data)
radiojunkbox 0:79620c558b0c 176 printHex(data,len);
radiojunkbox 0:79620c558b0c 177 }
radiojunkbox 0:79620c558b0c 178
non 3:31fbce33c25b 179 void Open(BD_ADDR* bdAddr, inquiry_info* info) {
radiojunkbox 0:79620c558b0c 180 printf("L2CAPAddr size %d\n",sizeof(L2CAPAddr));
radiojunkbox 0:79620c558b0c 181 _addr = *bdAddr;
radiojunkbox 0:79620c558b0c 182 L2CAPAddr sockAddr;
radiojunkbox 0:79620c558b0c 183 sockAddr.bdaddr = _addr;
radiojunkbox 0:79620c558b0c 184 sockAddr.psm = L2CAP_PSM_HID_INTR;
non 3:31fbce33c25b 185 printf("Socket_Open size %d\n",sizeof(L2CAPAddr));
radiojunkbox 0:79620c558b0c 186 _interrupt = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidInterrupt,this);
radiojunkbox 0:79620c558b0c 187 sockAddr.psm = L2CAP_PSM_HID_CNTL;
radiojunkbox 0:79620c558b0c 188 _control = Socket_Open(SOCKET_L2CAP,&sockAddr.hdr,OnHidControl,this);
radiojunkbox 0:79620c558b0c 189
radiojunkbox 0:79620c558b0c 190 printfBytes("OPEN DEVICE CLASS",info->dev_class,3);
radiojunkbox 0:79620c558b0c 191 _devClass = (info->dev_class[0] << 16) | (info->dev_class[1] << 8) | info->dev_class[2];
radiojunkbox 0:79620c558b0c 192 }
radiojunkbox 0:79620c558b0c 193
non 3:31fbce33c25b 194 void Close() {
radiojunkbox 0:79620c558b0c 195 if (_control)
radiojunkbox 0:79620c558b0c 196 Socket_Close(_control);
radiojunkbox 0:79620c558b0c 197 if (_interrupt)
radiojunkbox 0:79620c558b0c 198 Socket_Close(_interrupt);
non 3:31fbce33c25b 199 _control = _interrupt = 0;
radiojunkbox 0:79620c558b0c 200 }
radiojunkbox 0:79620c558b0c 201
non 3:31fbce33c25b 202 void Led(int id = 0x10) {
radiojunkbox 0:79620c558b0c 203 u8 led[3] = {0x52, 0x11, id};
radiojunkbox 0:79620c558b0c 204 if (_control)
radiojunkbox 0:79620c558b0c 205 Socket_Send(_control,led,3);
radiojunkbox 0:79620c558b0c 206 }
radiojunkbox 0:79620c558b0c 207
non 3:31fbce33c25b 208 void Hid(int report = 0x37) {
radiojunkbox 0:79620c558b0c 209 u8 hid[4] = { 0x52, 0x12, 0x00, report };
radiojunkbox 0:79620c558b0c 210 if (_control != -1)
radiojunkbox 0:79620c558b0c 211 Socket_Send(_control,hid,4);
radiojunkbox 0:79620c558b0c 212 }
radiojunkbox 0:79620c558b0c 213 };
radiojunkbox 0:79620c558b0c 214
radiojunkbox 0:79620c558b0c 215
radiojunkbox 0:79620c558b0c 216 HCI* gHCI = 0;
radiojunkbox 0:79620c558b0c 217
radiojunkbox 0:79620c558b0c 218 #define MAX_HID_DEVICES 8
radiojunkbox 0:79620c558b0c 219
radiojunkbox 0:79620c558b0c 220 class ShellApp
radiojunkbox 0:79620c558b0c 221 {
radiojunkbox 0:79620c558b0c 222 char _line[64];
radiojunkbox 0:79620c558b0c 223 HIDBluetooth _hids[MAX_HID_DEVICES];
radiojunkbox 0:79620c558b0c 224
radiojunkbox 0:79620c558b0c 225 public:
non 3:31fbce33c25b 226 void Ready() {
non 3:31fbce33c25b 227 printf("HIDBluetooth %d\n",sizeof(HIDBluetooth));
non 3:31fbce33c25b 228 memset(_hids,0,sizeof(_hids));
radiojunkbox 0:79620c558b0c 229 Inquiry();
radiojunkbox 0:79620c558b0c 230
radiojunkbox 0:79620c558b0c 231 }
radiojunkbox 0:79620c558b0c 232
radiojunkbox 0:79620c558b0c 233 // We have connected to a device
non 3:31fbce33c25b 234 void ConnectionComplete(HCI* hci, connection_info* info) {
non 3:31fbce33c25b 235 printf("ConnectionComplete ");
radiojunkbox 0:79620c558b0c 236 BD_ADDR* a = &info->bdaddr;
radiojunkbox 0:79620c558b0c 237 printf(a);
radiojunkbox 0:79620c558b0c 238 BTDevice* bt = hci->Find(a);
radiojunkbox 0:79620c558b0c 239 HIDBluetooth* hid = NewHIDBluetooth();
radiojunkbox 0:79620c558b0c 240 printf("%08x %08x\n",bt,hid);
radiojunkbox 0:79620c558b0c 241 if (hid)
radiojunkbox 0:79620c558b0c 242 hid->Open(a,&bt->_info);
radiojunkbox 0:79620c558b0c 243 }
radiojunkbox 0:79620c558b0c 244
non 3:31fbce33c25b 245 HIDBluetooth* NewHIDBluetooth() {
radiojunkbox 0:79620c558b0c 246 for (int i = 0; i < MAX_HID_DEVICES; i++)
radiojunkbox 0:79620c558b0c 247 if (!_hids[i].InUse())
radiojunkbox 0:79620c558b0c 248 return _hids+i;
radiojunkbox 0:79620c558b0c 249 return 0;
radiojunkbox 0:79620c558b0c 250 }
radiojunkbox 0:79620c558b0c 251
non 3:31fbce33c25b 252 void ConnectDevices() {
radiojunkbox 0:79620c558b0c 253 BTDevice* devs[8];
radiojunkbox 0:79620c558b0c 254 int count = gHCI->GetDevices(devs,8);
non 3:31fbce33c25b 255 for (int i = 0; i < count; i++) {
radiojunkbox 0:79620c558b0c 256 printfBytes("DEVICE CLASS",devs[i]->_info.dev_class,3);
non 3:31fbce33c25b 257 if (devs[i]->_handle == 0) {
radiojunkbox 0:79620c558b0c 258 BD_ADDR* bd = &devs[i]->_info.bdaddr;
radiojunkbox 0:79620c558b0c 259 printf("Connecting to ");
radiojunkbox 0:79620c558b0c 260 printf(bd);
radiojunkbox 0:79620c558b0c 261 printf("\n");
radiojunkbox 0:79620c558b0c 262 gHCI->CreateConnection(bd);
radiojunkbox 0:79620c558b0c 263 }
radiojunkbox 0:79620c558b0c 264 }
radiojunkbox 0:79620c558b0c 265 }
radiojunkbox 0:79620c558b0c 266
non 3:31fbce33c25b 267 const char* ReadLine() {
radiojunkbox 0:79620c558b0c 268 int i;
non 3:31fbce33c25b 269 for (i = 0; i < 255; ) {
radiojunkbox 0:79620c558b0c 270 USBLoop();
radiojunkbox 0:79620c558b0c 271 int c = GetConsoleChar();
radiojunkbox 0:79620c558b0c 272 if (c == -1)
radiojunkbox 0:79620c558b0c 273 continue;
radiojunkbox 0:79620c558b0c 274 if (c == '\n' || c == 13)
radiojunkbox 0:79620c558b0c 275 break;
radiojunkbox 0:79620c558b0c 276 _line[i++] = c;
radiojunkbox 0:79620c558b0c 277 }
radiojunkbox 0:79620c558b0c 278 _line[i] = 0;
radiojunkbox 0:79620c558b0c 279 return _line;
radiojunkbox 0:79620c558b0c 280 }
radiojunkbox 0:79620c558b0c 281
non 3:31fbce33c25b 282 void Inquiry() {
radiojunkbox 0:79620c558b0c 283 printf("Inquiry..\n");
radiojunkbox 0:79620c558b0c 284 gHCI->Inquiry();
radiojunkbox 0:79620c558b0c 285 }
radiojunkbox 0:79620c558b0c 286
non 3:31fbce33c25b 287 void List() {
non 3:31fbce33c25b 288 #if 0
radiojunkbox 0:79620c558b0c 289 printf("%d devices\n",_deviceCount);
non 3:31fbce33c25b 290 for (int i = 0; i < _deviceCount; i++) {
radiojunkbox 0:79620c558b0c 291 printf(&_devices[i].info.bdaddr);
radiojunkbox 0:79620c558b0c 292 printf("\n");
radiojunkbox 0:79620c558b0c 293 }
non 3:31fbce33c25b 294 #endif
radiojunkbox 0:79620c558b0c 295 }
radiojunkbox 0:79620c558b0c 296
non 3:31fbce33c25b 297 void Connect() {
radiojunkbox 0:79620c558b0c 298 ConnectDevices();
radiojunkbox 0:79620c558b0c 299 }
radiojunkbox 0:79620c558b0c 300
non 3:31fbce33c25b 301 void Disconnect() {
radiojunkbox 0:79620c558b0c 302 gHCI->DisconnectAll();
radiojunkbox 0:79620c558b0c 303 }
radiojunkbox 0:79620c558b0c 304
non 3:31fbce33c25b 305 void CloseMouse() {
radiojunkbox 0:79620c558b0c 306 }
radiojunkbox 0:79620c558b0c 307
non 3:31fbce33c25b 308 void Quit() {
radiojunkbox 0:79620c558b0c 309 CloseMouse();
radiojunkbox 0:79620c558b0c 310 }
radiojunkbox 0:79620c558b0c 311
non 3:31fbce33c25b 312 void Run() {
non 3:31fbce33c25b 313 for(;;) {
non 2:7576d1327cf1 314 const char* cmd = "";
non 2:7576d1327cf1 315 USBLoop();
non 2:7576d1327cf1 316 if (IsConsoleReadable())
non 2:7576d1327cf1 317 cmd = ReadLine();
non 2:7576d1327cf1 318
non 3:31fbce33c25b 319 if (mySW2 == 0) {
non 3:31fbce33c25b 320 myLED1 = 1;
non 3:31fbce33c25b 321 PlaySMF("/local/test.mid");
non 3:31fbce33c25b 322 myLED1 = 0;
non 3:31fbce33c25b 323 } else if ((strcmp(cmd,"s") == 0) || (mySW1 == 0)) {
non 2:7576d1327cf1 324 myLED1 = 1;
non 2:7576d1327cf1 325 Miku(3);
non 2:7576d1327cf1 326 wait(0.001);
non 2:7576d1327cf1 327 NoteOn(0, 72, 0x7f);
non 2:7576d1327cf1 328 wait(0.8);
non 2:7576d1327cf1 329 NoteOff(0, 72, 0x7f);
non 2:7576d1327cf1 330 wait(0.001);
non 3:31fbce33c25b 331
non 2:7576d1327cf1 332 Miku(124);
non 2:7576d1327cf1 333 wait(0.001);
non 2:7576d1327cf1 334 NoteOn(0, 74, 0x7f);
non 2:7576d1327cf1 335 wait(0.5);
non 2:7576d1327cf1 336 NoteOff(0, 74, 0x7f);
non 2:7576d1327cf1 337 wait(0.001);
non 3:31fbce33c25b 338
non 2:7576d1327cf1 339 Miku(79);
non 2:7576d1327cf1 340 wait(0.001);
non 2:7576d1327cf1 341 NoteOn(0, 76, 0x7f);
non 2:7576d1327cf1 342 wait(0.5);
non 2:7576d1327cf1 343 NoteOff(0, 76, 0x7f);
non 1:892f8922bdc4 344
non 2:7576d1327cf1 345 wait(0.2);
non 1:892f8922bdc4 346
non 2:7576d1327cf1 347 Miku(50);
non 2:7576d1327cf1 348 wait(0.001);
non 2:7576d1327cf1 349 NoteOn(0, 76, 0x7f);
non 2:7576d1327cf1 350 wait(0.5);
non 2:7576d1327cf1 351 NoteOff(0, 76, 0x7f);
non 2:7576d1327cf1 352 myLED1 = 0;
non 3:31fbce33c25b 353 } else if (strcmp(cmd,"scan") == 0 || strcmp(cmd,"inquiry") == 0)
radiojunkbox 0:79620c558b0c 354 Inquiry();
radiojunkbox 0:79620c558b0c 355 else if (strcmp(cmd,"ls") == 0)
radiojunkbox 0:79620c558b0c 356 List();
radiojunkbox 0:79620c558b0c 357 else if (strcmp(cmd,"connect") == 0)
radiojunkbox 0:79620c558b0c 358 Connect();
radiojunkbox 0:79620c558b0c 359 else if (strcmp(cmd,"disconnect") == 0)
radiojunkbox 0:79620c558b0c 360 Disconnect();
non 3:31fbce33c25b 361 else if (strcmp(cmd,"q")== 0) {
radiojunkbox 0:79620c558b0c 362 Quit();
radiojunkbox 0:79620c558b0c 363 break;
non 2:7576d1327cf1 364 } else if (*cmd == 0) {
non 2:7576d1327cf1 365 /* ignore */
radiojunkbox 0:79620c558b0c 366 } else {
radiojunkbox 0:79620c558b0c 367 printf("eh? %s\n",cmd);
radiojunkbox 0:79620c558b0c 368 }
radiojunkbox 0:79620c558b0c 369 }
radiojunkbox 0:79620c558b0c 370 }
radiojunkbox 0:79620c558b0c 371 };
radiojunkbox 0:79620c558b0c 372
radiojunkbox 0:79620c558b0c 373 // Instance
radiojunkbox 0:79620c558b0c 374 ShellApp gApp;
radiojunkbox 0:79620c558b0c 375
radiojunkbox 0:79620c558b0c 376 static int HciCallback(HCI* hci, HCI_CALLBACK_EVENT evt, const u8* data, int len)
radiojunkbox 0:79620c558b0c 377 {
non 3:31fbce33c25b 378 switch (evt) {
radiojunkbox 0:79620c558b0c 379 case CALLBACK_READY:
radiojunkbox 0:79620c558b0c 380 printf("CALLBACK_READY\n");
radiojunkbox 0:79620c558b0c 381 gApp.Ready();
radiojunkbox 0:79620c558b0c 382 break;
radiojunkbox 0:79620c558b0c 383
radiojunkbox 0:79620c558b0c 384 case CALLBACK_INQUIRY_RESULT:
radiojunkbox 0:79620c558b0c 385 printf("CALLBACK_INQUIRY_RESULT ");
radiojunkbox 0:79620c558b0c 386 printf((BD_ADDR*)data);
radiojunkbox 0:79620c558b0c 387 printf("\n");
radiojunkbox 0:79620c558b0c 388 break;
radiojunkbox 0:79620c558b0c 389
radiojunkbox 0:79620c558b0c 390 case CALLBACK_INQUIRY_DONE:
radiojunkbox 0:79620c558b0c 391 printf("CALLBACK_INQUIRY_DONE\n");
radiojunkbox 0:79620c558b0c 392 gApp.ConnectDevices();
radiojunkbox 0:79620c558b0c 393 break;
radiojunkbox 0:79620c558b0c 394
non 3:31fbce33c25b 395 case CALLBACK_REMOTE_NAME: {
non 3:31fbce33c25b 396 BD_ADDR* addr = (BD_ADDR*)data;
non 3:31fbce33c25b 397 const char* name = (const char*)(data + 6);
non 3:31fbce33c25b 398 printf(addr);
non 3:31fbce33c25b 399 printf(" % s\n",name);
non 3:31fbce33c25b 400 }
non 3:31fbce33c25b 401 break;
radiojunkbox 0:79620c558b0c 402
radiojunkbox 0:79620c558b0c 403 case CALLBACK_CONNECTION_COMPLETE:
radiojunkbox 0:79620c558b0c 404 gApp.ConnectionComplete(hci,(connection_info*)data);
radiojunkbox 0:79620c558b0c 405 break;
radiojunkbox 0:79620c558b0c 406 };
radiojunkbox 0:79620c558b0c 407 return 0;
radiojunkbox 0:79620c558b0c 408 }
radiojunkbox 0:79620c558b0c 409
radiojunkbox 0:79620c558b0c 410 // these should be placed in the DMA SRAM
non 3:31fbce33c25b 411 typedef struct {
radiojunkbox 0:79620c558b0c 412 u8 _hciBuffer[MAX_HCL_SIZE];
radiojunkbox 0:79620c558b0c 413 u8 _aclBuffer[MAX_ACL_SIZE];
radiojunkbox 0:79620c558b0c 414 } SRAMPlacement;
radiojunkbox 0:79620c558b0c 415
radiojunkbox 0:79620c558b0c 416 HCITransportUSB _HCITransportUSB;
radiojunkbox 0:79620c558b0c 417 HCI _HCI;
radiojunkbox 0:79620c558b0c 418
radiojunkbox 0:79620c558b0c 419 u8* USBGetBuffer(u32* len);
radiojunkbox 0:79620c558b0c 420 int OnBluetoothInsert(int device)
radiojunkbox 0:79620c558b0c 421 {
radiojunkbox 0:79620c558b0c 422 printf("Bluetooth inserted of %d\n",device);
radiojunkbox 0:79620c558b0c 423 u32 sramLen;
radiojunkbox 0:79620c558b0c 424 u8* sram = USBGetBuffer(&sramLen);
radiojunkbox 0:79620c558b0c 425 sram = (u8*)(((u32)sram + 1023) & ~1023);
radiojunkbox 0:79620c558b0c 426 SRAMPlacement* s = (SRAMPlacement*)sram;
radiojunkbox 0:79620c558b0c 427 _HCITransportUSB.Open(device,s->_hciBuffer,s->_aclBuffer);
radiojunkbox 0:79620c558b0c 428 _HCI.Open(&_HCITransportUSB,HciCallback);
radiojunkbox 0:79620c558b0c 429 RegisterSocketHandler(SOCKET_L2CAP,&_HCI);
radiojunkbox 0:79620c558b0c 430 gHCI = &_HCI;
radiojunkbox 0:79620c558b0c 431 gApp.Inquiry();
radiojunkbox 0:79620c558b0c 432 return 0;
radiojunkbox 0:79620c558b0c 433 }
radiojunkbox 0:79620c558b0c 434
radiojunkbox 0:79620c558b0c 435 void TestShell()
radiojunkbox 0:79620c558b0c 436 {
radiojunkbox 0:79620c558b0c 437 USBInit();
radiojunkbox 0:79620c558b0c 438 gApp.Run();
radiojunkbox 0:79620c558b0c 439 }
non 3:31fbce33c25b 440
non 3:31fbce33c25b 441 /* For Handling Standard Midi File */
non 3:31fbce33c25b 442 struct midiPacket {
non 3:31fbce33c25b 443 unsigned short delta;
non 3:31fbce33c25b 444 unsigned short len;
non 3:31fbce33c25b 445 unsigned char *p;
non 3:31fbce33c25b 446 };
non 3:31fbce33c25b 447
non 3:31fbce33c25b 448 class midiHeader
non 3:31fbce33c25b 449 {
non 3:31fbce33c25b 450 private:
non 3:31fbce33c25b 451 char magic[4];
non 3:31fbce33c25b 452 unsigned long sz;
non 3:31fbce33c25b 453 public:
non 3:31fbce33c25b 454 unsigned short fmt;
non 3:31fbce33c25b 455 unsigned short tracks;
non 3:31fbce33c25b 456 unsigned short delta;
non 3:31fbce33c25b 457
non 3:31fbce33c25b 458 void readFile(FILE *fp);
non 3:31fbce33c25b 459 int check();
non 3:31fbce33c25b 460 };
non 3:31fbce33c25b 461
non 3:31fbce33c25b 462 class midiTrack
non 3:31fbce33c25b 463 {
non 3:31fbce33c25b 464 private:
non 3:31fbce33c25b 465 char magic[4];
non 3:31fbce33c25b 466 unsigned char run_status;
non 3:31fbce33c25b 467 unsigned char last_len;
non 3:31fbce33c25b 468 unsigned char buf[128];
non 3:31fbce33c25b 469 public:
non 3:31fbce33c25b 470 unsigned long tempo;
non 3:31fbce33c25b 471 unsigned long sz;
non 3:31fbce33c25b 472 unsigned char *dat;
non 3:31fbce33c25b 473 unsigned char *cur;
non 3:31fbce33c25b 474
non 3:31fbce33c25b 475 midiTrack() {
non 3:31fbce33c25b 476 tempo = 1000*1000L;
non 3:31fbce33c25b 477 dat = NULL;
non 3:31fbce33c25b 478 }
non 3:31fbce33c25b 479 ~midiTrack() {
non 3:31fbce33c25b 480 if (dat != NULL) delete dat;
non 3:31fbce33c25b 481 }
non 3:31fbce33c25b 482 void dump();
non 3:31fbce33c25b 483 bool isEnd() {
non 3:31fbce33c25b 484 if (cur < (dat + sz)) return false;
non 3:31fbce33c25b 485 return true;
non 3:31fbce33c25b 486 }
non 3:31fbce33c25b 487 struct midiPacket next();
non 3:31fbce33c25b 488 void readFile(FILE *fp);
non 3:31fbce33c25b 489 void rewind() {
non 3:31fbce33c25b 490 cur = dat;
non 3:31fbce33c25b 491 }
non 3:31fbce33c25b 492 };
non 3:31fbce33c25b 493
non 3:31fbce33c25b 494 unsigned long read32(FILE *fp);
non 3:31fbce33c25b 495 unsigned short read16(FILE *fp);
non 3:31fbce33c25b 496
non 3:31fbce33c25b 497 /* ------------------------- Functions ---------------------- */
non 3:31fbce33c25b 498 unsigned long read32(FILE *fp)
non 3:31fbce33c25b 499 {
non 3:31fbce33c25b 500 int i;
non 3:31fbce33c25b 501 unsigned long ret = 0;
non 3:31fbce33c25b 502
non 3:31fbce33c25b 503 for (i = 0, ret = 0; i < 4; i ++) {
non 3:31fbce33c25b 504 ret = (ret << 8) | (unsigned char)fgetc(fp);
non 3:31fbce33c25b 505 }
non 3:31fbce33c25b 506 return ret;
non 3:31fbce33c25b 507 }
non 3:31fbce33c25b 508
non 3:31fbce33c25b 509 unsigned short read16(FILE *fp)
non 3:31fbce33c25b 510 {
non 3:31fbce33c25b 511 int i;
non 3:31fbce33c25b 512 unsigned short ret = 0;
non 3:31fbce33c25b 513
non 3:31fbce33c25b 514 for (i = 0, ret = 0; i < 2; i ++) {
non 3:31fbce33c25b 515 ret = (ret << 8) | (unsigned char)fgetc(fp);
non 3:31fbce33c25b 516 }
non 3:31fbce33c25b 517 return ret;
non 3:31fbce33c25b 518 }
non 3:31fbce33c25b 519
non 3:31fbce33c25b 520 int midiHeader::check()
non 3:31fbce33c25b 521 {
non 3:31fbce33c25b 522 if (strncmp(magic, "MThd", 4) != 0 || sz != 6) {
non 3:31fbce33c25b 523 return 1;
non 3:31fbce33c25b 524 }
non 3:31fbce33c25b 525 return 0;
non 3:31fbce33c25b 526 }
non 3:31fbce33c25b 527
non 3:31fbce33c25b 528 void midiHeader::readFile(FILE *fp)
non 3:31fbce33c25b 529 {
non 3:31fbce33c25b 530 fread(magic, 4, 1, fp);
non 3:31fbce33c25b 531 sz = read32(fp);
non 3:31fbce33c25b 532 fmt = read16(fp);
non 3:31fbce33c25b 533 tracks = read16(fp);
non 3:31fbce33c25b 534 delta = read16(fp);
non 3:31fbce33c25b 535 }
non 3:31fbce33c25b 536
non 3:31fbce33c25b 537 void midiTrack::dump()
non 3:31fbce33c25b 538 {
non 3:31fbce33c25b 539 unsigned char *p = dat, *e = dat + sz;
non 3:31fbce33c25b 540 unsigned long delta;
non 3:31fbce33c25b 541
non 3:31fbce33c25b 542 while (p < e) {
non 3:31fbce33c25b 543 delta = 0;
non 3:31fbce33c25b 544 while ((*p & 0x80) != 0) {
non 3:31fbce33c25b 545 delta = (delta << 7) | (*p & 0x7f);
non 3:31fbce33c25b 546 p ++;
non 3:31fbce33c25b 547 }
non 3:31fbce33c25b 548 delta = (delta << 7) | *p;
non 3:31fbce33c25b 549 p ++;
non 3:31fbce33c25b 550
non 3:31fbce33c25b 551 fprintf(stderr, "%lu: ", delta);
non 3:31fbce33c25b 552
non 3:31fbce33c25b 553 unsigned char evt = (*p & 0xf0);
non 3:31fbce33c25b 554 switch (evt) {
non 3:31fbce33c25b 555 case 0xd0:
non 3:31fbce33c25b 556 /* 2bytes events */
non 3:31fbce33c25b 557 fprintf(stderr, "%02x %02x\n", *p, *(p+1));
non 3:31fbce33c25b 558 p += 2;
non 3:31fbce33c25b 559 last_len = 2;
non 3:31fbce33c25b 560 break;
non 3:31fbce33c25b 561
non 3:31fbce33c25b 562 case 0x80:
non 3:31fbce33c25b 563 case 0x90:
non 3:31fbce33c25b 564 case 0xa0:
non 3:31fbce33c25b 565 case 0xe0:
non 3:31fbce33c25b 566 /* 3bytes events */
non 3:31fbce33c25b 567 fprintf(stderr, "%02x %02x %02x \n", *p, *(p+1), *(p+2));
non 3:31fbce33c25b 568 p += 3;
non 3:31fbce33c25b 569 last_len = 3;
non 3:31fbce33c25b 570 break;
non 3:31fbce33c25b 571
non 3:31fbce33c25b 572 case 0xb0:
non 3:31fbce33c25b 573 /* 3-4bytes events */
non 3:31fbce33c25b 574 if (*(p+1) == 0x7e && *(p+2) == 0x00 && *(p+3) == 0x04) {
non 3:31fbce33c25b 575 /* 4bytes */
non 3:31fbce33c25b 576 fprintf(stderr, "%02x %02x %02x %02x \n", *p, *(p+1), *(p+2), *(p+3));
non 3:31fbce33c25b 577 p += 4;
non 3:31fbce33c25b 578 } else {
non 3:31fbce33c25b 579 /* 3bytes events */
non 3:31fbce33c25b 580 fprintf(stderr, "%02x %02x %02x \n", *p, *(p+1), *(p+2));
non 3:31fbce33c25b 581 p += 3;
non 3:31fbce33c25b 582 }
non 3:31fbce33c25b 583 last_len = 0;
non 3:31fbce33c25b 584 break;
non 3:31fbce33c25b 585
non 3:31fbce33c25b 586 case 0xf0:
non 3:31fbce33c25b 587 if (*p == 0xff) {
non 3:31fbce33c25b 588 /* meta events */
non 3:31fbce33c25b 589 if (*(p+1) == 0x51 && *(p+2) == 0x03) {
non 3:31fbce33c25b 590 tempo = (*(p+3)<<16) | (*(p+4)<<8) | *(p+5);
non 3:31fbce33c25b 591 fprintf(stderr, "(Tempo: %lu)", tempo);
non 3:31fbce33c25b 592 }
non 3:31fbce33c25b 593 fprintf(stderr, "%02x %02x %02x ", *p, *(p+1), *(p+2));
non 3:31fbce33c25b 594 unsigned char len = *(p+2);
non 3:31fbce33c25b 595 p += 3;
non 3:31fbce33c25b 596 for (int i=0; i<len; i++) {
non 3:31fbce33c25b 597 fprintf(stderr, "%02x ", *(p++));
non 3:31fbce33c25b 598 }
non 3:31fbce33c25b 599 fprintf(stderr, "\n");
non 3:31fbce33c25b 600 } else {
non 3:31fbce33c25b 601 /* SysEx event (variable length) */
non 3:31fbce33c25b 602 fprintf(stderr, "%02x %02x ", *p, *(p+1));
non 3:31fbce33c25b 603 unsigned char len = *(p+1);
non 3:31fbce33c25b 604 p += 2;
non 3:31fbce33c25b 605 for (int i=0; i<len; i++) {
non 3:31fbce33c25b 606 fprintf(stderr, "%02x ", *(p++));
non 3:31fbce33c25b 607 }
non 3:31fbce33c25b 608 fprintf(stderr, "\n");
non 3:31fbce33c25b 609 }
non 3:31fbce33c25b 610 last_len = 0;
non 3:31fbce33c25b 611 break;
non 3:31fbce33c25b 612
non 3:31fbce33c25b 613 default:
non 3:31fbce33c25b 614 /* running status */
non 3:31fbce33c25b 615 for (int i=1; i<last_len; i++) {
non 3:31fbce33c25b 616 fprintf(stderr, "%02x ", *(p++));
non 3:31fbce33c25b 617 }
non 3:31fbce33c25b 618 fprintf(stderr, "\n");
non 3:31fbce33c25b 619 break;
non 3:31fbce33c25b 620 }
non 3:31fbce33c25b 621 }
non 3:31fbce33c25b 622 }
non 3:31fbce33c25b 623
non 3:31fbce33c25b 624 struct midiPacket midiTrack::next() {
non 3:31fbce33c25b 625 struct midiPacket ret;
non 3:31fbce33c25b 626 unsigned char *p = cur, *e = dat + sz, *q = buf;
non 3:31fbce33c25b 627 unsigned long delta;
non 3:31fbce33c25b 628
non 3:31fbce33c25b 629 ret.len = 0;
non 3:31fbce33c25b 630 if (cur >= dat + sz)
non 3:31fbce33c25b 631 return ret;
non 3:31fbce33c25b 632
non 3:31fbce33c25b 633 delta = 0;
non 3:31fbce33c25b 634 while ((*p & 0x80) != 0) {
non 3:31fbce33c25b 635 delta = (delta << 7) | (*p & 0x7f);
non 3:31fbce33c25b 636 p ++;
non 3:31fbce33c25b 637 }
non 3:31fbce33c25b 638 delta = (delta << 7) | *p;
non 3:31fbce33c25b 639 p ++;
non 3:31fbce33c25b 640 ret.delta = delta;
non 3:31fbce33c25b 641 ret.p = buf;
non 3:31fbce33c25b 642
non 3:31fbce33c25b 643 while (p < e) {
non 3:31fbce33c25b 644 unsigned char evt = (*p & 0xf0);
non 3:31fbce33c25b 645 switch (evt) {
non 3:31fbce33c25b 646 case 0xd0:
non 3:31fbce33c25b 647 /* 2bytes events */
non 3:31fbce33c25b 648 run_status = *p;
non 3:31fbce33c25b 649 *(q++) = evt >> 4 | (0x00);
non 3:31fbce33c25b 650 memcpy(q, p, 2);
non 3:31fbce33c25b 651 p += 2;
non 3:31fbce33c25b 652 q += 2;
non 3:31fbce33c25b 653 *(q++) = 0;
non 3:31fbce33c25b 654 ret.len += 4;
non 3:31fbce33c25b 655 last_len = 2;
non 3:31fbce33c25b 656 break;
non 3:31fbce33c25b 657
non 3:31fbce33c25b 658 case 0x80:
non 3:31fbce33c25b 659 case 0x90:
non 3:31fbce33c25b 660 case 0xa0:
non 3:31fbce33c25b 661 case 0xe0:
non 3:31fbce33c25b 662 run_status = *p;
non 3:31fbce33c25b 663 *(q++) = evt >> 4 | (0x00);
non 3:31fbce33c25b 664 memcpy(q, p, 3);
non 3:31fbce33c25b 665 p += 3;
non 3:31fbce33c25b 666 q += 3;
non 3:31fbce33c25b 667 ret.len += 4;
non 3:31fbce33c25b 668 last_len = 3;
non 3:31fbce33c25b 669 break;
non 3:31fbce33c25b 670
non 3:31fbce33c25b 671 case 0xb0:
non 3:31fbce33c25b 672 run_status = *p;
non 3:31fbce33c25b 673 *(q++) = evt >> 4 | (0x00);
non 3:31fbce33c25b 674 /* 3-4bytes events */
non 3:31fbce33c25b 675 if (*(p+1) == 0x7e && *(p+2) == 0x00 && *(p+3) == 0x04) {
non 3:31fbce33c25b 676 /* 4bytes */
non 3:31fbce33c25b 677 memcpy(q, p, 4);
non 3:31fbce33c25b 678 p += 4;
non 3:31fbce33c25b 679 q += 4;
non 3:31fbce33c25b 680 ret.len += 5;
non 3:31fbce33c25b 681 } else {
non 3:31fbce33c25b 682 /* 3bytes events */
non 3:31fbce33c25b 683 memcpy(q, p, 3);
non 3:31fbce33c25b 684 p += 3;
non 3:31fbce33c25b 685 q += 3;
non 3:31fbce33c25b 686 ret.len += 4;
non 3:31fbce33c25b 687 }
non 3:31fbce33c25b 688 last_len = 0;
non 3:31fbce33c25b 689 break;
non 3:31fbce33c25b 690
non 3:31fbce33c25b 691 case 0xf0: {
non 3:31fbce33c25b 692 unsigned char len;
non 3:31fbce33c25b 693 if (*p == 0xff) {
non 3:31fbce33c25b 694 /* meta events */
non 3:31fbce33c25b 695 if (*(p+1) == 0x51 && *(p+2) == 0x03) {
non 3:31fbce33c25b 696 tempo = (*(p+3)<<16) | (*(p+4)<<8) | *(p+5);
non 3:31fbce33c25b 697 }
non 3:31fbce33c25b 698 len = *(p+2) + 3;
non 3:31fbce33c25b 699 #if 0
non 3:31fbce33c25b 700 memcpy(q, p, len);
non 3:31fbce33c25b 701 p += len;
non 3:31fbce33c25b 702 q += len;
non 3:31fbce33c25b 703 ret.len += len;
non 3:31fbce33c25b 704 #else
non 3:31fbce33c25b 705 /* just ignore */
non 3:31fbce33c25b 706 p += len;
non 3:31fbce33c25b 707 #endif
non 3:31fbce33c25b 708 } else {
non 3:31fbce33c25b 709 /* SysEx event (variable length) */
non 3:31fbce33c25b 710 len = *(p+1) + 1;
non 3:31fbce33c25b 711 unsigned char buf_[127], *s;
non 3:31fbce33c25b 712
non 3:31fbce33c25b 713 buf_[0] = *p;
non 3:31fbce33c25b 714 memcpy(buf_+1, p+2, len);
non 3:31fbce33c25b 715 s = buf_;
non 3:31fbce33c25b 716 p += len + 1;
non 3:31fbce33c25b 717
non 3:31fbce33c25b 718 while (len > 3) {
non 3:31fbce33c25b 719 *(q++) = 0x4 | 0x00;
non 3:31fbce33c25b 720 memcpy(q, s, 3);
non 3:31fbce33c25b 721 q += 3;
non 3:31fbce33c25b 722 s += 3;
non 3:31fbce33c25b 723 ret.len += 4;
non 3:31fbce33c25b 724 len -= 3;
non 3:31fbce33c25b 725 }
non 3:31fbce33c25b 726 switch (len) {
non 3:31fbce33c25b 727 case 3:
non 3:31fbce33c25b 728 *(q++) = 0x7 | 0x00;
non 3:31fbce33c25b 729 memcpy(q, s, 3);
non 3:31fbce33c25b 730 q += 3;
non 3:31fbce33c25b 731 ret.len += 4;
non 3:31fbce33c25b 732 break;
non 3:31fbce33c25b 733 case 2:
non 3:31fbce33c25b 734 *(q++) = 0x6 | 0x00;
non 3:31fbce33c25b 735 memcpy(q, s, 2);
non 3:31fbce33c25b 736 q += 2;
non 3:31fbce33c25b 737 *(q++) = 0;
non 3:31fbce33c25b 738 ret.len += 4;
non 3:31fbce33c25b 739 break;
non 3:31fbce33c25b 740 case 1:
non 3:31fbce33c25b 741 *(q++) = 0x5 | 0x00;
non 3:31fbce33c25b 742 memcpy(q, s, 1);
non 3:31fbce33c25b 743 q += 1;
non 3:31fbce33c25b 744 *(q++) = 0;
non 3:31fbce33c25b 745 *(q++) = 0;
non 3:31fbce33c25b 746 ret.len += 4;
non 3:31fbce33c25b 747 break;
non 3:31fbce33c25b 748 }
non 3:31fbce33c25b 749 }
non 3:31fbce33c25b 750 }
non 3:31fbce33c25b 751 last_len = 0;
non 3:31fbce33c25b 752 break;
non 3:31fbce33c25b 753
non 3:31fbce33c25b 754 default:
non 3:31fbce33c25b 755 /* running status */
non 3:31fbce33c25b 756 *(q++) = run_status >> 4;
non 3:31fbce33c25b 757 *(q++) = run_status;
non 3:31fbce33c25b 758 memcpy(q, p, last_len);
non 3:31fbce33c25b 759 p += last_len;
non 3:31fbce33c25b 760 q += last_len;
non 3:31fbce33c25b 761 ret.len += (last_len+2);
non 3:31fbce33c25b 762 }
non 3:31fbce33c25b 763 if (*p != 0) /* Breaks if delta is not 0 */
non 3:31fbce33c25b 764 break;
non 3:31fbce33c25b 765 p ++;
non 3:31fbce33c25b 766 }
non 3:31fbce33c25b 767 cur = p;
non 3:31fbce33c25b 768
non 3:31fbce33c25b 769 return ret;
non 3:31fbce33c25b 770 }
non 3:31fbce33c25b 771
non 3:31fbce33c25b 772 void midiTrack::readFile(FILE *fp)
non 3:31fbce33c25b 773 {
non 3:31fbce33c25b 774 fread(magic, 4, 1, fp);
non 3:31fbce33c25b 775 sz = read32(fp);
non 3:31fbce33c25b 776 dat = new unsigned char[sz];
non 3:31fbce33c25b 777 fread(dat, 1, sz, fp);
non 3:31fbce33c25b 778 cur = dat;
non 3:31fbce33c25b 779 }
non 3:31fbce33c25b 780
non 3:31fbce33c25b 781 int PlaySMF(char *fname)
non 3:31fbce33c25b 782 {
non 3:31fbce33c25b 783 FILE *fp;
non 3:31fbce33c25b 784
non 3:31fbce33c25b 785 if ((fp = fopen(fname, "r")) == NULL) {
non 3:31fbce33c25b 786 fprintf(stderr, "Could not open file %s.\n", fname);
non 3:31fbce33c25b 787 return 1;
non 3:31fbce33c25b 788 }
non 3:31fbce33c25b 789
non 3:31fbce33c25b 790 struct midiHeader *mh = new midiHeader;
non 3:31fbce33c25b 791 mh->readFile(fp);
non 3:31fbce33c25b 792
non 3:31fbce33c25b 793 if (mh->check() != 0) {
non 3:31fbce33c25b 794 fprintf(stderr, "Not a MIDI file.\n");
non 3:31fbce33c25b 795 delete mh;
non 3:31fbce33c25b 796 fclose(fp);
non 3:31fbce33c25b 797 return 1;
non 3:31fbce33c25b 798 }
non 3:31fbce33c25b 799
non 3:31fbce33c25b 800 midiTrack* trks[32] = {NULL};
non 3:31fbce33c25b 801
non 3:31fbce33c25b 802 for (int i=0; i<mh->tracks; i++) {
non 3:31fbce33c25b 803 trks[i] = new midiTrack;
non 3:31fbce33c25b 804 trks[i]->readFile(fp);
non 3:31fbce33c25b 805 }
non 3:31fbce33c25b 806 fclose(fp);
non 3:31fbce33c25b 807
non 3:31fbce33c25b 808 for (int i=0; i<mh->tracks; i++) {
non 3:31fbce33c25b 809 if (trks[i] == NULL)
non 3:31fbce33c25b 810 continue;
non 3:31fbce33c25b 811 trks[i]->rewind();
non 3:31fbce33c25b 812 }
non 3:31fbce33c25b 813
non 3:31fbce33c25b 814 for (;;) {
non 3:31fbce33c25b 815 struct midiPacket pkt[32];
non 3:31fbce33c25b 816 bool songEnd = true;
non 3:31fbce33c25b 817
non 3:31fbce33c25b 818 for (int i=0; i<mh->tracks; i++) {
non 3:31fbce33c25b 819 pkt[i].len = 0;
non 3:31fbce33c25b 820
non 3:31fbce33c25b 821 if (trks[i] == NULL)
non 3:31fbce33c25b 822 continue;
non 3:31fbce33c25b 823
non 3:31fbce33c25b 824 if (!trks[i]->isEnd()) {
non 3:31fbce33c25b 825 pkt[i] = trks[i]->next();
non 3:31fbce33c25b 826 songEnd = false;
non 3:31fbce33c25b 827 }
non 3:31fbce33c25b 828 }
non 3:31fbce33c25b 829 if (songEnd)
non 3:31fbce33c25b 830 break;
non 3:31fbce33c25b 831
non 3:31fbce33c25b 832 for (int t=0; ; t += 10) {
non 3:31fbce33c25b 833 USBLoop();
non 3:31fbce33c25b 834 bool toNext = true;
non 3:31fbce33c25b 835 for (int i=0; i<mh->tracks; i++) {
non 3:31fbce33c25b 836 if (pkt[i].len == 0) {
non 3:31fbce33c25b 837 continue;
non 3:31fbce33c25b 838 }
non 3:31fbce33c25b 839 toNext = false;
non 3:31fbce33c25b 840 if (t >= pkt[i].delta) {
non 3:31fbce33c25b 841 fprintf(stderr, "%d[%d] ", t, i);
non 3:31fbce33c25b 842 for (int j=0; j<pkt[i].len; j++) {
non 3:31fbce33c25b 843 fprintf(stderr, "%02x ", pkt[i].p[j]);
non 3:31fbce33c25b 844 }
non 3:31fbce33c25b 845 fprintf(stderr, "\n");
non 3:31fbce33c25b 846 USBBulkTransfer(NSX39_device, NSX39_endpoint,
non 3:31fbce33c25b 847 pkt[i].p, pkt[i].len, NULL, NULL);
non 3:31fbce33c25b 848 pkt[i].len = 0;
non 3:31fbce33c25b 849 }
non 3:31fbce33c25b 850 }
non 3:31fbce33c25b 851 if (toNext)
non 3:31fbce33c25b 852 break;
non 3:31fbce33c25b 853 // fprintf(stderr, "%f ", (float)trks[0]->tempo/(float)mh->delta/1000000.0);
non 3:31fbce33c25b 854 wait((float)trks[0]->tempo/(float)mh->delta/100000.0);
non 3:31fbce33c25b 855 }
non 3:31fbce33c25b 856 }
non 3:31fbce33c25b 857
non 3:31fbce33c25b 858 for (int i=0; i<mh->tracks; i++) {
non 3:31fbce33c25b 859 delete trks[i];
non 3:31fbce33c25b 860 }
non 3:31fbce33c25b 861 delete mh;
non 3:31fbce33c25b 862
non 3:31fbce33c25b 863 return 0;
non 3:31fbce33c25b 864 }