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 USBMIDI-CV Exapmple 00003 // Copyright (C) 2012 RJB RadioJunkBox 00004 // Released under the MIT License: http://mbed.org/license/mit 00005 //------------------------------------------------------------- 00006 00007 #include "mbed.h" 00008 #include "TextLCD.h" 00009 #include "USBMIDI.h" 00010 #include <stdlib.h> 00011 #include <math.h> 00012 00013 //------------------------------------------------------------- 00014 // Define 00015 00016 #define AD5551 // 14bitDAC 00017 00018 #define SPI_RATE 1000000 // 1Mbps 00019 #define MIDI_RATE 31250 // 31.25kbps 00020 #define BEEP_FREQ 1760.0 // 1760Hz 00021 #define UPDATE_INTERVAL 100 // 100us 00022 #define SW_WATCH_INTERVAL (25000/UPDATE_INTERVAL) // 25ms 00023 #define PARAM_GLIDE 6554.0 00024 #define PARAM_DP 6912.0 // UPDATE_INTERVAL = 100us 00025 //#define PARAM_DP 8192.0 // UPDATE_INTERVAL = 50us 00026 00027 #define UPDATE_MODE0 0 // Update Interval CV ch1-6 1200us, ch7,8 400us 00028 #define UPDATE_MODE1 1 // Update Interval CV ch1-6 N/A, ch7,8 200us 00029 00030 #define GATE1 0x01 00031 #define GATE2 0x02 00032 #define GATE3 0x04 00033 #define GATE4 0x08 00034 #define GATE_LED5 0x10 00035 00036 #define SYNC1CLK 0x01 00037 #define SYNC1RUN 0x02 00038 #define SYNC2CLK 0x04 00039 #define SYNC2RUN 0x08 00040 00041 #define MODE_CV 0x00 00042 #define MODE_GATE 0x40 00043 #define MODE_SYNC 0x80 00044 #define MODE_SET_SYNC 0xC0 00045 00046 #define SW1 0x01 00047 #define SW2 0x02 00048 #define SW3 0x04 00049 #define SW4 0x08 00050 #define SYNC1CLK_IN 0x10 00051 #define SYNC1RUN_IN 0x20 00052 #define SYNC2CLK_IN 0x40 00053 #define GATE_IN 0x80 00054 00055 #define _ENABLE 0 00056 #define _DISABLE 1 00057 00058 #define BUFSIZE 32 // size of ring buffer (ex 4,8,16,32...) 00059 #define LFO_WF_TRI 0 00060 #define LFO_WF_SQR 1 00061 #define LFO_WF_SAW 2 00062 #define LFO_WF_NONE 3 00063 #define MINIMUMNOTE 12 00064 #define SYNC_TURN_TIME (5000/UPDATE_INTERVAL) // 5ms 00065 00066 //------------------------------------------------------------- 00067 // Functions 00068 00069 void InitKamui(void); 00070 void UpdateCV(void); 00071 unsigned char CheckSW(unsigned char); 00072 00073 void RcvMIDI(void); 00074 void RcvUSBMIDI(MIDIMessage); 00075 void MidiCV(void); 00076 void CalcHzVTbl(void); 00077 unsigned short OctVtoHzV(unsigned short); 00078 void DinSync(void); 00079 extern void MIDI_Parser(unsigned char); 00080 00081 //------------------------------------------------------------- 00082 // Global Variables 00083 00084 int gUpdateMode; 00085 unsigned short gCV[8]; 00086 unsigned char gGATE; 00087 unsigned char gSYNC; 00088 unsigned char gSW; 00089 00090 union { 00091 unsigned short WORD; 00092 struct { 00093 unsigned char L; 00094 unsigned char H; 00095 } BYTE; 00096 } gDAC; 00097 00098 int gPtr_buf_in, gPtr_buf_out; 00099 unsigned char gRxBuf[BUFSIZE]; 00100 00101 float gGLIDE[4]; 00102 unsigned short gLFO_DP[4]; 00103 unsigned char gLFO_FORM[4]; 00104 unsigned char gMIDI_CH[4]; 00105 short gTblHzV[3072]; 00106 00107 extern unsigned char gPlayNoteBuf[]; 00108 extern unsigned char gGateBuf[]; 00109 extern unsigned char gPitchBendBuf[]; 00110 extern unsigned char gModWheelBuf[]; 00111 extern unsigned char gMIDISYNC_CLK; 00112 extern unsigned char gMIDISYNC_RUN; 00113 00114 //------------------------------------------------------------- 00115 // mbed Functions 00116 00117 // TextLCD 00118 TextLCD gLCD(p23, p24, p25, p26, p29, p30); // rs, e, d4-d7 00119 00120 // SPI 00121 SPI gSPI(p11,p12,p13); 00122 DigitalOut gCSA(p14); 00123 DigitalOut gCSB(p22); 00124 00125 // Sirial MIDI 00126 // Serial gMIDI(p9,p10); 00127 00128 // AnalogIn 00129 AnalogIn gAIN1(p15); // VR1 00130 AnalogIn gAIN2(p16); // VR2 00131 AnalogIn gAIN3(p17); // VR3 00132 AnalogIn gAIN4(p18); // VR4 00133 AnalogIn gAIN5(p19); // IN1 00134 AnalogIn gAIN6(p20); // IN2 00135 00136 // BEEP 00137 PwmOut gBEEP(p21); 00138 00139 // LED 00140 DigitalOut gLED1(LED1); 00141 DigitalOut gLED2(LED2); 00142 DigitalOut gLED3(LED3); 00143 DigitalOut gLED4(LED4); 00144 BusOut gLEDS(LED1,LED2,LED3,LED4); 00145 00146 // Ticker 00147 Ticker gTICKER; 00148 00149 //USBMIDI object 00150 USBMIDI gUSBMIDI; 00151 00152 //------------------------------------------------------------- 00153 // main 00154 00155 int main() { 00156 00157 int i; 00158 int pot[4],_pot[4]; 00159 unsigned char rb; 00160 unsigned char ch = 0; 00161 unsigned char mode = 7; // for Intialize 00162 unsigned char edit[4]; 00163 int val[2][4] = { 0, 0, 0, 0, 50, 50, 50, 50 }; 00164 char *wave[4] = { "TR","SQ","SW","--" }; 00165 00166 // Initialize 00167 gPtr_buf_in = gPtr_buf_out = 0; 00168 for( i=0; i<4; i++) { 00169 pot[i] = _pot[i] = 0; 00170 edit[i] = 0; 00171 gGLIDE[i] = 1.0 / expf(val[0][i]*656.0/PARAM_GLIDE); 00172 gLFO_DP[i] = expf(val[1][i]*656.0/PARAM_DP); 00173 gLFO_FORM[i] = LFO_WF_TRI; 00174 gMIDI_CH[i] = i; 00175 } 00176 00177 for( i=0; i<16; i++) { // MIDI Data Buffers 00178 gPlayNoteBuf[i] =24; 00179 gGateBuf[i] = 0; 00180 gPitchBendBuf[i] = 0x40; 00181 gModWheelBuf[i] = 0; 00182 } 00183 00184 gSW = 1; // for Intialize 00185 00186 CalcHzVTbl(); 00187 InitKamui(); 00188 00189 // loop 00190 while(1) { 00191 00192 // ring buffer empty? 00193 if(gPtr_buf_in != gPtr_buf_out) { 00194 00195 // get 1byte from ring buffer 00196 gPtr_buf_out++; 00197 gPtr_buf_out &= (BUFSIZE - 1); 00198 rb = gRxBuf[gPtr_buf_out]; 00199 MIDI_Parser(rb); 00200 continue; 00201 } 00202 00203 // Read pot 00204 pot[0] = gAIN1.read_u16(); 00205 pot[1] = gAIN2.read_u16(); 00206 pot[2] = gAIN3.read_u16(); 00207 pot[3] = gAIN4.read_u16(); 00208 00209 // change pot amount? 00210 if(abs(pot[ch] - _pot[ch]) > 0x2000) edit[ch] = 1; 00211 00212 if(edit[ch]) { 00213 switch(mode) { 00214 case 0: 00215 gGLIDE[ch] = 1.0 / expf(pot[ch]/PARAM_GLIDE); 00216 val[0][ch] = pot[ch] / 656; 00217 break; 00218 case 1: 00219 gLFO_DP[ch] = expf(pot[ch]/PARAM_DP); 00220 val[1][ch] = pot[ch] / 656; 00221 break; 00222 case 2: 00223 gLFO_FORM[ch] = pot[ch] / 0x4000; 00224 break; 00225 case 3: 00226 gMIDI_CH[ch] = pot[ch] / 0x1000; 00227 break; 00228 default: 00229 break; 00230 } 00231 } 00232 00233 // Push Mode SW 00234 if(gSW & SW1) { 00235 mode++; 00236 mode &= 0x03; 00237 for( i=0; i<4; i++) { 00238 _pot[i] = pot[i]; 00239 edit[i] = 0; 00240 } 00241 } 00242 gSW = 0; 00243 00244 // LCD Display 00245 gLCD.locate( 0, 1 ); 00246 switch(mode) { 00247 case 0: 00248 gLCD.printf("GLID %02d %02d %02d %02d", 00249 val[0][0], val[0][1], val[0][2], val[0][3]); 00250 break; 00251 case 1: 00252 gLCD.printf("FREQ %02d %02d %02d %02d", 00253 val[1][0], val[1][1], val[1][2], val[1][3]); 00254 break; 00255 case 2: 00256 gLCD.printf("FORM %s %s %s %s", 00257 wave[gLFO_FORM[0]], wave[gLFO_FORM[1]], 00258 wave[gLFO_FORM[2]], wave[gLFO_FORM[3]]); 00259 break; 00260 case 3: 00261 gLCD.printf("MIDI %02d %02d %02d %02d", 00262 gMIDI_CH[0]+1, gMIDI_CH[1]+1, 00263 gMIDI_CH[2]+1, gMIDI_CH[3]+1); 00264 break; 00265 } 00266 00267 ch++; 00268 ch &= 0x03; 00269 } 00270 } 00271 00272 //------------------------------------------------------------- 00273 // Initialize KAMUI 00274 00275 void InitKamui() 00276 { 00277 // Init. Variables 00278 for( int i=0; i<8; i++) { 00279 gCV[i] = 0x8000; 00280 } 00281 gGATE = 0; 00282 gSYNC = 0; 00283 00284 gUpdateMode = UPDATE_MODE0; 00285 00286 // Init. SPI 00287 gCSA = _DISABLE; 00288 gCSB = _DISABLE; 00289 gSPI.format(8,0); 00290 gSPI.frequency(SPI_RATE); 00291 00292 // Call Back for USBMIDI Messages Received 00293 gUSBMIDI.attach(RcvUSBMIDI); 00294 00295 // Ticker 00296 gTICKER.attach_us(&UpdateCV, UPDATE_INTERVAL); 00297 00298 // Beep 00299 gBEEP.period(1.0/BEEP_FREQ); 00300 gBEEP.write(0.5); 00301 wait(0.2); 00302 gBEEP.write(0.0); 00303 00304 // Init Display 00305 gLCD.locate( 0, 0 ); 00306 // 123456789ABCDEF 00307 gLCD.printf("USBMIDI-CV Exam"); 00308 } 00309 00310 //------------------------------------------------------------- 00311 // Update CV, GATE, SYNC 00312 00313 void UpdateCV() 00314 { 00315 unsigned char rcv,ch; 00316 unsigned char ptn[] = { 0,1,6,7,2,3,6,7,4,5,6,7 }; 00317 const int numptn = (sizeof ptn / sizeof ptn[0]) - 1; 00318 static unsigned char cnt; 00319 00320 __disable_irq(); 00321 00322 // SET DAC 00323 ch = ptn[cnt]; 00324 if(gUpdateMode) ch |= 0x06; 00325 00326 #ifdef AD5551 // 14bitDAC 00327 gDAC.WORD = gCV[ch] >> 2; 00328 #else 00329 gDAC.WORD = gCV[ch]; 00330 #endif 00331 00332 gCSA = _ENABLE; 00333 gSPI.write(gDAC.BYTE.H); 00334 gSPI.write(gDAC.BYTE.L); 00335 gCSA = _DISABLE; 00336 00337 // GATE or SYNC OUT 00338 if(cnt & 0x01) { 00339 // GATE OUT 00340 gCSB = _ENABLE; 00341 rcv = gSPI.write(gGATE | MODE_GATE) & 0x0F; 00342 gCSB = _DISABLE; 00343 } 00344 else { 00345 // SYNC OUT 00346 gCSB = _ENABLE; 00347 rcv = gSPI.write(gSYNC | MODE_SYNC); 00348 gCSB = _DISABLE; 00349 } 00350 00351 // SEL CV CHANNEL 00352 gCSB = _ENABLE; 00353 gSPI.write(ch); 00354 gCSB = _DISABLE; 00355 00356 cnt < numptn ? cnt++ : cnt = 0; 00357 00358 __enable_irq(); 00359 00360 gSW |= CheckSW(rcv); 00361 DinSync(); 00362 MidiCV(); 00363 } 00364 00365 //------------------------------------------------------------- 00366 // Check SW 00367 00368 unsigned char CheckSW(unsigned char c) { 00369 00370 static unsigned char swbuf[2]; 00371 static unsigned int cntsw; 00372 unsigned char ret = 0; 00373 00374 if(cntsw > SW_WATCH_INTERVAL) { 00375 if(c &= 0x0F) { 00376 if(!swbuf[1]) { 00377 if( swbuf[0] == c) { 00378 swbuf[1] = c; 00379 ret = c; 00380 } 00381 else { 00382 swbuf[0] = c; 00383 } 00384 } 00385 } 00386 else { 00387 swbuf[1] = 0; 00388 swbuf[0] = 0; 00389 } 00390 cntsw = 0; 00391 } 00392 cntsw++; 00393 return ret; 00394 } 00395 00396 //------------------------------------------- 00397 // Receive USBMIDI Data & Store Ring Buffer 00398 void RcvUSBMIDI(MIDIMessage msg) { 00399 00400 if(msg.data[0] == 0) return; 00401 00402 // gGATE ^= GATE_LED5; 00403 // printf("%02x %02x %02x %02x\r\n",msg.data[0],msg.data[1],msg.data[2],msg.data[3]); 00404 00405 for( int i=1; i<4; i++) { 00406 gPtr_buf_in++; 00407 gPtr_buf_in &= (BUFSIZE - 1); 00408 gRxBuf[gPtr_buf_in] = msg.data[i]; 00409 } 00410 } 00411 00412 //------------------------------------------------------------- 00413 // MIDI Data to CV, GATE 00414 00415 void MidiCV() 00416 { 00417 static unsigned char ch; 00418 static unsigned short phase[4]; 00419 static float cvf[4]; 00420 int lfo,mod; 00421 unsigned char midi_ch; 00422 unsigned int cv; 00423 unsigned int note; 00424 00425 midi_ch = gMIDI_CH[ch]; 00426 00427 note = gPlayNoteBuf[midi_ch]; 00428 if( note < MINIMUMNOTE) note = MINIMUMNOTE; 00429 note -= MINIMUMNOTE; 00430 00431 // DDS Phase 00432 phase[ch] += gLFO_DP[ch]; 00433 00434 // LFO DDS Genelator 00435 switch(gLFO_FORM[ch]) { 00436 case LFO_WF_TRI: 00437 if(phase[ch] < 32738) lfo = phase[ch] - 16384; 00438 else lfo = (16383 + 32768) - phase[ch]; 00439 break; 00440 case LFO_WF_SQR: 00441 if(phase[ch] < 32738) lfo = 32767; 00442 else lfo = 0; 00443 break; 00444 case LFO_WF_SAW: 00445 lfo = phase[ch] / 2 - 16384; 00446 break; 00447 default : 00448 lfo = 0; 00449 break; 00450 } 00451 00452 // Modulation amount 00453 mod = lfo * gModWheelBuf[midi_ch] >> 7; 00454 00455 // Calculate CV 00456 cvf[ch] = ((float)(note << 8) - cvf[ch]) * gGLIDE[ch] + cvf[ch]; 00457 cv = (unsigned int)cvf[ch] + (0x8000 - (0x0040 << 3)) 00458 + (gPitchBendBuf[midi_ch] << 2) + mod; 00459 if(cv > 0xFFFF) cv = 0xFFFF; 00460 gCV[ch] = (unsigned short)cv; 00461 gCV[ch+4] = OctVtoHzV(gCV[ch]); 00462 00463 // GATE 00464 gGateBuf[midi_ch] ? gGATE |= (1<<ch) : gGATE &= ~(1<<ch); 00465 00466 ch++; 00467 ch &= 0x03; 00468 } 00469 00470 //------------------------------------------------------------- 00471 // Oct/V to Hz/V Converter 00472 00473 void CalcHzVTbl() // Calc Conv. Table 00474 { 00475 int i; 00476 float v; 00477 00478 for( i=0; i<3072; i++) { 00479 v = 24576.0 * pow(2.0,(i/3072.0)); 00480 gTblHzV[i] = (unsigned short)v; 00481 } 00482 } 00483 00484 unsigned short OctVtoHzV( unsigned short vin) 00485 { 00486 int oct,res; 00487 unsigned short vout; 00488 00489 if(vin > 0xE400) vin = 0xE400; // Maximum Note E8 Vin = 10.794V 00490 if(vin < 0x6800) vin = 0x6800; // Minimum Note C-2 Vin = -2.000V 00491 vin -= 0x6800; 00492 00493 oct = vin / 0xC00; // 0xC00 : 3072 00494 res = vin % 0xC00; 00495 00496 vout = ((unsigned short)gTblHzV[res] >> (10 - oct)) + 0x8000; 00497 return vout; 00498 } 00499 00500 //------------------------------------------------------------- 00501 // DIN SYNC Control 00502 00503 void DinSync() 00504 { 00505 static unsigned int cnt; 00506 static unsigned int cnt24 = 10; 00507 00508 if(gMIDISYNC_RUN) gSYNC |= (SYNC1RUN | SYNC2RUN); 00509 else gSYNC &= ~(SYNC1RUN | SYNC2RUN); 00510 00511 if(cnt >= SYNC_TURN_TIME) gSYNC &= ~(SYNC1CLK | SYNC2CLK); 00512 00513 if(gMIDISYNC_CLK) { 00514 gSYNC |= (SYNC1CLK | SYNC2CLK); 00515 gMIDISYNC_CLK = 0; 00516 cnt = 0; 00517 cnt24++; 00518 } 00519 if(cnt24 >= 24) cnt24 = 0; 00520 00521 gLED3 = gSYNC & SYNC1RUN ? 1 : 0; 00522 gLED4 = cnt24 < 4 ? 1 : 0; 00523 00524 cnt++; 00525 }
Generated on Sat Jul 16 2022 12:03:52 by
