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.
main.cpp
00001 //------------------------------------------------------------- 00002 // KAMUI MIDI-CV Exapmple 00003 // Copyright (C) 2012 RJB RadioJunkBox 00004 // Released under the MIT License: http://mbed.org/license/mit 00005 //------------------------------------------------------------- 00006 00007 /* 00008 Copyright (c) 2010 Peter Barrett 00009 00010 Permission is hereby granted, free of charge, to any person obtaining a copy 00011 of this software and associated documentation files (the "Software"), to deal 00012 in the Software without restriction, including without limitation the rights 00013 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00014 copies of the Software, and to permit persons to whom the Software is 00015 furnished to do so, subject to the following conditions: 00016 00017 The above copyright notice and this permission notice shall be included in 00018 all copies or substantial portions of the Software. 00019 00020 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00021 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00022 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00023 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00024 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00025 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00026 THE SOFTWARE. 00027 */ 00028 00029 #include "mbed.h" 00030 #include "TextLCD.h" 00031 #include "USBHost.h" 00032 #include "Utils.h" 00033 #include "FATFileSystem.h" 00034 #include <stdlib.h> 00035 #include <math.h> 00036 00037 int MassStorage_ReadCapacity(int device, u32* blockCount, u32* blockSize); 00038 int MassStorage_Read(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize); 00039 int MassStorage_Write(int device, u32 blockAddr, u32 blockCount, u8* dst, u32 blockSize); 00040 00041 class USBFileSystem : public FATFileSystem 00042 { 00043 int _device; 00044 u32 _blockSize; 00045 u32 _blockCount; 00046 00047 public: 00048 USBFileSystem() : FATFileSystem("usb"),_device(0),_blockSize(0),_blockCount(0) 00049 { 00050 } 00051 00052 void SetDevice(int device) 00053 { 00054 _device = device; 00055 } 00056 00057 virtual int disk_initialize() 00058 { 00059 return MassStorage_ReadCapacity(_device,&_blockCount,&_blockSize); 00060 } 00061 00062 virtual int disk_write(const char *buffer, int block_number) 00063 { 00064 return MassStorage_Write(_device,block_number,1,(u8*)buffer,_blockSize); 00065 } 00066 00067 virtual int disk_read(char *buffer, int block_number) 00068 { 00069 return MassStorage_Read(_device,block_number,1,(u8*)buffer,_blockSize); 00070 } 00071 00072 virtual int disk_sectors() 00073 { 00074 return _blockCount; 00075 } 00076 }; 00077 00078 void DumpFS(int depth, int count) 00079 { 00080 DIR *d = opendir("/usb"); 00081 if (!d) 00082 { 00083 printf("USB file system borked\n"); 00084 return; 00085 } 00086 00087 printf("\nDumping root dir\n"); 00088 struct dirent *p; 00089 for(;;) 00090 { 00091 p = readdir(d); 00092 if (!p) 00093 break; 00094 int len = sizeof( dirent); 00095 printf("%s %d\n", p->d_name, len); 00096 } 00097 closedir(d); 00098 } 00099 00100 int OnDiskInsert(int device) 00101 { 00102 USBFileSystem fs; 00103 fs.SetDevice(device); 00104 DumpFS(0,0); 00105 return 0; 00106 } 00107 00108 /* 00109 Simple test shell to exercise mouse,keyboard,mass storage and hubs. 00110 Add 2 15k pulldown resistors between D+/D- and ground, attach a usb socket and have at it. 00111 */ 00112 00113 Serial pc(USBTX, USBRX); 00114 int GetConsoleChar() 00115 { 00116 if (!pc.readable()) 00117 return -1; 00118 char c = pc.getc(); 00119 pc.putc(c); // echo 00120 return c; 00121 } 00122 00123 //------------------------------------------------------------- 00124 // Define 00125 00126 #define AD5551 // 14bitDAC 00127 00128 #define SPI_RATE 1000000 // 1Mbps 00129 #define MIDI_RATE 31250 // 31.25kbps 00130 #define BEEP_FREQ 1760.0 // 1760Hz 00131 #define UPDATE_INTERVAL 100 // 100us 00132 #define SW_WATCH_INTERVAL (25000/UPDATE_INTERVAL) // 25ms 00133 #define PARAM_GLIDE 6554.0 00134 #define PARAM_DP 6912.0 // UPDATE_INTERVAL = 100us 00135 //#define PARAM_DP 8192.0 // UPDATE_INTERVAL = 50us 00136 00137 #define UPDATE_MODE0 0 // Update Interval CV ch1-6 1200us, ch7,8 400us 00138 #define UPDATE_MODE1 1 // Update Interval CV ch1-6 N/A, ch7,8 200us 00139 00140 #define GATE1 0x01 00141 #define GATE2 0x02 00142 #define GATE3 0x04 00143 #define GATE4 0x08 00144 00145 #define SYNC1CLK 0x01 00146 #define SYNC1RUN 0x02 00147 #define SYNC2CLK 0x04 00148 #define SYNC2RUN 0x08 00149 00150 #define MODE_CV 0x00 00151 #define MODE_GATE 0x40 00152 #define MODE_SYNC 0x80 00153 #define MODE_SET_SYNC 0xC0 00154 00155 #define SW1 0x01 00156 #define SW2 0x02 00157 #define SW3 0x04 00158 #define SW4 0x08 00159 #define SYNC1CLK_IN 0x10 00160 #define SYNC1RUN_IN 0x20 00161 #define SYNC2CLK_IN 0x40 00162 #define GATE_IN 0x80 00163 00164 #define _ENABLE 0 00165 #define _DISABLE 1 00166 00167 #define BUFSIZE 32 // size of ring buffer (ex 4,8,16,32...) 00168 #define LFO_WF_TRI 0 00169 #define LFO_WF_SQR 1 00170 #define LFO_WF_SAW 2 00171 #define LFO_WF_NONE 3 00172 #define MINIMUMNOTE 12 00173 #define SYNC_TURN_TIME (5000/UPDATE_INTERVAL) // 5ms 00174 00175 #define MENULOOP_INTERVAL 25000 // 25ms 00176 00177 //------------------------------------------------------------- 00178 // Functions 00179 00180 void MenuLoop(void); 00181 void InitKamui(void); 00182 void UpdateCV(void); 00183 unsigned char CheckSW(unsigned char); 00184 00185 void RcvMIDI(void); 00186 void GetMIDI(void); 00187 void MidiCV(void); 00188 void CalcHzVTbl(void); 00189 unsigned short OctVtoHzV(unsigned short); 00190 void DinSync(void); 00191 extern void MIDI_Parser(unsigned char); 00192 00193 //------------------------------------------------------------- 00194 // Global Variables 00195 00196 int gUpdateMode; 00197 unsigned short gCV[8]; 00198 unsigned char gGATE; 00199 unsigned char gSYNC; 00200 unsigned char gSW; 00201 00202 union { 00203 unsigned short WORD; 00204 struct { 00205 unsigned char L; 00206 unsigned char H; 00207 } BYTE; 00208 } gDAC; 00209 00210 int gPtr_buf_in, gPtr_buf_out; 00211 unsigned char gRxBuf[BUFSIZE]; 00212 00213 float gGLIDE[4]; 00214 unsigned short gLFO_DP[4]; 00215 unsigned char gLFO_FORM[4]; 00216 unsigned char gMIDI_CH[4]; 00217 short gTblHzV[3072]; 00218 00219 extern unsigned char gPlayNoteBuf[]; 00220 extern unsigned char gGateBuf[]; 00221 extern unsigned char gPitchBendBuf[]; 00222 extern unsigned char gModWheelBuf[]; 00223 extern unsigned char gMIDISYNC_CLK; 00224 extern unsigned char gMIDISYNC_RUN; 00225 00226 int pot[4],_pot[4]; 00227 unsigned char mode = 7; // for Intialize 00228 unsigned char edit[4]; 00229 int val[2][4] = { 0, 0, 0, 0, 50, 50, 50, 50 }; 00230 char *wave[4] = { "TR","SQ","SW","--" }; 00231 00232 //------------------------------------------------------------- 00233 // mbed Functions 00234 00235 // TextLCD 00236 TextLCD gLCD(p23, p24, p25, p26, p29, p30); // rs, e, d4-d7 00237 00238 // SPI 00239 SPI gSPI(p11,p12,p13); 00240 DigitalOut gCSA(p14); 00241 DigitalOut gCSB(p22); 00242 00243 // Sirial MIDI 00244 Serial gMIDI(p9,p10); 00245 00246 // AnalogIn 00247 AnalogIn gAIN1(p15); // VR1 00248 AnalogIn gAIN2(p16); // VR2 00249 AnalogIn gAIN3(p17); // VR3 00250 AnalogIn gAIN4(p18); // VR4 00251 AnalogIn gAIN5(p19); // IN1 00252 AnalogIn gAIN6(p20); // IN2 00253 00254 // BEEP 00255 PwmOut gBEEP(p21); 00256 00257 // LED 00258 DigitalOut gLED1(LED1); 00259 DigitalOut gLED2(LED2); 00260 DigitalOut gLED3(LED3); 00261 DigitalOut gLED4(LED4); 00262 BusOut gLEDS(LED1,LED2,LED3,LED4); 00263 00264 // Ticker 00265 Ticker gTICKER; 00266 Ticker gTICKER2; 00267 00268 // Implemented in TestShell.cpp 00269 void TestShell(); 00270 void USBInit(); 00271 00272 //------------------------------------------------------------- 00273 // main 00274 00275 int main() { 00276 00277 int i; 00278 00279 USBInit(); 00280 00281 // Initialize 00282 gPtr_buf_in = gPtr_buf_out = 0; 00283 for( i=0; i<4; i++) { 00284 pot[i] = _pot[i] = 0; 00285 edit[i] = 0; 00286 gGLIDE[i] = 1.0 / expf(val[0][i]*656.0/PARAM_GLIDE); 00287 gLFO_DP[i] = expf(val[1][i]*656.0/PARAM_DP); 00288 gLFO_FORM[i] = LFO_WF_TRI; 00289 gMIDI_CH[i] = i; 00290 } 00291 00292 for( i=0; i<16; i++) { // MIDI Data Buffers 00293 gPlayNoteBuf[i] =24; 00294 gGateBuf[i] = 0; 00295 gPitchBendBuf[i] = 0x40; 00296 gModWheelBuf[i] = 0; 00297 } 00298 00299 gSW = 1; // for Intialize 00300 00301 CalcHzVTbl(); 00302 InitKamui(); 00303 gTICKER2.attach_us(&MenuLoop, MENULOOP_INTERVAL); 00304 TestShell(); 00305 } 00306 00307 //------------------------------------------------------------- 00308 // Menu LOOP 00309 void MenuLoop() 00310 { 00311 int i; 00312 static unsigned char ch; 00313 00314 // Read pot 00315 pot[0] = gAIN1.read_u16(); 00316 pot[1] = gAIN2.read_u16(); 00317 pot[2] = gAIN3.read_u16(); 00318 pot[3] = gAIN4.read_u16(); 00319 00320 // change pot amount? 00321 if(abs(pot[ch] - _pot[ch]) > 0x2000) edit[ch] = 1; 00322 00323 if(edit[ch]) { 00324 switch(mode) { 00325 case 0: 00326 gGLIDE[ch] = 1.0 / expf(pot[ch]/PARAM_GLIDE); 00327 val[0][ch] = pot[ch] / 656; 00328 break; 00329 case 1: 00330 gLFO_DP[ch] = expf(pot[ch]/PARAM_DP); 00331 val[1][ch] = pot[ch] / 656; 00332 break; 00333 case 2: 00334 gLFO_FORM[ch] = pot[ch] / 0x4000; 00335 break; 00336 case 3: 00337 gMIDI_CH[ch] = pot[ch] / 0x1000; 00338 break; 00339 default: 00340 break; 00341 } 00342 } 00343 00344 // Push Mode SW 00345 if(gSW & SW1) { 00346 mode++; 00347 mode &= 0x03; 00348 for( i=0; i<4; i++) { 00349 _pot[i] = pot[i]; 00350 edit[i] = 0; 00351 } 00352 } 00353 gSW = 0; 00354 00355 // LCD Display 00356 gLCD.locate( 0, 1 ); 00357 switch(mode) { 00358 case 0: 00359 gLCD.printf("GLID %02d %02d %02d %02d", 00360 val[0][0], val[0][1], val[0][2], val[0][3]); 00361 break; 00362 case 1: 00363 gLCD.printf("FREQ %02d %02d %02d %02d", 00364 val[1][0], val[1][1], val[1][2], val[1][3]); 00365 break; 00366 case 2: 00367 gLCD.printf("FORM %s %s %s %s", 00368 wave[gLFO_FORM[0]], wave[gLFO_FORM[1]], 00369 wave[gLFO_FORM[2]], wave[gLFO_FORM[3]]); 00370 break; 00371 case 3: 00372 gLCD.printf("MIDI %02d %02d %02d %02d", 00373 gMIDI_CH[0]+1, gMIDI_CH[1]+1, 00374 gMIDI_CH[2]+1, gMIDI_CH[3]+1); 00375 break; 00376 } 00377 00378 ch++; 00379 ch &= 0x03; 00380 } 00381 00382 //------------------------------------------------------------- 00383 // Initialize KAMUI 00384 00385 void InitKamui() 00386 { 00387 // Init. Variables 00388 for( int i=0; i<8; i++) { 00389 gCV[i] = 0x8000; 00390 } 00391 gGATE = 0; 00392 gSYNC = 0; 00393 00394 gUpdateMode = UPDATE_MODE0; 00395 00396 // Init. SPI 00397 gCSA = _DISABLE; 00398 gCSB = _DISABLE; 00399 gSPI.format(8,0); 00400 gSPI.frequency(SPI_RATE); 00401 00402 // Init. Serial MIDI 00403 gMIDI.baud(MIDI_RATE); 00404 00405 // Ticker 00406 gTICKER.attach_us(&UpdateCV, UPDATE_INTERVAL); 00407 00408 // Beep 00409 gBEEP.period(1.0/BEEP_FREQ); 00410 gBEEP.write(0.5); 00411 wait(0.2); 00412 gBEEP.write(0.0); 00413 00414 // Init Display 00415 gLCD.locate( 0, 0 ); 00416 // 123456789ABCDEF 00417 gLCD.printf("USBHOST MIDI-CV"); 00418 } 00419 00420 //------------------------------------------------------------- 00421 // Update CV, GATE, SYNC 00422 00423 void UpdateCV() 00424 { 00425 unsigned char rcv,ch; 00426 unsigned char ptn[] = { 0,1,6,7,2,3,6,7,4,5,6,7 }; 00427 const int numptn = (sizeof ptn / sizeof ptn[0]) - 1; 00428 static unsigned char cnt; 00429 00430 // SET DAC 00431 ch = ptn[cnt]; 00432 if(gUpdateMode) ch |= 0x06; 00433 00434 #ifdef AD5551 // 14bitDAC 00435 gDAC.WORD = gCV[ch] >> 2; 00436 #else 00437 gDAC.WORD = gCV[ch]; 00438 #endif 00439 00440 gCSA = _ENABLE; 00441 gSPI.write(gDAC.BYTE.H); 00442 gSPI.write(gDAC.BYTE.L); 00443 gCSA = _DISABLE; 00444 00445 // GATE or SYNC OUT 00446 if(cnt & 0x01) { 00447 // GATE OUT 00448 gCSB = _ENABLE; 00449 rcv = gSPI.write(gGATE | MODE_GATE) & 0x0F; 00450 gCSB = _DISABLE; 00451 } 00452 else { 00453 // SYNC OUT 00454 gCSB = _ENABLE; 00455 rcv = gSPI.write(gSYNC | MODE_SYNC); 00456 gCSB = _DISABLE; 00457 } 00458 00459 // SEL CV CHANNEL 00460 gCSB = _ENABLE; 00461 gSPI.write(ch); 00462 gCSB = _DISABLE; 00463 00464 cnt < numptn ? cnt++ : cnt = 0; 00465 00466 gSW |= CheckSW(rcv); 00467 RcvMIDI(); 00468 GetMIDI(); 00469 DinSync(); 00470 MidiCV(); 00471 } 00472 00473 //------------------------------------------------------------- 00474 // Check SW 00475 00476 unsigned char CheckSW(unsigned char c) { 00477 00478 static unsigned char swbuf[2]; 00479 static unsigned int cntsw; 00480 unsigned char ret = 0; 00481 00482 if(cntsw > SW_WATCH_INTERVAL) { 00483 if(c &= 0x0F) { 00484 if(!swbuf[1]) { 00485 if( swbuf[0] == c) { 00486 swbuf[1] = c; 00487 ret = c; 00488 } 00489 else { 00490 swbuf[0] = c; 00491 } 00492 } 00493 } 00494 else { 00495 swbuf[1] = 0; 00496 swbuf[0] = 0; 00497 } 00498 cntsw = 0; 00499 } 00500 cntsw++; 00501 return ret; 00502 } 00503 00504 //------------------------------------------------------------- 00505 // Receive MIDI Data & Store Ring Buffer 00506 00507 void RcvMIDI() { 00508 00509 if(!gMIDI.readable()) return; 00510 00511 gPtr_buf_in++; 00512 gPtr_buf_in &= (BUFSIZE - 1); 00513 gRxBuf[gPtr_buf_in] = gMIDI.getc(); 00514 } 00515 00516 //------------------------------------------------------------- 00517 // Get MIDI Data from Ring Buffer 00518 00519 void GetMIDI() { 00520 unsigned char rb; 00521 00522 // ring buffer empty? 00523 if(gPtr_buf_in != gPtr_buf_out) { 00524 // get 1byte from ring buffer 00525 gPtr_buf_out++; 00526 gPtr_buf_out &= (BUFSIZE - 1); 00527 rb = gRxBuf[gPtr_buf_out]; 00528 MIDI_Parser(rb); 00529 gMIDI.putc(rb); 00530 } 00531 } 00532 00533 //------------------------------------------------------------- 00534 // MIDI Data to CV, GATE 00535 00536 void MidiCV() 00537 { 00538 static unsigned char ch; 00539 static unsigned short phase[4]; 00540 static float cvf[4]; 00541 int lfo,mod; 00542 unsigned char midi_ch; 00543 unsigned int cv; 00544 unsigned int note; 00545 00546 midi_ch = gMIDI_CH[ch]; 00547 00548 note = gPlayNoteBuf[midi_ch]; 00549 if( note < MINIMUMNOTE) note = MINIMUMNOTE; 00550 note -= MINIMUMNOTE; 00551 00552 // DDS Phase 00553 phase[ch] += gLFO_DP[ch]; 00554 00555 // LFO DDS Genelator 00556 switch(gLFO_FORM[ch]) { 00557 case LFO_WF_TRI: 00558 if(phase[ch] < 32738) lfo = phase[ch] - 16384; 00559 else lfo = (16383 + 32768) - phase[ch]; 00560 break; 00561 case LFO_WF_SQR: 00562 if(phase[ch] < 32738) lfo = 32767; 00563 else lfo = 0; 00564 break; 00565 case LFO_WF_SAW: 00566 lfo = phase[ch] / 2 - 16384; 00567 break; 00568 default : 00569 lfo = 0; 00570 break; 00571 } 00572 00573 // Modulation amount 00574 mod = lfo * gModWheelBuf[midi_ch] >> 8; 00575 00576 // Calculate CV 00577 cvf[ch] = ((float)(note << 8) - cvf[ch]) * gGLIDE[ch] + cvf[ch]; 00578 cv = (unsigned int)cvf[ch] + (0x8000 - (0x0040 << 3)) 00579 + (gPitchBendBuf[midi_ch] << 2) + mod; 00580 if(cv > 0xFFFF) cv = 0xFFFF; 00581 gCV[ch] = (unsigned short)cv; 00582 gCV[ch+4] = OctVtoHzV(gCV[ch]); 00583 00584 // GATE 00585 gGateBuf[midi_ch] ? gGATE |= (1<<ch) : gGATE &= ~(1<<ch); 00586 00587 ch++; 00588 ch &= 0x03; 00589 } 00590 00591 //------------------------------------------------------------- 00592 // Oct/V to Hz/V Converter 00593 00594 void CalcHzVTbl() // Calc Conv. Table 00595 { 00596 int i; 00597 float v; 00598 00599 for( i=0; i<3072; i++) { 00600 v = 24576.0 * pow(2.0,(i/3072.0)); 00601 gTblHzV[i] = (unsigned short)v; 00602 } 00603 } 00604 00605 unsigned short OctVtoHzV( unsigned short vin) 00606 { 00607 int oct,res; 00608 unsigned short vout; 00609 00610 if(vin > 0xE400) vin = 0xE400; // Maximum Note E8 Vin = 10.794V 00611 if(vin < 0x6800) vin = 0x6800; // Minimum Note C-2 Vin = -2.000V 00612 vin -= 0x6800; 00613 00614 oct = vin / 0xC00; // 0xC00 : 3072 00615 res = vin % 0xC00; 00616 00617 vout = ((unsigned short)gTblHzV[res] >> (10 - oct)) + 0x8000; 00618 return vout; 00619 } 00620 00621 //------------------------------------------------------------- 00622 // DIN SYNC Control 00623 00624 void DinSync() 00625 { 00626 static unsigned int cnt; 00627 static unsigned int cnt24 = 10; 00628 00629 if(gMIDISYNC_RUN) gSYNC |= (SYNC1RUN | SYNC2RUN); 00630 else gSYNC &= ~(SYNC1RUN | SYNC2RUN); 00631 00632 if(cnt >= SYNC_TURN_TIME) gSYNC &= ~(SYNC1CLK | SYNC2CLK); 00633 00634 if(gMIDISYNC_CLK) { 00635 gSYNC |= (SYNC1CLK | SYNC2CLK); 00636 gMIDISYNC_CLK = 0; 00637 cnt = 0; 00638 cnt24++; 00639 } 00640 if(cnt24 >= 24) cnt24 = 0; 00641 00642 gLED3 = gSYNC & SYNC1RUN ? 1 : 0; 00643 gLED4 = cnt24 < 4 ? 1 : 0; 00644 00645 cnt++; 00646 }
Generated on Sun Nov 13 2022 18:06:30 by
1.7.2