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