KAMUI OSC-CV Example refer to OSCReceiver by xshige http://mbed.org/users/xshige/programs/OSCReceiver/

Dependencies:   NetServices TextLCD mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 //-------------------------------------------------------------
00002 // KAMUI OSC-CV Exapmple
00003 //   referred to xshige's OSCReceiver
00004 //   http://mbed.org/users/xshige/programs/OSCReceiver/
00005 // Copyright (C) 2012 RJB RadioJunkBox
00006 // Released under the MIT License: http://mbed.org/license/mit
00007 //-------------------------------------------------------------
00008 
00009 #include "mbed.h"
00010 #include "TextLCD.h"
00011 #include "EthernetNetIf.h"
00012 #include "UDPSocket.h"
00013 #include "OSCReceiver.h"
00014 #include <stdlib.h>
00015 #include <ctype.h>
00016 #include <math.h>
00017 
00018 //-------------------------------------------------------------
00019 // Define
00020 
00021 #define AD5551                      // 14bitDAC
00022 
00023 #define SPI_RATE            1000000 // 1Mbps
00024 #define MIDI_RATE           31250   // 31.25kbps
00025 #define BEEP_FREQ           1760.0  // 1760Hz
00026 #define UPDATE_INTERVAL     100     // 100us
00027 #define SW_WATCH_INTERVAL   (25000/UPDATE_INTERVAL) // 25ms
00028 #define PARAM_GLIDE         6554.0
00029 
00030 #define UPDATE_MODE0        0       // Update Interval CV ch1-6 1200us, ch7,8 400us
00031 #define UPDATE_MODE1        1       // Update Interval CV ch1-6 N/A,    ch7,8 200us
00032 
00033 #define GATE1               0x01
00034 #define GATE2               0x02
00035 #define GATE3               0x04
00036 #define GATE4               0x08
00037 
00038 #define SYNC1CLK            0x01
00039 #define SYNC1RUN            0x02
00040 #define SYNC2CLK            0x04
00041 #define SYNC2RUN            0x08
00042 
00043 #define MODE_CV             0x00
00044 #define MODE_GATE           0x40
00045 #define MODE_SYNC           0x80
00046 #define MODE_SET_SYNC       0xC0
00047 
00048 #define SW1                 0x01
00049 #define SW2                 0x02
00050 #define SW3                 0x04
00051 #define SW4                 0x08
00052 #define SYNC1CLK_IN         0x10
00053 #define SYNC1RUN_IN         0x20
00054 #define SYNC2CLK_IN         0x40
00055 #define GATE_IN             0x80
00056 
00057 #define _ENABLE             0
00058 #define _DISABLE            1
00059 
00060 //-------------------------------------------------------------
00061 // Functions
00062 
00063 void            InitKamui(void);
00064 void            UpdateCV(void);
00065 unsigned char   CheckSW(unsigned char);
00066 
00067 void            SetCV(void);
00068 int             SetupEthNetIf(void);
00069 void            onUDPSocketEvent(UDPSocketEvent);
00070 
00071 //-------------------------------------------------------------
00072 // Global Variables
00073 
00074 int gUpdateMode;
00075 unsigned short gCV[8];
00076 unsigned char  gGATE;
00077 unsigned char  gSYNC;
00078 unsigned char  gSW;
00079 
00080 union {
00081     unsigned short    WORD;    
00082     struct {
00083         unsigned char L;
00084         unsigned char H; 
00085     } BYTE;
00086 } gDAC;
00087 
00088 float           gGLIDE[8];
00089 float           gOSC_CV[8];
00090 
00091 //-------------------------------------------------------------
00092 // mbed Functions
00093 
00094 // TextLCD
00095 TextLCD gLCD(p23, p24, p25, p26, p29, p30); // rs, e, d4-d7
00096 
00097 // SPI
00098 SPI gSPI(p11,p12,p13);
00099 DigitalOut gCSA(p14);
00100 DigitalOut gCSB(p22);
00101 
00102 // Sirial MIDI
00103 //Serial gMIDI(p9,p10);
00104 
00105 // AnalogIn
00106 AnalogIn    gAIN1(p15);   // VR1
00107 AnalogIn    gAIN2(p16);   // VR2
00108 AnalogIn    gAIN3(p17);   // VR3
00109 AnalogIn    gAIN4(p18);   // VR4
00110 AnalogIn    gAIN5(p19);   // IN1
00111 AnalogIn    gAIN6(p20);   // IN2
00112 
00113 // BEEP
00114 PwmOut gBEEP(p21);
00115 
00116 // LED
00117 DigitalOut gLED1(LED1);
00118 DigitalOut gLED2(LED2);
00119 DigitalOut gLED3(LED3);
00120 DigitalOut gLED4(LED4);
00121 BusOut gLEDS(LED1,LED2,LED3,LED4);
00122 
00123 // Ticker
00124 Ticker gTICKER;
00125 
00126 // Ethernet
00127 EthernetNetIf gEth;
00128 UDPSocket gUdp;
00129 
00130 //-------------------------------------------------------------
00131 // main
00132 
00133 int main() {
00134 
00135     int i;
00136     int pot[4],_pot[4];
00137     unsigned char ch = 0;
00138     unsigned char mode = 7; // for Intialize
00139     unsigned char edit[4];
00140     int val[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
00141 
00142     // Initialize
00143     for( i=0; i<4; i++) {
00144         pot[i] = _pot[i] = 0;
00145         edit[i] = 0;
00146         gGLIDE[i] = 1.0 / expf(val[i]*656.0/PARAM_GLIDE);
00147         gGLIDE[i+4] = 1.0 / expf(val[i+4]*656.0/PARAM_GLIDE);
00148     }
00149     gSW = SW4; // for Intialize
00150     
00151     InitKamui();
00152     if(SetupEthNetIf() == -1)
00153     {
00154         gBEEP.write(0.5);
00155         wait(1);
00156         gBEEP.write(0.0);
00157         return -1;
00158     }
00159 
00160     // loop
00161     while(1) {
00162     
00163         // Ethernet Polling
00164         Net::poll();
00165 
00166         // Read pot
00167         pot[0] =  gAIN1.read_u16();
00168         pot[1] =  gAIN2.read_u16();
00169         pot[2] =  gAIN3.read_u16();
00170         pot[3] =  gAIN4.read_u16();
00171         
00172         // change pot amount?
00173         if(abs(pot[ch] - _pot[ch]) > 0x2000) edit[ch] = 1;
00174 
00175         if(edit[ch]) {
00176             switch(mode) {
00177                 case 0:
00178                     gGLIDE[ch] = 1.0 / expf(pot[ch]/PARAM_GLIDE);
00179                     val[ch] = pot[ch] / 656;
00180                     break;
00181                 case 1:
00182                     gGLIDE[ch+4] = 1.0 / expf(pot[ch]/PARAM_GLIDE);
00183                     val[ch+4] = pot[ch] / 656;
00184                     break;
00185                 default:
00186                     break;
00187             }
00188         }
00189         
00190         // Push Mode SW
00191         if(gSW & SW4) {
00192             mode++;
00193             mode &= 0x01;                      
00194             for( i=0; i<4; i++) {
00195                 _pot[i] = pot[i];
00196                 edit[i] = 0;
00197             }
00198         }
00199         gSW = 0;
00200 
00201         // LCD Display
00202         gLCD.locate( 0, 1 );
00203         switch(mode) {
00204             case 0:
00205                 gLCD.printf("G1-4 %02d %02d %02d %02d",
00206                     val[0], val[1], val[2], val[3]);
00207                 break;
00208             case 1:
00209                 gLCD.printf("G5-8 %02d %02d %02d %02d",
00210                     val[4], val[5], val[6], val[7]);
00211                 break;
00212         }
00213 
00214         ch++;
00215         ch &= 0x03;
00216     }
00217 }
00218 
00219 //-------------------------------------------------------------
00220 // Initialize KAMUI
00221 
00222 void InitKamui()
00223 {
00224     // Init. Variables
00225     for( int i=0; i<8; i++) {
00226         gCV[i] = 0x8000;
00227     }
00228     gGATE = 0;
00229     gSYNC = 0;
00230 
00231     gUpdateMode = UPDATE_MODE0;
00232   
00233     // Init. SPI
00234     gCSA = _DISABLE;
00235     gCSB = _DISABLE;
00236     gSPI.format(8,0);
00237     gSPI.frequency(SPI_RATE);
00238 
00239     // Init. Serial MIDI
00240 //    gMIDI.baud(MIDI_RATE);
00241     
00242     // Ticker
00243     gTICKER.attach_us(&UpdateCV, UPDATE_INTERVAL);
00244 
00245     // Beep
00246     gBEEP.period(1.0/BEEP_FREQ);
00247     gBEEP.write(0.5);
00248     wait(0.2);
00249     gBEEP.write(0.0);
00250 
00251     // Init Display
00252     gLCD.locate( 0, 0 );
00253               // 123456789ABCDEF
00254     gLCD.printf("OSC-CV Example ");
00255 }
00256 
00257 //-------------------------------------------------------------
00258 // Update CV, GATE, SYNC
00259 
00260 void UpdateCV()
00261 { 
00262     unsigned char rcv,ch;
00263     unsigned char ptn[] = { 0,1,6,7,2,3,6,7,4,5,6,7 };
00264     const int numptn = (sizeof ptn / sizeof ptn[0]) - 1;
00265     static unsigned char  cnt;
00266 
00267     __disable_irq();
00268 
00269     // SET DAC 
00270     ch = ptn[cnt];
00271     if(gUpdateMode) ch |= 0x06;
00272 
00273 #ifdef AD5551 // 14bitDAC
00274     gDAC.WORD = gCV[ch] >> 2;
00275 #else
00276     gDAC.WORD = gCV[ch];    
00277 #endif
00278     
00279     gCSA = _ENABLE;
00280     gSPI.write(gDAC.BYTE.H);
00281     gSPI.write(gDAC.BYTE.L);
00282     gCSA = _DISABLE;        
00283 
00284     // GATE or SYNC OUT
00285     if(cnt & 0x01) {
00286         // GATE OUT
00287         gCSB = _ENABLE;
00288         rcv = gSPI.write(gGATE | MODE_GATE) & 0x0F;
00289         gCSB = _DISABLE;
00290     }
00291     else {
00292         // SYNC OUT
00293         gCSB = _ENABLE;
00294         rcv = gSPI.write(gSYNC | MODE_SYNC);
00295         gCSB = _DISABLE;
00296     }
00297 
00298     // SEL CV CHANNEL
00299     gCSB = _ENABLE;
00300     gSPI.write(ch);
00301     gCSB = _DISABLE;
00302 
00303     cnt < numptn ? cnt++ : cnt = 0;
00304 
00305     __enable_irq();
00306 
00307     gSW |= CheckSW(rcv);
00308     SetCV();
00309 }
00310 
00311 //-------------------------------------------------------------
00312 // Check SW
00313 
00314 unsigned char CheckSW(unsigned char c) {
00315 
00316     static unsigned char  swbuf[2];
00317     static unsigned int   cntsw;
00318     unsigned char ret = 0;
00319 
00320     if(cntsw > SW_WATCH_INTERVAL) {
00321         if(c &= 0x0F) {
00322             if(!swbuf[1]) {
00323                 if( swbuf[0] == c) {
00324                     swbuf[1] = c;
00325                     ret = c;
00326                 }
00327                 else {
00328                     swbuf[0] = c;
00329                 }
00330             }
00331         }
00332         else {
00333             swbuf[1] = 0;
00334             swbuf[0] = 0;
00335         }
00336         cntsw = 0;
00337     }
00338     cntsw++;
00339     return ret;
00340 }
00341 
00342 //-------------------------------------------------------------
00343 // Set CV
00344 
00345 void SetCV()
00346 {
00347     static unsigned char ch;
00348     static float cvf[8];
00349     unsigned int cv;
00350     
00351     // Calculate CV
00352     cvf[ch] = (gOSC_CV[ch] - cvf[ch]) * gGLIDE[ch] + cvf[ch];       
00353     cv = (unsigned int)cvf[ch] + 0x8000;
00354     if(cv > 0xFFFF) cv = 0xFFFF;
00355     gCV[ch] = cv;
00356 
00357     ch++;
00358     ch &= 0x07;
00359 }
00360 
00361 //-------------------------------------------------------------
00362 // Setup Ethernet port
00363 
00364 int SetupEthNetIf()
00365 {
00366     gLCD.locate( 0, 1 );
00367     gLCD.printf("Setting up...   ");
00368 //    printf("Setting up...\r\n");
00369 
00370     EthernetErr ethErr = gEth.setup();
00371     if(ethErr)
00372     {
00373         gLCD.locate( 0, 1 );
00374         gLCD.printf("Error in setup.");
00375 //        printf("Error %d in setup.\r\n", ethErr);
00376         return -1;
00377     }
00378 //    printf("Setup OK\r\n");
00379 
00380 //    printf("IP address %d.%d.%d.%d\r\n", gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], gEth.getIp()[3]);
00381     Host broadcast(IpAddr(gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], 255), 12345, NULL);
00382     gUdp.setOnEvent(&onUDPSocketEvent);
00383     gUdp.bind(broadcast);
00384 
00385     gLCD.locate( 0, 1 );
00386     gLCD.printf("%03d.%03d.%03d.%03d", gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], gEth.getIp()[3]);
00387     wait(2.0);
00388     
00389     return 0;
00390 }
00391 
00392 //-------------------------------------------------------------
00393 // Handller receive UDP Packet
00394 
00395 void onUDPSocketEvent(UDPSocketEvent e)
00396 {
00397     union OSCarg msg[10];
00398     int num;
00399 
00400     switch(e)
00401     {
00402         case UDPSOCKET_READABLE: //The only event for now
00403             char buf[256] = {0};
00404             Host host;
00405             
00406             while( int len = gUdp.recvfrom( buf, 256, &host ) )
00407             {
00408                 if(len <= 0)  break;
00409                 // printf("\r\nFrom %d.%d.%d.%d:\r\n", 
00410                 // host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]);
00411       
00412                 getOSCmsg(buf,msg);
00413 //                printf("OSCmsg: %s %s %f %i\r\n", 
00414 //                    msg[0].address, msg[1].typeTag, msg[2].f, msg[2].i);
00415                 
00416                 len = strlen(msg[0].address);
00417                 if(isdigit(msg[0].address[len-1])) num = msg[0].address[len-1] - '0' - 1;
00418                 else num = -1;
00419 
00420                 // address pattern CV
00421                 if((strncmp(msg[0].address,"/kamui/cv",9)==0) && (num != -1)) {
00422 
00423                     if(num > 7) break;
00424                     if(msg[1].typeTag[1] == 'f') gOSC_CV[num] = msg[2].f * 3072.0;
00425                     if(msg[1].typeTag[1] == 'i') gOSC_CV[num] = msg[2].i * 3072.0;
00426 
00427                     break;
00428                 }
00429 
00430                 // address pattern GATE
00431                 if((strncmp(msg[0].address,"/kamui/gate",11)==0) && (num != -1)) {
00432 
00433                     if(num > 3) break;
00434                         if(msg[2].i) gGATE |=  (0x01 << num);
00435                         else         gGATE &= ~(0x01 << num);
00436 
00437                     break;
00438                 }
00439             
00440                 //  printf("undefined OSCmsg:%s %s\r\n",msg[0].address, msg[1].typeTag);
00441         }
00442         break;
00443     }
00444 }