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

/media/uploads/casiotone401/tumblr_nsg7y4pkfg1qlle9fo1_540.png

main.cpp

Committer:
casiotone401
Date:
2016-01-17
Revision:
23:2cb7fad36ce0
Parent:
21:2273c3676f1b
Child:
24:99045b0f7c4a

File content as of revision 23:2cb7fad36ce0:

//-------------------------------------------------------------
//                  TI DAC8568  OSCtoCV Converter
//
//   DAC8568 16bit Octal DAC http://www.ti.com/product/dac8568
//
//   referred to
//   xshige's OSCReceiver
//   http://mbed.org/users/xshige/programs/OSCReceiver/
//   radiojunkbox's OSC-CV_Example
//   http://mbed.org/users/radiojunkbox/code/KAMUI_OSC-CV_Example/
//   Robin Price's Homebrew midi-cv box
//   http://crx091081gb.net/?p=69
//   Masahiro Hattori's TextLCD Module Functions
//   http://www.eleclabo.com/denshi/device/lcd1602/gcram.html
//   Dirk-Willem van Gulik's BonjourLib
//   http://mbed.org/users/dirkx/code/BonjourLib/file/bb6472f455e8/services/mDNS
//
// Released under the MIT License: http://mbed.org/license/mit
//-------------------------------------------------------------

#pragma O3
#pragma Otime

#include "mbed.h"
#include "FastIO.h"
//#include "FastAnalogIn.h"
#include "DebouncedInterrupt.h"
#include "TextLCD.h"       //edit "writeCommand" "writeData" protected -> public
#include "EthernetNetIf.h"
#include "HTTPServer.h"
#include "mDNSResponder.h" // mDNS response to announce oneselve
#include "UDPSocket.h"
#include "OSCReceiver.h"
#include "mbedOSC.h"
#include "MIDI.h"
#include "OSCtoCV.h"
#include "OSCtoCV_Sequencer.h"
#include "OSCtoCV_GateSequencer.h"
#include "OSCtoCV_Euclidean.h"
#include "OSCtoCV_Random.h"
#include "OSCtoCV_LFO.h"

#include <stdlib.h>
#include <ctype.h>
#include <math.h>

//-------------------------------------------------------------
// Macros

#define MODE_Calb           0        // Calibration (for VCO Tuning)
#define MODE_OSC            1        // Mode OSCtoCV 
#define MODE_SEQ            2        // Mode Shift Sequencer
#define MODE_185            3        // Mode M185 Sequencer
#define MODE_EUC            4        // Mode Euclidean Sequencer
#define MODE_RND            5        // Mode xshift Random Generator 
#define MODE_LFO            6        // Mode Stepped LFO 

#define MODE_TOTAL          7        // Modes

//-------------------------------------------------------------
// Functions

void InitOSCCV(void);
inline void NetPoll(void);
void CalibrationCV(void);
inline void SetCV(void);
inline int CheckBPM(void);
void CheckModeSW(void);
inline void LCD();
void WriteCustomChar(unsigned char, unsigned char*);
int  SetupEthNetIf(void);
inline void onUDPSocketEvent(UDPSocketEvent);


//-------------------------------------------------------------
// Global Variables

// CV Meter Custom Character
unsigned char str1[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F};
unsigned char str2[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
unsigned char str3[8] = {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F};
unsigned char str4[8] = {0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F};
unsigned char str5[8] = {0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F};
unsigned char str6[8] = {0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
unsigned char str7[8] = {0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
unsigned char str8[8] = {0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};

// OSCtoCV Converter Mode 
int         gMode;

// UDP Socket
UDPSocket   gUdp;

//-------------------------------------------------------------
// main
 
int main() 
{ 
    float pot, _pot;
    int bpm;
        
    InitOSCCV();
    
    InitEuclideanSeq();         // Init Euclidean Sequencer
    
    gCtrl[3] = _pot = pot = gMode = 0;
    gGlide = gAIN.read();
        
    LCD();
    gLCD.locate( 0, 1 );
    gLCD.printf("12345678 G>>%3.2f", gGlide);
    
// Main loop
    while (1) 
    {   
        LCD(); // Check Text LCD
        
        pot = gAIN.read();  // Update glide value
        
        if (!pot) // when glide pot value == 0 
        {         // use gCtrl[3] value
            if (abs(gCtrl[3] - _pot) > 0.01f)
            {
                _pot = gGlide = gCtrl[3];
            
                gLCD.locate( 9, 1 );
                gLCD.printf("G>>%3.2f", gGlide);
            }
        
        } else if (abs(pot - _pot) > 0.01f) {
            
            _pot = gGlide =  gAIN.read();
            
            gLCD.locate( 9, 1 );
            gLCD.printf("G>>%3.2f", gGlide);
        }
        
        bpm = CheckBPM(); // check current BPM
        
        switch (gMode)
        {               
            case MODE_OSC: // OSCtoCV mode
            
                SetCV();
                break;
                
            case MODE_SEQ: // Shift Sequencer mode
            
                ShiftCVSeq(GateSeq(bpm, N16TH, GATE1, 3, NON_INVERT, GATESOUT_OFF, SYNC_ON), gCtrlSW[0]);
                GateSeq(bpm, N8TH, GATE2, 3, NON_INVERT, GATESOUT_ON, SYNC_OFF);
                
                if (gCtrlSW[3])
                {
                    EuclideanSeq(GateSeq(bpm, N16TH, SUBGATE, 1, NON_INVERT, GATESOUT_OFF, SYNC_OFF), gCtrlSW[0], GATESOUT_OFF);
                }
                break;
                
            case MODE_185: // M185 Sequencer mode
            
                M185Seq(GateSeq(bpm, N16TH, GATE1, 3, NON_INVERT, GATESOUT_OFF, SYNC_ON), gCtrlSW[0]);
                GateSeq(bpm, N8TH, GATE2, 3, NON_INVERT, GATESOUT_ON, SYNC_OFF);
                
                if (gCtrlSW[3])
                {
                    EuclideanSeq(GateSeq(bpm, N16TH, SUBGATE, 1, NON_INVERT, GATESOUT_OFF, SYNC_OFF), gCtrlSW[0], GATESOUT_OFF);
                }
                break;
                
            case MODE_EUC: // Euclidean Sequencer mode
            
                ShiftCVSeq(GateSeq(bpm, N1ST, SUBGATE, 3, NON_INVERT, GATESOUT_OFF, SYNC_OFF), gCtrlSW[0]); 
                EuclideanSeq(GateSeq(bpm, N16TH, GATE1, 1, NON_INVERT, GATESOUT_OFF, SYNC_OFF), gCtrlSW[0], GATESOUT_ON);
                break;
                
            case MODE_RND: // Random CV Generator mode
    
                RandomCVGenerator(GateSeq(bpm, N32TH, GATE1, 3, NON_INVERT, GATESOUT_OFF, SYNC_ON));
                break;

            case MODE_LFO: // Stepped LFO mode
    
                SteppedLFO();
                break;
                
            default:       // CV Calibration mode
                
                CalibrationCV(); 
                break;
        }
        
    }
}

//-------------------------------------------------------------
// Ethernet Polling

inline void NetPoll()
{
    Net::poll();
}

//-------------------------------------------------------------
// Initialize OSCtoCV

void InitOSCCV()
{
    int i;
    
//Clock Up --------------------------------------------------------------------
    LPC_SC->PLL0CON   = 0x00;             /* PLL0 Disable                    */
    LPC_SC->PLL0FEED  = 0xAA;
    LPC_SC->PLL0FEED  = 0x55;
 
    LPC_SC->CCLKCFG   = 0x00000003;       /* Select Clock Divisor = 4        */
    LPC_SC->PLL0CFG   = 0x00020038;       /* configure PLL0                  */
    LPC_SC->PLL0FEED  = 0xAA;             /* divide by 3 then multiply by 50 */
    LPC_SC->PLL0FEED  = 0x55;             /* PLL0 frequency = 400,000,000    */
 
    LPC_SC->PLL0CON   = 0x01;             /* PLL0 Enable                     */
    LPC_SC->PLL0FEED  = 0xAA;
    LPC_SC->PLL0FEED  = 0x55;
    while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0                 */
 
    LPC_SC->PLL0CON   = 0x03;             /* PLL0 Enable & Connect           */
    LPC_SC->PLL0FEED  = 0xAA;
    LPC_SC->PLL0FEED  = 0x55;
    while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24))));/* Wait for PLLC0_STAT & PLLE0_STAT */
    
    SystemCoreClockUpdate();
//-----------------------------------------------------------------------------
    
    wait(0.5);

// Setup Ethernet   
    SetupEthNetIf();

// Announce mdnsResponder  (Bonjour)
    HTTPServer svr;
    mDNSResponder mdns;
    
    svr.addHandler<SimpleHandler>("/");
    svr.bind(INPUT_PORT);
    IpAddr ip = gEth.getIp();
    mdns.announce(ip, "OSCtoCV", "_osc._udp", INPUT_PORT, "mbed(OSCtoCV)", (char *[]) {"path=/",NULL});
        
// Write custom char LCD CGRAM
    WriteCustomChar(0x00, str1);
    WriteCustomChar(0x01, str2);
    WriteCustomChar(0x02, str3);
    WriteCustomChar(0x03, str4);
    WriteCustomChar(0x04, str5);
    WriteCustomChar(0x05, str6);
    WriteCustomChar(0x06, str7);
    WriteCustomChar(0x07, str8);
    
// Init  SPI
    gLDAC = _ENABLE;
    gSPI.format(8,1);           // Data word length 8bit, Mode=1
    gSPI.frequency(SPI_RATE);
    
    UpdateCV(CLR, 0, 0);        // Ignore CLR Pin
     
// Init BPM
    gCtrl[0] = 0.398f;

// Init Sequence Data
    for (i = 0; i < 16; ++i) 
    {
        gSeq_cv[i] = calibMap1[69] * SCALING_N;
    }
    
// Init M185 Reset Count    
    gCtrl[4] = 1;
    
// Set OSC message for sending 
    sendMes.setIp(touchOSCAddress); 
    sendMes.setPort(touchOSCPort);
    
    gSW.attach(&CheckModeSW,IRQ_RISE, 30);     // InterruptIn rising edge(ModeSW)
    wait(0.5);
    
    gPoller.attach_us(&NetPoll, POLLING_INTERVAL);  // Ticker Polling
    wait(1.8);
}

//-------------------------------------------------------------
// Calibration Mode

void CalibrationCV()
{
    static int ch;
    unsigned int cv;

    switch (gMode) 
        {
            case MODE_Calb:
                
                cv = (unsigned int)(calibMap1[69] * SCALING_N);  // A880.0Hz
                
                gSUBGATE = gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = true;
                
                UpdateCV(WRITE_UPDATE_N, ch, &cv);
                
                break;
        }

        UpdateCVMeter(ch, &cv);
        
        ++ch;
        ch &= 0x07;
}

//-------------------------------------------------------------
// Calculate CV

inline void SetCV()
{
    static int ch, qmode, amode, mcount;
    static float glidecv[8];
    unsigned int cv;
    static float qcv;

    qmode = (gCtrl[1] * (SCALE_NUM - 1));
    amode = SCALE_AOUT * qmode;
    
    gAOUT.write_u16(amode);

    switch (qmode) 
        {
            case Lin:
                
                glidecv[ch] = glidecv[ch] * gGlide + gOSC_cv[ch] * (1.0f - gGlide);
                break;
                    
            case Chr:

                qcv = calibMap1[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES1 - 1))];
                    
                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);

                break;
                
            case Maj:

                qcv = calibMap2[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES2 - 1))];

                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);

                break;
            
            case M7:
                
                qcv = calibMap3[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES3 - 1))];
                    
                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);

                break;
                
            case Min7:

                qcv = calibMap4[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES4 - 1))];

                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);

                break;
                    
            case Dor:
                
                qcv = calibMap5[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES5 - 1))];

                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);

                break;
        
            case Min:
                
                qcv = calibMap6[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES6 - 1))];

                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);

                break;
                
            case S5th:

                qcv = calibMap7[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES7 - 1))];

                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);

                break;
                
            case Wht:
                
                qcv = calibMap8[(unsigned int)MapFloat(gOSC_cv[ch], 0, SCALING_N, 0, (QUAN_RES8 - 1))];

                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
                
                break;
        }
        
    cv = (unsigned int)glidecv[ch];
            
    UpdateCV(WRITE_UPDATE_N, ch, &cv);

    if (mcount == 0x1F) 
    {
        UpdateCVMeter(ch, &cv);
    }

    ++ch;
    
    if (ch &= 0x07)
    {
        ++mcount;
        mcount &= 0x3F;
    }
}


//-------------------------------------------------------------
// Check BPM

inline int CheckBPM()
{   
    static int _bpm = -1;
    int bpm;
    
    if (gCtrlSW[0]) 
    {
        bpm = 0;

        return bpm;
    }
    
    if (gCtrl[0]) {

        bpm = (gCtrl[0] * 240 + 5);

        if (abs(bpm - _bpm) > 1)
        {
            _bpm = bpm;
            
            sendMes.setTopAddress("/bpm");
            sendMes.setArgs("i", bpm);
            osc.sendOsc(&sendMes);
        }
    }
                        
    return bpm;
}

//-------------------------------------------------------------
// Check Mode SW

void CheckModeSW()
{   
    if (gMode < MODE_TOTAL - 1) 
    {   
        ++gMode;
            
    } else {
                
        gMode = 0;
    }
    
    gCLOCKOUT = gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = false;
    gSubModeCount1 = gSubModeCount2 = 0;
    
    if (gMode == MODE_SEQ || gMode == MODE_185 || gMode == MODE_EUC || gMode == MODE_RND || gMode == MODE_LFO)
    {
        gTimer.start();     // Sequencer Timer Start
        midi.begin(1);
        
    } else {
            
        gTimer.stop();      // Sequencer Timer Stop
    }
    
}

//-------------------------------------------------------------
// Print LCD Mode Status

inline void LCD()
{
    static int _mode = -1;
    static int _qmode = -1;
    static int qmode;
    
    if (_mode != gMode)
    {
        sendMes.setTopAddress("/mode");
        
        switch (gMode) 
            {
                case MODE_Calb: 
                    gLCD.locate( 9, 0 );
                    gLCD.printf("CLB|880");
                    
                    gLCD.locate( 0, 1 );
                    gLCD.printf("12345678 G>>%3.2f", gGlide);
                    
                    sendMes.setArgs("s", "Calibration");
                    osc.sendOsc(&sendMes);
                    
                    sendMes.setTopAddress("/scale");
                    sendMes.setArgs("s", "880Hz");
                    
                    _qmode = -1;
                    
                    break;
                
                case MODE_OSC:
                    gLCD.locate( 9, 0 );
                    gLCD.printf("OSC|");
                    
                    sendMes.setArgs("s", "OSCtoCV");
                    
                    break;

                case MODE_SEQ:  
                    gLCD.locate( 9, 0 );
                    gLCD.printf("ASR|");
                    
                    sendMes.setArgs("s", "ASR SEQ");
                    
                    break;
                    
                case MODE_185:  
                    gLCD.locate( 9, 0 );
                    gLCD.printf("185|");
            
                    sendMes.setArgs("s", "M185 SEQ");
            
                    break;
                        
                case MODE_EUC:  
                    gLCD.locate( 9, 0 );
                    gLCD.printf("EUC|");
                    
                    sendMes.setArgs("s", "Euclidean SEQ");
                    
                    break;
                    
                default:
                    break;
            }
            
            osc.sendOsc(&sendMes);
            _mode = gMode;
    }
    
    qmode = (gCtrl[1] * (SCALE_NUM - 1));
    
    if (_qmode != qmode)
    {
        sendMes.setTopAddress("/scale");
        
        switch (qmode) 
            {
                case Lin:
                    gLCD.locate( 13, 0 );
                    gLCD.printf("lin");

                    sendMes.setArgs("s", "Linear");

                    break;
                    
                case Chr:
                    gLCD.locate( 13, 0 );
                    gLCD.printf("chr");

                    sendMes.setArgs("s", "Chromatic");

                    break;
                
                case Maj:
                    gLCD.locate( 13, 0 );
                    gLCD.printf("maj");
                    
                    sendMes.setArgs("s", "Major");

                    break;
            
                case M7:
                    gLCD.locate( 13, 0 );
                    gLCD.printf("ma7");
                    
                    sendMes.setArgs("s", "Major7");

                    break;
                
                case Min7:
                    gLCD.locate( 13, 0 );
                    gLCD.printf("mi7");
                    
                    sendMes.setArgs("s", "Minor7");

                    break;
                    
                case Dor:
                    gLCD.locate( 13, 0 );
                    gLCD.printf("dor");
                    
                    sendMes.setArgs("s", "Dorian");

                    break;
        
                case Min:
                    gLCD.locate( 13, 0 );
                    gLCD.printf("min");
                    
                    sendMes.setTopAddress("/scale");
                    sendMes.setArgs("s", "Minor");

                    break;
                
                case S5th:
                    gLCD.locate( 13, 0 );
                    gLCD.printf("5th");
                    
                    sendMes.setArgs("s", "5th");

                    break;
                
                case Wht:
                    gLCD.locate( 13, 0 );
                    gLCD.printf("wht");
                    
                    sendMes.setArgs("s", "Whole Tone");
                    break;
                    
                default:
                    break;
            }
            
            osc.sendOsc(&sendMes);
            _qmode = qmode;
    }

}


//-------------------------------------------------------------
// Write command Custom Char LCD CGRAM for CV Meter)

void WriteCustomChar(unsigned char addr, unsigned char *c)
{   
    char cnt = 0;
    addr = ((addr << 3) | 0x40);
    
    while (cnt < 0x08)
    {
        gLCD.writeCommand(addr | cnt);
        gLCD.writeData(*c);
        
        ++cnt;
        ++c;
    }
}

//-------------------------------------------------------------
// Setup Ethernet port

int SetupEthNetIf()
{
    gLCD.locate( 0, 1 );
    gLCD.printf("Setting up...   ");
//  printf("Setting up...\r\n");
    EthernetErr ethErr = gEth.setup();
    
    if (ethErr)
    {
        gLCD.locate( 0, 1 );
        gLCD.printf("Error in setup.");
//  printf("Error %d in setup.\r\n", ethErr);
        return -1;
    }
//  printf("Setup OK\r\n");
 
//  printf("IP address %d.%d.%d.%d\r\n", gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], gEth.getIp()[3]);
    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(1.0);
    
    return 0;
}


//-------------------------------------------------------------
// Handller receive OSC UDP Packet

inline void onUDPSocketEvent(UDPSocketEvent e)
{
    static union OSCarg msg[10];
    static char buf[896] = {0};
    static int recvlen;
    static int num, len, offset;
    int messagepos = 0;
    bool bundleflag = false;
    
    Host host;
    
    switch (e)
    {
        case UDPSOCKET_READABLE: // The only event for now
        
        recvlen = gUdp.recvfrom(buf, 896, &host);  // packet length    
        
        if (recvlen <= 0)  break;
        
        if (!bundleflag && buf[0] == '#') // #bundle
        {
            messagepos += 16;     // skip #bundle & timetag
            recvlen -= 16;
            
            bundleflag = true;  
        }
        
        do {
                if (bundleflag)
                {
                    messagepos += 4;
                    recvlen -= 4;
                    
                    if (recvlen <= 8)
                    {
                        bundleflag = false;
                        break;
                    }
                }
                
                if (getOSCmsg(buf + messagepos, msg) == -1)  continue;
            
                len = strlength(msg[0].address);
        
                if (isdigit(msg[0].address[len-1])) 
                {       
                    num = msg[0].address[len-1] - '0' - 1;
                    
                    offset = 1;
                    
                    if (isdigit(msg[0].address[len-2])) 
                    {
                        offset = 2;
                        num += 10;
                    }
                        
                } else {
            
                    num = -1;
                }
        
            // address pattern SYNC & GATE (Type Tag int, float)
                if (!strncmp(msg[0].address + (len - offset) - 4, "sync", 4)) 
                { 
                    if (msg[2].i != 0) gCLOCKOUT = true;
                    else              gCLOCKOUT = false;
                    continue;

                } else if (!strncmp(msg[0].address + (len - offset) - 4, "gate", 4) && (num != -1)) {
                    if (num > 3) continue;
                    if (msg[2].i != 0) gGATES[num] = true;
                    else              gGATES[num] = false;
                    continue;
            // (touchOSC Control push, toggle)
                } else if (!strncmp(msg[0].address + (len - offset) - 5, "fader", 5) && (num != -1)) {
                    if (num > 7) continue;                                              
                    gOSC_cv[num] = msg[2].f * (SCALING_N);
                    continue;

                } else if (!strncmp(msg[0].address + (len - offset) - 9, "multixy1/", 9) && (num != -1)) {
                    if (num > 7) continue;
                    if (msg[1].typeTag[1] == 'f') gOSC_cv[num] = msg[2].f * (SCALING_N);
                    if (msg[1].typeTag[1] == 'f') gOSC_cv[++num] = msg[3].f * (SCALING_N);
                    continue;
    
                } else if (!strncmp(msg[0].address + (len - offset) -12, "multifader1/", 12) && (num != -1)) {
                    if (num > 7) continue;
                    if (msg[1].typeTag[1] == 'f') gOSC_cv[num] = msg[2].f * (SCALING_N);
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset) -10, "sequencer/", 10) && (num != -1)) {
                    if (num > 15) continue;
                    gSeq_cv[num] = msg[2].f * (SCALING_N);
                    continue;
                            
                } else if (!strncmp(msg[0].address + (len - offset) - 6, "ctrlsw", 6) && (num != -1)) {
                    if (num > 7) continue;
                    if (msg[2].i != 0) gCtrlSW[num] = true;
                    else              gCtrlSW[num] = false;
                    continue;
                                                
                } else if (!strncmp(msg[0].address + (len - offset) - 4, "ctrl", 4) && (num != -1)) {
                    if (num > 7) continue;                                             
                    gCtrl[num] = msg[2].f;
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset) - 9, "pulsecnt/", 9) && (num != -1)) {
                    if (num > 7) continue;
                    gPulseCount[num] = msg[2].f;
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset) - 9, "gatemode/", 9) && (num != -1)) {
                    if (num > 15) continue;
                    gGateMode[num] = msg[2].f;
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset) - 6, "slide/", 6) && (num != -1)) {
                    if (num > 15) continue;
                    gSlide[num] = msg[2].f;
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset-2) - 7, "accent/", 7) && (num != -1)) {
                    
                    if (isdigit(msg[0].address[len-3])) 
                    {       
                        num = msg[0].address[len-3] - '0' - 1;
                    }
                    
                    gAccent[num] = msg[2].i;
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset-3) - 7, "accent/", 7) && (num != -1)) {
                    
                    if (isdigit(msg[0].address[len-3])) 
                    {       
                        num = msg[0].address[len-3] - '0' - 1;
                        
                        if (isdigit(msg[0].address[len-4])) 
                        {
                            num += 10;
                        }
                    }
                    
                    gAccent[num] = msg[2].i;
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset) - 4, "euca", 4) && (num != -1)) {
                    if (num > 5) continue;                                             
                    gEucA[num] = msg[2].f;
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset) - 4, "eucb", 4) && (num != -1)) {
                    if (num > 5) continue;                                             
                    gEucB[num] = msg[2].f;
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset) - 3, "acv", 3) && (num != -1)) {
                    if (num > 3) continue;                                             
                    gArdCV[num] = msg[2].f * (SCALING_N);
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset) - 3, "pot", 3) && (num != -1)) {
                    if (num > 1) continue;                                             
                    gArdPot[num] = msg[2].f;
                    continue;
                    
                } else if (!strncmp(msg[0].address + (len - offset) - 2, "sw", 2) && (num != -1)) {
                    if (num > 1) continue;
                    if (msg[2].i != 0) gArdSW[num] = true;
                    else               gArdSW[num] = false;                                       
                    continue;
                    
                } else {
                    continue;
                }
                
            } while (bundleflag);                   
    }
}