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

Files at this revision

API Documentation at this revision

Comitter:
casiotone401
Date:
Sun Aug 02 10:01:07 2015 +0000
Parent:
14:977f3c5a4b4e
Child:
16:1196b8c87bb7
Commit message:
ver. 2

Changed in this revision

BurstSPI.lib Show annotated file Show diff for this revision Revisions of this file
DebouncedInterrupt.lib Show annotated file Show diff for this revision Revisions of this file
FastIO.lib Show annotated file Show diff for this revision Revisions of this file
MIDI.lib Show annotated file Show diff for this revision Revisions of this file
OSC.lib Show annotated file Show diff for this revision Revisions of this file
example.h Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rpc.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BurstSPI.lib	Sun Aug 02 10:01:07 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/Sissors/code/BurstSPI/#bc069279eb37
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DebouncedInterrupt.lib	Sun Aug 02 10:01:07 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/kandangath/code/DebouncedInterrupt/#9733f886810a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/FastIO.lib	Sun Aug 02 10:01:07 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/Sissors/code/FastIO/#87872fcf8586
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MIDI.lib	Sun Aug 02 10:01:07 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/okini3939/code/MIDI/#0eeca7deec08
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/OSC.lib	Sun Aug 02 10:01:07 2015 +0000
@@ -0,0 +1,1 @@
+https://developer.mbed.org/users/casiotone401/code/OSC/#507dea4cc97a
--- a/example.h	Thu Oct 16 14:14:25 2014 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,675 +0,0 @@
-//-------------------------------------------------------------
-//                  TI DAC8568  OSC-CV 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 "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 <stdlib.h>
-#include <ctype.h>
-#include <math.h>
-
-//-------------------------------------------------------------
-// Define
-
-#define MODE_LIN            0       // Linear       ~LinearCV Mode
-#define MODE_QChr           1       // Chromatic    ~Quantize Mode 
-#define MODE_QMaj           2       // Major
-#define MODE_QDor           3       // Dorian
-#define MODE_Q5th           4       // 5th
-#define MODE_QWht           5       // Wholetone
-#define MODE_Calb           6       // Calibration
-
-#define QUAN_RES1           116     // Quantize voltage Steps
-#define QUAN_RES2           69
-#define QUAN_RES3           68  
-#define QUAN_RES4           17
-#define QUAN_RES5           58
-
-#define MODE_NUM            7        // Modes
-
-#define SPI_RATE            40000000 // 40Mbps SPI Clock
-#define SCALING_N           38400.0
-#define INPUT_PORT          12345    // Input Port Number
-
-#define POLLING_INTERVAL    20       // Polling Interval (us)
-
-//-------------------------------------------------------------
-// DAC8568 Control Bits
-
-#define WRITE               0x00
-#define UPDATE              0x01
-#define WRITE_UPDATE_ALL    0x02       // LDAC Write to Selected Update All
-#define WRITE_UPDATE_N      0x03       // LDAC Write to Selected Update Respective
-#define POWER               0x04
-#define CLR                 0x05       // Clear Code Register
-#define WRITE_LDAC_REG      0x06
-#define RESET               0x07       // Software Reset DAC8568
-#define SETUP_INTERNAL_REF  0x08
-
-//------------------------------------------------------------- 
-
-#define _DISABLE            0
-#define _ENABLE             1
-
-//-------------------------------------------------------------
-// Functions
-
-inline void NetPoll(void);
-void InitOSCCV(void);
-inline void UpdateCV(int, int, const unsigned int*);
-void SetCV(void);
-void CheckSW(void);
-void CVMeter(int, const unsigned int*);
-void WriteCustomChar(unsigned char, unsigned char*);
-int  SetupEthNetIf(void);
-void onUDPSocketEvent(UDPSocketEvent);
-
-//-------------------------------------------------------------
-// Silentway Calibration Data Mapping
-// http://www.expert-sleepers.co.uk/silentway.html
-
-//  Chromatic Scale
-const float calibMap1[QUAN_RES1] = {
-0.00663080,   0.01433030,   0.02202980,   0.02972930,   0.03742880,
-0.04512830,   0.05282781,   0.06052731,   0.06822681,   0.07592630,
-0.08362581,   0.09132531,   0.09902481,   0.10672431,   0.11442380,
-0.12212331,   0.12951356,   0.13671936,   0.14392516,   0.15113096,
-0.15833676,   0.16554256,   0.17274836,   0.17995416,   0.18715996,
-0.19436575,   0.20157155,   0.20877735,   0.21598317,   0.22318897,
-0.23039477,   0.23760056,   0.24480636,   0.25202271,   0.25926629,
-0.26650983,   0.27375340,   0.28099698,   0.28824055,   0.29548413,
-0.30272770,   0.30997124,   0.31721482,   0.32445839,   0.33170196,
-0.33894554,   0.34618911,   0.35343266,   0.36067623,   0.36791980,
-0.37516347,   0.38241133,   0.38965923,   0.39690709,   0.40415496,
-0.41140282,   0.41865072,   0.42589858,   0.43314645,   0.44039431,
-0.44764221,   0.45489007,   0.46213794,   0.46938580,   0.47663370,
-0.48388156,   0.49112943,   0.49837729,   0.50566339,   0.51296055,
-0.52025765,   0.52755481,   0.53485191,   0.54214907,   0.54944617,
-0.55674326,   0.56404042,   0.57133752,   0.57863468,   0.58593178,
-0.59322894,   0.60052603,   0.60782319,   0.61512029,   0.62241745,
-0.62976688,   0.63714498,   0.64452308,   0.65190119,   0.65927929,
-0.66665739,   0.67403549,   0.68141359,   0.68879169,   0.69616979,
-0.70354789,   0.71092600,   0.71830410,   0.72568226,   0.73306036,
-0.74043846,   0.74781656,   0.75820577,   0.76986063,   0.78151548,
-0.79317033,   0.80482519,   0.81648004,   0.82813489,   0.83978975,
-0.85144460,   0.86309946,   0.87475431,   0.90686423,   0.93941462,
-0.97196496
-};
-
-//  Major Scale
-const float calibMap2[QUAN_RES2] = {
-0.00663080,   0.01433030,   0.02972930,   0.04512830,   0.05282781,
-0.06822681,   0.08362581,   0.09902481,   0.10672431,   0.12212331,
-0.13671936,   0.14392516,   0.15833676,   0.17274836,   0.18715996,
-0.19436575,   0.20877735,   0.22318897,   0.23039477,   0.24480636,
-0.25926629,   0.27375340,   0.28099698,   0.29548413,   0.30997124,
-0.31721482,   0.33170196,   0.34618911,   0.36067623,   0.36791980,
-0.38241133,   0.39690709,   0.40415496,   0.41865072,   0.43314645,
-0.44764221,   0.45489007,   0.46938580,   0.48388156,   0.49112943,
-0.50566339,   0.52025765,   0.53485191,   0.54214907,   0.55674326,
-0.57133752,   0.57863468,   0.59322894,   0.60782319,   0.62241745,
-0.62976688,   0.64452308,   0.65927929,   0.66665739,   0.68141359,
-0.69616979,   0.71092600,   0.71830410,   0.73306036,   0.74781656,
-0.75820577,   0.78151548,   0.80482519,   0.82813489,   0.83978975,
-0.86309946,   0.90686423,   0.93941462
-};
-
-//  Dorian Scale
-const float calibMap3[QUAN_RES3] = {
-0.00663080,   0.01433030,   0.02972930,   0.04512830,   0.06052731,
-0.06822681,   0.08362581,   0.09902481,   0.10672431,   0.12212331,
-0.13671936,   0.15113096,   0.15833676,   0.17274836,   0.18715996,
-0.19436575,   0.20877735,   0.22318897,   0.23760056,   0.24480636,
-0.25926629,   0.27375340,   0.28099698,   0.29548413,   0.30997124,
-0.32445839,   0.33170196,   0.34618911,   0.36067623,   0.36791980,
-0.38241133,   0.39690709,   0.41140282,   0.41865072,   0.43314645,
-0.44764221,   0.45489007,   0.46938580,   0.48388156,   0.49837729,
-0.50566339,   0.52025765,   0.53485191,   0.54214907,   0.55674326,
-0.57133752,   0.58593178,   0.59322894,   0.60782319,   0.62241745,
-0.62976688,   0.64452308,   0.65927929,   0.67403549,   0.68141359,
-0.69616979,   0.71092600,   0.71830410,   0.73306036,   0.74781656,
-0.76986063,   0.78151548,   0.80482519,   0.82813489,   0.83978975,
-0.86309946,   0.90686423,   0.97196496
-};
-
-//  5th
-const float calibMap4[QUAN_RES4] = {
-0.00663080,   0.06052731,    0.11442380,   0.16554256,   0.21598317,
-0.26650983,   0.31721482,    0.36791980,   0.41865072,   0.46938580,
-0.52025765,   0.57133752,    0.62241745,   0.67403549,   0.72568226,
-0.79317033,   0.87475431
-
-};
-
-//  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,
-0.15833676,    0.17274836,    0.18715996,    0.20157155,    0.21598317,
-0.23039477,    0.24480636,    0.25926629,    0.27375340,    0.28824055,
-0.30272770,    0.31721482,    0.33170196,    0.34618911,    0.36067623,
-0.37516347,    0.38965923,    0.40415496,    0.41865072,    0.43314645,
-0.44764221,    0.46213794,    0.47663370,    0.49112943,    0.50566339,
-0.52025765,    0.53485191,    0.54944617,    0.56404042,    0.57863468,
-0.59322894,    0.60782319,    0.62241745,    0.63714498,    0.65190119,
-0.66665739,    0.68141359,    0.69616979,    0.71092600,    0.72568226,
-0.74043846,    0.75820577,    0.78151548,    0.80482519,    0.82813489,
-0.85144460,    0.87475431,    0.93941462
-    
-};
-
-//-------------------------------------------------------------
-// CV Meter Custom Character
-
-const unsigned char str1[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F};
-const unsigned char str2[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
-const unsigned char str3[8] = {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F};
-const unsigned char str4[8] = {0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F};
-const unsigned char str5[8] = {0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F};
-const unsigned char str6[8] = {0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
-const unsigned char str7[8] = {0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
-const unsigned char str8[8] = {0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
-
-//-------------------------------------------------------------
-// Global Variables
-
-static float    gOSC_cv[8];
-static float    gGlide;
-unsigned int    gMode;
-
-//-------------------------------------------------------------
-// mbed Functions
-
-TextLCD gLCD(p9, p10, p11, p12, p13, p14); // rs, e, d4-d7
-
-SPI         gSPI(p5,p6,p7);     // SPI (p6 unconnected)
-DigitalOut  gSYNCMODE(p15);     // SYNC DAC8568
-DigitalOut  gLDAC(p16);         // LDAC DAC8568
-
-DigitalOut  gGATES[4] = {p21, p22, p23, p24};   // GateOut
-DigitalOut  gLEDS[4] = {p18, p19, p20, p28};    // LED
-DigitalOut  gCLOCKOUT(p25);             // ClockOut
-
-AnalogIn    gAIN(p17);  // Glide Potentiometer
-InterruptIn gSW(p30);   // Mode SW
-
-Ticker      gSetter;    // Ticker SetCV
-Ticker      gPoller;    // Ticker Polling
-
-// Ethernet
-EthernetNetIf   gEth;
-UDPSocket       gUdp;
-
-//-------------------------------------------------------------
-// main
- 
-int main() 
-{ 
-    int i;
-    float pot, _pot;
-    
-    if(SetupEthNetIf() == -1)
-    {
-        for(i = 0; i < 4; i++) 
-        {
-            gLEDS[i] = 1;
-            wait(0.25);
-        }
-        return -1;
-    }
-    
-    // mdns (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});
-    
-    InitOSCCV();
-    
-    pot = _pot = 0;
-    gGlide = gMode = 0;
-        
-    gLCD.locate( 9, 0 );
-    gLCD.printf("OSC-CV");
-    gLCD.locate( 0, 1 );
-    gLCD.printf("12345678 G>>%3.2f", gGlide);
-    
-    // loop
-    while(1) 
-    {
-        gGlide = pot = gAIN.read();
-        
-        if(abs(pot - _pot) > 0.01f) 
-        {
-            gLCD.locate( 0, 1 );
-            gLCD.printf("12345678 G>>%3.2f", gGlide);
-            
-            _pot = gAIN.read();
-        }
-        
-        SetCV();
-    }
-}
-
-//-------------------------------------------------------------
-// Ethernet Polling
-
-inline void NetPoll()
-{
-    Net::poll();
-}
-
-//-------------------------------------------------------------
-// Initialize OSC-CV
-
-void InitOSCCV()
-{
-    // 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
-    
-    gSW.mode(PullUp);       // Use internal pullup for ModeSW
-    wait(.001);
-    
-    gSW.rise(&CheckSW);     // InterruptIn rising edge(ModeSW)
-    gPoller.attach_us(&NetPoll, POLLING_INTERVAL);  // Ticker Polling
-    
-    wait(0.2);
-}
-
-//-------------------------------------------------------------
-// SPI Transfer
-// DAC8568 data word length 32bit (8bit shift out)
-
-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);
-            gSYNCMODE = _ENABLE;
-            gLDAC = _DISABLE;
-            gLDAC = _ENABLE;
-            break;
-        }
-        case RESET:
-        {   
-            gSYNCMODE = _DISABLE;
-            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(00000000);
-            gSPI.write(00000000);
-            gSPI.write(00000011);   // Ignore CLR Pin
-            gSYNCMODE = _ENABLE;
-            break;
-        }
-    }
-    
-    __enable_irq();
-}
-
-//-------------------------------------------------------------
-// Calculate CV
-
-void SetCV()
-{
-    static int ch;
-    float glidecv[8];
-    unsigned int cv[8];
-    static float oldcv[8];
-    static unsigned int quan;
-    float qcv;
-
-    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]);
-                break;
-                    
-            case MODE_QChr:
-            
-                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]);
-                break;
-                    
-            case MODE_QDor:
-                
-                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]);
-                break;
-                
-            case MODE_Q5th:
-                
-                quan = 40616 / 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]);
-                break;
-                
-            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_Calb:
-                
-                cv[ch] = 19212;     // A440.0Hz
-                        
-                UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
-                break;
-        }
-
-        CVMeter(ch, &cv[ch]);
-        ch++;
-        ch &= 0x07;
-}
-
-//-------------------------------------------------------------
-// Check SW
-
-void CheckSW()
-{   
-    if(gMode < MODE_NUM - 1) 
-    {   
-        gMode++;
-            
-    } else {
-                
-        gMode = 0;
-    }
-    
-    switch(gMode) 
-        {
-            case MODE_LIN:
-                gLCD.locate( 9, 0 );
-                gLCD.printf("OSC-CV ");
-                break;
-                    
-            case MODE_QChr:
-                gLCD.locate( 9, 0 );
-                gLCD.printf("QUAN_C ");
-                break;
-                
-            case MODE_QMaj: 
-                gLCD.locate( 9, 0 );
-                gLCD.printf("QUAN_M ");
-                break;
-                    
-            case MODE_QDor: 
-                gLCD.locate( 9, 0 );
-                gLCD.printf("QUAN_D ");
-                break;
-                
-            case MODE_Q5th: 
-                gLCD.locate( 9, 0 );
-                gLCD.printf("QUAN_5 "); 
-                break;
-                    
-            case MODE_QWht: 
-                gLCD.locate( 9, 0 );
-                gLCD.printf("QUAN_W "); 
-                break;
-                
-            case MODE_Calb: 
-                gLCD.locate( 9, 0 );
-                gLCD.printf("Calibr "); 
-                break;
-        }
-}
-
-//-------------------------------------------------------------
-// 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
-}
-
-//-------------------------------------------------------------
-// Write command Custom Char LCD CGRAM(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(2.0);
-    
-    return 0;
-}
-
-//-------------------------------------------------------------
-// Handller receive UDP Packet
-
-void onUDPSocketEvent(UDPSocketEvent e)
-{
-    union OSCarg msg[10];
-    static int num;
-    
-    switch(e)
-    {
-        case UDPSOCKET_READABLE: // The only event for now
-        char buf[256] = {0};
-        Host host;
-            
-        while( int len = gUdp.recvfrom( buf, 256, &host ))
-        {
-            if(len <= 0)  break;
-            //  printf("\r\nFrom %d.%d.%d.%d:\r\n", 
-            //  host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]);
-            
-            getOSCmsg(buf,msg);
-            //  printf("OSCmsg: %s %s %f %i\r\n", 
-            //  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;
-            
-            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)) { 
-                if(num > 1) break;
-                if(absv >= 1 || msg[2].i >= 1) gCLOCKOUT = 1;
-                else                           gCLOCKOUT = 0;
-                break;
-    
-                } else if ((strncmp(msg[0].address+(len-1)-4, "gate", 4)==0) && (num != -1)) {
-                    if(num > 3) break;
-                    if(absv >= 1 || msg[2].i >= 1) gLEDS[num] = gGATES[num] = 1;
-                    else                           gLEDS[num] = gGATES[num] = 0;
-                    break;
-                    // (touchOSC Control push, toggle)
-                    } else if ((strncmp(msg[0].address+(len-1)-4, "push", 4)==0) && (num != -1)) {     
-                        if(num > 3) break;
-                        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+(len-1)-6, "toggle", 6)==0) && (num != -1)) {
-                            if(num > 3) break;
-                            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;
-                                else                           gLEDS[num] = gGATES[num] = 0;
-                                break;
-                            }
-
-                        // address pattern CV (Type Tag float)
-                            if((strncmp(msg[0].address+(len-1)-2, "cv", 2)==0) && (num != -1)) {
-                                if(num > 7) break;
-                                if(msg[1].typeTag[1] == 'f') gOSC_cv[num] = msg[2].f * (SCALING_N);
-                                break;
-                            // (touchOSC Control fader, rotary, xy, multixy, multifader)
-                                } else if ((strncmp(msg[0].address+(len-1)-5, "fader", 5)==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)-6, "rotary", 6)==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)-2, "xy", 2)==0) && (num != -1)) {
-                                            if(num > 7) break;
-                                            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);
-                                            break;
-                            
-                                            } else if ((strncmp(msg[0].address+(len-1)-9, "multixy1/", 9)==0) && (num != -1)) {
-                                                if(num > 7) break;
-                                                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);
-                                                break;
-                                
-                                                } 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);
-                                                }
-                                            }
-                                        }                           
-                                    }
--- a/main.cpp	Thu Oct 16 14:14:25 2014 +0000
+++ b/main.cpp	Sun Aug 02 10:01:07 2015 +0000
@@ -1,5 +1,7 @@
 //-------------------------------------------------------------
-//                  TI DAC8568  OSC-CV Converter
+//                  OSCtoCV Converter
+//   Schematic, touchOSC template & VST Plug-in 
+//   http://gtbts.tumblr.com/post/125663817741/osc-to-cv-converter-ver2-mbed-osctocv
 //
 //   DAC8568 16bit Octal DAC http://www.ti.com/product/dac8568
 //
@@ -14,6 +16,9 @@
 //   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
+//   ADDAC System & sneak-thief's Euclidean Polyrhythm generator
+//   https://github.com/addacsystem/ADDAC-Library
+//   https://www.muffwiggler.com/forum/viewtopic.php?p=1451228#1451228
 //
 // Released under the MIT License: http://mbed.org/license/mit
 //-------------------------------------------------------------
@@ -22,12 +27,17 @@
 #pragma Otime
 
 #include "mbed.h"
+#include "FastIO.h"
+#include "DebouncedInterrupt.h"
+#include "BurstSPI.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 <stdlib.h>
 #include <ctype.h>
 #include <math.h>
@@ -36,10 +46,12 @@
 // Define
 
 #define MODE_Calb           0        // Calibration (for VCO Tuning)
-#define MODE_LIN            1        // Linear LinearCV
-#define MODE_SEQ            2        // Mode Shift
-
-#define MODE_NUM            3        // Modes
+#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_TOTAL          5        // Modes
 
 #define Lin                 0        // Linear LinearCV
 #define Chr                 1        // Chromatic
@@ -51,17 +63,20 @@
 #define S5th                7        // 5th
 #define Wht                 8        // Wholetone
 
-#define QUAN_RES1           115      // Quantize voltage Steps
-#define QUAN_RES2           67
-#define QUAN_RES3           39
-#define QUAN_RES4           48
-#define QUAN_RES5           67
-#define QUAN_RES6           67  
-#define QUAN_RES7           17
-#define QUAN_RES8           57
-
-#define SPI_RATE            20000000 // 20Mbps SPI Clock
-#define SCALING_N           38400.0
+#define SCALE_NUM           9        // Count Scale
+#define SCALE_AOUT          (65535 / SCALE_NUM - 1)
+
+#define QUAN_RES1           116      // Quantize voltage Steps
+#define QUAN_RES2           68
+#define QUAN_RES3           46
+#define QUAN_RES4           40
+#define QUAN_RES5           68
+#define QUAN_RES6           68  
+#define QUAN_RES7           16
+#define QUAN_RES8           58
+
+#define SPI_RATE            20000000 // 10Mbps SPI Clock
+#define SCALING_N           32256.0f
 #define INPUT_PORT          12345    // Input Port Number
 
 #define POLLING_INTERVAL    20       // Polling Interval (us)
@@ -80,6 +95,7 @@
 #define SETUP_INTERNAL_REF  0x08
 
 //------------------------------------------------------------- 
+// Gate Sequencer Macros
 
 #define _DISABLE            0
 #define _ENABLE             1
@@ -88,7 +104,17 @@
 #define GATE2               1
 #define GATE3               2
 #define GATE4               3
-#define GATEALL             4
+#define SUBGATE             4
+#define GATE_TOTAL          5
+
+#define INVERT              1
+#define NON_INVERT          0
+
+#define GATESOUT_ON         0
+#define GATESOUT_OFF        1
+
+#define SYNC_ON             0
+#define SYNC_OFF            1
 
 //------------------------------------------------------------- 
 // Beats (Note values)
@@ -97,174 +123,217 @@
 #define N2ND                2   // harf
 #define N4TH                4   // quarter
 #define N8TH                8
-#define N16TH               16
-#define N32TH               32
-#define N64TH               64
+#define N16TH              16
+#define N32TH              32
+#define N64TH              64
 #define NDOT2               3   // dotted
 #define NDOT4               7
 #define NDOT8               9
-#define NDOT16              11
-#define NDOT32              13
-#define TRIP2               15  // triplets
-#define TRIP4               17
-#define TRIP8               19
-#define TRIP16              21
-#define TRIP32              23
+#define NDOT16             11
+#define NDOT32             13
+#define TRIP2               3   // triplets
+#define TRIP4               6
+#define TRIP8              12
+#define TRIP16             24
+#define TRIP32             48
+#define SYNC24             96
 #define NRESET              0   // Gate Reset
 
+//------------------------------------------------------------- 
+// Sequencer Macros
+
+#define STEP_INDICATOR_ADDRESS "/seqstep/"   // touchOSC multi toggle(1x16(8)) for Current Step Indicator
+#define RESET_COUNTER_ADDRESS  "/reset"      // touchOSC label for Sequencer reset count                 
+
+//------------------------------------------------------------- 
+// M185 Macros
+
+#define PULSE_COUNT_ADDRESS    "/pulse"      // /pulse1 ~ pulse8        M185 Pulse Count
+#define GATE_MODE_ADDRESS      "/gatemode"   // /gatemode1 ~ gatemode8  M185 Gate Mode
+
+#define SINGLE              0
+#define MUTE                1
+#define MULTI               2
+#define HOLD                3
+
+//------------------------------------------------------------- 
+// Euclidean Sequencer Macros
+
+#define READ_DELAY         10 // for debouncing 
+#define MAXCHANNELS         4
+#define MAXSTEPS           16 // max step length
+#define TRIGGER_DURATION 2200
+
+#define DISPLAY_UPDATE   2000 // how long active channel display is shown
+#define MATRIX_ADDRESS   "/matrix/" // touchOSC multi toggle(9x16) OSC address
+
+
 //-------------------------------------------------------------
 // Functions
 
+void InitOSCCV(void);
 inline void NetPoll(void);
-void InitOSCCV(void);
+inline float MapFloat(float, float, float, float, float);
 inline void UpdateCV(int, int, const unsigned int*);
-inline void CalibCV(void);
-inline void SetSCV(void);
-inline void SeqCV(int);
-inline void Seq(void);
-inline int UpdateGate(int, int, int, int, bool);
-inline void UpdateSync(int, int, bool);
-void CheckModeSW(void);
-inline void CVMeter(int, const unsigned int*);
-void LCD();
+inline void CalibrationCV(void);
+inline void SetCV(void);
+inline void ShiftCVSeq(int, bool);
+inline void M185Seq(int, bool);
+inline void SendCtrlState(uint8_t, uint8_t, uint8_t);
+inline int GateSeq(int, int, int, int, bool, bool, bool);
+inline int CheckBPM(void);
+inline void CheckModeSW(void);
+inline void LCD();
+inline void UpdateCVMeter(int, const unsigned int*);
 void WriteCustomChar(unsigned char, unsigned char*);
 int  SetupEthNetIf(void);
 inline size_t strlength(const char *);
 inline void onUDPSocketEvent(UDPSocketEvent);
+void EuclideanSeq(int, bool, bool);
+unsigned int Euclid(int, int, int);
+inline int BitRead(uint16_t, int);
+uint16_t BitReadOffset(int, uint16_t, uint16_t); 
+unsigned int ConcatBin(unsigned int, unsigned int);
+void Sync(int, bool);
+int EncodeReadN(int);
+int EncodeReadK(int);
+int EncodeReadO(int);
+inline char * SetMatrixAddress(int, int, bool);
 
 //-------------------------------------------------------------
 // Silentway Calibration Data Mapping
 // http://www.expert-sleepers.co.uk/silentway.html
 
-// Chromatic Scale
+//  Chromatic Scale
 const float calibMap1[QUAN_RES1] = {
-0.00331362,   0.01097947,   0.01864531,   0.02631116,   0.03397701, 
-0.04164285,   0.04930869,   0.05697454,   0.06464039,   0.07230624, 
-0.07997208,   0.08763793,   0.09530377,   0.10296962,   0.11063547, 
-0.11830132,   0.12590303,   0.13306051,   0.14021800,   0.14737549, 
-0.15453300,   0.16169049,   0.16884798,   0.17600547,   0.18316296, 
-0.19032045,   0.19747795,   0.20463544,   0.21179293,   0.21895042, 
-0.22610791,   0.23326540,   0.24042290,   0.24758039,   0.25476459, 
-0.26196238,   0.26916021,   0.27635801,   0.28355584,   0.29075363, 
-0.29795146,   0.30514926,   0.31234708,   0.31954488,   0.32674271, 
-0.33394051,   0.34113833,   0.34833613,   0.35553396,   0.36273175, 
-0.36992958,   0.37713069,   0.38433966,   0.39154866,   0.39875764, 
-0.40596664,   0.41317561,   0.42038459,   0.42759359,   0.43480256, 
-0.44201156,   0.44922054,   0.45642951,   0.46363851,   0.47084749, 
-0.47805649,   0.48526546,   0.49247447,   0.49968344,   0.50694764, 
-0.51421440,   0.52148110,   0.52874786,   0.53601462,   0.54328132, 
-0.55054808,   0.55781484,   0.56508154,   0.57234830,   0.57961506, 
-0.58688176,   0.59414852,   0.60141528,   0.60868198,   0.61594874, 
-0.62321550,   0.63052768,   0.63785475,   0.64518178,   0.65250880, 
-0.65983582,   0.66716284,   0.67448992,   0.68181694,   0.68914396, 
-0.69647098,   0.70379800,   0.71112502,   0.71845210,   0.72577912, 
-0.73310614,   0.74043316,   0.74776018,   0.75861782,   0.77102989, 
-0.78344196,   0.79585397,   0.80826604,   0.82067811,   0.83309019, 
-0.84550226,   0.85791427,   0.87032634,   0.90296346,   0.94781560
+0.00076928,   0.00900736,   0.01724544,   0.02548352,   0.03372160,
+0.04195968,   0.05019776,   0.05843584,   0.06667392,   0.07491200,
+0.08315008,   0.09138816,   0.09962624,   0.10786432,   0.11610240,
+0.12434047,   0.13258974,   0.14083999,   0.14909023,   0.15734047,
+0.16559070,   0.17384095,   0.18209119,   0.19034143,   0.19859168,
+0.20684192,   0.21509215,   0.22334240,   0.23159264,   0.23984288,
+0.24809311,   0.25634655,   0.26460093,   0.27285531,   0.28110969,
+0.28936407,   0.29761845,   0.30587283,   0.31412721,   0.32238159,
+0.33063596,   0.33889034,   0.34714472,   0.35539910,   0.36365348,
+0.37190786,   0.38017464,   0.38844886,   0.39672306,   0.40499726,
+0.41327149,   0.42154568,   0.42981988,   0.43809411,   0.44636831,
+0.45464250,   0.46291673,   0.47119093,   0.47946513,   0.48773935,
+0.49601355,   0.50430328,   0.51260746,   0.52091163,   0.52921581,
+0.53751999,   0.54582411,   0.55412829,   0.56243247,   0.57073665,
+0.57904083,   0.58734500,   0.59564912,   0.60395330,   0.61225748,
+0.62056166,   0.62890279,   0.63728637,   0.64566994,   0.65405351,
+0.66243708,   0.67082065,   0.67920423,   0.68758780,   0.69597137,
+0.70435494,   0.71273851,   0.72112209,   0.72950566,   0.73788923,
+0.74627280,   0.75476575,   0.76334614,   0.77192658,   0.78050703,
+0.78908741,   0.79766786,   0.80624831,   0.81482869,   0.82340914,
+0.83198959,   0.84056997,   0.84915042,   0.85773087,   0.86631125,
+0.87489170,   0.88425636,   0.89363104,   0.90300572,   0.91238040,
+0.92175508,   0.93112975,   0.94050443,   0.94987911,   0.95925385,
+0.96862853
 };
 
 //  Major Scale
 const float calibMap2[QUAN_RES2] = {
-0.01097947,   0.02631116,   0.03397701,   0.04930869,   0.06464039,
-0.07997208,   0.08763793,   0.10296962,   0.11830132,   0.12590303,
-0.14021800,   0.15453300,   0.16884798,   0.17600547,   0.19032045,
-0.20463544,   0.21179293,   0.22610791,   0.24042290,   0.25476459,
-0.26196238,   0.27635801,   0.29075363,   0.29795146,   0.31234708,
-0.32674271,   0.34113833,   0.34833613,   0.36273175,   0.37713069,
-0.38433966,   0.39875764,   0.41317561,   0.42759359,   0.43480256,
-0.44922054,   0.46363851,   0.47084749,   0.48526546,   0.49968344,
-0.51421440,   0.52148110,   0.53601462,   0.55054808,   0.55781484,
-0.57234830,   0.58688176,   0.60141528,   0.60868198,   0.62321550,
-0.63785475,   0.64518178,   0.65983582,   0.67448992,   0.68914396,
-0.69647098,   0.71112502,   0.72577912,   0.73310614,   0.74776018,
-0.77102989,   0.79585397,   0.80826604,   0.83309019,   0.85791427,
-0.87032634,   0.94781560
+calibMap1[0], calibMap1[2], calibMap1[4], calibMap1[5], calibMap1[7],
+calibMap1[9], calibMap1[11], calibMap1[12], calibMap1[14], calibMap1[16],
+calibMap1[17], calibMap1[19], calibMap1[21], calibMap1[23], calibMap1[24],
+calibMap1[26], calibMap1[28], calibMap1[29], calibMap1[31], calibMap1[33],
+calibMap1[35], calibMap1[36], calibMap1[38], calibMap1[40], calibMap1[41],
+calibMap1[43], calibMap1[45], calibMap1[47], calibMap1[48], calibMap1[50],
+calibMap1[52], calibMap1[53], calibMap1[55], calibMap1[57], calibMap1[59],
+calibMap1[60], calibMap1[62], calibMap1[64], calibMap1[65], calibMap1[67],
+calibMap1[69], calibMap1[71], calibMap1[72], calibMap1[74], calibMap1[76],
+calibMap1[77], calibMap1[79], calibMap1[81], calibMap1[83], calibMap1[84],
+calibMap1[86], calibMap1[88], calibMap1[89], calibMap1[91], calibMap1[93],
+calibMap1[95], calibMap1[96], calibMap1[98], calibMap1[100], calibMap1[101],
+calibMap1[103], calibMap1[105], calibMap1[107], calibMap1[108], calibMap1[110],
+calibMap1[112], calibMap1[113], calibMap1[115]
 };
 
 //  M7(9)
 const float calibMap3[QUAN_RES3] = {
-0.02631116,   0.04930869,   0.07997208,   0.08763793,   0.11830132,
-0.14021800,   0.16884798,   0.17600547,   0.20463544,   0.22610791,
-0.25476459,   0.26196238,   0.29075363,   0.31234708,   0.34113833,
-0.34833613,   0.37713069,   0.39875764,   0.42759359,   0.43480256,
-0.44922054,   0.46363851,   0.48526546,   0.51421440,   0.52148110,
-0.55054808,   0.57234830,   0.60141528,   0.60868198,   0.62321550,
-0.63785475,   0.65983582,   0.68914396,   0.69647098,   0.72577912,
-0.74776018,   0.79585397,   0.85791427,   0.94781560
+calibMap1[0],  calibMap1[4], calibMap1[7], calibMap1[11], calibMap1[12], 
+calibMap1[14], calibMap1[16], calibMap1[19], calibMap1[23], calibMap1[24],
+calibMap1[26], calibMap1[28], calibMap1[31], calibMap1[35], calibMap1[36], 
+calibMap1[38], calibMap1[40], calibMap1[43], calibMap1[47], calibMap1[48], 
+calibMap1[50], calibMap1[52], calibMap1[55], calibMap1[59], calibMap1[60], 
+calibMap1[62], calibMap1[64], calibMap1[67], calibMap1[71], calibMap1[72], 
+calibMap1[76], calibMap1[79], calibMap1[83], calibMap1[84], calibMap1[86], 
+calibMap1[88], calibMap1[91], calibMap1[95], calibMap1[96], calibMap1[100],
+calibMap1[103], calibMap1[107], calibMap1[108], calibMap1[110], calibMap1[112], 
+calibMap1[115]
 };
 
 //  m7(9)
 const float calibMap4[QUAN_RES4] = {
-0.01097947,   0.01864531,   0.03397701,   0.04930869,   0.07230624,
-0.08763793,   0.11063547,   0.14021800,   0.16169049,   0.17600547,
-0.19747795,   0.22610791,   0.24042290,   0.24758039,   0.26196238,
-0.29075363,   0.31234708,   0.33394051,   0.34833613,   0.36273175,
-0.36992958,   0.38433966,   0.39875764,   0.41317561,   0.42038459,
-0.43480256,   0.45642951,   0.48526546,   0.50694764,   0.52148110,
-0.53601462,   0.55781484,   0.57234830,   0.59414852,   0.62321550,
-0.63052768,   0.64518178,   0.65983582,   0.68181694,   0.69647098,
-0.71845210,   0.74776018,   0.77102989,   0.78344196,   0.80826604,
-0.83309019,   0.84550226,   0.94781560
+calibMap1[0], calibMap1[3], calibMap1[7], calibMap1[10], calibMap1[12], 
+calibMap1[15], calibMap1[19], calibMap1[22], calibMap1[26], calibMap1[27], 
+calibMap1[31], calibMap1[34], calibMap1[36], calibMap1[38], calibMap1[39], 
+calibMap1[43], calibMap1[46], calibMap1[50], calibMap1[53], calibMap1[55], 
+calibMap1[58], calibMap1[60], calibMap1[63], calibMap1[67], calibMap1[70], 
+calibMap1[72], calibMap1[74], calibMap1[75], calibMap1[79], calibMap1[82], 
+calibMap1[86], calibMap1[89], calibMap1[91], calibMap1[94], calibMap1[96], 
+calibMap1[99],  calibMap1[103], calibMap1[106], calibMap1[110], calibMap1[113]
 };
 
 //  Dorian Scale
 const float calibMap5[QUAN_RES5] = {
-0.01097947,   0.02631116,   0.04164285,    0.04930869,   0.06464039,
-0.07997208,   0.08763793,   0.10296962,    0.11830132,   0.13306051,
-0.14021800,   0.15453300,   0.16884798,    0.17600547,   0.19032045,
-0.20463544,   0.21895042,   0.22610791,    0.24042290,   0.25476459,
-0.26196238,   0.27635801,   0.29075363,    0.30514926,   0.31234708,
-0.32674271,   0.34113833,   0.34833613,    0.36273175,   0.37713069,
-0.39154866,   0.39875764,   0.41317561,    0.42759359,   0.43480256,
-0.44922054,   0.46363851,   0.47805649,    0.48526546,   0.49968344,
-0.51421440,   0.52148110,   0.53601462,    0.55054808,   0.56508154,
-0.57234830,   0.58688176,   0.60141528,    0.60868198,   0.62321550,
-0.63785475,   0.65250880,   0.65983582,    0.67448992,   0.68914396,
-0.69647098,   0.71112502,   0.72577912,    0.74043316,   0.74776018,
-0.77102989,   0.79585397,   0.80826604,    0.83309019,   0.85791427,
-0.90296346,   0.94781560
+calibMap1[0], calibMap1[2], calibMap1[3], calibMap1[5], calibMap1[7],
+calibMap1[9], calibMap1[10], calibMap1[12], calibMap1[14], calibMap1[15],
+calibMap1[17], calibMap1[19], calibMap1[20], calibMap1[21], calibMap1[24],
+calibMap1[26], calibMap1[27], calibMap1[29], calibMap1[31], calibMap1[33],
+calibMap1[34], calibMap1[36], calibMap1[38], calibMap1[39], calibMap1[41],
+calibMap1[43], calibMap1[45], calibMap1[46], calibMap1[48], calibMap1[50],
+calibMap1[51], calibMap1[53], calibMap1[55], calibMap1[57], calibMap1[58],
+calibMap1[60], calibMap1[62], calibMap1[63], calibMap1[65], calibMap1[67],
+calibMap1[69], calibMap1[70], calibMap1[72], calibMap1[74], calibMap1[75],
+calibMap1[77], calibMap1[79], calibMap1[81], calibMap1[82], calibMap1[84],
+calibMap1[86], calibMap1[87], calibMap1[89], calibMap1[91], calibMap1[93],
+calibMap1[94], calibMap1[96], calibMap1[98], calibMap1[99], calibMap1[101],
+calibMap1[103], calibMap1[105], calibMap1[106], calibMap1[108], calibMap1[110],
+calibMap1[111], calibMap1[113], calibMap1[115]
 };
 
 //  Minor Scale
 const float calibMap6[QUAN_RES6] = {
-0.01097947,   0.01864531,   0.03397701,   0.04930869,   0.05697454,
-0.07230624,   0.08763793,   0.10296962,   0.11063547,   0.12590303,
-0.14021800,   0.14737549,   0.16169049,   0.17600547,   0.19032045,
-0.19747795,   0.21179293,   0.22610791,   0.23326540,   0.24758039,
-0.26196238,   0.27635801,   0.28355584,   0.29795146,   0.31234708,
-0.31954488,   0.33394051,   0.34833613,   0.36273175,   0.36992958,
-0.38433966,   0.39875764,   0.40596664,   0.42038459,   0.43480256,
-0.44922054,   0.45642951,   0.47084749,   0.48526546,   0.49247447,
-0.50694764,   0.52148110,   0.53601462,   0.54328132,   0.55781484,
-0.57234830,   0.57961506,   0.59414852,   0.60868198,   0.62321550,
-0.63052768,   0.64518178,   0.65983582,   0.66716284,   0.68181694,
-0.69647098,   0.71112502,   0.71845210,   0.73310614,   0.74776018,
-0.75861782,   0.78344196,   0.80826604,   0.83309019,   0.84550226,
-0.87032634,   0.94781560
+calibMap1[0], calibMap1[2], calibMap1[3], calibMap1[5], calibMap1[7],
+calibMap1[8], calibMap1[10], calibMap1[12], calibMap1[14], calibMap1[15],
+calibMap1[17], calibMap1[19], calibMap1[20], calibMap1[22], calibMap1[24],
+calibMap1[26], calibMap1[27], calibMap1[29], calibMap1[31], calibMap1[32],
+calibMap1[34], calibMap1[36], calibMap1[38], calibMap1[39], calibMap1[41],
+calibMap1[43], calibMap1[44], calibMap1[46], calibMap1[48], calibMap1[50],
+calibMap1[51], calibMap1[53], calibMap1[55], calibMap1[56], calibMap1[58],
+calibMap1[60], calibMap1[62], calibMap1[63], calibMap1[65], calibMap1[67],
+calibMap1[68], calibMap1[70], calibMap1[72], calibMap1[74], calibMap1[75],
+calibMap1[77], calibMap1[79], calibMap1[80], calibMap1[82], calibMap1[84],
+calibMap1[86], calibMap1[87], calibMap1[89], calibMap1[91], calibMap1[92],
+calibMap1[94], calibMap1[96], calibMap1[98], calibMap1[99], calibMap1[101],
+calibMap1[103], calibMap1[104], calibMap1[106], calibMap1[108], calibMap1[110],
+calibMap1[111], calibMap1[113], calibMap1[115]
 };
 
 //  5th
 const float calibMap7[QUAN_RES7] = {
-0.01097947,  0.06464039,   0.11830132,    0.16884798,    0.21895042,
-0.26916021,  0.31954488,   0.36992958,    0.42038459,    0.47084749,
-0.52148110,  0.57234830,   0.62321550,    0.67448992,    0.72577912,
-0.79585397,  0.90296346
+calibMap1[0], calibMap1[7], calibMap1[14], calibMap1[21], calibMap1[28],
+calibMap1[35], calibMap1[42], calibMap1[49], calibMap1[56], calibMap1[63],
+calibMap1[70], calibMap1[77], calibMap1[84], calibMap1[91], calibMap1[98],
+calibMap1[105]
 };
 
 //  Whole tone
 const float calibMap8[QUAN_RES8] = {
-0.01097947,   0.02631116,   0.04164285,   0.05697454,    0.07230624,
-0.08763793,   0.10296962,   0.11830132,   0.13306051,    0.14737549,
-0.16169049,   0.17600547,   0.19032045,   0.20463544,    0.21895042,
-0.23326540,   0.24758039,   0.26196238,   0.27635801,    0.29075363,
-0.30514926,   0.31954488,   0.33394051,   0.34833613,    0.36273175,
-0.37713069,   0.39154866,   0.40596664,   0.42038459,    0.43480256,
-0.44922054,   0.46363851,   0.47805649,   0.49247447,    0.50694764,
-0.52148110,   0.53601462,   0.55054808,   0.56508154,    0.57961506,
-0.59414852,   0.60868198,   0.62321550,   0.63785475,    0.65250880,
-0.66716284,   0.68181694,   0.69647098,   0.71112502,    0.72577912,
-0.74043316,   0.75861782,   0.78344196,   0.80826604,    0.83309019,
-0.85791427,   0.90296346
+calibMap1[0], calibMap1[1], calibMap1[2], calibMap1[6], calibMap1[8],
+calibMap1[10], calibMap1[12], calibMap1[14], calibMap1[16], calibMap1[18],
+calibMap1[20], calibMap1[22], calibMap1[24], calibMap1[26], calibMap1[28],
+calibMap1[30], calibMap1[32], calibMap1[34], calibMap1[36], calibMap1[38],
+calibMap1[40], calibMap1[42], calibMap1[44], calibMap1[46], calibMap1[48],
+calibMap1[50], calibMap1[52], calibMap1[54], calibMap1[56], calibMap1[58],
+calibMap1[60], calibMap1[62], calibMap1[64], calibMap1[66], calibMap1[68],
+calibMap1[70], calibMap1[72], calibMap1[74], calibMap1[76], calibMap1[78],
+calibMap1[80], calibMap1[82], calibMap1[84], calibMap1[86], calibMap1[88],
+calibMap1[90], calibMap1[92], calibMap1[94], calibMap1[96], calibMap1[98],
+calibMap1[100], calibMap1[102], calibMap1[104], calibMap1[106], calibMap1[108],
+calibMap1[110], calibMap1[112], calibMap1[114]
 };
 
 //-------------------------------------------------------------
@@ -283,52 +352,127 @@
 // Global Variables
 
 float   gOSC_cv[8];
-float   gSeq_cv1[8], gSeq_cv2[8];
+float   gSeq_cv[16];
 float   gGlide;
 int     gMode;
 
 // Variables for Control
-
-float gCtrl[6];
-bool gCtrlSW[6] = {false};
+/*
+gCtrl[0] /ctrl1 BPM
+gCtrl[1] /ctrl2 Quantize mode
+gCtrl[3] /ctrl4 Glide
+gCtrl[4] /ctrl5 M185 Reset Count
+
+gCtrlSW[0] /ctrlsw1 Sequencer STOP
+gCtrlSW[1] /ctrlsw2 Euclidean Sequencer reset
+gCtrlSW[2] /ctrlsw3 Sequencer Loop
+gCtrlSW[3] /ctrlsw4 Euclid Seq ON
+
+float gPulseCount[8] = {0};  M185 Pulse Count
+float gGateMode[8] = {0};    M185 Gate Mode
+float gSlide[8];             M185 Slide
+
+gEucA[0] /euca1 Euclidean Pattern length  (n) ch1
+gEucA[1] /euca2 Euclidean Pattern density (k) ch1
+gEucA[2] /euca3 Euclidean Pattern offset  (o) ch1
+gEucA[3] ~ [5] /euca4 ~ /euca6 Euclidean Pattern nko ch2
+gEucB[0] ~ [5] /eucb1 ~ /eucb6 Euclidean Pattern nko ch3 ~ ch4
+*/
+
+float gCtrl[8];
+bool  gCtrlSW[8] = {false};
+
+// Variables for Sequencer
+float gPulseCount[8] = {0};
+float gGateMode[16] = {0};
+float gSlide[16];
+
+// Euclidean SEQ Variables
+float gEucA[6], gEucB[6];
+int channels = MAXCHANNELS;
+unsigned int beat_holder[MAXCHANNELS];
+unsigned int channelbeats[MAXCHANNELS][5];
+
+bool pulses_active = false; // is active while a beat pulse is playing 
+bool lights_active = false;
+int pulse_length = TRIGGER_DURATION; //pulse length
+
+unsigned int last_read[MAXCHANNELS];
+unsigned int last_changed[MAXCHANNELS];
+unsigned int last_sync;
+
+unsigned int euc_time;
+
+// Variables for Arduino
+uint16_t gArdCV[4];
+uint16_t gArdCtrl[4];
+bool gArdSW[4] = {false};
 
 //-------------------------------------------------------------
 // mbed Functions
 
-TextLCD gLCD(p9, p10, p11, p12, p13, p14); // rs, e, d4-d7
-
-SPI         gSPI(p5,p6,p7);     // SPI (p6 unconnected)
-DigitalOut  gSYNCMODE(p15);     // SYNC DAC8568
-DigitalOut  gLDAC(p16);         // LDAC DAC8568
-
-DigitalOut  gGATES[4] = {p23, p24, p24, p25};   // GateOut
-DigitalOut  gLEDS[4] = {p18, p19, p20, p21};    // LED
-DigitalOut  gCLOCKOUT(p26);                     // ClockOut
-
-AnalogIn    gAIN(p17);  // Glide Potentiometer
-InterruptIn gSW(p30);   // Mode SW
-
-Timer       gTimer;     // Timer
-Ticker      gPoller;    // Ticker Polling
+TextLCD      gLCD(p9, p10, p11, p12, p13, p14); // rs, e, d4-d7
+
+BurstSPI     gSPI(p5,p6,p7);    // SPI (p6 unconnected)
+
+FastOut<p15> gSYNCMODE;         // SYNC DAC8568
+FastOut<p16> gLDAC;             // LDAC DAC8568
+
+DigitalOut   gGATES[4] = {p21, p22, p23, p24};   // GateOut
+FastOut<p19> gSUBGATE;                           // SubGateOut
+FastOut<p25> gCLOCKOUT;                          // ClockOut
+
+AnalogOut    gAOUT(p18);
+
+AnalogIn gAIN(p17);
+DebouncedInterrupt  gSW(p30);   // Mode SW
+
+// Serial for Arduino
+MIDI midi(p28, p27);
+
+Timer        gTimer;     // Timer
+Ticker       gPoller;    // Ticker for Polling
 
 // Ethernet
-EthernetNetIf   gEth;
+EthernetNetIf   gEth(
+                     IpAddr(192,168,1,6),
+                     IpAddr(255,255,255,0),
+                     IpAddr(192,168,1,1),
+                     IpAddr(192,168,1,1)
+                    );
+/* static ip
+EthernetNetIf   gEth(
+                     IpAddr(192,168,1,2),
+                     IpAddr(255,255,255,0),
+                     IpAddr(192,168,1,1),
+                     IpAddr(192,168,1,1)
+                    );
+*/
+                     
 UDPSocket       gUdp;
 
+// touchOSC Address
+uint8_t touchOSCAddress[] = { 192, 168, 1, 7 };
+int touchOSCPort = 9000;
+
+OSCClass osc;
+OSCMessage sendMes;
+
 //-------------------------------------------------------------
 // main
  
 int main() 
 { 
     float pot, _pot;
+    int bpm;
     
-//Clock Up 110Mhz -------------------------------------------------------------
+//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   = 0x00020037;       /* configure PLL0                  */
+    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    */
  
@@ -344,18 +488,163 @@
     
     SystemCoreClockUpdate();
 //-----------------------------------------------------------------------------
-    
-    if(SetupEthNetIf() == -1)
+        
+    if (SetupEthNetIf() == -1)
     {
-        for(int i = 0; i < 4; i++) 
+        for (int i = 0; i < 4; ++i) 
         {
-            gLEDS[i] = 1;
+            gGATES[i] = true;
             wait(0.25);
         }
         
         return -1;
     }
     
+    InitOSCCV();
+    
+    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);
+        }
+        
+        switch (gMode)
+        {               
+            case MODE_OSC: // OSCtoCV mode
+            
+                SetCV();
+                break;
+                
+            case MODE_SEQ: // Shift Sequencer mode
+            
+                bpm = CheckBPM();
+
+                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
+            
+                bpm = CheckBPM();
+            
+                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
+            
+                bpm = CheckBPM();
+                
+                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;
+                
+            default:       // CV Calibration mode
+                
+                CalibrationCV(); 
+                break;
+        }
+        
+    }
+}
+
+//-------------------------------------------------------------
+// Initialize OSCtoCV
+
+void InitOSCCV()
+{
+    int i;
+// 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
+
+// Initialize Euclid Sequencer
+    channelbeats[0][0] = 16;
+    channelbeats[0][1] = 8;
+    channelbeats[0][2] = 0;
+    channelbeats[0][3] = 0;
+    
+    channelbeats[1][0] = 16;
+    channelbeats[1][1] = 9;
+    channelbeats[1][2] = 0;
+    channelbeats[1][3] = 0;
+    
+    channelbeats[2][0] = 16;
+    channelbeats[2][1] = 7;
+    channelbeats[2][2] = 0;
+    channelbeats[2][3] = 0;
+    
+    channelbeats[3][0] = 16;
+    channelbeats[3][1] = 9;
+    channelbeats[3][2] = 0;
+    channelbeats[3][3] = 0;
+
+    for (i = 0; i < channels; ++i) 
+    {
+        beat_holder[i] = Euclid(channelbeats[i][0], channelbeats[i][1], channelbeats[i][3]);
+    }
+    
+// 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;
+
 // mdns (Bonjour)
     HTTPServer svr;
     mDNSResponder mdns;
@@ -364,57 +653,18 @@
     svr.bind(INPUT_PORT);
     IpAddr ip = gEth.getIp();
     mdns.announce(ip, "OSCtoCV", "_osc._udp", INPUT_PORT, "mbed(OSCtoCV)", (char *[]) {"path=/",NULL});
-    
-    InitOSCCV();
-    
-    _pot = pot = gMode = 0;
-    gGlide = gCtrl[3] = gAIN.read();
-        
-    LCD();
-    gLCD.locate( 0, 1 );
-    gLCD.printf("12345678 G>>%3.2f", gGlide);
+
+// Set OSC message for sending 
+    sendMes.setIp(touchOSCAddress); 
+    sendMes.setPort(touchOSCPort);
     
-// loop
-    while(1) 
-    {
-        pot = gAIN.read();  // Glide Value
-        
-        if(pot == 0) 
-        {
-            if(abs(gCtrl[3] - _pot) > 0.01f)
-            {
-                _pot = gGlide = gCtrl[3];
-            
-                gLCD.locate( 0, 1 );
-                gLCD.printf("12345678 G>>%3.2f", gGlide);
-            }
-        
-        } else if (abs(pot - _pot) > 0.01f) {
-            
-            gGlide = _pot = gAIN.read();
-            
-            gLCD.locate( 0, 1 );
-            gLCD.printf("12345678 G>>%3.2f", gGlide);
-        }
-        
-        switch(gMode)
-        {               
-            case MODE_LIN:
-            
-                SetSCV();
-                break;
-                
-            case MODE_SEQ:
-        
-                Seq();
-                break;
-                
-            default:
-                
-                CalibCV();
-                break;
-        }
-    }
+    gSW.attach(&CheckModeSW,IRQ_RISE, 30);     // InterruptIn rising edge(ModeSW)
+    gPoller.attach_us(&NetPoll, POLLING_INTERVAL);  // Ticker Polling
+    
+    wait(0.4);
+
+    // Begin Serial for Arduino
+    //ardSerial.baud(115200);
 }
 
 //-------------------------------------------------------------
@@ -426,34 +676,11 @@
 }
 
 //-------------------------------------------------------------
-// Initialize OSC-CV
-
-void InitOSCCV()
+// Map Function 
+
+inline float MapFloat(float x, float in_min, float in_max, float out_min, float out_max)
 {
-// 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
-    
-    gSW.mode(PullUp);           // Use internal pullup for ModeSW
-    wait(.001);
-    
-    gSW.rise(&CheckModeSW);     // InterruptIn rising edge(ModeSW)
-    gPoller.attach_us(&NetPoll, POLLING_INTERVAL);  // Ticker Polling
-    
-    wait(0.2);
+  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
 }
 
 //-------------------------------------------------------------
@@ -462,9 +689,8 @@
 
 inline void UpdateCV(int control, int address, const unsigned int *data)
 {
-    __disable_irq();
-    
-    switch(control)
+
+    switch (control)
     {
         case WRITE_UPDATE_N:
 
@@ -476,6 +702,7 @@
             gSYNCMODE = _ENABLE;
             gLDAC = _DISABLE;
             gLDAC = _ENABLE;
+            
             break;
 
         case RESET:
@@ -486,6 +713,7 @@
             gSPI.write(00000000);
             gSPI.write(00000000);
             gSYNCMODE = _ENABLE;
+            
             break;
 
         case CLR:
@@ -496,52 +724,54 @@
             gSPI.write(00000000);
             gSPI.write(00000011);   // Ignore CLR Pin
             gSYNCMODE = _ENABLE;
+            
             break;
     }
-    
-    __enable_irq();
 }
 
 //-------------------------------------------------------------
-// Calibrate Mode
-
-inline void CalibCV()
+// Calibration Mode
+
+inline void CalibrationCV()
 {
     static int ch;
     unsigned int cv;
 
-    switch(gMode) 
+    switch (gMode) 
         {
             case MODE_Calb:
                 
-                cv = (unsigned int)((calibMap1[68] + 0.0007) * SCALING_N);    // A880.0Hz
+                cv = (unsigned int)(calibMap1[69] * SCALING_N);  // A880.0Hz
                 
-                gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = 1;
-                gLEDS[0] = gLEDS[1] = gLEDS[2] = gLEDS[3] = 1;
+                gSUBGATE = gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = true;
                 
                 UpdateCV(WRITE_UPDATE_N, ch, &cv);
+                
                 break;
         }
 
-        CVMeter(ch, &cv);
+        UpdateCVMeter(ch, &cv);
         
-        ch++;
+        ++ch;
         ch &= 0x07;
 }
 
 //-------------------------------------------------------------
 // Calculate CV
 
-inline void SetSCV()
+inline void SetCV()
 {
-    static int ch, quan, mode, mcount;
+    static int ch, qmode, amode, mcount;
     static float glidecv[8];
     unsigned int cv;
     static float qcv;
 
-    mode = (gCtrl[1] * 8);
-
-    switch(mode) 
+    qmode = (gCtrl[1] * (SCALE_NUM - 1));
+    amode = SCALE_AOUT * qmode;
+    
+    gAOUT.write_u16(amode);
+
+    switch (qmode) 
         {
             case Lin:
                 
@@ -549,402 +779,697 @@
                 cv = (unsigned int)glidecv[ch];
                     
                 UpdateCV(WRITE_UPDATE_N, ch, &cv);
+
                 break;
                     
             case Chr:
-            
-                quan = (40616 / QUAN_RES1);
-                qcv = calibMap1[(unsigned int)(gOSC_cv[ch] / quan)];
-                    
-                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
-                cv = (unsigned int)glidecv[ch];
-                        
-                UpdateCV(WRITE_UPDATE_N, ch, &cv);
-                break;
-                
-            case Maj:
-                
-                quan = (40616 / QUAN_RES2);
-                qcv = calibMap2[(unsigned int)(gOSC_cv[ch] / quan)];
-                    
-                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
-                cv = (unsigned int)glidecv[ch];
-                        
-                UpdateCV(WRITE_UPDATE_N, ch, &cv);
-                break;
-            
-            case M7:
-            
-                quan = (40616 / QUAN_RES3);
-                qcv = calibMap3[(unsigned int)(gOSC_cv[ch] / quan)];
+
+                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);
                 cv = (unsigned int)glidecv[ch];
                         
                 UpdateCV(WRITE_UPDATE_N, ch, &cv);
+
                 break;
                 
-            case Min7:
-                
-                quan = (40616 / QUAN_RES4);
-                qcv = calibMap4[(unsigned int)(gOSC_cv[ch] / quan)];
-                    
-                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
-                cv = (unsigned int)glidecv[ch];
-                        
-                UpdateCV(WRITE_UPDATE_N, ch, &cv);
-                break;
-                    
-            case Dor:
-                
-                quan = (40616 / QUAN_RES5);
-                qcv = calibMap5[(unsigned int)(gOSC_cv[ch] / quan)];
-                    
+            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);
                 cv = (unsigned int)glidecv[ch];
-                        
+                                        
                 UpdateCV(WRITE_UPDATE_N, ch, &cv);
+
                 break;
-        
-            case Min:
-                
-                quan = (40616 / QUAN_RES6);
-                qcv = calibMap6[(unsigned int)(gOSC_cv[ch] / quan)];
-                    
-                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
-                cv = (unsigned int)glidecv[ch];
-                        
-                UpdateCV(WRITE_UPDATE_N, ch, &cv);
-                break;
+            
+            case M7:
                 
-            case S5th:
-                
-                quan = (40616 / QUAN_RES7);
-                qcv = calibMap7[(unsigned int)(gOSC_cv[ch] / quan)];
-                    
-                glidecv[ch] = glidecv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
-                cv = (unsigned int)glidecv[ch];
-                        
-                UpdateCV(WRITE_UPDATE_N, ch, &cv);
-                break;
-                
-            case Wht:
-                
-                quan = (40616 / QUAN_RES8);
-                qcv = calibMap8[(unsigned int)(gOSC_cv[ch] / quan)];
+                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);
                 cv = (unsigned int)glidecv[ch];
                         
                 UpdateCV(WRITE_UPDATE_N, ch, &cv);
+
+                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);
+                cv = (unsigned int)glidecv[ch];
+                        
+                UpdateCV(WRITE_UPDATE_N, ch, &cv);
+
+                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);
+                cv = (unsigned int)glidecv[ch];
+                        
+                UpdateCV(WRITE_UPDATE_N, ch, &cv);
+
+                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);
+                cv = (unsigned int)glidecv[ch];
+                        
+                UpdateCV(WRITE_UPDATE_N, ch, &cv);
+
+                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);
+                cv = (unsigned int)glidecv[ch];
+                        
+                UpdateCV(WRITE_UPDATE_N, ch, &cv);
+
+                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);
+                cv = (unsigned int)glidecv[ch];
+                        
+                UpdateCV(WRITE_UPDATE_N, ch, &cv);
+
                 break;
         }
 
-        if(mcount % 16 == 0) 
+        if (mcount == 0x1F) 
         {
-            CVMeter(ch, &cv);
+            UpdateCVMeter(ch, &cv);
         }
 
-        ch++;
+        ++ch;
         
-        if(ch &= 0x07)
+        if (ch &= 0x07)
         {
-            mcount ++;
+            ++mcount;
             mcount &= 0x3F;
         }
-        
 }
 
 //-------------------------------------------------------------
 // Sequence & Shift Out CV
 
-inline void SeqCV(int shift)
+inline void ShiftCVSeq(int trigger, bool reset)
 {
     int i, j;
-    static int ch, quan, mode;
+    static bool triggerState = false;
+    static bool stepFoward = false;
+    static bool _reset = false;
+    static uint8_t currentStep;
+    static int _resetCount, resetCount;
+    static uint8_t gateMode;
+    static uint8_t _gateMode[16];
+    static uint8_t ch, qmode, amode;
     static float glidecv[8], shiftcv[8];
     unsigned int cv;
     static float qcv;
         
-    mode = (gCtrl[1] * 8);  // Sequencer Quantize Mode (gCtrl[1])
+    qmode = (gCtrl[1] * (SCALE_NUM - 1.0f));  // Sequencer Quantize Mode (gCtrl[1])
+    amode = SCALE_AOUT * qmode;
     
-    switch(mode) 
+    gAOUT.write_u16(amode);
+    
+    switch (qmode) 
         {
             case 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);
-                }
-                
+
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + gSeq_cv[currentStep] * (1.0f - gSlide[currentStep]);
+
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+    
+            case Chr:
+
+                qcv = calibMap1[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES1 - 1))];
+    
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
                 cv = (unsigned int)glidecv[0];
-                
+
                 UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+
+            case Maj:
+
+                qcv = calibMap2[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES2 - 1))];
+    
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
                 break;
-                    
-            case Chr:
+
+            case M7:
+
+                qcv = calibMap3[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES3 - 1))];
+    
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+    
+            case Min7:
+
+                qcv = calibMap4[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES4 - 1))];
             
-                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);
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
                 cv = (unsigned int)glidecv[0];
-                
+
                 UpdateCV(WRITE_UPDATE_N, 0, &cv);
-                break;
-                
-            case Maj:
-                
-                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 = (unsigned int)glidecv[0];
-                
-                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
                 break;
             
-            case M7:
-                
-                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);
+            case Dor:
+
+                qcv = calibMap5[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES5 - 1))];
+
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
                 cv = (unsigned int)glidecv[0];
-                
+
                 UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
                 break;
-                    
-            case Min7:
-                
-                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);
+
+            case Min:
+
+                qcv = calibMap6[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES6 - 1))];
+
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
                 cv = (unsigned int)glidecv[0];
-                
+
                 UpdateCV(WRITE_UPDATE_N, 0, &cv);
-                break;
-                            
-            case Dor:
-                
-                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 = (unsigned int)glidecv[0];
-                
-                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
                 break;
-                
-            case Min:
-                
-                quan = 40616 / QUAN_RES6;
-                
-                if(ch < 8)
-                {
-                    qcv = calibMap6[(unsigned int)(gSeq_cv1[ch] / quan)];
-                            
-                } else {
-                        
-                    qcv = calibMap6[(unsigned int)(gSeq_cv2[ch-8] / quan)];
-                }
-                
-                glidecv[0] = glidecv[0] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
-                cv = (unsigned int)glidecv[0];
-                
-                UpdateCV(WRITE_UPDATE_N, 0, &cv);
-                break;
-            
+
             case S5th:
-                
-                quan = 40616 / QUAN_RES7;
-                
-                if(ch < 8)
-                {
-                    qcv = calibMap7[(unsigned int)(gSeq_cv1[ch] / quan)];
-                            
-                } else {
-                        
-                    qcv = calibMap7[(unsigned int)(gSeq_cv2[ch-8] / quan)];
-                }
-                
-                glidecv[0] = glidecv[0] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
+
+                qcv = calibMap7[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES7 - 1))];
+
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
                 cv = (unsigned int)glidecv[0];
-                
+
                 UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
                 break;
-                
+
             case Wht:
-                
-                quan = 40616 / QUAN_RES8;
-                
-                if(ch < 8)
-                {
-                    qcv = calibMap8[(unsigned int)(gSeq_cv1[ch] / quan)];
-                            
-                } else {
-                        
-                    qcv = calibMap8[(unsigned int)(gSeq_cv2[ch-8] / quan)];
-                }
-                    
-                glidecv[0] = glidecv[0] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
+
+                qcv = calibMap8[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES8 - 1))];
+    
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
                 cv = (unsigned int)glidecv[0];
-                
+
                 UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
                 break;
         }
-            
-        for(i = 1; i < 8; ++i)
+    
+    for (i = 1; i < 8; ++i)
+    {
+        glidecv[i] = glidecv[i] * gSlide[currentStep] + shiftcv[i] * (1.0f - gSlide[currentStep]);
+        cv = (unsigned int)glidecv[i];
+
+        UpdateCV(WRITE_UPDATE_N, i, &cv);
+    }   
+        
+    if (trigger && !triggerState) // trigger ON
+    {        
+        stepFoward = triggerState = true;
+        
+    } else if (!trigger) { // trigger OFF
+        
+        if (gateMode != HOLD) 
         {
-            glidecv[i] = glidecv[i] * gGlide + shiftcv[i] * (1.0f - gGlide);
-            cv = (unsigned int)glidecv[i];
-                
-            UpdateCV(WRITE_UPDATE_N, i, &cv);
+            gGATES[0] = false;
         }
         
-        if(shift == 1)                  // GATE1
+        triggerState = false;
+    }
+    
+// check & update touchOSC ctrl parameter              
+    if (_gateMode[ch] != (gGateMode[ch] * 3))
+    {
+        _gateMode[ch] = (gGateMode[ch] * 3);
+            
+        if (_gateMode[ch] == MULTI)
         {
-            for(j = 1; j < 8; ++j)      // Shift ch2~8
+            _gateMode[ch] = HOLD;
+        }
+        
+        SendCtrlState(ch, _gateMode[ch], 8);
+    }
+    
+    if (reset && !_reset) // Stop & Reset
+    {
+        sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+        sendMes.setArgs("i", 0);
+        osc.sendOsc(&sendMes);
+        
+        currentStep = 0;
+
+        sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+        sendMes.setArgs("i", 1);
+        osc.sendOsc(&sendMes);
+        
+        _reset = true;
+
+    } else if (!reset) {
+
+        _reset = false;
+    }
+    
+    if (stepFoward)
+    {
+        if (gateMode != HOLD) // shift CV
+        {
+            for (j = 1; j < 8; ++j)
             {
                 shiftcv[j] = glidecv[j-1];
             }
+        }
+   
+        sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+        sendMes.setArgs("i", 0);
+        osc.sendOsc(&sendMes);
+                    
+        ++currentStep;
+
+        if (gCtrlSW[2]) 
+        {
+            resetCount = 3;
+            
+        } else {
+            
+            resetCount = gCtrl[4] * 15;
+        }
         
-            ch++;
-            ch &= 0x0F;
+        if (_resetCount != resetCount)
+        {
+            sendMes.setTopAddress(RESET_COUNTER_ADDRESS);
+            sendMes.setArgs("i", (resetCount + 1));
+            osc.sendOsc(&sendMes);
+        }
+        
+        if (currentStep > resetCount)  // reset
+        {
+            currentStep = 0;
         }
         
-     
-        if(ch < 8)
+        sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+        sendMes.setArgs("i", 1);
+        osc.sendOsc(&sendMes);
+                    
+        if (currentStep < 8)
         {
-            CVMeter(ch, &cv);
-                            
+            UpdateCVMeter(currentStep, &cv);
+                    
         } else {
-                        
-            CVMeter((ch-8), &cv);
+                
+            UpdateCVMeter((currentStep - 8), &cv);
+        }
+        
+        gateMode = (gGateMode[currentStep] * 3);
+    
+        if (gateMode == MULTI) // omit MULTI mode
+        {
+            gateMode = HOLD;
         }
-
+        
+        if (gateMode != MUTE) 
+        {
+            gGATES[0] = true;
+        }
+        
+        stepFoward = false;
+    }
+    
+    ++ch;
+    ch &= 0x0F;
 }
 
 //-------------------------------------------------------------
-// Sequencer Mode
-
-inline void Seq()
+// M185 Sequencer
+
+inline void M185Seq(int trigger, bool reset)
 {
-    static int bpm, _bpm;
+    int i, j;
+    static bool triggerState = false;
+    static bool stepFoward = false;
+    static bool _reset = false;
+    static uint8_t currentStep;
+    static int stepCount;
+    static int _resetCount, resetCount;
+    static uint8_t gateMode;
+    static uint8_t _gateMode[8];
+    static uint8_t _pulseCount[8];
+    static uint8_t ch, qmode, amode;
+    static float glidecv[8], shiftcv[8];
+    unsigned int cv;
+    static float qcv;
+    
+    qmode = (gCtrl[1] * (SCALE_NUM - 1));  // Sequencer Quantize Mode (gCtrl[1])
+    amode = SCALE_AOUT * qmode;
+    
+    gAOUT.write_u16(amode);
+    
+    switch (qmode) 
+        {
+            case Lin:
+
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + gSeq_cv[currentStep] * (1.0f - gSlide[currentStep]);
+
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+    
+            case Chr:
+
+                qcv = calibMap1[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES1 - 1))];
+    
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+
+            case Maj:
+
+                qcv = calibMap2[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES2 - 1))];
+    
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+
+            case M7:
+
+                qcv = calibMap3[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES3 - 1))];
     
-    bpm = (gCtrl[0] * 300 + 10);                    // Set BPM (gCtrl[0])
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+    
+            case Min7:
+
+                qcv = calibMap4[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES4 - 1))];
+            
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
             
-    if(abs(bpm - _bpm) > 1)
+            case Dor:
+
+                qcv = calibMap5[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES5 - 1))];
+
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+
+            case Min:
+
+                qcv = calibMap6[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES6 - 1))];
+
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+
+            case S5th:
+
+                qcv = calibMap7[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES7 - 1))];
+
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+
+            case Wht:
+
+                qcv = calibMap8[(unsigned int)MapFloat(gSeq_cv[currentStep], 0, SCALING_N, 0, (QUAN_RES8 - 1))];
+    
+                glidecv[0] = glidecv[0] * gSlide[currentStep] + (qcv * SCALING_N) * (1.0f - gSlide[currentStep]);
+                cv = (unsigned int)glidecv[0];
+
+                UpdateCV(WRITE_UPDATE_N, 0, &cv);
+
+                break;
+        }
+    
+    for (i = 1; i < 8; ++i)
     {
-        UpdateGate(bpm, NRESET, GATEALL, 3, false); // Reset (if bpm change)
-        _bpm = bpm;
-                    
-    } else if (gCtrlSW[0]) {                        // Stop (gCtrlSW[0])
-                        
-        bpm = 0;
-    }
-            
-    if(!gCtrlSW[2] && !gCtrlSW[3])                  // Sequencer Mode1
-    {
-        SeqCV((UpdateGate(bpm, N16TH, GATE1, 3, false)));   // Shift Timming 16th note
-        UpdateGate(bpm, N8TH, GATE2, 3, 0);
-        UpdateGate(bpm, NDOT8, GATE3, 3, 0);
-        UpdateGate(bpm, TRIP4, GATE4, 3, 0);            
+        glidecv[i] = glidecv[i] * gSlide[currentStep] + shiftcv[i] * (1.0f - gSlide[currentStep]);
+        cv = (unsigned int)glidecv[i];
+
+        UpdateCV(WRITE_UPDATE_N, i, &cv);
     }
     
+    if (trigger && !triggerState) // trigger ON
+    {
+        if (gateMode == MULTI) 
+        {
+            gGATES[0] = true;
+            
+            sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+            sendMes.setArgs("i", 1);
+            osc.sendOsc(&sendMes);
+        }
+        
+        stepFoward = triggerState = true;
+        
+    } else if (!trigger) { // trigger OFF
+
+        if (gateMode != HOLD) 
+        {
+            gGATES[0] = false;
+        } 
+        
+        if (gateMode == MULTI)
+        {
+            sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+            sendMes.setArgs("i", 0);
+            osc.sendOsc(&sendMes);
+        }
+        
+        triggerState = false;
+    }
+
+// check & update touchOSC ctrl parameter        
+    if (_gateMode[ch] != gGateMode[ch] * 3 || _pulseCount[ch] != gPulseCount[ch] * 7)
+    {
+        _gateMode[ch] = (gGateMode[ch] * 3);
+        _pulseCount[ch] = (gPulseCount[ch] * 7);
+        
+        SendCtrlState(ch, _gateMode[ch], _pulseCount[ch]);
+    }
+    
+    if (reset && !_reset) // Stop & Reset
+    {
+        sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+        sendMes.setArgs("i", 0);
+        osc.sendOsc(&sendMes);
+        
+        currentStep = 0;
+
+        sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+        sendMes.setArgs("i", 1);
+        osc.sendOsc(&sendMes);
+        
+        _reset = true;
+
+    } else if (!reset) {
+
+        _reset = false;
+    }
+    
+    if (stepFoward)
+    {
+        if (gateMode != HOLD) // shift CV
+        {
+            for (j = 1; j < 8; ++j) 
+            {
+                shiftcv[j] = glidecv[j-1];
+            }
+        }
+        
+        --stepCount;
+                
+        if (stepCount == -1)
+        {            
+            sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+            sendMes.setArgs("i", 0);
+            osc.sendOsc(&sendMes); 
+            
+            ++currentStep;
+            
+            if (gCtrlSW[2]) 
+            {
+                resetCount = 3;
+            
+            } else {
+            
+                resetCount = gCtrl[4] * 7;
+            }
+        
+            if (_resetCount != resetCount)
+            {
+                sendMes.setTopAddress(RESET_COUNTER_ADDRESS);
+                sendMes.setArgs("i", (resetCount + 1));
+                osc.sendOsc(&sendMes);
+            }
+
+            if (currentStep > resetCount) // reset
+            {
+                currentStep = 0;
+            }
+        
+            sendMes.setTopAddress(SetMatrixAddress(0, currentStep, false));
+            sendMes.setArgs("i", 1);
+            osc.sendOsc(&sendMes);
+                    
+            UpdateCVMeter(currentStep, &cv);
+            
+        // check Pulse Count & Gate Mode
+            stepCount = (gPulseCount[currentStep] * 7);
+        
+            gateMode = (gGateMode[currentStep] * 3);
+            
+            if (gateMode != MUTE)
+            {
+                gGATES[0] = true;
+            }
+            
+        }
+                
+        stepFoward = false;
+    }
+        
+    ++ch;
+    ch &= 0x07;
 }
 
 //-------------------------------------------------------------
-// Check SW
-
-void CheckModeSW()
-{   
-    wait(0.05);
+// Send M185 Sequencer Status to touchOSC
+
+inline void SendCtrlState(uint8_t step, uint8_t gateMode, uint8_t stepCount)
+{
+    char pulseAddress[10] = PULSE_COUNT_ADDRESS;
+    char gateModeAddress[10] = GATE_MODE_ADDRESS;
+    char currentStep[2];
     
-    if(gMode < MODE_NUM - 1) 
-    {   
-        gMode++;
-            
-    } else {
-                
-        gMode = 0;
+    sprintf(currentStep, "%d", step + 1);
+    
+    strcat(gateModeAddress, currentStep);
+    
+    if(stepCount != 8) 
+    {
+        strcat(pulseAddress, currentStep);
+        sendMes.setTopAddress(pulseAddress);
+        sendMes.setArgs("i", (stepCount + 1));
+        osc.sendOsc(&sendMes);
     }
-    
-    gCLOCKOUT = gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = 0;
-    gLEDS[0] = gLEDS[1] = gLEDS[2] = gLEDS[3] = 0;
-    
-    if(gMode == MODE_SEQ)
-    {
-        gTimer.start();     // Sequencer Timer Start
+
+    sendMes.setTopAddress(gateModeAddress);
         
-    } else {
+    switch (gateMode)
+        {
+            case SINGLE:
+            
+                sendMes.setArgs("s", "|");
+                
+                break;
+
+            case MUTE:
             
-        gTimer.stop();      // Sequencer Timer Stop
-    }
-    
-    LCD();
+                sendMes.setArgs("s", "O");
+                
+                break;
+
+            case MULTI:
+
+                sendMes.setArgs("s", "||");
+                
+                break;
+
+            case HOLD:
+                
+                sendMes.setArgs("s", "|-");
+                
+                break;
+        }
+
+        osc.sendOsc(&sendMes);
 }
 
 //-------------------------------------------------------------
-// GateOutSequence  beat(Note values) length(Gate time) invert(invert Gate)
-
-inline int UpdateGate(int bpm, int beat, int ch, int length, bool invert)
+// Gate Sequencer  beat(Note values) length(Gate time) invert(invert Gate)
+
+inline int GateSeq(int bpm, int beat, int ch, int length, bool invert, bool gatesoff, bool syncoff)
 {
     int i;
-    static int gatetime[4], oldgatetime[4];
-    static int bar, sync24, oldsynctime;
+    static int gatetime[GATE_TOTAL], oldgatetime[GATE_TOTAL];
+    static int _bpm, bar, sync24, oldsynctime;
     
     int time = gTimer.read_us();
     
-    bar = (60.0f / bpm) * 4000000;
-    sync24 = (bar / 4) / 24; // sync24 not tested
+    if (_bpm != bpm)
+    {
+        if (!bpm)
+        {
+            beat = NRESET;
+
+        } else {
+
+            bar = (60.0f / bpm) * 4000000;
+            //sync24 = (bar / 4) / 24; // sync24 not tested
+            
+            _bpm = bpm;
+        }
+    }
     
-    switch(beat)                                // Calculate Note values 
+    switch (beat) // Calculate Note values 
         {
             case NDOT2:
                 
@@ -972,58 +1497,100 @@
                 break;
                 
             case NRESET:
+            
+                gTimer.reset();
                 
-                for(i = 0; i < GATEALL; ++i)    // Reset
+                for (i = 0; i < GATE_TOTAL; ++i)    // Reset
                 {
-                    gTimer.reset();
                     oldsynctime = oldgatetime[i] = gatetime[i] = NRESET;
                 }
-                break;
-                
+
+                return 0;
+
             default:
                 
                 gatetime[ch] = bar / beat;
+                sync24 = bar / 16;
+                break;
         }
         
-        if(time > oldsynctime + sync24)  // sync24 not tested
+    if (time > oldsynctime + sync24)  // sync24 not tested
+    {
+        if (!syncoff) 
         {
             oldsynctime = time;
-            gCLOCKOUT = 1;
+            gCLOCKOUT = true;
             
-        } else if (time > sync24 - (sync24 - 2)) {
+            midi.sendRealTime(Clock); // MIDI Clock
+        }
         
-            gCLOCKOUT = 0;
+    } else if (time > oldsynctime - (sync24 - 2)) {
+
+        if (!syncoff) 
+        {
+            gCLOCKOUT = false;
         }
-    
-    if (ch == GATEALL) 
+    }
+
+    if (ch == GATE_TOTAL) 
     {
         return -1;
         
     } else if (time > oldgatetime[ch] + gatetime[ch] && !invert) {
         
         oldgatetime[ch] = time;
-        gLEDS[ch] = gGATES[ch] = 1;
         
-        return ch + 1;
+        if (!gatesoff) 
+        {
+            gGATES[ch] = true;
+            
+        } else if (ch == SUBGATE) {
+            
+            gSUBGATE = true;
+        }
+        
+        return 1;
     
     } else if (time > oldgatetime[ch] + gatetime[ch] && invert) {
         
         oldgatetime[ch] = time;
-        gLEDS[ch] = gGATES[ch] = 0;
+        
+        if (!gatesoff) 
+        {
+            gGATES[ch] = false;
+            
+        } else if (ch == SUBGATE) {
+            
+            gSUBGATE = false;
+        }
         
         return 0;
         
     } else if (time > oldgatetime[ch] + (gatetime[ch] - gatetime[ch] / length) && !invert) {
         
-        gLEDS[ch] = gGATES[ch] = 0;
+        if (!gatesoff) 
+        {
+            gGATES[ch] = false;
+            
+        } else if (ch == SUBGATE) {
+            
+            gSUBGATE = false;
+        }
         
         return 0;
         
     } else if (time > oldgatetime[ch] + (gatetime[ch] - gatetime[ch] / length) && invert) {
         
-        gLEDS[ch] = gGATES[ch] = 1;
+        if (!gatesoff) 
+        {
+            gGATES[ch] = true;
+            
+        } else if (ch == SUBGATE) {
+            
+            gSUBGATE = true;
+        }
         
-        return ch + 1;
+        return 1;
         
     } else {
         
@@ -1031,93 +1598,264 @@
     }
 }
 
+
 //-------------------------------------------------------------
-// SyncOut Sequence  beat(Note values) invert(invert Gate)
-
-inline void UpdateSync(int bpm, int beat, bool invert)
-{
-    static int bar, synctime, oldsynctime;
+// Check BPM
+
+inline int CheckBPM()
+{   
+    static int _bpm = -1;
+    int bpm;
     
-    int time = gTimer.read_us();
-    
-    bar = (60.0f / bpm) * 4000000;
-
-    synctime = bar / beat;
-    
-    if(beat == NRESET) 
+    if (gCtrlSW[0]) 
     {
-        bar = synctime = oldsynctime = gCLOCKOUT = 0;
+        bpm = 0;
+
+        return bpm;
     }
     
-    if((time > oldsynctime + synctime) && !invert)
+    if (!gCtrl[0]) 
     {
-        oldsynctime = time;
-        gCLOCKOUT = 1;
-        
-    } else if ((time > synctime - (synctime / 2)) && !invert) {
+        bpm = gArdCtrl[0] * 0.25f + 5;
+
+        if (abs(bpm - _bpm) > 1)
+        {
+            _bpm = bpm;
+            
+            sendMes.setTopAddress("/bpm");
+            sendMes.setArgs("i", bpm);
+            osc.sendOsc(&sendMes);
+        }
     
-        gCLOCKOUT = 0;
+    } else 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
+
+inline void CheckModeSW()
+{   
+    if (gMode < MODE_TOTAL - 1) 
+    {   
+        ++gMode;
+            
+    } else {
+                
+        gMode = 0;
+    }
+    
+    gCLOCKOUT = gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = false;
+    
+    if (gMode == MODE_SEQ || gMode == MODE_185 || gMode == MODE_EUC)
+    {
+        gTimer.start();     // Sequencer Timer Start
+        midi.begin(1);
         
-    } else if((time > oldsynctime + synctime) && invert) {
-        
-        oldsynctime = time;
-        gCLOCKOUT = 0;
-        
-    } else if ((time > synctime - (synctime / 2)) && invert) {
-    
-        gCLOCKOUT = 1;
+    } else {
+            
+        gTimer.stop();      // Sequencer Timer Stop
     }
     
 }
 
 //-------------------------------------------------------------
-// CV meter
-
-inline void CVMeter(int ch, const unsigned int *level)
-{       
-    gLCD.locate ( ch, 0 );
-    gLCD.putc(*level * 0.000205729);     // put custom char
+// 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");
+                    
+                    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) && gMode)
+    {
+        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;
+    }
+
 }
 
 //-------------------------------------------------------------
-// Print LCD Mode Status
-
-void LCD()
-{
-    switch(gMode) 
-        {
-            case MODE_Calb: 
-                gLCD.locate( 9, 0 );
-                gLCD.printf("Calibr "); 
-                break;
-                
-            case MODE_LIN:
-                gLCD.locate( 9, 0 );
-                gLCD.printf("OSC-CV ");
-                break;
-
-            case MODE_SEQ:  
-                gLCD.locate( 9, 0 );
-                gLCD.printf("SHIFTCV");
-                break;
-        }
+// CV Meter
+
+inline void UpdateCVMeter(int ch, const unsigned int *level)
+{       
+    gLCD.locate ( ch, 0 );
+    gLCD.putc(*level * 0.0002192f);     // put custom char
 }
 
+
 //-------------------------------------------------------------
-// Write command Custom Char LCD CGRAM(CV Meter) 
+// 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)
+    while (cnt < 0x08)
     {
         gLCD.writeCommand(addr | cnt);
         gLCD.writeData(*c);
         
-        cnt++;
-        c++;
+        ++cnt;
+        ++c;
     }
 }
 
@@ -1131,7 +1869,7 @@
 //  printf("Setting up...\r\n");
     EthernetErr ethErr = gEth.setup();
     
-    if(ethErr)
+    if (ethErr)
     {
         gLCD.locate( 0, 1 );
         gLCD.printf("Error in setup.");
@@ -1147,6 +1885,7 @@
     
     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;
@@ -1159,40 +1898,40 @@
 {
     size_t len = 0;
     
-    for(;;) 
+    for (;;) 
     {
         unsigned x = *(unsigned*)s;
-        if((x & 0xFF) == 0) return len;
-        if((x & 0xFF00) == 0) return len + 1;
-        if((x & 0xFF0000) == 0) return len + 2;
-        if((x & 0xFF000000) == 0) return len + 3;
+        if ((x & 0xFF) == 0) return len;
+        if ((x & 0xFF00) == 0) return len + 1;
+        if ((x & 0xFF0000) == 0) return len + 2;
+        if ((x & 0xFF000000) == 0) return len + 3;
         s += 4, len += 4;
     }
 }
 
 //-------------------------------------------------------------
-// Handller receive UDP Packet
+// Handller receive OSC UDP Packet
 
 inline void onUDPSocketEvent(UDPSocketEvent e)
 {
-    union OSCarg msg[10];
-    char buf[768] = {0};
-    int num, len;
-    int recvlen;
+    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;
     
-    recvlen = gUdp.recvfrom(buf, 768, &host);  // packet length
-            
-    switch(e)
+    switch (e)
     {
         case UDPSOCKET_READABLE: // The only event for now
-            
-        if(recvlen <= 0)  break;
+        
+        recvlen = gUdp.recvfrom(buf, 896, &host);  // packet length    
         
-        if(buf[0] == '#') // #bundle
+        if (recvlen <= 0)  break;
+        
+        if (!bundleflag && buf[0] == '#') // #bundle
         {
             messagepos += 16;     // skip #bundle & timetag
             recvlen -= 16;
@@ -1201,117 +1940,960 @@
         }
         
         do {
-                if(bundleflag)
+                if (bundleflag)
                 {
                     messagepos += 4;
                     recvlen -= 4;
-                
-                    if(recvlen <= 0)
+                    
+                    if (recvlen <= 8)
                     {
                         bundleflag = false;
                         break;
                     }
                 }
                 
-                if(getOSCmsg(buf + messagepos, msg) == -1)  continue;
+                if (getOSCmsg(buf + messagepos, msg) == -1)  continue;
             
-                len = strlen(msg[0].address);
+                len = strlength(msg[0].address);
         
-                if(isdigit(msg[0].address[len-1])) 
+                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-1)-4, "sync", 4)) 
+                if (!strncmp(msg[0].address+(len-offset)-4, "sync", 4)) 
                 { 
-                    if(msg[2].i != 0) gCLOCKOUT = 1;
-                    else              gCLOCKOUT = 0;
+                    if (msg[2].i != 0) gCLOCKOUT = true;
+                    else              gCLOCKOUT = false;
                     continue;
 
-                } else if (!strncmp(msg[0].address+(len-1)-4, "gate", 4) && (num != -1)) {
-                    if(num > 3) continue;
-                    if(msg[2].i != 0) gLEDS[num] = gGATES[num] = 1;
-                    else              gLEDS[num] = gGATES[num] = 0;
+                } 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-1)-4, "push", 4) && (num != -1)) {     
-                    if(num > 4) continue;
-                    if(msg[2].i != 0) gLEDS[num] = gGATES[num] = 1;
-                    else              gLEDS[num] = gGATES[num] = 0;
-                    continue;
-                
-                } else if (!strncmp(msg[0].address+(len-1)-6, "toggle", 6) && (num != -1)) {
-                    if(num > 4) continue;
-                    if(msg[2].i != 0) gLEDS[num] = gGATES[num] = 1;
-                    else              gLEDS[num] = gGATES[num] = 0;
-                    continue;
-                        
-                } else if (!strncmp(msg[0].address,"/1/multipush",12) && (num != -1)) {
-                    if(num > 4) continue;
-                    if(msg[2].i != 0) gLEDS[num] = gGATES[num] = 1;
-                    else              gLEDS[num] = gGATES[num] = 0;
-                    continue;
-            // address pattern CV (Type Tag float)  
-                } else if(!strncmp(msg[0].address+(len-1)-2, "cv", 2) && (num != -1)) {
-                    if(num > 7) continue;
-                    if(msg[1].typeTag[1] == 'f') gOSC_cv[num] = msg[2].f * (SCALING_N);
+                } 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;
-            // (touchOSC Control fader, rotary, xy, multixy, multifader)        
-                } else if (!strncmp(msg[0].address+(len-1)-5, "fader", 5) && (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-1)-6, "rotary", 6) && (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-1)-2, "xy", 2) && (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-1)-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);
+
+                } 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-1)-12, "multifader1/", 12) && (num != -1)) {
-                    if(num > 7) continue;
-                    if(msg[1].typeTag[1] == 'f') gOSC_cv[num] = msg[2].f * (SCALING_N);
+                } 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;
-            // (touchOSC multifader for Sequencer Mode)
-                } else if (!strncmp(msg[0].address+(len-1)-11, "sequencer1/", 11) && (num != -1)) {
-                    if(num > 7) continue;
-                    if(msg[1].typeTag[1] == 'f') gSeq_cv1[num] = msg[2].f * (SCALING_N);
+                    
+                } 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-1)-11, "sequencer2/", 11) && (num != -1)) {
-                    if(num > 7) continue;
-                    if(msg[1].typeTag[1] == 'f') gSeq_cv2[num] = msg[2].f * (SCALING_N);
-                    continue;
-            // address pattern for control
-                } else if (!strncmp(msg[0].address+(len-1)-6, "ctrlsw", 6) && (num != -1)) {
-                    if(num > 5) continue;
-                    if(msg[2].i != 0) gCtrlSW[num] = true;
+                } 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-1)-4, "ctrl", 4) && (num != -1)) {
-                    if(num > 5) continue;                                             
-                    if(msg[1].typeTag[1] == 'f') gCtrl[num] = msg[2].f;
+                } 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)-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 {
                     continue;
                 }
                 
-            } while(bundleflag);
+            } while (bundleflag);                   
+    }
+}
+
+//-------------------------------------------------------------
+// Euclidean Sequencer
+
+void EuclideanSeq(int trigger, bool reset, bool gatesoff) {
+    /*
+       What's in the loop: 
+       Update euc_time variable 
+       Check to see if it is euc_time go go to sleep 
+       Changes routine - update beat_holder when channelbeats changes - triggered by changes == true
+       Trigger routines - on trigget update displays and pulse
+       Read encoders 
+       Read switches
+     */
+
+    static uint8_t nn, kk, oo;
+    static uint8_t changes[MAXCHANNELS] = {0};
+    static int nknob, kknob, oknob;
+    static int _nknob, _kknob, _oknob;
+    static bool triggerState = false;
+    
+    uint8_t i, ch;
+    uint8_t maxn = MAXSTEPS; // maximums and minimums for n and k
+    uint8_t minn = 1;
+    uint8_t mink = 1; 
+    uint8_t mino = 0; 
+    
+    static uint8_t active_channel;  
+    
+    euc_time = gTimer.read_ms();
+
+    nn = channelbeats[active_channel][0];  
+    kk = channelbeats[active_channel][1]; 
+    oo = channelbeats[active_channel][3];
+    
+    // UPDATE BEAT HOLDER WHEN KNOBS ARE MOVED
+    if (changes[active_channel]) {
+        
+        beat_holder[active_channel] = Euclid(nn, kk, oo);
+        
+        switch (changes[active_channel]) 
+        {
+            case 1:
+            case 3:
+                for (int i = 0; i < MAXSTEPS; ++i) {
+                
+                    if (BitRead(beat_holder[active_channel], nn - 1 - i) && (i < nn)) {
+                        sendMes.setTopAddress(SetMatrixAddress(active_channel * 2, i, true));
+                        sendMes.setArgs("i", 1);
+                        osc.sendOsc(&sendMes);          
+                    
+                    } else {
+                        
+                        sendMes.setTopAddress(SetMatrixAddress(active_channel * 2, i, true));
+                        sendMes.setArgs("i", 0);
+                        osc.sendOsc(&sendMes);      
+                    }
+                }
+            
+                break;
+            
+            case 2:
+                for (int i = 0; i < MAXSTEPS; ++i) {
+            
+                    if (i < nn) {
+                        sendMes.setTopAddress(SetMatrixAddress(active_channel * 2, i, true));
+                        sendMes.setArgs("i", 1);
+                        osc.sendOsc(&sendMes);          
                     
+                    } else {
+                        
+                        sendMes.setTopAddress(SetMatrixAddress(active_channel * 2, i, true));
+                        sendMes.setArgs("i", 0);
+                        osc.sendOsc(&sendMes);          
+                    }
+                }
+        
+                break;
+            
+            default: 
+                break;
+        }
+        
+        changes[active_channel] = 0;
+        last_changed[active_channel] = gTimer.read_ms();
+    }
+    
+    // ANALOG PULSE TRIGGER
+    if (trigger && !triggerState) {
+        
+        Sync(active_channel, gatesoff);
+        triggerState = true;
+    
+    } else if (!trigger) {
+        
+        triggerState = false;
+    }
+
+    // READ K KNOB 
+    kknob = EncodeReadK(active_channel);
+    
+    if (_kknob != kknob) {
+        
+        _kknob = kknob;
+        
+        if (kknob != 0 && (euc_time - last_read[active_channel] > READ_DELAY)) {
+        
+            if ((kk + kknob) > nn) {          
+            
+                kknob = 0;
+                kk = nn;
+            
+            } else if ((kk + kknob) < mink) {
+            
+                kknob = 0;
+                kk = mink;
+            };
+
+            kk = channelbeats[active_channel][1] = (kk + kknob); // update with encoder reading
+
+            last_read[active_channel] = gTimer.read_ms();
+            changes[active_channel] = 1; // k change = 1
+        }
+    }
+    
+    // READ N KNOB 
+    nknob = EncodeReadN(active_channel);
+    
+    if (_nknob != nknob) {
+        
+        _nknob = nknob;
+        
+        if (nknob != 0 && (euc_time - last_read[active_channel] > READ_DELAY)) { 
+
+            if ((nn + nknob) > maxn) {
+            
+                nknob = 0;
+                nn = maxn;
+            
+            } else if ((nn + nknob) < minn) {
+            
+                nknob = 0;
+                nn = minn;
+            };
+
+            if (kk > (nn + nknob)) {// check if new n is lower than k + reduce K if it is 
+                channelbeats[active_channel][1] = (nn + nknob);
+            }; 
+
+            if (oo > (nn + nknob - 1)) {// check if new n is lower than o + reduce o if it is 
+                channelbeats[active_channel][3] = (nn + nknob - 1);
+            }; 
+
+            nn = channelbeats[active_channel][0] = (nn + nknob); // update with encoder reading
+            oo = channelbeats[active_channel][3];
+
+            last_read[active_channel] = gTimer.read_ms();
+            changes[active_channel] = 2; // n change = 2 
+        }
+        
+    }
+    
+    // READ O KNOB 
+    oknob = EncodeReadO(active_channel);
+    
+    if (_oknob != oknob) {
+        
+        _oknob = oknob;
+            
+        if (oknob != 0 && (euc_time - last_read[active_channel] > READ_DELAY)) { 
+            // Sense check o encoder reading to prevent crashes 
+
+            if ((oo + oknob) > (nn - 1)) {
+            
+                oknob = 0;
+                oo = (nn - 1);
+        
+            } else if ((oo + oknob) < mino) {
+            
+                oknob = 0;
+                oo = mino;
+            }
+
+            channelbeats[active_channel][3] = (oo + oknob);
+        
+            last_read[active_channel] = gTimer.read_ms();
+            changes[active_channel] = 3; // o change = 3
+        }
+        
+    }
+    
+    // ENABLE RESET BUTTON ** ADD FLASH RESET HERE ***
+    if (gCtrlSW[1] && channelbeats[active_channel][2]) {
+        
+        for (ch = 0; ch < channels; ++ch) {
+            channelbeats[ch][2] = 0; 
+        }
+    }
+    
+    // Stop & Reset (gCtrlSW[0])
+    if (reset) {
+        
+        for (ch = 0; ch < channels; ++ch) {
+            
+            channelbeats[ch][2] = 0;
+            
+            for (i = 0; i < MAXSTEPS; ++i) {
+            
+                sendMes.setTopAddress(SetMatrixAddress(ch * 2 + 1, i, true));
+                sendMes.setArgs("i", 0);
+                osc.sendOsc(&sendMes);
+            }
+            
+        }
+        
+    }
+    
+    // TURN OFF ANY LIGHTS THAT ARE ON 
+    if ((euc_time - last_sync) > pulse_length && lights_active) {
+        
+        for (ch = 0; ch < channels; ++ch) {
+            sendMes.setTopAddress(SetMatrixAddress((MAXCHANNELS * 2), 3 - ch, true));
+            sendMes.setArgs("i", 0);
+            osc.sendOsc(&sendMes);
+            
+            sendMes.setTopAddress(SetMatrixAddress((MAXCHANNELS * 2), 5, true));
+            sendMes.setArgs("i", 0);
+            osc.sendOsc(&sendMes);
+            
+      }
+      
+      lights_active = false; 
+    }
+    
+    // FINISH ANY PULSES THAT ARE ACTIVE - PULSES LAST 1/4 AS LONG AS LIGHTS 
+    if (euc_time - last_sync > (pulse_length / 4) && pulses_active) {
+        
+        for (ch = 0; ch < channels; ++ch) {
+            
+            if (!gatesoff)
+            {
+                gGATES[ch] = false;
+                gCLOCKOUT = false;
+                //digitalWrite(sparepin, LOW);
+            }
+        }
+        
+        pulses_active = false; 
+    }
+    
+    ++active_channel;
+    active_channel &= (channels - 1);
+}
+
+//-------------------------------------------------------------
+// Euclid calculation function
+
+unsigned int Euclid(int n, int k, int o) { // inputs: n=total, k=beats, o = offset
+    int pauses = (n - k);
+    int pulses = k;
+    int offset = o;
+    int steps = n;
+    int per_pulse = (pauses / k);
+    int remainder = (pauses % pulses);  
+    unsigned int workbeat[n];
+    unsigned int outbeat;
+    uint16_t outbeat2;
+    int workbeat_count = n;
+    int a_remainder, b_remainder;
+    int groupa, groupb;
+    int i, j; 
+    int trim_count;
+
+    for (i = 0; i < n; ++i) { // Populate workbeat with unsorted pulses and pauses 
+
+        if (i < pulses) {
+
+            workbeat[i] = 1;
+
+        } else {
+
+            workbeat[i] = 0;
+        }
+    }
+
+    if (per_pulse > 0 && remainder < 2) { // Handle easy cases where there is no or only one remainer
+
+        for (i = 0; i < pulses; ++i) {
+
+            for (j = (workbeat_count - 1); j > (workbeat_count - per_pulse - 1); --j) {
+                workbeat[i]  = ConcatBin(workbeat[i], workbeat[j]);
+            }
+
+            workbeat_count = (workbeat_count - per_pulse);
+            
+        }
+
+        outbeat = 0; // Concatenate workbeat into outbeat - according to workbeat_count
+
+        for (i = 0; i < workbeat_count; ++i) {
+            outbeat = ConcatBin(outbeat, workbeat[i]);
+        }
+
+
+        if (offset != 0) {
+            
+            outbeat2 = BitReadOffset(offset, outbeat, steps); // Add offset to the step pattern
+
+        } else {
+            
+            outbeat2 = outbeat;
+        }
+
+        return outbeat2;
+
+    } else { 
+
+        groupa = pulses;
+        groupb = pauses; 
+
+        while (groupb > 1) { //main recursive loop
+
+            if (groupa > groupb) { // more Group A than Group B
+                
+                a_remainder = (groupa - groupb); // what will be left of groupa once groupB is interleaved 
+                trim_count = 0;
+
+                for (i = 0; i < (groupa - a_remainder); ++i) { //count through the matching sets of A, ignoring remaindered
+                    workbeat[i]  = ConcatBin(workbeat[i], workbeat[workbeat_count - 1 - i]);
+                    ++trim_count;
+                }
+                
+                workbeat_count = (workbeat_count - trim_count);
+
+                groupa = groupb;
+                groupb = a_remainder;
+
+            } else if (groupb > groupa) { // More Group B than Group A
+                
+                b_remainder = (groupb - groupa); // what will be left of group once group A is interleaved 
+                trim_count = 0;
+
+                for (i = workbeat_count-1; i >= (groupa + b_remainder); --i) { //count from right back through the Bs
+                    workbeat[workbeat_count - i - 1] = ConcatBin(workbeat[workbeat_count - 1 - i], workbeat[i]);
+
+                    ++trim_count;
+                }
+
+                workbeat_count = (workbeat_count - trim_count);
+                groupb = b_remainder;
+
+            } else if (groupa == groupb) { // groupa = groupb 
+                
+                trim_count = 0;
+
+                for (i = 0; i < groupa; ++i) {
+                    workbeat[i] = ConcatBin(workbeat[i], workbeat[workbeat_count - 1 - i]);
+                    ++trim_count;
+                }
+
+                workbeat_count = (workbeat_count - trim_count);
+                groupb = 0;
+
+            }
+        }
+
+        outbeat = 0; // Concatenate workbeat into outbeat - according to workbeat_count
+
+        for (i = 0; i < workbeat_count; ++i) {
+            
+            outbeat = ConcatBin(outbeat, workbeat[i]);
+        }
+
+        if (offset != 0) {
+            
+            outbeat2 = BitReadOffset(offset, outbeat, steps); // Add offset to the step pattern
+
+        } else {
+
+            outbeat2 = outbeat;
+        }
+
+        return outbeat2;
     }
 }
+
+//-------------------------------------------------------------
+// Reads a bit of a number
+
+inline int BitRead(uint16_t b, int bitPos) {
+    int x;
+        
+    x = b & (1 << bitPos);
+    
+    return x == 0 ? 0 : 1;
+}
+
+//-------------------------------------------------------------
+// Function to right rotate n by d bits
+
+uint16_t BitReadOffset(int shift, uint16_t value, uint16_t pattern_length) {
+    uint16_t mask = ((1 << pattern_length) - 1);
+    value &= mask;
+
+    return ((value >> shift) | (value << (pattern_length - shift))) & mask;
+}
+
+//-------------------------------------------------------------
+// Function to find the binary length of a number by counting bitwise
+
+int findlength(unsigned int bnry) {
+    bool lengthfound = false;
+    int i;
+    int length = 1; // no number can have a length of zero - single 0 has a length of one, but no 1s for the sytem to count
+
+    for (i = 32; i >= 0; i--) {
+
+        if ((BitRead(bnry, i)) && !lengthfound) {
+            length = (i + 1);
+            lengthfound = true;
+        }
+        
+    }
+
+    return length;
+}
+
+//-------------------------------------------------------------
+// Function to concatenate two binary numbers bitwise
+
+unsigned int ConcatBin(unsigned int bina, unsigned int binb) {
+    int binb_len = findlength(binb);
+    unsigned int sum = (bina << binb_len);
+
+    sum = sum | binb;
+
+    return sum;
+}
+
+//-------------------------------------------------------------
+// routine triggered by each beat
+
+void Sync(int active_channel, bool gatesoff) {
+    int read_head, erase;
+    int rand_vel, rand_len;
+    int ch, i;
+    static int masterclock;
+    
+    if (masterclock % 2 == 0) {
+        sendMes.setTopAddress(SetMatrixAddress((MAXCHANNELS * 2), 7, true));
+        sendMes.setArgs("i", 1);
+        osc.sendOsc(&sendMes);
+    
+    } else {
+        
+        sendMes.setTopAddress(SetMatrixAddress((MAXCHANNELS * 2), 7, true));
+        sendMes.setArgs("i", 0);
+        osc.sendOsc(&sendMes);
+    }
+
+    // Cycle through channels 
+    for (ch = 0; ch < channels; ++ch) {
+        
+        read_head = (channelbeats[ch][0] - channelbeats[ch][2] - 1);  
+
+        if (ch != active_channel || (euc_time - last_changed[active_channel]) > DISPLAY_UPDATE) {
+            
+            if (channelbeats[ch][2] < MAXSTEPS) {
+                
+                for (i = 0; i < MAXSTEPS; ++i) {
+                    
+                    if (BitRead(beat_holder[ch],channelbeats[ch][0] - 1 - i) && i < channelbeats[ch][0]) {
+                        
+                        sendMes.setTopAddress(SetMatrixAddress(ch * 2, i, true));
+                        sendMes.setArgs("i", 1);
+                        osc.sendOsc(&sendMes);
+                    
+                    } else {
+                        
+                        sendMes.setTopAddress(SetMatrixAddress(ch * 2, i, true));
+                        sendMes.setArgs("i", 0);
+                        osc.sendOsc(&sendMes);
+                    }
+                    
+                }
+            }
+        }
+        
+        if (channelbeats[ch][2]) {
+            
+            if (!masterclock) {
+                
+                erase = MAXSTEPS - 1;
+                
+            } else {
+                
+                erase = masterclock - 1;
+            }
+            
+            sendMes.setTopAddress(SetMatrixAddress((ch * 2) + 1, erase, true));
+            sendMes.setArgs("i", 0);
+            osc.sendOsc(&sendMes);
+
+            sendMes.setTopAddress(SetMatrixAddress((ch * 2) + 1, masterclock, true));
+            sendMes.setArgs("i", 1);
+            osc.sendOsc(&sendMes);
+            
+            }
+            
+        // turn on pulses on channels where a beat is present  
+        if (BitRead(beat_holder[ch], read_head)) {
+            
+            if (!gatesoff)
+            {
+                gGATES[ch] = true; // pulse out
+            }
+            
+            sendMes.setTopAddress(SetMatrixAddress((MAXCHANNELS * 2), 3 - ch, true));
+            sendMes.setArgs("i", 1);
+            osc.sendOsc(&sendMes);
+            
+            lights_active = pulses_active = true;
+            
+            if (!ch || (ch == 2)) { 
+                
+                rand_vel = 127 - (rand() / (RAND_MAX / 40)); // random velocity ch1, ch3
+                
+            } else {
+                
+                rand_vel = 95 - (rand() / (RAND_MAX / 70));  // random velocity ch2, ch4
+            }
+            
+            rand_len = 127 - (rand() / (RAND_MAX / 110));    // random Amp EG Decay
+            
+            midi.sendControlChange(0x07, rand_vel, (ch + 1)); // volca sample Vol
+            midi.sendControlChange(0x30, rand_len, (ch + 1)); // volca sample Amp EG Decay
+            midi.sendNoteOn(0, 127, (ch + 1)); // volca sample trriger on
+        }
+
+        // send off pulses to spare output for the first channel 
+        if (!(BitRead(beat_holder[ch], read_head)) && !ch) { // only relates to first channel
+            
+            if (!gatesoff)
+            {
+                gCLOCKOUT = true;
+            }
+            
+            sendMes.setTopAddress(SetMatrixAddress((MAXCHANNELS * 2), 5, true));
+            sendMes.setArgs("i", 1);
+            osc.sendOsc(&sendMes);
+            
+            lights_active = pulses_active = true;
+        }
+
+        // move counter to next position, ready for next pulse  
+        ++channelbeats[ch][2];
+
+        if ((channelbeats[ch][2]) >= (channelbeats[ch][0])) {
+            channelbeats[ch][2] = 0; 
+        }
+    }
+    
+    ++masterclock;
+    masterclock &= (MAXSTEPS - 1);
+
+    pulse_length = ((euc_time - last_sync) / 5);
+    last_sync = euc_time;
+}
+
+/* 3 functions to read each encoder   
+   returns +1, 0 or -1 dependent on direction 
+   Contains no internal debounce, so calls should be delayed 
+ */
+
+//-------------------------------------------------------------
+// Check Euclidean Seq N(length) Value
+
+int EncodeReadN(int ch) {
+    static float _enc[4];
+    int result = 0;
+    
+    switch (ch)
+    {
+        case 0:
+        
+            if (gEucA[0] == 0) {
+                _enc[ch] = result = 0;
+        
+            } else if (gEucA[0] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucA[0];
+    
+            } else if (gEucA[0] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucA[0];
+            }
+            
+            break;
+        
+        case 1:
+        
+            if (gEucA[3] == 0) {
+                _enc[ch] = result = 0;
+    
+            } else if (gEucA[3] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucA[3];
+
+            } else if (gEucA[3] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucA[3];
+            }
+        
+            break;
+        
+        case 2:
+        
+            if (gEucB[0] == 0) {
+                _enc[ch] = result = 0;
+    
+            } else if (gEucB[0] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucB[0];
+
+            } else if (gEucB[0] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucB[0];
+            }
+        
+            break;
+        
+        case 3:
+        
+            if (gEucB[3] == 0) {
+                _enc[ch] = result = 0;
+    
+            } else if (gEucB[3] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucB[3];
+
+            } else if (gEucB[3] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucB[3];
+            }
+        
+            break;
+        
+        default:
+            break;
+    }
+    
+    return result;
+}
+
+//-------------------------------------------------------------
+// Check Euclidean Seq K(Density) Value
+
+int EncodeReadK(int ch) { 
+    static float _enc[4];
+    int result = 0;
+    
+    switch (ch)
+    {
+        case 0:
+        
+            if (gEucA[1] == 0) {
+                _enc[ch] = result = 0;
+        
+            } else if (gEucA[1] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucA[1];
+    
+            } else if (gEucA[1] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucA[1];
+            }
+            
+            break;
+        
+        case 1:
+        
+            if (gEucA[4] == 0) {
+                _enc[ch] = result = 0;
+    
+            } else if (gEucA[4] < _enc[ch]) {  
+                result = -4;
+                _enc[ch] = gEucA[4];
+
+            } else if (gEucA[4] > _enc[ch]) { 
+                result = 4;
+                _enc[ch] = gEucA[4];
+            }
+        
+            break;
+        
+        case 2:
+        
+            if (gEucB[1] == 0) {
+                _enc[ch] = result = 0;
+    
+            } else if (gEucB[1] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucB[1];
+
+            } else if (gEucB[1] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucB[1];
+            }
+        
+            break;
+        
+        case 3:
+        
+            if (gEucB[4] == 0) {
+                _enc[ch] = result = 0;
+    
+            } else if (gEucB[4] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucB[4];
+
+            } else if (gEucB[4] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucB[4];
+            }
+        
+            break;
+        
+        default:
+            break;      
+    }
+    
+    return result;
+}
+
+//-------------------------------------------------------------
+// Check Euclidean Seq O(Offset) Value
+
+int EncodeReadO(int ch) { 
+    static float _enc[4];
+    int result = 0;
+    
+    switch (ch)
+    {
+        case 0:
+        
+            if (gEucA[2] == 0) {
+                _enc[ch] = result = 0;
+        
+            } else if (gEucA[2] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucA[2];
+    
+            } else if (gEucA[2] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucA[2];
+            }
+            
+            break;
+        
+        case 1:
+        
+            if (gEucA[5] == 0) {
+                _enc[ch] = result = 0;
+    
+            } else if (gEucA[5] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucA[5];
+
+            } else if (gEucA[5] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucA[5];
+            }
+        
+            break;
+        
+        case 2:
+        
+            if (gEucB[2] == 0) {
+                _enc[ch] = result = 0;
+    
+            } else if (gEucB[2] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucB[2];
+
+            } else if (gEucB[2] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucB[2];
+            }
+        
+            break;
+        
+        case 3:
+        
+            if (gEucB[5] == 0) {
+                _enc[ch] = result = 0;
+    
+            } else if (gEucB[5] < _enc[ch]) {  
+                result = -1;
+                _enc[ch] = gEucB[5];
+
+            } else if (gEucB[5] > _enc[ch]) { 
+                result = 1;
+                _enc[ch] = gEucB[5];
+            }
+        
+            break;
+        
+        default:
+            break;
+    }
+    
+    return result;
+}
+
+inline char * SetMatrixAddress(int row, int column, bool euclid) {
+    static char address[32];
+    char col[2];
+    char ch[2];
+    
+    if(euclid)
+    {
+        strcpy(address, MATRIX_ADDRESS);
+    
+    } else {
+        
+        strcpy(address, STEP_INDICATOR_ADDRESS);
+    }
+    
+    sprintf(col, "%d", column + 1);
+    strcat(address, col);
+    
+    if(euclid)
+    {
+        strcat(address, "/");
+        
+        sprintf(ch, "%d", row + 1);
+        strcat(address, ch);
+    
+    } else {
+        
+        strcat(address, "/1");
+    }
+    
+    return address;
+}
+
--- a/mbed-rpc.lib	Thu Oct 16 14:14:25 2014 +0000
+++ b/mbed-rpc.lib	Sun Aug 02 10:01:07 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/teams/mbed-official/code/mbed-rpc/#2a26fd6a2b36
+http://mbed.org/teams/mbed-official/code/mbed-rpc/#d3e03663a6f4
--- a/mbed.bld	Thu Oct 16 14:14:25 2014 +0000
+++ b/mbed.bld	Sun Aug 02 10:01:07 2015 +0000
@@ -1,1 +1,1 @@
-http://mbed.org/users/mbed_official/code/mbed/builds/552587b429a1
\ No newline at end of file
+http://mbed.org/users/mbed_official/code/mbed/builds/bad568076d81
\ No newline at end of file