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
Revision 20:a44f4a024902, committed 2016-01-09
- Comitter:
- casiotone401
- Date:
- Sat Jan 09 10:58:45 2016 +0000
- Parent:
- 19:467f98c51e2d
- Child:
- 21:2273c3676f1b
- Commit message:
- separate source
Changed in this revision
--- a/OSC.lib Mon Jan 04 12:45:30 2016 +0000 +++ b/OSC.lib Sat Jan 09 10:58:45 2016 +0000 @@ -1,1 +1,1 @@ -http://developer.mbed.org/users/casiotone401/code/OSC/#f4118f0bc1ab +http://developer.mbed.org/users/casiotone401/code/OSC/#601f6a1141fb
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/OSCtoCV.lib Sat Jan 09 10:58:45 2016 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/casiotone401/code/OSCtoCV/#f26aadbd38a8
--- a/main.cpp Mon Jan 04 12:45:30 2016 +0000 +++ b/main.cpp Sat Jan 09 10:58:45 2016 +0000 @@ -1,6 +1,5 @@ //------------------------------------------------------------- -// TI DAC8568 OSCtoCV Converter ver.2 -// http://gtbts.tumblr.com/post/125663817741/osc-to-cv-converter-ver2-mbed-osctocv +// TI DAC8568 OSCtoCV Converter // // DAC8568 16bit Octal DAC http://www.ti.com/product/dac8568 // @@ -24,8 +23,8 @@ #include "mbed.h" #include "FastIO.h" +//#include "FastAnalogIn.h" #include "DebouncedInterrupt.h" -#include "BurstSPI.h" #include "TextLCD.h" //edit "writeCommand" "writeData" protected -> public #include "EthernetNetIf.h" #include "HTTPServer.h" @@ -34,12 +33,17 @@ #include "OSCReceiver.h" #include "mbedOSC.h" #include "MIDI.h" +#include "OSCtoCV.h" +#include "OSCtoCV_Sequencer.h" +#include "OSCtoCV_GateSequencer.h" +#include "OSCtoCV_Euclidean.h" + #include <stdlib.h> #include <ctype.h> #include <math.h> //------------------------------------------------------------- -// Define +// Macros #define MODE_Calb 0 // Calibration (for VCO Tuning) #define MODE_OSC 1 // Mode OSCtoCV @@ -49,292 +53,25 @@ #define MODE_TOTAL 5 // 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 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 21 // 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 - -//------------------------------------------------------------- -// Gate Sequencer Macros - -#define _DISABLE 0 -#define _ENABLE 1 - -#define GATE1 0 -#define GATE2 1 -#define GATE3 2 -#define GATE4 3 -#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) - -#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 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); -inline float MapFloat(float, float, float, float, float); -inline void UpdateCV(int, int, const unsigned int*); -inline void CalibrationCV(void); +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); +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 -const float calibMap1[QUAN_RES1] = { -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] = { -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] = { -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] -}; +// Global Variables -// m7(9) -const float calibMap4[QUAN_RES4] = { -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] = { -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] = { -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] = { -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] = { -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] -}; - -//------------------------------------------------------------- // 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}; @@ -344,113 +81,11 @@ 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_cv[16]; -float gGlide; -int gMode; - -// Variables for Control -/* -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 -gCtrlSW[4] /ctrlsw5 ASR Analog Mode - -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]; -float gAccent[16] = {0}; - -// 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 +// OSCtoCV Converter Mode +int gMode; -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 - -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 -//BufferedSoftSerial ardSerial(p25, p26); -MIDI midi(p28, p27); - -Timer gTimer; // Timer -Ticker gPoller; // Ticker for Polling - -// Ethernet -EthernetNetIf gEth; -/* 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; +// UDP Socket +UDPSocket gUdp; //------------------------------------------------------------- // main @@ -459,42 +94,10 @@ { float pot, _pot; int bpm; + + InitOSCCV(); -//Clock Up -------------------------------------------------------------------- - LPC_SC->PLL0CON = 0x00; /* PLL0 Disable */ - LPC_SC->PLL0FEED = 0xAA; - LPC_SC->PLL0FEED = 0x55; - - LPC_SC->CCLKCFG = 0x00000003; /* Select Clock Divisor = 4 */ - LPC_SC->PLL0CFG = 0x00020038; /* configure PLL0 */ - LPC_SC->PLL0FEED = 0xAA; /* divide by 3 then multiply by 50 */ - LPC_SC->PLL0FEED = 0x55; /* PLL0 frequency = 400,000,000 */ - - LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */ - LPC_SC->PLL0FEED = 0xAA; - LPC_SC->PLL0FEED = 0x55; - while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0 */ - - LPC_SC->PLL0CON = 0x03; /* PLL0 Enable & Connect */ - LPC_SC->PLL0FEED = 0xAA; - LPC_SC->PLL0FEED = 0x55; - while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24))));/* Wait for PLLC0_STAT & PLLE0_STAT */ - - SystemCoreClockUpdate(); -//----------------------------------------------------------------------------- - - if (SetupEthNetIf() == -1) - { - for (int i = 0; i < 4; ++i) - { - gGATES[i] = true; - wait(0.25); - } - - return -1; - } - - InitOSCCV(); + InitEuclideanSeq(); // Init Euclidean Sequencer gCtrl[3] = _pot = pot = gMode = 0; gGlide = gAIN.read(); @@ -575,11 +178,57 @@ } //------------------------------------------------------------- +// Ethernet Polling + +inline void NetPoll() +{ + Net::poll(); +} + +//------------------------------------------------------------- // Initialize OSCtoCV void InitOSCCV() { int i; + +//Clock Up -------------------------------------------------------------------- + LPC_SC->PLL0CON = 0x00; /* PLL0 Disable */ + LPC_SC->PLL0FEED = 0xAA; + LPC_SC->PLL0FEED = 0x55; + + LPC_SC->CCLKCFG = 0x00000003; /* Select Clock Divisor = 4 */ + LPC_SC->PLL0CFG = 0x00020038; /* configure PLL0 */ + LPC_SC->PLL0FEED = 0xAA; /* divide by 3 then multiply by 50 */ + LPC_SC->PLL0FEED = 0x55; /* PLL0 frequency = 400,000,000 */ + + LPC_SC->PLL0CON = 0x01; /* PLL0 Enable */ + LPC_SC->PLL0FEED = 0xAA; + LPC_SC->PLL0FEED = 0x55; + while (!(LPC_SC->PLL0STAT & (1<<26)));/* Wait for PLOCK0 */ + + LPC_SC->PLL0CON = 0x03; /* PLL0 Enable & Connect */ + LPC_SC->PLL0FEED = 0xAA; + LPC_SC->PLL0FEED = 0x55; + while (!(LPC_SC->PLL0STAT & ((1<<25) | (1<<24))));/* Wait for PLLC0_STAT & PLLE0_STAT */ + + SystemCoreClockUpdate(); +//----------------------------------------------------------------------------- + + wait(0.5); + +// Setup Ethernet + SetupEthNetIf(); + +// Announce mdnsResponder (Bonjour) + HTTPServer svr; + mDNSResponder mdns; + + svr.addHandler<SimpleHandler>("/"); + svr.bind(INPUT_PORT); + IpAddr ip = gEth.getIp(); + mdns.announce(ip, "OSCtoCV", "_osc._udp", INPUT_PORT, "mbed(OSCtoCV)", (char *[]) {"path=/",NULL}); + // Write custom char LCD CGRAM WriteCustomChar(0x00, str1); WriteCustomChar(0x01, str2); @@ -596,33 +245,7 @@ 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; @@ -634,16 +257,7 @@ // Init M185 Reset Count gCtrl[4] = 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}); - // Set OSC message for sending sendMes.setIp(touchOSCAddress); sendMes.setPort(touchOSCPort); @@ -652,78 +266,13 @@ wait(0.5); gPoller.attach_us(&NetPoll, POLLING_INTERVAL); // Ticker Polling - wait(1.5); - - // Begin Serial for Arduino - //ardSerial.baud(115200); -} - -//------------------------------------------------------------- -// Ethernet Polling - -inline void NetPoll() -{ - Net::poll(); -} - -//------------------------------------------------------------- -// Map Function - -inline float MapFloat(float x, float in_min, float in_max, float out_min, float out_max) -{ - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; -} - -//------------------------------------------------------------- -// 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; - } + wait(1.8); } //------------------------------------------------------------- // Calibration Mode -inline void CalibrationCV() +void CalibrationCV() { static int ch; unsigned int cv; @@ -852,694 +401,6 @@ } } -//------------------------------------------------------------- -// Sequence & Shift Out CV - -inline void ShiftCVSeq(int trigger, bool reset) -{ - int i, j; - 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; - static int jitterCount; - static int jitter; - - qmode = (gCtrl[1] * (SCALE_NUM - 1.0f)); // 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]); - - 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]); - - 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]); - - break; - - 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]); - - 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]); - - break; - - 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]); - - 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]); - - 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]); - - 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]); - - break; - } - - if (!gCtrlSW[4]) - { - jitter = 0; - - } else if (gCtrlSW[4] && jitterCount % 64 == 0) { // ASR Analog Mode - - jitter = (rand() % 100 - 50); - } - - cv = (unsigned int)(glidecv[0] + jitter); - - UpdateCV(WRITE_UPDATE_N, 0, &cv); - - for (i = 1; i < 8; ++i) - { - glidecv[i] = glidecv[i] * gSlide[currentStep] + shiftcv[i] * (1.0f - gSlide[currentStep]); - cv = (unsigned int)(glidecv[i] + jitter); - - UpdateCV(WRITE_UPDATE_N, i, &cv); - } - - if (trigger && !triggerState) // trigger ON - { - stepFoward = triggerState = true; - - } else if (!trigger) { // trigger OFF - - if (gateMode != HOLD) - { - gGATES[0] = false; - } - - triggerState = false; - } - -// check & update touchOSC ctrl parameter - if (_gateMode[ch] != (gGateMode[ch] * 3)) - { - _gateMode[ch] = (gGateMode[ch] * 3); - - if (_gateMode[ch] == MULTI) - { - _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; - } - - 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); - - if (currentStep < 8) - { - UpdateCVMeter(currentStep, &cv); - - } else { - - UpdateCVMeter((currentStep - 8), &cv); - } - - gateMode = (gGateMode[currentStep] * 3); - - if (gateMode == MULTI) // omit MULTI mode - { - gateMode = HOLD; - } - - if (gateMode != MUTE) - { - gGATES[0] = true; - } - - if (gAccent[currentStep]) // accent - { - gGATES[2] = gGATES[3] = true; - - } else { - - gGATES[2] = gGATES[3] = false; - } - - stepFoward = false; - } - - ++ch; - ch &= 0x0F; - - ++jitterCount; - jitterCount &= 0x1FF; -} - -//------------------------------------------------------------- -// M185 Sequencer - -inline void M185Seq(int trigger, bool reset) -{ - 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]); - - 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]); - - 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]); - - break; - - 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]); - - 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]); - - break; - - 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]); - - 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]); - - 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]); - - 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]); - - break; - } - - cv = (unsigned int)glidecv[0]; - - UpdateCV(WRITE_UPDATE_N, 0, &cv); - - 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 - { - 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; -} - -//------------------------------------------------------------- -// 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]; - - 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); - } - - sendMes.setTopAddress(gateModeAddress); - - switch (gateMode) - { - case SINGLE: - - sendMes.setArgs("s", "|"); - - break; - - case MUTE: - - sendMes.setArgs("s", "O"); - - break; - - case MULTI: - - sendMes.setArgs("s", "||"); - - break; - - case HOLD: - - sendMes.setArgs("s", "|-"); - - break; - } - - osc.sendOsc(&sendMes); -} - -//------------------------------------------------------------- -// 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[GATE_TOTAL], oldgatetime[GATE_TOTAL]; - static int _bpm, bar, sync24, oldsynctime; - - int time = gTimer.read_us(); - - 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 - { - 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 NRESET: - - gTimer.reset(); - - for (i = 0; i < GATE_TOTAL; ++i) // Reset - { - oldsynctime = oldgatetime[i] = gatetime[i] = NRESET; - } - - return 0; - - default: - - gatetime[ch] = bar / beat; - sync24 = bar / 16; - break; - } - - if (time > oldsynctime + sync24) // sync24 not tested - { - if (!syncoff) - { - oldsynctime = time; - gCLOCKOUT = true; - - midi.sendRealTime(Clock); // MIDI Clock - } - - } else if (time > oldsynctime - (sync24 - 2)) { - - if (!syncoff) - { - gCLOCKOUT = false; - } - } - - if (ch == GATE_TOTAL) - { - return -1; - - } else if (time > oldgatetime[ch] + gatetime[ch] && !invert) { - - oldgatetime[ch] = time; - - if (!gatesoff) - { - gGATES[ch] = true; - - } else if (ch == SUBGATE) { - - gSUBGATE = true; - } - - return 1; - - } else if (time > oldgatetime[ch] + gatetime[ch] && invert) { - - oldgatetime[ch] = time; - - if (!gatesoff) - { - gGATES[ch] = false; - - } else if (ch == SUBGATE) { - - gSUBGATE = false; - } - - return 0; - - } else if (time > oldgatetime[ch] + (gatetime[ch] - gatetime[ch] / length) && !invert) { - - if (!gatesoff) - { - gGATES[ch] = false; - - } else if (ch == SUBGATE) { - - gSUBGATE = false; - } - - return 0; - - } else if (time > oldgatetime[ch] + (gatetime[ch] - gatetime[ch] / length) && invert) { - - if (!gatesoff) - { - gGATES[ch] = true; - - } else if (ch == SUBGATE) { - - gSUBGATE = true; - } - - return 1; - - } else { - - return -1; - } -} - //------------------------------------------------------------- // Check BPM @@ -1556,20 +417,7 @@ return bpm; } - if (!gCtrl[0]) - { - bpm = gArdCtrl[0] * 0.25f + 5; - - if (abs(bpm - _bpm) > 1) - { - _bpm = bpm; - - sendMes.setTopAddress("/bpm"); - sendMes.setArgs("i", bpm); - osc.sendOsc(&sendMes); - } - - } else if (gCtrl[0]) { + if (gCtrl[0]) { bpm = (gCtrl[0] * 240 + 5); @@ -1589,7 +437,7 @@ //------------------------------------------------------------- // Check Mode SW -inline void CheckModeSW() +void CheckModeSW() { if (gMode < MODE_TOTAL - 1) { @@ -1773,15 +621,6 @@ } -//------------------------------------------------------------- -// 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 for CV Meter) @@ -1833,23 +672,6 @@ return 0; } -//------------------------------------------------------------- -// Fast strlen function http://www.strchr.com/optimized_strlen_function - -size_t strlength(const char *s) -{ - size_t len = 0; - - 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; - s += 4, len += 4; - } -} //------------------------------------------------------------- // Handller receive OSC UDP Packet @@ -2010,6 +832,22 @@ gEucB[num] = msg[2].f; continue; + } else if (!strncmp(msg[0].address + (len - offset) - 3, "acv", 3) && (num != -1)) { + if (num > 3) continue; + gArd_cv[num] = msg[2].f * (SCALING_N); + continue; + + } else if (!strncmp(msg[0].address + (len - offset) - 3, "pot", 3) && (num != -1)) { + if (num > 2) continue; + gArdPot[num] = msg[2].f; + continue; + + } else if (!strncmp(msg[0].address + (len - offset) - 2, "sw", 2) && (num != -1)) { + if (num > 2) continue; + if (msg[2].i != 0) gArdSW[num] = true; + else gArdSW[num] = false; + continue; + } else { continue; } @@ -2018,832 +856,3 @@ } } -//------------------------------------------------------------- -// 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]; - - if (euclid) - { - sprintf(address, "%s%d/%d", MATRIX_ADDRESS, column + 1, row + 1); - - } else { - - sprintf(address, "%s%d/1", STEP_INDICATOR_ADDRESS, column + 1); - } - - return address; -} -