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
Diff: example.h
- Revision:
- 12:33c8f06c2e03
- Child:
- 13:3f42e451a8d3
diff -r ef7610cd7ebe -r 33c8f06c2e03 example.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/example.h Sun Apr 14 00:54:10 2013 +0000
@@ -0,0 +1,1597 @@
+//-------------------------------------------------------------
+// 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);
+
+ }
+}