Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Bonjour OSCReceiver TextLCD mbed mbed-rpc BurstSPI DebouncedInterrupt FastIO MIDI OSC OSCtoCV ClockControl
example.h
- Committer:
- casiotone401
- Date:
- 2013-04-14
- Revision:
- 12:33c8f06c2e03
- Child:
- 13:3f42e451a8d3
File content as of revision 12:33c8f06c2e03:
//-------------------------------------------------------------
// 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_Calb 0 // Calibration (for VCO Tuning)
#define MODE_LIN 1 // Linear LinearCV
#define MODE_QChr 2 // Chromatic Quantize Mode
#define MODE_QMaj 3 // Major
#define MODE_QDor 4 // Dorian
#define MODE_Q5th 5 // 5th
#define MODE_QWht 6 // Wholetone
#define MODE_SEQ 7 // Sequencer & Shift Register
#define MODE_SHIF 8 // Mode Shift
#define MODE_NUM 9 // Modes
#define Lin 0 // Linear LinearCV
#define Chr 1 // Chromatic
#define Maj 2 // Major
#define M7 3 // Major7
#define Min7 4 // Minor7
#define Dor 5 // Dorian
#define Min 6 // Minor
#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 48000000 // 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 (See datasheet)
#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
#define GATE1 0
#define GATE2 1
#define GATE3 2
#define GATE4 3
#define GATEALL 4
//-------------------------------------------------------------
// Beats (Note values)
#define N1ST 1 // whole
#define N2ND 2 // harf
#define N4TH 4 // quarter
#define N8TH 8
#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 NRESET 0 // Gate Reset
//-------------------------------------------------------------
// Functions
inline void NetPoll(void);
void InitOSCCV(void);
inline void Seq(void);
inline void UpdateCV(int, int, const unsigned int*);
inline int UpdateTrigger(volatile bool);
inline int UpdateGate(int, int, int, int, bool);
inline void SetCV(void);
inline void SetSCV(void);
inline void ShiftCV(int);
inline void SeqCV(int);
void CheckModeSW(void);
inline void CVMeter(int, const unsigned int*);
void LCD();
void WriteCustomChar(unsigned char, unsigned char*);
int SetupEthNetIf(void);
inline void onUDPSocketEvent(UDPSocketEvent);
//-------------------------------------------------------------
// Silentway Calibration Data Mapping
// http://www.expert-sleepers.co.uk/silentway.html
// Chromatic Scale
const float calibMap1[QUAN_RES1] = {
0.00559238, 0.01324014, 0.02088790, 0.02853566, 0.03618342,
0.04383118, 0.05147894, 0.05912671, 0.06677447, 0.07442223,
0.08206999, 0.08971775, 0.09736551, 0.10501327, 0.11266103,
0.12030879, 0.12775089, 0.13486665, 0.14198242, 0.14909819,
0.15621395, 0.16332972, 0.17044549, 0.17756125, 0.18467702,
0.19179279, 0.19890857, 0.20602433, 0.21314010, 0.22025587,
0.22737163, 0.23448740, 0.24160317, 0.24871893, 0.25587305,
0.26303557, 0.27019811, 0.27736065, 0.28452319, 0.29168573,
0.29884824, 0.30601078, 0.31317332, 0.32033587, 0.32749838,
0.33466092, 0.34182346, 0.34898600, 0.35614854, 0.36331105,
0.37047359, 0.37764084, 0.38481620, 0.39199156, 0.39916691,
0.40634227, 0.41351759, 0.42069295, 0.42786831, 0.43504366,
0.44221902, 0.44939438, 0.45656973, 0.46374506, 0.47092041,
0.47809577, 0.48527113, 0.49244648, 0.49962184, 0.50685716,
0.51409578, 0.52133441, 0.52857304, 0.53581166, 0.54305035,
0.55028898, 0.55752760, 0.56476623, 0.57200485, 0.57924354,
0.58648217, 0.59372079, 0.60095942, 0.60819805, 0.61543667,
0.62267536, 0.62996829, 0.63728690, 0.64460552, 0.65192413,
0.65924275, 0.66656137, 0.67387998, 0.68119860, 0.68851727,
0.69583589, 0.70315450, 0.71047312, 0.71779174, 0.72511035,
0.73242897, 0.73974758, 0.74706620, 0.75810421, 0.77163076,
0.78515732, 0.79868382, 0.81221038, 0.82573694, 0.83926344,
0.85279000, 0.86631656, 0.88188213, 0.90110368, 0.92032516
};
// Major Scale
const float calibMap2[QUAN_RES2] = {
0.01324014, 0.02853566, 0.03618342, 0.05147894, 0.06677447,
0.08206999, 0.08971775, 0.10501327, 0.12030879, 0.12775089,
0.14198242, 0.15621395, 0.17044549, 0.17756125, 0.19179279,
0.20602433, 0.21314010, 0.22737163, 0.24160317, 0.25587305,
0.26303557, 0.27736065, 0.29168573, 0.29884824, 0.31317332,
0.32749838, 0.34182346, 0.34898600, 0.36331105, 0.37764084,
0.38481620, 0.39916691, 0.41351759, 0.42786831, 0.43504366,
0.44939438, 0.46374506, 0.47092041, 0.48527113, 0.49962184,
0.51409578, 0.52133441, 0.53581166, 0.55028898, 0.55752760,
0.57200485, 0.58648217, 0.60095942, 0.60819805, 0.62267536,
0.63728690, 0.64460552, 0.65924275, 0.67387998, 0.68851727,
0.69583589, 0.71047312, 0.72511035, 0.73242897, 0.74706620,
0.77163076, 0.79868382, 0.81221038, 0.83926344, 0.86631656,
0.88188213, 0.92032516
};
// M7(9)
const float calibMap3[QUAN_RES3] = {
0.02853566, 0.05147894, 0.08206999, 0.08971775, 0.12030879,
0.14198242, 0.17044549, 0.17756125, 0.20602433, 0.22737163,
0.25587305, 0.26303557, 0.29168573, 0.31317332, 0.34182346,
0.34898600, 0.37764084, 0.39916691, 0.42786831, 0.43504366,
0.44939438, 0.46374506, 0.48527113, 0.51409578, 0.52133441,
0.55028898, 0.57200485, 0.60095942, 0.60819805, 0.62267536,
0.63728690, 0.65924275, 0.68851727, 0.69583589, 0.72511035,
0.74706620, 0.79868382, 0.86631656, 0.92032516
};
// m7(9)
const float calibMap4[QUAN_RES4] = {
0.01324014, 0.02088790, 0.03618342, 0.05147894, 0.07442223,
0.08971775, 0.11266103, 0.14198242, 0.16332972, 0.17756125,
0.19890857, 0.22737163, 0.24160317, 0.24871893, 0.26303557,
0.29168573, 0.31317332, 0.33466092, 0.34898600, 0.36331105,
0.37047359, 0.38481620, 0.39916691, 0.41351759, 0.42069295,
0.43504366, 0.45656973, 0.48527113, 0.50685716, 0.52133441,
0.53581166, 0.55752760, 0.57200485, 0.59372079, 0.62267536,
0.62996829, 0.64460552, 0.65924275, 0.68119860, 0.69583589,
0.71779174, 0.74706620, 0.77163076, 0.78515732, 0.81221038,
0.83926344, 0.85279000, 0.92032516
};
// Dorian Scale
const float calibMap5[QUAN_RES5] = {
0.01324014, 0.02853566, 0.04383118, 0.05147894, 0.06677447,
0.08206999, 0.08971775, 0.10501327, 0.12030879, 0.13486665,
0.14198242, 0.15621395, 0.17044549, 0.17756125, 0.19179279,
0.20602433, 0.22025587, 0.22737163, 0.24160317, 0.25587305,
0.26303557, 0.27736065, 0.29168573, 0.30601078, 0.31317332,
0.32749838, 0.34182346, 0.34898600, 0.36331105, 0.37764084,
0.39199156, 0.39916691, 0.41351759, 0.42786831, 0.43504366,
0.44939438, 0.46374506, 0.47809577, 0.48527113, 0.49962184,
0.51409578, 0.52133441, 0.53581166, 0.55028898, 0.56476623,
0.57200485, 0.58648217, 0.60095942, 0.60819805, 0.62267536,
0.63728690, 0.65192413, 0.65924275, 0.67387998, 0.68851727,
0.69583589, 0.71047312, 0.72511035, 0.73974758, 0.74706620,
0.77163076, 0.79868382, 0.81221038, 0.83926344, 0.86631656,
0.90110368, 0.92032516
};
// Minor Scale
const float calibMap6[QUAN_RES6] = {
0.01324014, 0.02088790, 0.03618342, 0.05147894, 0.05912671,
0.07442223, 0.08971775, 0.10501327, 0.11266103, 0.12775089,
0.14198242, 0.14909819, 0.16332972, 0.17756125, 0.19179279,
0.19890857, 0.21314010, 0.22737163, 0.23448740, 0.24871893,
0.26303557, 0.27736065, 0.28452319, 0.29884824, 0.31317332,
0.32033587, 0.33466092, 0.34898600, 0.36331105, 0.37047359,
0.38481620, 0.39916691, 0.40634227, 0.42069295, 0.43504366,
0.44939438, 0.45656973, 0.47092041, 0.48527113, 0.49244648,
0.50685716, 0.52133441, 0.53581166, 0.54305035, 0.55752760,
0.57200485, 0.57924354, 0.59372079, 0.60819805, 0.62267536,
0.62996829, 0.64460552, 0.65924275, 0.66656137, 0.68119860,
0.69583589, 0.71047312, 0.71779174, 0.73242897, 0.74706620,
0.75810421, 0.78515732, 0.81221038, 0.83926344, 0.85279000,
0.88188213, 0.92032516
};
// 5th
const float calibMap7[QUAN_RES7] = {
0.01324014, 0.06677447, 0.12030879, 0.17044549, 0.22025587,
0.27019811, 0.32033587, 0.37047359, 0.42069295, 0.47092041,
0.52133441, 0.57200485, 0.62267536, 0.67387998, 0.72511035,
0.79868382, 0.90110368
};
// Whole tone
const float calibMap8[QUAN_RES8] = {
0.01324014, 0.02853566, 0.04383118, 0.05912671, 0.07442223,
0.08971775, 0.10501327, 0.12030879, 0.13486665, 0.14909819,
0.16332972, 0.17756125, 0.19179279, 0.20602433, 0.22025587,
0.23448740, 0.24871893, 0.26303557, 0.27736065, 0.29168573,
0.30601078, 0.32033587, 0.33466092, 0.34898600, 0.36331105,
0.37764084, 0.39199156, 0.40634227, 0.42069295, 0.43504366,
0.44939438, 0.46374506, 0.47809577, 0.49244648, 0.50685716,
0.52133441, 0.53581166, 0.55028898, 0.56476623, 0.57924354,
0.59372079, 0.60819805, 0.62267536, 0.63728690, 0.65192413,
0.66656137, 0.68119860, 0.69583589, 0.71047312, 0.72511035,
0.73974758, 0.75810421, 0.78515732, 0.81221038, 0.83926344,
0.86631656, 0.90110368
};
//-------------------------------------------------------------
// CV Meter Custom Character
unsigned char str1[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F};
unsigned char str2[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x1F};
unsigned char str3[8] = {0x00,0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F};
unsigned char str4[8] = {0x00,0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F};
unsigned char str5[8] = {0x00,0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F};
unsigned char str6[8] = {0x00,0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
unsigned char str7[8] = {0x00,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
unsigned char str8[8] = {0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F,0x1F};
//-------------------------------------------------------------
// Global Variables
float gOSC_cv[8];
float gSeq_cv1[8], gSeq_cv2[8];
float gGlide;
volatile int gMode;
// Variables for Control
float gCtrl[3];
volatile bool gCtrlSW[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] = {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
Timer gTimer; // Timer
Ticker gPoller; // Ticker Polling
// Ethernet
EthernetNetIf gEth;
UDPSocket gUdp;
//-------------------------------------------------------------
// main
int main()
{
float pot, _pot;
//http://mbed.org/forum/mbed/topic/229/?page=2#comment-13047
//Clock Up 100Mhz -------------------------------------------------------------
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 = 0x00020031; /* configure PLL0 */
LPC_SC->PLL0FEED = 0xAA; /* divide by 3 then multiply by 50 */
LPC_SC->PLL0FEED = 0x55; /* PLL0 frequency = 400,000,000 */
LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0 */
LPC_SC->PLL0CON = 0x03; /* PLL0 Enable & Connect */
LPC_SC->PLL0FEED = 0xAA;
LPC_SC->PLL0FEED = 0x55;
while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24))));/* Wait for PLLC0_STAT & PLLE0_STAT */
SystemCoreClockUpdate();
//-----------------------------------------------------------------------------
if(SetupEthNetIf() == -1)
{
for(int 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;
LCD();
gLCD.locate( 0, 1 );
gLCD.printf("12345678 G>>%3.2f", gGlide);
// loop
while(1)
{
gGlide = pot = gAIN.read(); // Glide Value
if(abs(pot - _pot) > 0.01f)
{
gLCD.locate( 0, 1 );
gLCD.printf("12345678 G>>%3.2f", gGlide);
_pot = gAIN.read();
}
switch(gMode)
{
case MODE_SEQ:
Seq();
break;
case MODE_SHIF:
ShiftCV((UpdateTrigger(gGATES[0])));
break;
case MODE_LIN:
SetSCV();
break;
default:
SetCV();
break;
}
}
}
//-------------------------------------------------------------
// 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(&CheckModeSW); // InterruptIn rising edge(ModeSW)
gPoller.attach_us(&NetPoll, POLLING_INTERVAL); // Ticker Polling
wait(0.2);
}
//-------------------------------------------------------------
// Ethernet Polling
inline void NetPoll()
{
Net::poll();
}
//-------------------------------------------------------------
// Sequencer Mode
inline void Seq()
{
static int bpm, _bpm;
bpm = (gCtrl[0] * 300 + 10); // Set BPM (gCtrl[0])
if(abs(bpm - _bpm) > 1)
{
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);
} else if (gCtrlSW[2] && !gCtrlSW[3]) { // Sequencer Mode2 (if gCtrlSW[2] ON)
SeqCV((UpdateGate(bpm, N16TH, GATE1, 3, false))); // Do shift ch 1~5
SeqCV((UpdateGate(bpm, N4TH, GATE2, 3, false))); // Do shift ch 6
SeqCV((UpdateGate(bpm, NDOT4, GATE3, 3, false))); // Do shift ch 7
SeqCV((UpdateGate(bpm, TRIP8, GATE4, 3, false))); // Do shift ch 8
} else if (gCtrlSW[3]) { // Sequencer Mode3 (if gCtrlSW[3] ON)
// (ch6,7,8, short loop)
SeqCV((UpdateGate(bpm, N16TH, GATE1, 3, false))); // Do shift ch 1~5
SeqCV((UpdateGate(bpm, N8TH, GATE2, 3, false))); // Do shift ch 6
SeqCV((UpdateGate(bpm, NDOT8, GATE3, 3, false))); // Do shift ch 7
SeqCV((UpdateGate(bpm, TRIP4, GATE4, 3, false))); // Do shift ch 8
}
}
//-------------------------------------------------------------
// SPI Transfer
// DAC8568 data word length 32bit (8bit shift out)
inline void UpdateCV(int control, int address, const unsigned int *data)
{
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;
}
}
//-------------------------------------------------------------
// UpdateTrigger
inline int UpdateTrigger(bool gate)
{
static bool clkstate;
static int gatetime, oldgatetime;
static int oldshift;
int time = gTimer.read_ms();
if(gate && !clkstate)
{
oldgatetime = time;
clkstate = 1;
} else if (!gate && clkstate) {
gatetime = time - oldgatetime + 2;
clkstate = 0;
} else if (gCtrlSW[0]) {
gTimer.reset();
oldshift = clkstate = 0;
}
if(time >= oldshift + gatetime)
{
oldshift = time;
return 1;
} else {
return 0;
}
}
//-------------------------------------------------------------
// GateOutSequence beat(Note values) length(Gate time) invert(invert Gate)
inline int UpdateGate(int bpm, int beat, int ch, int length, bool invert)
{
int i;
static int gatetime[4], oldgatetime[4];
static int bar, sync24, oldsynctime;
int time = gTimer.read_us();
bar = (60.0f / bpm) * 4000000;
sync24 = (bar / 4) / 24; // sync24 not tested
switch(beat) // Calculate Note values
{
case NDOT2:
gatetime[ch] = (bar / 4) * 3;
break;
case NDOT4:
gatetime[ch] = (bar / 8) * 3;
break;
case NDOT8:
gatetime[ch] = (bar / 16) * 3;
break;
case NDOT16:
gatetime[ch] = (bar / 32) * 3;
break;
case NDOT32:
gatetime[ch] = (bar / 64) * 3;
break;
case TRIP2:
gatetime[ch] = bar / 3;
break;
case TRIP4:
gatetime[ch] = (bar / 2) / 3;
break;
case TRIP8:
gatetime[ch] = (bar / 4) / 3;
break;
case TRIP16:
gatetime[ch] = (bar / 8) / 3;
break;
case TRIP32:
gatetime[ch] = (bar / 16) / 3;
break;
case NRESET:
for(i = 0; i < GATEALL; ++i) // Reset
{
gTimer.reset();
oldsynctime = oldgatetime[i] = gatetime[i] = NRESET;
}
break;
default:
gatetime[ch] = bar / beat;
}
if(time > oldsynctime + sync24) // sync24 not tested
{
oldsynctime = time;
gCLOCKOUT = 1;
} else if (time > sync24 - (sync24 - 2)) {
gCLOCKOUT = 0;
}
if (ch == GATEALL)
{
return -1;
} else if (time > oldgatetime[ch] + gatetime[ch] && !invert) {
oldgatetime[ch] = time;
gLEDS[ch] = gGATES[ch] = 1;
return ch + 1;
} else if (time > oldgatetime[ch] + gatetime[ch] && invert) {
oldgatetime[ch] = time;
gLEDS[ch] = gGATES[ch] = 0;
return 0;
} else if (time > oldgatetime[ch] + (gatetime[ch] - gatetime[ch] / length) && !invert) {
gLEDS[ch] = gGATES[ch] = 0;
return 0;
} else if (time > oldgatetime[ch] + (gatetime[ch] - gatetime[ch] / length) && invert) {
gLEDS[ch] = gGATES[ch] = 1;
return ch + 1;
} else {
return -1;
}
}
//-------------------------------------------------------------
// Calculate CV
inline void SetCV()
{
static int ch, quan;
static float glidecv[8], oldcv[8];
unsigned int cv[8];
float qcv;
switch(gMode)
{
case MODE_LIN:
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + gOSC_cv[ch] * (1.0f - gGlide);
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)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
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)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case MODE_QDor:
quan = 40616 / QUAN_RES5;
qcv = calibMap5[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case MODE_Q5th:
quan = 40616 / QUAN_RES7;
qcv = calibMap7[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case MODE_QWht:
quan = 40616 / QUAN_RES8;
qcv = calibMap8[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case MODE_Calb:
cv[ch] = 19212; // A880.0Hz
gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = 1;
gLEDS[0] = gLEDS[1] = gLEDS[2] = gLEDS[3] = 1;
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
}
CVMeter(ch, &cv[ch]);
ch++;
ch &= 0x07;
}
//-------------------------------------------------------------
// Calculate CV
inline void SetSCV()
{
static int ch, quan, mode;
static float glidecv[8], oldcv[8];
unsigned int cv[8];
float qcv;
mode = (gCtrl[1] * 8);
gCLOCKOUT = gGATES[0];
switch(mode)
{
case Lin:
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + gOSC_cv[ch] * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case Chr:
quan = 40616 / QUAN_RES1;
qcv = calibMap1[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case Maj:
quan = 40616 / QUAN_RES2;
qcv = calibMap2[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case M7:
quan = 40616 / QUAN_RES3;
qcv = calibMap3[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case Min7:
quan = 40616 / QUAN_RES4;
qcv = calibMap4[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case Dor:
quan = 40616 / QUAN_RES5;
qcv = calibMap5[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case Min:
quan = 40616 / QUAN_RES6;
qcv = calibMap6[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case S5th:
quan = 40616 / QUAN_RES7;
qcv = calibMap7[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
case Wht:
quan = 40616 / QUAN_RES8;
qcv = calibMap8[(unsigned int)(gOSC_cv[ch] / quan)];
oldcv[ch] = glidecv[ch] = oldcv[ch] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[ch] = (unsigned int)glidecv[ch];
UpdateCV(WRITE_UPDATE_N, ch, &cv[ch]);
break;
}
CVMeter(ch, &cv[ch]);
ch++;
ch &= 0x07;
}
//-------------------------------------------------------------
// Sequence & Shift Out CV
inline void SeqCV(int shift)
{
int i, j, k;
static int ch, quan, mode;
static int cnt1, cnt2, cnt3;
static int cntloop1, cntloop2, cntloop3;
static float glidecv[8], shiftcv[8];
static float buffercv[9], loopcv[3];
unsigned int cv[8];
float qcv;
mode = (gCtrl[1] * 8); // Sequencer Quantize Mode (gCtrl[1])
switch(mode)
{
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);
}
cv[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
break;
case Chr:
quan = 40616 / QUAN_RES1;
if(ch < 8)
{
qcv = calibMap1[(unsigned int)(gSeq_cv1[ch] / quan)];
} else {
qcv = calibMap1[(unsigned int)(gSeq_cv2[ch-8] / quan)];
}
glidecv[0] = glidecv[0] * gGlide + (qcv * SCALING_N) * (1.0f - gGlide);
cv[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
break;
case 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[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
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);
cv[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
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);
cv[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
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[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
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[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
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);
cv[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
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);
cv[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
break;
}
if(!gCtrlSW[2] && !gCtrlSW[3]) // Sequencer Mode1
{
for(i = 1; i < 8; ++i)
{
glidecv[i] = glidecv[i] * gGlide + shiftcv[i] * (1.0f - gGlide);
cv[i] = (unsigned int)glidecv[i];
UpdateCV(WRITE_UPDATE_N, i, &cv[i]);
}
if(shift == 1) // GATE1
{
for(j = 1; j < 8; ++j) // Shift ch2~8
{
shiftcv[j] = glidecv[j-1];
}
ch++;
ch &= 0x0F;
}
cnt1 = cnt2 = cnt3 = 0;
} else if (gCtrlSW[2] && !gCtrlSW[3]) { // Sequencer Mode2
for(i = 1; i < 8; ++i)
{
glidecv[i] = glidecv[i] * gGlide + shiftcv[i] * (1.0f - gGlide);
cv[i] = (unsigned int)glidecv[i];
UpdateCV(WRITE_UPDATE_N, i, &cv[i]);
}
if(shift == 1) // GATE1
{
for(j = 1; j < 5; ++j)
{
shiftcv[j] = glidecv[j-1]; // Shift ch2~5
}
ch++;
ch &= 0x0F;
} else if (shift == 2) { // GATE2
shiftcv[5] = glidecv[1]; // Shift ch6
} else if (shift == 3) { // GATE3
shiftcv[6] = glidecv[2]; // Shift ch7
} else if (shift == 4) { // GATE4
shiftcv[7] = glidecv[3]; // Shift ch8
}
cnt1 = cnt2 = cnt3 = 0;
} else if (gCtrlSW[3]) { // Sequencer Mode3
for(i = 1; i < 5; ++i)
{
glidecv[i] = glidecv[i] * gGlide + shiftcv[i] * (1.0f - gGlide);
cv[i] = (unsigned int)glidecv[i];
UpdateCV(WRITE_UPDATE_N, i, &cv[i]);
}
for(j = 5; j < 8; ++j)
{
glidecv[j] = glidecv[j] * gGlide + loopcv[j - 5] * (1.0f - gGlide);
cv[j] = (unsigned int)glidecv[j];
UpdateCV(WRITE_UPDATE_N, j, &cv[j]);
}
if(shift == 1) // GATE1
{
for(k = 1; k < 8; ++k)
{
shiftcv[k] = glidecv[k-1]; // Shift ch2~5
}
ch++;
ch &= 0x0F;
} else if (shift == 2) { // GATE2
if(cnt1 < 4)
{
loopcv[0] = buffercv[cnt1] = shiftcv[4];
cnt1++;
} else if (cnt1 >= 4) {
loopcv[0] = buffercv[cntloop1];
cntloop1++;
cntloop1 &= 0x03;
}
} else if (shift == 3) { // GATE3
if(cnt2 < 3)
{
loopcv[1] = buffercv[(cnt2 + 4)] = shiftcv[5];
cnt2++;
} else if (cnt2 >= 3) {
loopcv[1] = buffercv[(cntloop2 + 4)];
cntloop2++;
cntloop2 &= 0x03;
}
} else if (shift == 4) { // GATE4
if(cnt3 < 2)
{
loopcv[2] = buffercv[(cnt3 + 7)] = shiftcv[6];
cnt3++;
} else if (cnt3 >= 2) {
loopcv[2] = buffercv[(cntloop3 + 7)];
cntloop3++;
cntloop3 &= 0x01;
}
}
if(gCtrlSW[1]) // Update loop buffer (if gCtrlSW[1] ON)
{
cnt1 = cnt2 = cnt3 = 0;
}
}
if(ch < 8)
{
CVMeter(ch, &cv[0]);
} else {
CVMeter((ch-8), &cv[0]);
}
}
//-------------------------------------------------------------
// Shift CV
inline void ShiftCV(int shift)
{
int i;
static int ch;
static float glidecv[8], shiftcv[8], oldcv;
unsigned int cv[8];
gLEDS[1] = gGATES[1] = gGATES[0];
oldcv = glidecv[0] = glidecv[0] * gGlide + gOSC_cv[0] * (1.0f - gGlide);
cv[0] = (unsigned int)glidecv[0];
UpdateCV(WRITE_UPDATE_N, 0, &cv[0]);
glidecv[ch+1] = glidecv[ch+1] * gGlide + shiftcv[ch+1] * (1.0f - gGlide);
cv[ch+1] = (unsigned int)glidecv[ch+1];
UpdateCV(WRITE_UPDATE_N, ch+1, &cv[ch+1]);
if(shift == 1) // GATE1
{
shiftcv[0] = oldcv;
for(i = 7; i > 0; --i)
{
shiftcv[i] = shiftcv[i-1];
}
}
if(ch < 8)
{
CVMeter(ch, &cv[0]);
} else {
CVMeter((ch-8), &cv[0]);
}
ch++;
ch &= 0x07;
}
//-------------------------------------------------------------
// Check SW
void CheckModeSW()
{
wait(0.05);
if(gMode < MODE_NUM - 1)
{
gMode++;
} else {
gMode = 0;
}
gCLOCKOUT = gGATES[0] = gGATES[1] = gGATES[2] = gGATES[3] = 0;
gLEDS[0] = gLEDS[1] = gLEDS[2] = gLEDS[3] = 0;
if((gMode == MODE_SEQ) || (gMode == MODE_SHIF))
{
gTimer.start(); // Sequencer Timer Start
} else {
gTimer.stop(); // Sequencer Timer Stop
}
LCD();
}
//-------------------------------------------------------------
// CV meter
inline void CVMeter(int ch, const unsigned int *level)
{
int cvmeter;
cvmeter = *level / (SCALING_N / 7.9f);
gLCD.locate ( ch, 0 );
gLCD.putc(cvmeter); // put custom char
}
//-------------------------------------------------------------
// 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_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_SEQ:
gLCD.locate( 9, 0 );
gLCD.printf("ASRSEQ ");
break;
case MODE_SHIF:
gLCD.locate( 9, 0 );
gLCD.printf("ASHSEQ ");
break;
}
}
//-------------------------------------------------------------
// 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(1.0);
return 0;
}
//-------------------------------------------------------------
// Handller receive UDP Packet
inline void onUDPSocketEvent(UDPSocketEvent e)
{
union OSCarg msg[10];
char buf[768] = {0};
int num, recvlen, len;
unsigned int absv;
int messagepos = 0;
bool bundleflag = false;
Host host;
switch(e)
{
case UDPSOCKET_READABLE: // The only event for now
recvlen = gUdp.recvfrom(buf, 768, &host); // packet length
if(recvlen <= 0) break;
if(buf[0] == '#') // #bundle
{
messagepos += 16; // skip #bundle & timetag
recvlen -= 16;
bundleflag = true;
}
do {
if(bundleflag)
{
messagepos += 4;
recvlen -= 4;
if(recvlen <= 0)
{
bundleflag = false;
break;
}
}
if(getOSCmsg(buf + messagepos, msg) == -1) continue;
len = strlen(msg[0].address);
if(isdigit(msg[0].address[len-1]))
{
num = msg[0].address[len-1] - '0' - 1;
} else {
num = -1;
}
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))
{
if(absv >= 1 || msg[2].i >= 1) gCLOCKOUT = 1;
else gCLOCKOUT = 0;
continue;
} else if (!strncmp(msg[0].address+(len-1)-4, "gate", 4) && (num != -1)) {
if(num > 4) continue;
if(absv >= 1 || msg[2].i >= 1) gLEDS[num] = gGATES[num] = 1;
else gLEDS[num] = gGATES[num] = 0;
continue;
// (touchOSC Control push, toggle)
} else if (!strncmp(msg[0].address+(len-1)-4, "push", 4) && (num != -1)) {
if(num > 4) continue;
if(absv >= 1 || msg[2].i >= 1) 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(absv >= 1 || msg[2].i >= 1) 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(absv >= 1 || msg[2].i >= 1) 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);
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);
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);
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);
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 > 4) continue;
if(absv >= 1 || msg[2].i >= 1) gCtrlSW[num] = true;
else gCtrlSW[num] = false;
continue;
} else if (!strncmp(msg[0].address+(len-1)-4, "ctrl", 4) && (num != -1)) {
if(num > 3) continue;
if(msg[1].typeTag[1] == 'f') gCtrl[num] = msg[2].f;
continue;
}
} while(bundleflag);
}
}