OSC-CV Converter
Dependencies: Bonjour OSCReceiver TextLCD mbed mbed-rpc BurstSPI DebouncedInterrupt FastIO MIDI OSC OSCtoCV ClockControl
OSC to CV Converter
http://gtbts.tumblr.com/post/125663817741/osc-to-cv-converter-ver2-mbed-osctocv
Diff: main.cpp
- Revision:
- 4:b9f5ae574447
- Parent:
- 3:ca15241dd6b4
- Child:
- 5:e305509d53f3
--- a/main.cpp Fri Jan 11 11:33:55 2013 +0000 +++ b/main.cpp Sat Jan 19 12:03:20 2013 +0000 @@ -41,6 +41,8 @@ #define MODE_QDor 3 // Dorian #define MODE_Q5th 4 // 5th #define MODE_QWht 5 // Wholetone +#define MODE_SEQ 6 // Sequencer & Shift Register +#define MODE_Calb 7 // Calibration (VCO Tuning) #define QUAN_RES1 116 // Quantize voltage Steps #define QUAN_RES2 69 @@ -48,7 +50,7 @@ #define QUAN_RES4 17 #define QUAN_RES5 58 -#define MODE_NUM 6 // Modes +#define MODE_NUM 8 // Modes #define SPI_RATE 40000000 // 40Mbps SPI Clock #define SCALING_N 38400.0 @@ -77,15 +79,17 @@ //------------------------------------------------------------- // Functions -void NetPoll(void); +inline void NetPoll(void); void InitOSCCV(void); -void UpdateCV(unsigned char, unsigned char, unsigned int); +inline void UpdateCV(int, int, const unsigned int*); void SetCV(void); +void SeqCV(void); void CheckSW(void); -void CVMeter(unsigned int, unsigned int); +void CVMeter(int, const unsigned int*); +void LCD(); void WriteCustomChar(unsigned char, unsigned char*); int SetupEthNetIf(void); -void onUDPSocketEvent(UDPSocketEvent); +inline void onUDPSocketEvent(UDPSocketEvent); //------------------------------------------------------------- // Silentway Calibration Data Mapping @@ -164,7 +168,7 @@ }; -// 5th +// Whole tone const float calibMap5[QUAN_RES5] = { 0.00663080, 0.02202980, 0.03742880, 0.05282781, 0.06822681, 0.08362581, 0.09902481, 0.11442380, 0.12951356, 0.14392516, @@ -196,8 +200,12 @@ //------------------------------------------------------------- // Global Variables -float gOSC_cv[8]; -float gGlide; +static float gOSC_cv[8]; +static float gSeq_cv1[8]; +static float gSeq_cv2[8]; +static float gGlide; +static float gCtrl[2]; +unsigned int gCtrlSW[2]; unsigned int gMode; //------------------------------------------------------------- @@ -216,7 +224,7 @@ AnalogIn gAIN(p17); // Glide Potentiometer InterruptIn gSW(p30); // Mode SW -Ticker gSetter; // Ticker SetCV +Timer gTimer; // Timer Ticker gPoller; // Ticker Polling // Ethernet @@ -228,12 +236,11 @@ int main() { - int i; float pot, _pot; if(SetupEthNetIf() == -1) { - for(i = 0; i < 4; i++) + for(int i = 0; i < 4; i++) { gLEDS[i] = 1; wait(0.25); @@ -244,6 +251,7 @@ // mdns (Bonjour) HTTPServer svr; mDNSResponder mdns; + svr.addHandler<SimpleHandler>("/"); svr.bind(INPUT_PORT); IpAddr ip = gEth.getIp(); @@ -251,34 +259,41 @@ InitOSCCV(); - pot = _pot = 0; - - gLCD.locate( 9, 0 ); - gLCD.printf("OSC-CV"); + pot = _pot = 0; + gGlide = gMode = 0; + + LCD(); gLCD.locate( 0, 1 ); gLCD.printf("12345678 G>>%3.2f", gGlide); - // loop while(1) { gGlide = pot = gAIN.read(); - if(abs(pot - _pot) > 0.01) + if(abs(pot - _pot) > 0.01f) { gLCD.locate( 0, 1 ); gLCD.printf("12345678 G>>%3.2f", gGlide); + _pot = gAIN.read(); } - SetCV(); + if(gMode == MODE_SEQ) + { + SeqCV(); + + } else { + + SetCV(); + } } } //------------------------------------------------------------- // Ethernet Polling -void NetPoll() +inline void NetPoll() { Net::poll(); } @@ -305,11 +320,9 @@ UpdateCV(CLR, 0, 0); // Ignore CLR Pin - gSW.mode(PullUp); //Use internal pullup for ModeSW + gSW.mode(PullUp); // Use internal pullup for ModeSW wait(.001); - gMode = 0; - gSW.rise(&CheckSW); // InterruptIn rising edge(ModeSW) gPoller.attach_us(&NetPoll, POLLING_INTERVAL); // Ticker Polling @@ -320,44 +333,43 @@ // SPI Transfer // DAC8568 data word length 32bit (8bit shift out) -void UpdateCV(unsigned char control, unsigned char address, unsigned int data) +inline void UpdateCV(int control, int address, const unsigned int *data) { __disable_irq(); switch(control) { case WRITE_UPDATE_N: - { + gSYNCMODE = _DISABLE; - gSPI.write(00000000|control); //padding at beginning of byte and control bits - gSPI.write(address << 4 | data >> 12); //address(ch) bits - gSPI.write((data << 4) >> 8); // middle 8 bits of data - gSPI.write((data << 12) >> 8 | 00001111); + gSPI.write(00000000|control); // padding at beginning of byte and control bits + gSPI.write(address << 4 | *data >> 12); // address(ch) bits + gSPI.write((*data << 4) >> 8); // middle 8 bits of data + gSPI.write((*data << 12) >> 8 | 00001111); gSYNCMODE = _ENABLE; gLDAC = _DISABLE; gLDAC = _ENABLE; break; - } + case RESET: - { + gSYNCMODE = _DISABLE; - gSPI.write(00000111); //Software RESET + gSPI.write(00000111); // Software RESET gSPI.write(00000000); gSPI.write(00000000); gSPI.write(00000000); gSYNCMODE = _ENABLE; break; - } + case CLR: - { + gSYNCMODE = _DISABLE; - gSPI.write(00000101); //CLR Register + gSPI.write(00000101); // CLR Register gSPI.write(00000000); gSPI.write(00000000); - gSPI.write(00000011); //Ignore CLR Pin + gSPI.write(00000011); // Ignore CLR Pin gSYNCMODE = _ENABLE; break; - } } __enable_irq(); @@ -368,7 +380,7 @@ void SetCV() { - static unsigned int ch; + static int ch; float glidecv[8]; unsigned int cv[8]; static float oldcv[8]; @@ -378,94 +390,314 @@ switch(gMode) { case MODE_LIN: - + glidecv[ch] = oldcv[ch] * gGlide + gOSC_cv[ch] * (1.0f - gGlide); oldcv[ch] = glidecv[ch]; cv[ch] = (unsigned int)glidecv[ch]; - UpdateCV(WRITE_UPDATE_N, ch, cv[ch]); + UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]); break; case MODE_QChr: - quan = 43690 / QUAN_RES1; - qcv = calibMap1[(unsigned int)(gOSC_cv[ch] / quan )]; + quan = 40616 / QUAN_RES1; + qcv = calibMap1[(unsigned int)(gOSC_cv[ch] / quan)]; + + glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); + oldcv[ch] = glidecv[ch]; + cv[ch] = (unsigned int)glidecv[ch]; + + UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]); + break; + + case MODE_QMaj: + + quan = 40616 / QUAN_RES2; + qcv = calibMap2[(unsigned int)(gOSC_cv[ch] / quan)]; glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); oldcv[ch] = glidecv[ch]; cv[ch] = (unsigned int)glidecv[ch]; - UpdateCV(WRITE_UPDATE_N, ch, cv[ch]); + UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]); break; + + case MODE_QDor: - case MODE_QMaj: - - quan = 43690 / QUAN_RES2; - qcv = calibMap2[(unsigned int)(gOSC_cv[ch] / quan )]; + quan = 40616 / QUAN_RES3; + qcv = calibMap3[(unsigned int)(gOSC_cv[ch] / quan)]; glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); oldcv[ch] = glidecv[ch]; cv[ch] = (unsigned int)glidecv[ch]; - UpdateCV(WRITE_UPDATE_N, ch, cv[ch]); + UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]); break; + + case MODE_Q5th: + + quan = 40616 / QUAN_RES4; + qcv = calibMap4[(unsigned int)(gOSC_cv[ch] / quan)]; - case MODE_QDor: + glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); + oldcv[ch] = glidecv[ch]; + cv[ch] = (unsigned int)glidecv[ch]; + + UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]); + break; - quan = 43690 / QUAN_RES3; - qcv = calibMap3[(unsigned int)(gOSC_cv[ch] / quan )]; + case MODE_QWht: + + quan = 40616 / QUAN_RES5; + qcv = calibMap5[(unsigned int)(gOSC_cv[ch] / quan)]; glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); oldcv[ch] = glidecv[ch]; cv[ch] = (unsigned int)glidecv[ch]; - UpdateCV(WRITE_UPDATE_N, ch, cv[ch]); - break; - - case MODE_Q5th: - - quan = 43690 / QUAN_RES4; - qcv = calibMap4[(unsigned int)(gOSC_cv[ch] / quan )]; - - glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); - oldcv[ch] = glidecv[ch]; - cv[ch] = (unsigned int)glidecv[ch]; - - UpdateCV(WRITE_UPDATE_N, ch, cv[ch]); + UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]); break; - case MODE_QWht: + case MODE_Calb: - quan = 43690 / QUAN_RES5; - qcv = calibMap5[(unsigned int)(gOSC_cv[ch] / quan )]; - - glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); - oldcv[ch] = glidecv[ch]; - cv[ch] = (unsigned int)glidecv[ch]; + cv[ch] = 19212; // A440.0Hz - UpdateCV(WRITE_UPDATE_N, ch, cv[ch]); + UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]); break; } + + CVMeter(ch, &cv[ch]); - CVMeter(ch, cv[ch]); ch++; ch &= 0x07; } //------------------------------------------------------------- +// Sequence & Shift Out CV + +void SeqCV() +{ + static int ch; + static int count; + static unsigned int SeqMode; + static float glidecv[8]; + unsigned int cv[8]; + static float shiftcv[8]; + static unsigned int quan; + float qcv; + static float clock; + static float time; + + SeqMode = (unsigned int)(gCtrl[1] * (MODE_NUM - 3)); // Sequencer Quantize Mode + + time = gTimer.read(); + clock = gCtrl[0] * 0.5 + 0.01; + + gLEDS[0] = gGATES[0] = 0; // Trigger + + if(time > (clock / 2)) + { + gLEDS[1] = gGATES[1] = 0; // Gate + + } else if (count % 2) { + + gLEDS[2] = gGATES[2] = 0; + + } else if (count % 3) { + + gLEDS[3] = gGATES[3] = 0; + count = 0; + } + + switch(SeqMode) + { + case MODE_LIN: + + if(ch < 8) + { + glidecv[0] = glidecv[0] * gGlide + gSeq_cv1[ch] * (1.0f - gGlide); + + } else { + + glidecv[0] = glidecv[0] * gGlide + gSeq_cv2[ch-8] * (1.0f - gGlide); + } + + cv[0] = (unsigned int)glidecv[0]; + + UpdateCV(WRITE_UPDATE_N, 0, &cv[0]); + break; + + case MODE_QChr: + + quan = 40616 / QUAN_RES1; + + if(ch < 8) + { + qcv = calibMap1[(unsigned int)(gSeq_cv1[ch] / quan)]; + + } else { + + qcv = calibMap1[(unsigned int)(gSeq_cv2[ch-8] / quan)]; + } + + glidecv[0] = glidecv[0] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); + cv[0] = (unsigned int)glidecv[0]; + + UpdateCV(WRITE_UPDATE_N, 0, &cv[0]); + break; + + case MODE_QMaj: + + quan = 40616 / QUAN_RES2; + + if(ch < 8) + { + qcv = calibMap2[(unsigned int)(gSeq_cv1[ch] / quan)]; + + } else { + + qcv = calibMap2[(unsigned int)(gSeq_cv2[ch-8] / quan)]; + } + + glidecv[0] = glidecv[0] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); + cv[0] = (unsigned int)glidecv[0]; + + UpdateCV(WRITE_UPDATE_N, 0, &cv[0]); + break; + + case MODE_QDor: + + quan = 40616 / QUAN_RES3; + + if(ch < 8) + { + qcv = calibMap3[(unsigned int)(gSeq_cv1[ch] / quan)]; + + } else { + + qcv = calibMap3[(unsigned int)(gSeq_cv2[ch-8] / quan)]; + } + + glidecv[0] = glidecv[0] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); + cv[0] = (unsigned int)glidecv[0]; + + UpdateCV(WRITE_UPDATE_N, 0, &cv[0]); + break; + + case MODE_Q5th: + + quan = 40616 / QUAN_RES4; + + if(ch < 8) + { + qcv = calibMap4[(unsigned int)(gSeq_cv1[ch] / quan)]; + + } else { + + qcv = calibMap4[(unsigned int)(gSeq_cv2[ch-8] / quan)]; + } + + glidecv[0] = glidecv[0] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); + cv[0] = (unsigned int)glidecv[0]; + + UpdateCV(WRITE_UPDATE_N, 0, &cv[0]); + break; + + case MODE_QWht: + + quan = 40616 / QUAN_RES5; + + if(ch < 8) + { + qcv = calibMap5[(unsigned int)(gSeq_cv1[ch] / quan)]; + + } else { + + qcv = calibMap5[(unsigned int)(gSeq_cv2[ch-8] / quan)]; + } + + glidecv[0] = glidecv[0] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide); + cv[0] = (unsigned int)glidecv[0]; + + UpdateCV(WRITE_UPDATE_N, 0, &cv[0]); + break; + } + + for(int i = 1; i < 8; ++i) + { + glidecv[i] = glidecv[i] * gGlide + shiftcv[i] * (1.0f - gGlide); + cv[i] = (unsigned int)glidecv[i]; + + UpdateCV(WRITE_UPDATE_N, i, &cv[i]); + } + + if(time > clock) + { + gLEDS[0] = gGATES[0] = 1; + gLEDS[1] = gGATES[1] = 1; + gLEDS[2] = gGATES[2] = 1; + gLEDS[3] = gGATES[3] = 1; + + count++; + + for(int j = 1; j < 8; ++j) // Shift Note + { + shiftcv[j] = glidecv[j-1]; + } + + ch++; + ch &= 0x0F; + gTimer.reset(); + } + + if(ch < 8) + { + CVMeter(ch, &cv[0]); + + } else { + + CVMeter((ch-8), &cv[0]); + } +} + +//------------------------------------------------------------- // Check SW -void CheckSW() +void CheckSW() { + wait(0.01); + if(gMode < MODE_NUM - 1) { gMode++; } else { - + gMode = 0; } + LCD(); +} + +//------------------------------------------------------------- +// CV meter + +void CVMeter(int ch, const unsigned int *level) +{ + unsigned int cvmeter; + + cvmeter = *level / 4860; + // cvmeter = *level / (SCALING_N / 7.9); + + gLCD.locate ( ch, 0 ); + gLCD.putc(cvmeter); // put custom char +} + +//------------------------------------------------------------- +// Print LCD Menu + +void LCD() +{ switch(gMode) { case MODE_LIN: @@ -497,23 +729,22 @@ gLCD.locate( 9, 0 ); gLCD.printf("QUAN_W "); break; + + case MODE_SEQ: + gLCD.locate( 9, 0 ); + gLCD.printf("ASRSEQ "); + + gTimer.start(); // Sequencer Timer Start + break; + + case MODE_Calb: + gLCD.locate( 9, 0 ); + gLCD.printf("Calibr "); + break; } } //------------------------------------------------------------- -// CV meter - -void CVMeter(unsigned int ch, unsigned int level) -{ - unsigned int cvmeter; - - cvmeter = level / (SCALING_N / 7.9); - - gLCD.locate ( ch, 0 ); - gLCD.putc(cvmeter); // put custom char -} - -//------------------------------------------------------------- // Write command Custom Char LCD CGRAM(CV Meter) void WriteCustomChar(unsigned char addr, unsigned char *c) @@ -525,6 +756,7 @@ { gLCD.writeCommand(addr | cnt); gLCD.writeData(*c); + cnt++; c++; } @@ -545,7 +777,6 @@ gLCD.locate( 0, 1 ); gLCD.printf("Error in setup."); // printf("Error %d in setup.\r\n", ethErr); - return -1; } // printf("Setup OK\r\n"); @@ -554,10 +785,10 @@ Host broadcast(IpAddr(gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], 255), INPUT_PORT, NULL); gUdp.setOnEvent(&onUDPSocketEvent); gUdp.bind(broadcast); - + gLCD.locate( 0, 1 ); gLCD.printf("%03d.%03d.%03d.%03d", gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], gEth.getIp()[3]); - wait(2.0); + wait(1.0); return 0; } @@ -565,14 +796,14 @@ //------------------------------------------------------------- // Handller receive UDP Packet -void onUDPSocketEvent(UDPSocketEvent e) +inline void onUDPSocketEvent(UDPSocketEvent e) { union OSCarg msg[10]; static int num; switch(e) { - case UDPSOCKET_READABLE: //The only event for now + case UDPSOCKET_READABLE: // The only event for now char buf[256] = {0}; Host host; @@ -587,10 +818,16 @@ // msg[0].address, msg[1].typeTag, msg[2].f, msg[2].i); len = strlen(msg[0].address); - if(isdigit(msg[0].address[len-1])) num = msg[0].address[len-1] - '0' - 1; - else num = -1; + + if(isdigit(msg[0].address[len-1])) + + num = msg[0].address[len-1] - '0' - 1; - unsigned int absv = msg[2].f * 1; //convert -0 to 0 + else + + num = -1; + + unsigned int absv = msg[2].f + 0; //convert -0 to 0 // address pattern SYNC & GATE (Type Tag int, float) if((strncmp(msg[0].address+(len-1)-4, "sync", 4)==0) && (num == -1)) { @@ -616,6 +853,7 @@ if(absv >= 1 || msg[2].i >= 1) gLEDS[num] = gGATES[num] = 1; else gLEDS[num] = gGATES[num] = 0; break; + } else if ((strncmp(msg[0].address,"/1/multipush",12)==0) && (num != -1)) { if(num > 3) break; if(absv >= 1 || msg[2].i >= 1) gLEDS[num] = gGATES[num] = 1; @@ -654,7 +892,31 @@ } else if ((strncmp(msg[0].address+(len-1)-12, "multifader1/", 12)==0) && (num != -1)) { if(num > 7) break; if(msg[1].typeTag[1] == 'f') gOSC_cv[num] = msg[2].f * (SCALING_N); + break; + + } else if ((strncmp(msg[0].address+(len-1)-11, "sequencer1/", 11)==0) && (num != -1)) { + if(num > 7) break; + if(msg[1].typeTag[1] == 'f') gSeq_cv1[num] = msg[2].f * (SCALING_N); + break; + + } else if ((strncmp(msg[0].address+(len-1)-11, "sequencer2/", 11)==0) && (num != -1)) { + if(num > 7) break; + if(msg[1].typeTag[1] == 'f') gSeq_cv2[num] = msg[2].f * (SCALING_N); + break; + } + + // address pattern controller + if ((strncmp(msg[0].address+(len-1)-6, "ctrlsw", 6)==0) && (num != -1)) { + if(num > 2) break; + if(absv >= 1 || msg[2].i >= 1) gCtrlSW[num] = 1; + else gCtrlSW[num] = 0; + break; + + } else if ((strncmp(msg[0].address+(len-1)-4, "ctrl", 4)==0) && (num != -1)) { + if(num > 2) break; + if(msg[1].typeTag[1] == 'f') gCtrl[num] = msg[2].f; + break; + } + } + } } - } - } - }