OSC-CV Converter

Dependencies:   Bonjour OSCReceiver TextLCD mbed mbed-rpc BurstSPI DebouncedInterrupt FastIO MIDI OSC OSCtoCV ClockControl

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 //-------------------------------------------------------------
00002 //                  TI DAC8568  OSCtoCV Converter
00003 //
00004 //   DAC8568 16bit Octal DAC http://www.ti.com/product/dac8568
00005 //
00006 //   referred to
00007 //   xshige's OSCReceiver
00008 //   http://mbed.org/users/xshige/programs/OSCReceiver/
00009 //   radiojunkbox's OSC-CV_Example
00010 //   http://mbed.org/users/radiojunkbox/code/KAMUI_OSC-CV_Example/
00011 //   Robin Price's Homebrew midi-cv box
00012 //   http://crx091081gb.net/?p=69
00013 //   Masahiro Hattori's TextLCD Module Functions
00014 //   http://www.eleclabo.com/denshi/device/lcd1602/gcram.html
00015 //   Dirk-Willem van Gulik's BonjourLib
00016 //   http://mbed.org/users/dirkx/code/BonjourLib/file/bb6472f455e8/services/mDNS
00017 //
00018 // Released under the MIT License: http://mbed.org/license/mit
00019 //-------------------------------------------------------------
00020 
00021 #pragma O3
00022 #pragma Otime
00023 
00024 #include "mbed.h"
00025 #include "FastIO.h"
00026 //#include "FastAnalogIn.h"
00027 #include "DebouncedInterrupt.h"
00028 #include "TextLCD.h"       //edit "writeCommand" "writeData" protected -> public
00029 #include "EthernetNetIf.h"
00030 #include "HTTPServer.h"
00031 #include "mDNSResponder.h" // mDNS response to announce oneselve
00032 #include "UDPSocket.h"
00033 #include "OSCReceiver.h"
00034 #include "mbedOSC.h"
00035 #include "MIDI.h"
00036 #include "ClockControl.h" // https://developer.mbed.org/users/JST2011/code/ClockControl/
00037 #include "OSCtoCV.h"
00038 #include "OSCtoCV_Sequencer.h"
00039 #include "OSCtoCV_GateSequencer.h"
00040 #include "OSCtoCV_Euclidean.h"
00041 #include "OSCtoCV_Random.h"
00042 #include "OSCtoCV_LFO.h"
00043 
00044 #include <stdlib.h>
00045 #include <ctype.h>
00046 #include <math.h>
00047 
00048 //-------------------------------------------------------------
00049 // Macros
00050 
00051 #define MODE_CLB            0        // Calibration (for VCO Tuning)
00052 #define MODE_OSC            1        // Mode OSCtoCV 
00053 #define MODE_SEQ            2        // Mode Shift Sequencer
00054 #define MODE_185            3        // Mode M185 Sequencer
00055 #define MODE_437            4        // Mode 437 Sequencer
00056 #define MODE_EUC            5        // Mode Euclidean Sequencer
00057 #define MODE_RND            6        // Mode xshift Random Generator 
00058 #define MODE_LFO            7        // Mode Stepped LFO 
00059 
00060 #define MODE_TOTAL          8        // Modes
00061 
00062 //-------------------------------------------------------------
00063 // Functions
00064 
00065 void InitOSCCV(void);
00066 inline void NetPoll(void);
00067 void CalibrationCV(void);
00068 inline void SetCV(void);
00069 inline int CheckBPM(void);
00070 inline float CheckGlide(void);
00071 inline float CheckDuration(void);
00072 void CheckModeSW(void);
00073 inline void UpdateLCD();
00074 void WriteCustomChar(unsigned char, unsigned char*);
00075 int  SetupEthNetIf(void);
00076 inline void onUDPSocketEvent(UDPSocketEvent);
00077 
00078 
00079 //-------------------------------------------------------------
00080 // Global Variables
00081 
00082 // CV Meter Custom Character
00083 unsigned char str1[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F};
00084 unsigned char str2[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
00085 unsigned char str3[8] = {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F};
00086 unsigned char str4[8] = {0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F};
00087 unsigned char str5[8] = {0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F};
00088 unsigned char str6[8] = {0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
00089 unsigned char str7[8] = {0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
00090 unsigned char str8[8] = {0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
00091 
00092 // OSCtoCV Converter Mode 
00093 int         gMode;
00094 
00095 // UDP Socket
00096 UDPSocket   gUdp;
00097 
00098 //-------------------------------------------------------------
00099 // main
00100  
00101 int main() 
00102 { 
00103     float duration;
00104     int bpm;
00105         
00106     InitOSCCV();
00107 
00108 // Init LCD        
00109     UpdateLCD();
00110     
00111 // Main loop
00112     while (1) 
00113     {
00114         UpdateLCD(); // Check Text LCD Mode Status
00115         
00116         CheckGlide(); // check glide value
00117         
00118         bpm = CheckBPM(); // check current BPM
00119         
00120         duration = CheckDuration(); // check current duration(Gate length)
00121         
00122         switch (gMode)
00123         {               
00124             case MODE_OSC: // OSCtoCV mode
00125             
00126                 SetCV();
00127                 break;
00128                 
00129             case MODE_SEQ: // Shift Sequencer mode
00130             
00131                 GateSeq(bpm, N8TH, GATE2, 3, NON_INVERT, GATESOUT_ON, SYNC_OFF);
00132                 
00133                 if (gCtrlSW[3])
00134                 {   // euclid sequencer auto offset
00135                     ShiftCVSeq(EuclideanSeq(GateSeq(bpm, N16TH, SUBGATE, (duration * 12.0f), NON_INVERT, GATESOUT_OFF, SYNC_ON), gCtrlSW[0], GATESOUT_OFF, true), gCtrlSW[0], CV_CHANNEL8);
00136                 
00137                 } else {
00138                     
00139                     ShiftCVSeq(BeatsSeq(GateSeq(bpm, N16TH, SUBGATE, (duration * 8.0f), NON_INVERT, GATESOUT_OFF, SYNC_ON), gCtrlSW[0], GATESOUT_OFF), gCtrlSW[0], CV_CHANNEL8);
00140                 }
00141                 break;
00142                 
00143             case MODE_185: // M185 Sequencer mode
00144             
00145                 
00146                 GateSeq(bpm, N8TH, GATE2, 3, NON_INVERT, GATESOUT_ON, SYNC_OFF);
00147                 
00148                 if (gCtrlSW[3])
00149                 {   // euclid sequencer auto offset
00150                     M185Seq(EuclideanSeq(GateSeq(bpm, N16TH, SUBGATE, (duration * 12.0f), NON_INVERT, GATESOUT_OFF, SYNC_ON), gCtrlSW[0], GATESOUT_OFF, true), gCtrlSW[0], CV_CHANNEL8);
00151                     
00152                 } else {
00153                     
00154                     M185Seq(BeatsSeq(GateSeq(bpm, N16TH, SUBGATE, (duration * 8.0f), NON_INVERT, GATESOUT_OFF, SYNC_ON), gCtrlSW[0], GATESOUT_OFF), gCtrlSW[0], CV_CHANNEL8);
00155                 }
00156                 break;
00157             
00158             case MODE_437: // F437 sequencer
00159                 
00160                 GateSeq(bpm, N8TH, GATE2, 3, NON_INVERT, GATESOUT_ON, SYNC_OFF);
00161                 
00162                 if (gCtrlSW[3])
00163                 {   // euclid sequencer auto offset
00164                     PolyCVSeq(EuclideanSeq(GateSeq(bpm, N16TH, SUBGATE, (duration * 12.0f), NON_INVERT, GATESOUT_OFF, SYNC_ON), gCtrlSW[0], GATESOUT_OFF, true), gCtrlSW[0]);
00165                     
00166                 } else {
00167                     
00168                     PolyCVSeq(BeatsSeq(GateSeq(bpm, N16TH, SUBGATE, (duration * 8.0f), NON_INVERT, GATESOUT_OFF, SYNC_ON), gCtrlSW[0], GATESOUT_OFF), gCtrlSW[0]);
00169                 }
00170                 break;
00171                     
00172             case MODE_EUC: // Euclidean Sequencer mode
00173             
00174                 ShiftCVSeq(GateSeq(bpm, N1ST, SUBGATE, (duration * 5.0f), NON_INVERT, GATESOUT_OFF, SYNC_OFF), gCtrlSW[0], CV_CHANNEL8); 
00175                 EuclideanSeq(GateSeq(bpm, N16TH, GATE1, 3, NON_INVERT, GATESOUT_OFF, SYNC_OFF), gCtrlSW[0], GATESOUT_ON, false);
00176                 break;
00177             
00178             case MODE_RND: // Random CV Generator mode
00179         
00180                 RandomCVGenerator(GateSeq(bpm, N32TH, GATE1, (duration * 5.0f), NON_INVERT, GATESOUT_OFF, SYNC_ON));
00181                 break;
00182 
00183             case MODE_LFO: // Stepped LFO mode
00184         
00185                 SteppedLFO(CV_CHANNEL1, false); // LFO out ch1 ~ ch8
00186                 break;
00187 
00188             default:       // CV Calibration mode
00189                 
00190                 CalibrationCV(); 
00191                 break;
00192         }
00193         
00194     }
00195 }
00196 
00197 //-------------------------------------------------------------
00198 // Ethernet Polling
00199 
00200 inline void NetPoll()
00201 {
00202     Net::poll();
00203 }
00204 
00205 //-------------------------------------------------------------
00206 // Initialize OSCtoCV
00207 
00208 void InitOSCCV()
00209 {
00210     
00211 // Set System Frequency 120Mhz 
00212     setSystemFrequency(0x3, 0x1, 15, 1);
00213     wait(0.5);
00214 
00215 // Setup Ethernet   
00216     SetupEthNetIf();
00217 
00218 // Announce mdnsResponder  (Bonjour)
00219     HTTPServer svr;
00220     mDNSResponder mdns;
00221     
00222     svr.addHandler<SimpleHandler>("/");
00223     svr.bind(INPUT_PORT);
00224     IpAddr ip = gEth.getIp();
00225     mdns.announce(ip, "OSCtoCV", "_osc._udp", INPUT_PORT, "mbed(OSCtoCV)", (char *[]) {"path=/",NULL});
00226         
00227 // Write custom char LCD CGRAM
00228     WriteCustomChar(0x00, str1);
00229     WriteCustomChar(0x01, str2);
00230     WriteCustomChar(0x02, str3);
00231     WriteCustomChar(0x03, str4);
00232     WriteCustomChar(0x04, str5);
00233     WriteCustomChar(0x05, str6);
00234     WriteCustomChar(0x06, str7);
00235     WriteCustomChar(0x07, str8);
00236     
00237 // Init  SPI
00238     gLDAC = _ENABLE;
00239     gSPI.format(8, 1);           // Data word length 8bit, Mode=1
00240     gSPI.frequency(SPI_RATE);
00241     
00242     UpdateCV(CLR, 0, 0);        // Ignore CLR Pin
00243 
00244 // Init Euclidean Sequencer    
00245     InitEuclideanSeq();    
00246     
00247 // Init Glide value
00248     gGlide = gAIN.read();
00249  
00250 // Init Mode
00251     gMode = MODE_CLB;
00252 
00253 // Init Sequencer Data
00254     for (int i = 0; i < 16; ++i) 
00255     {
00256         if (i < 8) 
00257         {
00258             g185_cv[i] = (calibMap1[69] * SCALING_N);
00259             gBeatsLevel[i] = gBeatsDecay[i] = 1;    
00260         }
00261         
00262         gSeq_cv[i] = (calibMap1[69] * SCALING_N);
00263     }
00264 
00265 // Set OSC message for sending 
00266     sendMes.setIp(touchOSCAddress); 
00267     sendMes.setPort(touchOSCPort);
00268     
00269     gSW.attach(&CheckModeSW, IRQ_RISE, 20);     // InterruptIn rising edge(ModeSW)
00270     wait(0.5);
00271     
00272     gPoller.attach_us(&NetPoll, POLLING_INTERVAL);  // Ticker Polling
00273     wait(0.2);
00274 }
00275 
00276 //-------------------------------------------------------------
00277 // Calibration Mode
00278 
00279 void CalibrationCV()
00280 {
00281     static int ch;
00282     unsigned int cv;
00283 
00284     cv = (unsigned int)(calibMap1[69] * SCALING_N);  // A880.0Hz
00285                 
00286     gSUBGATE = gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = true;
00287     
00288     UpdateCV(WRITE_UPDATE_N, ch, &cv);
00289     UpdateCVMeter(ch, &cv);
00290     
00291     ++ch;
00292     ch &= 0x07;
00293 }
00294 
00295 //-------------------------------------------------------------
00296 // Calculate CV
00297 
00298 inline void SetCV()
00299 {
00300     static int ch, mcount;
00301     static float glidecv[8];
00302     unsigned int cv;
00303     static float qcv;
00304 
00305     switch (CheckQuantizeMode()) 
00306         {
00307             case Lin:
00308                 
00309                 glidecv[ch] = glidecv[ch] * gGlide + gOSC_cv[ch] * (1.0f - gGlide);
00310                 break;
00311                     
00312             case Chr:
00313 
00314                 qcv = calibMap1[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES1 - 1))];
00315                     
00316                 glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
00317                 break;
00318                 
00319             case Maj:
00320 
00321                 qcv = calibMap2[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES2 - 1))];
00322 
00323                 glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
00324                 break;
00325             
00326             case M7:
00327                 
00328                 qcv = calibMap3[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES3 - 1))];
00329                     
00330                 glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
00331                 break;
00332                 
00333             case Min7:
00334 
00335                 qcv = calibMap4[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES4 - 1))];
00336 
00337                 glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
00338                 break;
00339                     
00340             case Dor:
00341                 
00342                 qcv = calibMap5[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES5 - 1))];
00343 
00344                 glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
00345 
00346                 break;
00347         
00348             case Min:
00349                 
00350                 qcv = calibMap6[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES6 - 1))];
00351 
00352                 glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
00353                 break;
00354                 
00355             case S5th:
00356 
00357                 qcv = calibMap7[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES7 - 1))];
00358 
00359                 glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
00360                 break;
00361                 
00362             case Wht:
00363                 
00364                 qcv = calibMap8[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES8 - 1))];
00365 
00366                 glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
00367                 break;
00368         }
00369         
00370     cv = (unsigned int)glidecv[ch];
00371             
00372     UpdateCV(WRITE_UPDATE_N, ch, &cv);
00373 
00374     if (mcount == 0x1F) 
00375     {
00376         UpdateCVMeter(ch, &cv);
00377     }
00378 
00379     ++ch;
00380     
00381     if (ch &= 0x07)
00382     {
00383         ++mcount;
00384         mcount &= 0x3F;
00385     }
00386 }
00387 
00388 
00389 //-------------------------------------------------------------
00390 // Check BPM
00391 
00392 inline int CheckBPM()
00393 {   
00394     static int _bpm = -1;
00395     int bpm;
00396     
00397     if (gCtrlSW[0]) 
00398     {
00399         bpm = 0;
00400 
00401         return bpm;
00402     }
00403     
00404     if (gCtrl[0]) {
00405 
00406         bpm = (gCtrl[0] * 240 + 5);
00407 
00408         if (bpm != _bpm)
00409         {
00410             _bpm = bpm;
00411             
00412             sendMes.setTopAddress("/bpm");
00413             sendMes.setArgs("i", bpm);
00414             osc.sendOsc(&sendMes);
00415             
00416             sendMes.setTopAddress("/ctrl1");
00417             sendMes.setArgs("f", gCtrl[0]);
00418             osc.sendOsc(&sendMes);
00419         }
00420     }
00421                         
00422     return bpm;
00423 }
00424 
00425 //-------------------------------------------------------------
00426 // Check Glide Value
00427 
00428 inline float CheckGlide()
00429 {
00430     static float _pot;
00431     float pot = 0;
00432     
00433     pot = gAIN.read();  // Update glide value
00434         
00435     if (!pot) // when (glide pot value == 0) && MODE_OSC
00436     {         // use gCtrl[3] value
00437         if (abs(gCtrl[3] - _pot) > 0.01f)
00438         {
00439             _pot = gGlide = gCtrl[3];
00440         
00441             gLCD.locate( 9, 1 );
00442             gLCD.printf("G>>%3.2f", gGlide);
00443         }
00444     
00445     } else if (abs(pot - _pot) > 0.01f) {
00446         
00447         _pot = gGlide = pot;
00448         
00449         gLCD.locate( 9, 1 );
00450         gLCD.printf("G>>%3.2f", gGlide);
00451     }
00452     
00453     return pot;
00454 }
00455 
00456 //-------------------------------------------------------------
00457 // Check Duration Value
00458 
00459 inline float CheckDuration()
00460 {
00461     static float _duration = 0.6f;
00462     
00463     if (_duration != gCtrl[6]) // check current gate duration
00464     {
00465         sendMes.setTopAddress("/ctrl7");
00466         sendMes.setArgs("f", gCtrl[6]);
00467         osc.sendOsc(&sendMes);
00468         
00469         _duration = gCtrl[6];
00470     }
00471     
00472     return gCtrl[6];    
00473 }
00474 
00475 //-------------------------------------------------------------
00476 // Check Mode SW
00477 
00478 void CheckModeSW()
00479 {   
00480     if (gMode < MODE_TOTAL - 1) 
00481     {   
00482         ++gMode;
00483             
00484     } else {
00485                 
00486         gMode = 0;
00487     }
00488     
00489     gCLOCKOUT = gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = false;
00490     gSubModeCount1 = gSubModeCount2 = 0;
00491     
00492     if (gMode != MODE_CLB || gMode != MODE_OSC)
00493     {
00494         gTimer.start();     // Sequencer Timer Start
00495         midi.begin(1);
00496         
00497     } else {
00498             
00499         gTimer.stop();      // Sequencer Timer Stop
00500     }
00501     
00502 }
00503 
00504 //-------------------------------------------------------------
00505 // Print LCD Mode Status
00506 
00507 inline void UpdateLCD()
00508 {
00509     static int _mode = -1;
00510     static int _qmode = -1;
00511     static int qmode;
00512     
00513     if (_mode != gMode)
00514     {
00515         sendMes.setTopAddress("/mode");
00516         
00517         switch (gMode) 
00518             {
00519                 case MODE_CLB: 
00520                     gLCD.locate( 9, 0 );
00521                     gLCD.printf("CLB|880");
00522                     
00523                     gLCD.locate( 0, 1 );
00524                     gLCD.printf("12345678 G>>%3.2f", gGlide);
00525                     
00526                     sendMes.setArgs("s", "Calibration");
00527                     osc.sendOsc(&sendMes);
00528                     
00529                     sendMes.setTopAddress("/scale");
00530                     sendMes.setArgs("s", "880Hz");
00531                     
00532                     _qmode = -1;
00533                     break;
00534                 
00535                 case MODE_OSC:
00536                     gLCD.locate( 9, 0 );
00537                     gLCD.printf("OSC|");
00538                     
00539                     sendMes.setArgs("s", "OSCtoCV");
00540                     break;
00541 
00542                 case MODE_SEQ:  
00543                     gLCD.locate( 9, 0 );
00544                     gLCD.printf("ASR|");
00545                     
00546                     sendMes.setArgs("s", "ASR SEQ");
00547                     break;
00548                     
00549                 case MODE_185:  
00550                     gLCD.locate( 9, 0 );
00551                     gLCD.printf("185|");
00552             
00553                     sendMes.setArgs("s", "M185 SEQ");
00554                     break;
00555                     
00556                 case MODE_437:  
00557                     gLCD.locate( 9, 0 );
00558                     gLCD.printf("437|");
00559             
00560                     sendMes.setArgs("s", "F437 SEQ");
00561             
00562                     break;
00563                         
00564                 case MODE_EUC:  
00565                     gLCD.locate( 9, 0 );
00566                     gLCD.printf("EUC|");
00567                     
00568                     sendMes.setArgs("s", "Euclidean SEQ");
00569                     break;
00570                 
00571                 case MODE_RND:  
00572                     gLCD.locate( 9, 0 );
00573                     gLCD.printf("RND|");
00574                 
00575                     sendMes.setArgs("s", "Xorshift Random");
00576                     break;
00577                     
00578                 case MODE_LFO:  
00579                     gLCD.locate( 9, 0 );
00580                     gLCD.printf("LFO|");
00581                 
00582                     sendMes.setArgs("s", "Stepped LFO");
00583                     break;
00584 
00585                 default:
00586                     break;
00587             }
00588             
00589             osc.sendOsc(&sendMes);
00590             _mode = gMode;
00591     }
00592     
00593     qmode = (gCtrl[1] * (SCALE_TOTAL - 1));
00594     
00595     if (_qmode != qmode)
00596     {
00597         sendMes.setTopAddress("/scale");
00598         
00599         switch (qmode) 
00600             {
00601                 case Lin:
00602                     gLCD.locate( 13, 0 );
00603                     gLCD.printf("lin");
00604 
00605                     sendMes.setArgs("s", "Linear");
00606                     break;
00607                     
00608                 case Chr:
00609                     gLCD.locate( 13, 0 );
00610                     gLCD.printf("chr");
00611 
00612                     sendMes.setArgs("s", "Chromatic");
00613                     break;
00614                 
00615                 case Maj:
00616                     gLCD.locate( 13, 0 );
00617                     gLCD.printf("maj");
00618                     
00619                     sendMes.setArgs("s", "Major");
00620                     break;
00621             
00622                 case M7:
00623                     gLCD.locate( 13, 0 );
00624                     gLCD.printf("ma7");
00625                     
00626                     sendMes.setArgs("s", "Major7");
00627                     break;
00628                 
00629                 case Min7:
00630                     gLCD.locate( 13, 0 );
00631                     gLCD.printf("mi7");
00632                     
00633                     sendMes.setArgs("s", "Minor7");
00634 
00635                     break;
00636                     
00637                 case Dor:
00638                     gLCD.locate( 13, 0 );
00639                     gLCD.printf("dor");
00640                     
00641                     sendMes.setArgs("s", "Dorian");
00642                     break;
00643         
00644                 case Min:
00645                     gLCD.locate( 13, 0 );
00646                     gLCD.printf("min");
00647                     
00648                     sendMes.setTopAddress("/scale");
00649                     sendMes.setArgs("s", "Minor");
00650                     break;
00651                 
00652                 case S5th:
00653                     gLCD.locate( 13, 0 );
00654                     gLCD.printf("5th");
00655                     
00656                     sendMes.setArgs("s", "5th");
00657                     break;
00658                 
00659                 case Wht:
00660                     gLCD.locate( 13, 0 );
00661                     gLCD.printf("wht");
00662                     
00663                     sendMes.setArgs("s", "Whole Tone");
00664                     break;
00665                     
00666                 default:
00667                     break;
00668             }
00669             
00670             osc.sendOsc(&sendMes);
00671             _qmode = qmode;
00672     }
00673 
00674 }
00675 
00676 
00677 //-------------------------------------------------------------
00678 // Write command Custom Char LCD CGRAM for CV Meter)
00679 
00680 void WriteCustomChar(unsigned char addr, unsigned char *c)
00681 {   
00682     char cnt = 0;
00683     addr = ((addr << 3) | 0x40);
00684     
00685     while (cnt < 0x08)
00686     {
00687         gLCD.writeCommand(addr | cnt);
00688         gLCD.writeData(*c);
00689         
00690         ++cnt;
00691         ++c;
00692     }
00693 }
00694 
00695 //-------------------------------------------------------------
00696 // Setup Ethernet port
00697 
00698 int SetupEthNetIf()
00699 {
00700     gLCD.locate( 0, 1 );
00701     gLCD.printf("Setting up...   ");
00702 //  printf("Setting up...\r\n");
00703     EthernetErr ethErr = gEth.setup();
00704     
00705     if (ethErr)
00706     {
00707         gLCD.locate( 0, 1 );
00708         gLCD.printf("Error in setup.");
00709 //  printf("Error %d in setup.\r\n", ethErr);
00710         return -1;
00711     }
00712 //  printf("Setup OK\r\n");
00713  
00714 //  printf("IP address %d.%d.%d.%d\r\n", gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], gEth.getIp()[3]);
00715     Host broadcast(IpAddr(gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], 255), INPUT_PORT, NULL);
00716     gUdp.setOnEvent(&onUDPSocketEvent);
00717     gUdp.bind(broadcast);
00718     
00719     gLCD.locate( 0, 1 );
00720     gLCD.printf("%03d.%03d.%03d.%03d", gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], gEth.getIp()[3]);
00721     
00722     wait(1.0);
00723     
00724     return 0;
00725 }
00726 
00727 
00728 //-------------------------------------------------------------
00729 // Handller receive OSC UDP Packet
00730 
00731 inline void onUDPSocketEvent(UDPSocketEvent e)
00732 {
00733     static union OSCarg msg[10];
00734     static char buf[768] = {0};
00735     int recvlen;
00736     int num, numrow, len, offset;
00737     int messagepos = 0;
00738     bool bundleflag = false;
00739     
00740     Host host;
00741     
00742     switch (e)
00743     {
00744         case UDPSOCKET_READABLE: // The only event for now
00745         
00746             recvlen = gUdp.recvfrom(buf, 768, &host);  // packet length    
00747 
00748             if (recvlen <= 0)  break;
00749 
00750             if (!bundleflag && buf[0] == '#') // #bundle
00751             {
00752                 messagepos += 16;     // skip #bundle & timetag
00753                 recvlen -= 16;
00754 
00755                 bundleflag = true;  
00756             }
00757 
00758             do {
00759 
00760                 if (bundleflag)
00761                 {
00762                     messagepos += 4;
00763                     recvlen -= 4;
00764 
00765                     if (recvlen < 0)
00766                     {
00767                         bundleflag = false;
00768                         break;
00769                     }
00770                 }
00771 
00772                 if (getOSCmsg(buf + messagepos, msg) == -1)  continue;
00773 
00774                 len = strlength(msg[0].address);
00775 
00776                 if (isdigit(msg[0].address[len-1])) 
00777                 {       
00778                     num = msg[0].address[len-1] - '0' - 1;
00779 
00780                     offset = 1;
00781 
00782                     if (isdigit(msg[0].address[len-2])) 
00783                     {
00784                         offset = 2;
00785                         num += 10;
00786                     }
00787 
00788                 } else {
00789 
00790                     num = -1;
00791                 }
00792 
00793                 if (!strncmp(msg[0].address + (len - offset) - 4, "page", 4)) // touchOSC page
00794                 { 
00795                     continue;
00796 
00797                 } else if (!strncmp(msg[0].address + (len - offset) - 4, "sync", 4)) { 
00798                     if (msg[2].i != 0) gCLOCKOUT = true;
00799                     else              gCLOCKOUT = false;
00800                     continue;
00801 
00802                 } else if (!strncmp(msg[0].address + (len - offset) - 4, "gate", 4) && (num != -1)) {
00803                     if (num > 3) continue;
00804                     if (msg[2].i != 0) gGATES[num] = true;
00805                     else              gGATES[num] = false;
00806                     continue;
00807                     // (touchOSC Control push, toggle)
00808                 } else if (!strncmp(msg[0].address + (len - offset) - 5, "fader", 5) && (num != -1)) {
00809                     if (num > 7) continue;                                              
00810                     gOSC_cv[num] = msg[2].f * (SCALING_N);
00811                     continue;
00812 
00813                 } else if (!strncmp(msg[0].address + (len - offset) - 9, "multixy1/", 9) && (num != -1)) {
00814                     if (num > 7) continue;
00815                     if (msg[1].typeTag[1] == 'f') gOSC_cv[num] = msg[2].f * (SCALING_N);
00816                     if (msg[1].typeTag[1] == 'f') gOSC_cv[++num] = msg[3].f * (SCALING_N);
00817                     continue;
00818 
00819                 } else if (!strncmp(msg[0].address + (len - offset) - 12, "multifader1/", 12) && (num != -1)) {
00820                     if (num > 7) continue;
00821                     if (msg[1].typeTag[1] == 'f') gOSC_cv[num] = msg[2].f * (SCALING_N);
00822                     continue;
00823 
00824                 } else if (!strncmp(msg[0].address + (len - offset) - 5, "m185/", 5) && (num != -1)) {
00825                     if (num > 7) continue;
00826                     if (msg[1].typeTag[1] == 'f') g185_cv[num] = msg[2].f * (SCALING_N);
00827                     continue;
00828 
00829                 } else if (!strncmp(msg[0].address + (len - offset) -10, "sequencer/", 10) && (num != -1)) {
00830                     if (num > 15) continue;
00831                     gSeq_cv[num] = msg[2].f * (SCALING_N);
00832                     continue;
00833 
00834                 } else if (!strncmp(msg[0].address + (len - offset) - 6, "ctrlsw", 6) && (num != -1)) {
00835                     if (num > 7) continue;
00836                     if (msg[2].i != 0) gCtrlSW[num] = true;
00837                     else              gCtrlSW[num] = false;
00838                     continue;
00839 
00840                 } else if (!strncmp(msg[0].address + (len - offset) - 4, "ctrl", 4) && (num != -1)) {
00841                     if (num > 7) continue;                                             
00842                     gCtrl[num] = msg[2].f;
00843                     continue;
00844 
00845                 } else if (!strncmp(msg[0].address + (len - offset) - 9, "pulsecnt/", 9) && (num != -1)) {
00846                     if (num > 7) continue;
00847                     gPulseCount[num] = msg[2].f;
00848                     continue;
00849 
00850                 } else if (!strncmp(msg[0].address + (len - offset) - 9, "gatemode/", 9) && (num != -1)) {
00851                     if (num > 15) continue;
00852                     gGateMode[num] = msg[2].f;
00853                     continue;
00854 
00855                 } else if (!strncmp(msg[0].address + (len - offset) - 9, "g185mode/", 9) && (num != -1)) {
00856                     if (num > 7) continue;
00857                     gGateMode185[num] = msg[2].f;
00858                     continue;
00859 
00860                 } else if (!strncmp(msg[0].address + (len - offset) - 6, "slide/", 6) && (num != -1)) {
00861                     if (num > 15) continue;
00862                     gSlide[num] = msg[2].f;
00863                     continue;
00864 
00865                 } else if (!strncmp(msg[0].address + (len - offset) - 9, "slide185/", 9) && (num != -1)) {
00866                     if (num > 7) continue;
00867                     gSlide185[num] = msg[2].f;
00868                     continue;
00869 
00870                 } else if (!strncmp(msg[0].address + (len - offset - 2) - 7, "accent/", 7) && (num != -1)) {
00871 
00872                     if (isdigit(msg[0].address[len - 3])) 
00873                     {       
00874                         num = msg[0].address[len - 3] - '0' - 1;
00875                     }
00876 
00877                     gAccent[num] = msg[2].i;
00878                     continue;
00879 
00880                 } else if (!strncmp(msg[0].address + (len - offset - 3) - 7, "accent/", 7) && (num != -1)) {
00881 
00882                     if (isdigit(msg[0].address[len - 3]))
00883                     {       
00884                         num = msg[0].address[len - 3] - '0' - 1;
00885 
00886                         if (isdigit(msg[0].address[len - 4])) 
00887                         {
00888                             num += 10;
00889                         }
00890                     }
00891 
00892                     gAccent[num] = msg[2].i;
00893                     continue;
00894 
00895                 } else if (!strncmp(msg[0].address + (len - offset - 3) - 6, "185acc/", 6) && (num != -1)) {
00896 
00897                     if (isdigit(msg[0].address[len-3])) 
00898                     {       
00899                         num = msg[0].address[len-3] - '0' - 1;
00900 
00901                         if (isdigit(msg[0].address[len - 4])) 
00902                         {
00903                             num += 10;
00904                         }
00905                     }
00906 
00907                     gAccent185[num] = msg[2].i;
00908                     continue;
00909 
00910                 } else if (!strncmp(msg[0].address + (len - offset - 2) - 3, "bm/", 3) && (num != -1)) {
00911 
00912                     if (isdigit(msg[0].address[len - 3])) 
00913                     {       
00914                         num = msg[0].address[len - 3] - '0' - 1;
00915 
00916                         if (isdigit(msg[0].address[len - 4])) 
00917                         {
00918                             num += 10;
00919                         }
00920                     }
00921 
00922                     if (isdigit(msg[0].address[len - 1])) 
00923                     {       
00924                         numrow = msg[0].address[len - 1] - '0' - 1;
00925                     }
00926 
00927                     gBeatsMatrix[numrow][num] = msg[2].i;
00928                     continue;
00929 
00930                 } else if (!strncmp(msg[0].address + (len - offset - 3) - 3, "bm/", 3) && (num != -1)) {
00931 
00932                     if (isdigit(msg[0].address[len - 3])) 
00933                     {       
00934                         num = msg[0].address[len - 3] - '0' - 1;
00935 
00936                         if (isdigit(msg[0].address[len - 4])) 
00937                         {
00938                             num += 10;
00939                         }
00940                     }
00941 
00942                     if (isdigit(msg[0].address[len - 1])) 
00943                     {       
00944                         numrow = msg[0].address[len - 1] - '0' - 1;
00945                     }
00946 
00947                     gBeatsMatrix[numrow][num] = msg[2].i;
00948                     continue;
00949 
00950                 } else if (!strncmp(msg[0].address + (len - offset) - 4, "bpc/", 4) && (num != -1)) {
00951                     if (num > 15) continue;
00952                     gPulseCountBeats[num] = msg[2].f;
00953                     continue;
00954 
00955                 } else if (!strncmp(msg[0].address + (len - offset) - 4, "blv/", 4) && (num != -1)) {
00956                     if (num > 7) continue;
00957                     gBeatsLevel[num] = msg[2].f;
00958                     continue;
00959 
00960                 } else if (!strncmp(msg[0].address + (len - offset) - 4, "bdc/", 4) && (num != -1)) {
00961                     if (num > 7) continue;
00962                     gBeatsDecay[num] = msg[2].f;
00963                     continue;
00964 
00965                 }  else if (!strncmp(msg[0].address + (len - offset) - 4, "euca", 4) && (num != -1)) {
00966                     if (num > 5) continue;                                             
00967                     gEucA[num] = msg[2].f;
00968                     continue;
00969 
00970                 } else if (!strncmp(msg[0].address + (len - offset) - 4, "eucb", 4) && (num != -1)) {
00971                     if (num > 5) continue;                                             
00972                     gEucB[num] = msg[2].f;
00973                     continue;
00974 
00975                 } else if (MODE_RND || MODE_LFO) {
00976                     
00977                     if (!strncmp(msg[0].address + (len - offset) - 3, "acv", 3) && (num != -1)) {
00978                         if (num > 3) continue;                                             
00979                         gArdCV[num] = msg[2].i;
00980                         continue;
00981 
00982                     } else if (!strncmp(msg[0].address + (len - offset) - 3, "pot", 3) && (num != -1)) {
00983                         if (num > 1) continue;                                             
00984                         gArdPot[num] = msg[2].f;
00985                         continue;
00986 
00987                     } else if (!strncmp(msg[0].address + (len - offset) - 2, "sw", 2) && (num != -1)) {
00988                         if (num > 1) continue;
00989                         if (msg[2].i != 0) gArdSW[num] = true;
00990                         else               gArdSW[num] = false;                                       
00991                         continue;
00992 
00993                     }
00994                     
00995                 } else {
00996                     
00997                     continue;
00998                 }
00999 
01000             } while (bundleflag);
01001     }
01002 }