KAMUI OSC-CV Example refer to OSCReceiver by xshige http://mbed.org/users/xshige/programs/OSCReceiver/
Dependencies: NetServices TextLCD mbed
Diff: main.cpp
- Revision:
- 0:eabe87e89290
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun May 06 07:17:59 2012 +0000 @@ -0,0 +1,444 @@ +//------------------------------------------------------------- +// KAMUI OSC-CV Exapmple +// referred to xshige's OSCReceiver +// http://mbed.org/users/xshige/programs/OSCReceiver/ +// Copyright (C) 2012 RJB RadioJunkBox +// Released under the MIT License: http://mbed.org/license/mit +//------------------------------------------------------------- + +#include "mbed.h" +#include "TextLCD.h" +#include "EthernetNetIf.h" +#include "UDPSocket.h" +#include "OSCReceiver.h" +#include <stdlib.h> +#include <ctype.h> +#include <math.h> + +//------------------------------------------------------------- +// Define + +#define AD5551 // 14bitDAC + +#define SPI_RATE 1000000 // 1Mbps +#define MIDI_RATE 31250 // 31.25kbps +#define BEEP_FREQ 1760.0 // 1760Hz +#define UPDATE_INTERVAL 100 // 100us +#define SW_WATCH_INTERVAL (25000/UPDATE_INTERVAL) // 25ms +#define PARAM_GLIDE 6554.0 + +#define UPDATE_MODE0 0 // Update Interval CV ch1-6 1200us, ch7,8 400us +#define UPDATE_MODE1 1 // Update Interval CV ch1-6 N/A, ch7,8 200us + +#define GATE1 0x01 +#define GATE2 0x02 +#define GATE3 0x04 +#define GATE4 0x08 + +#define SYNC1CLK 0x01 +#define SYNC1RUN 0x02 +#define SYNC2CLK 0x04 +#define SYNC2RUN 0x08 + +#define MODE_CV 0x00 +#define MODE_GATE 0x40 +#define MODE_SYNC 0x80 +#define MODE_SET_SYNC 0xC0 + +#define SW1 0x01 +#define SW2 0x02 +#define SW3 0x04 +#define SW4 0x08 +#define SYNC1CLK_IN 0x10 +#define SYNC1RUN_IN 0x20 +#define SYNC2CLK_IN 0x40 +#define GATE_IN 0x80 + +#define _ENABLE 0 +#define _DISABLE 1 + +//------------------------------------------------------------- +// Functions + +void InitKamui(void); +void UpdateCV(void); +unsigned char CheckSW(unsigned char); + +void SetCV(void); +int SetupEthNetIf(void); +void onUDPSocketEvent(UDPSocketEvent); + +//------------------------------------------------------------- +// Global Variables + +int gUpdateMode; +unsigned short gCV[8]; +unsigned char gGATE; +unsigned char gSYNC; +unsigned char gSW; + +union { + unsigned short WORD; + struct { + unsigned char L; + unsigned char H; + } BYTE; +} gDAC; + +float gGLIDE[8]; +float gOSC_CV[8]; + +//------------------------------------------------------------- +// mbed Functions + +// TextLCD +TextLCD gLCD(p23, p24, p25, p26, p29, p30); // rs, e, d4-d7 + +// SPI +SPI gSPI(p11,p12,p13); +DigitalOut gCSA(p14); +DigitalOut gCSB(p22); + +// Sirial MIDI +//Serial gMIDI(p9,p10); + +// AnalogIn +AnalogIn gAIN1(p15); // VR1 +AnalogIn gAIN2(p16); // VR2 +AnalogIn gAIN3(p17); // VR3 +AnalogIn gAIN4(p18); // VR4 +AnalogIn gAIN5(p19); // IN1 +AnalogIn gAIN6(p20); // IN2 + +// BEEP +PwmOut gBEEP(p21); + +// LED +DigitalOut gLED1(LED1); +DigitalOut gLED2(LED2); +DigitalOut gLED3(LED3); +DigitalOut gLED4(LED4); +BusOut gLEDS(LED1,LED2,LED3,LED4); + +// Ticker +Ticker gTICKER; + +// Ethernet +EthernetNetIf gEth; +UDPSocket gUdp; + +//------------------------------------------------------------- +// main + +int main() { + + int i; + int pot[4],_pot[4]; + unsigned char ch = 0; + unsigned char mode = 7; // for Intialize + unsigned char edit[4]; + int val[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + // Initialize + for( i=0; i<4; i++) { + pot[i] = _pot[i] = 0; + edit[i] = 0; + gGLIDE[i] = 1.0 / expf(val[i]*656.0/PARAM_GLIDE); + gGLIDE[i+4] = 1.0 / expf(val[i+4]*656.0/PARAM_GLIDE); + } + gSW = SW4; // for Intialize + + InitKamui(); + if(SetupEthNetIf() == -1) + { + gBEEP.write(0.5); + wait(1); + gBEEP.write(0.0); + return -1; + } + + // loop + while(1) { + + // Ethernet Polling + Net::poll(); + + // Read pot + pot[0] = gAIN1.read_u16(); + pot[1] = gAIN2.read_u16(); + pot[2] = gAIN3.read_u16(); + pot[3] = gAIN4.read_u16(); + + // change pot amount? + if(abs(pot[ch] - _pot[ch]) > 0x2000) edit[ch] = 1; + + if(edit[ch]) { + switch(mode) { + case 0: + gGLIDE[ch] = 1.0 / expf(pot[ch]/PARAM_GLIDE); + val[ch] = pot[ch] / 656; + break; + case 1: + gGLIDE[ch+4] = 1.0 / expf(pot[ch]/PARAM_GLIDE); + val[ch+4] = pot[ch] / 656; + break; + default: + break; + } + } + + // Push Mode SW + if(gSW & SW4) { + mode++; + mode &= 0x01; + for( i=0; i<4; i++) { + _pot[i] = pot[i]; + edit[i] = 0; + } + } + gSW = 0; + + // LCD Display + gLCD.locate( 0, 1 ); + switch(mode) { + case 0: + gLCD.printf("G1-4 %02d %02d %02d %02d", + val[0], val[1], val[2], val[3]); + break; + case 1: + gLCD.printf("G5-8 %02d %02d %02d %02d", + val[4], val[5], val[6], val[7]); + break; + } + + ch++; + ch &= 0x03; + } +} + +//------------------------------------------------------------- +// Initialize KAMUI + +void InitKamui() +{ + // Init. Variables + for( int i=0; i<8; i++) { + gCV[i] = 0x8000; + } + gGATE = 0; + gSYNC = 0; + + gUpdateMode = UPDATE_MODE0; + + // Init. SPI + gCSA = _DISABLE; + gCSB = _DISABLE; + gSPI.format(8,0); + gSPI.frequency(SPI_RATE); + + // Init. Serial MIDI +// gMIDI.baud(MIDI_RATE); + + // Ticker + gTICKER.attach_us(&UpdateCV, UPDATE_INTERVAL); + + // Beep + gBEEP.period(1.0/BEEP_FREQ); + gBEEP.write(0.5); + wait(0.2); + gBEEP.write(0.0); + + // Init Display + gLCD.locate( 0, 0 ); + // 123456789ABCDEF + gLCD.printf("OSC-CV Example "); +} + +//------------------------------------------------------------- +// Update CV, GATE, SYNC + +void UpdateCV() +{ + unsigned char rcv,ch; + unsigned char ptn[] = { 0,1,6,7,2,3,6,7,4,5,6,7 }; + const int numptn = (sizeof ptn / sizeof ptn[0]) - 1; + static unsigned char cnt; + + __disable_irq(); + + // SET DAC + ch = ptn[cnt]; + if(gUpdateMode) ch |= 0x06; + +#ifdef AD5551 // 14bitDAC + gDAC.WORD = gCV[ch] >> 2; +#else + gDAC.WORD = gCV[ch]; +#endif + + gCSA = _ENABLE; + gSPI.write(gDAC.BYTE.H); + gSPI.write(gDAC.BYTE.L); + gCSA = _DISABLE; + + // GATE or SYNC OUT + if(cnt & 0x01) { + // GATE OUT + gCSB = _ENABLE; + rcv = gSPI.write(gGATE | MODE_GATE) & 0x0F; + gCSB = _DISABLE; + } + else { + // SYNC OUT + gCSB = _ENABLE; + rcv = gSPI.write(gSYNC | MODE_SYNC); + gCSB = _DISABLE; + } + + // SEL CV CHANNEL + gCSB = _ENABLE; + gSPI.write(ch); + gCSB = _DISABLE; + + cnt < numptn ? cnt++ : cnt = 0; + + __enable_irq(); + + gSW |= CheckSW(rcv); + SetCV(); +} + +//------------------------------------------------------------- +// Check SW + +unsigned char CheckSW(unsigned char c) { + + static unsigned char swbuf[2]; + static unsigned int cntsw; + unsigned char ret = 0; + + if(cntsw > SW_WATCH_INTERVAL) { + if(c &= 0x0F) { + if(!swbuf[1]) { + if( swbuf[0] == c) { + swbuf[1] = c; + ret = c; + } + else { + swbuf[0] = c; + } + } + } + else { + swbuf[1] = 0; + swbuf[0] = 0; + } + cntsw = 0; + } + cntsw++; + return ret; +} + +//------------------------------------------------------------- +// Set CV + +void SetCV() +{ + static unsigned char ch; + static float cvf[8]; + unsigned int cv; + + // Calculate CV + cvf[ch] = (gOSC_CV[ch] - cvf[ch]) * gGLIDE[ch] + cvf[ch]; + cv = (unsigned int)cvf[ch] + 0x8000; + if(cv > 0xFFFF) cv = 0xFFFF; + gCV[ch] = cv; + + ch++; + ch &= 0x07; +} + +//------------------------------------------------------------- +// 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), 12345, NULL); + gUdp.setOnEvent(&onUDPSocketEvent); + gUdp.bind(broadcast); + + gLCD.locate( 0, 1 ); + gLCD.printf("%03d.%03d.%03d.%03d", gEth.getIp()[0], gEth.getIp()[1], gEth.getIp()[2], gEth.getIp()[3]); + wait(2.0); + + return 0; +} + +//------------------------------------------------------------- +// Handller receive UDP Packet + +void onUDPSocketEvent(UDPSocketEvent e) +{ + union OSCarg msg[10]; + int num; + + switch(e) + { + case UDPSOCKET_READABLE: //The only event for now + char buf[256] = {0}; + Host host; + + while( int len = gUdp.recvfrom( buf, 256, &host ) ) + { + if(len <= 0) break; + // printf("\r\nFrom %d.%d.%d.%d:\r\n", + // host.getIp()[0], host.getIp()[1], host.getIp()[2], host.getIp()[3]); + + getOSCmsg(buf,msg); +// printf("OSCmsg: %s %s %f %i\r\n", +// msg[0].address, msg[1].typeTag, msg[2].f, msg[2].i); + + len = strlen(msg[0].address); + if(isdigit(msg[0].address[len-1])) num = msg[0].address[len-1] - '0' - 1; + else num = -1; + + // address pattern CV + if((strncmp(msg[0].address,"/kamui/cv",9)==0) && (num != -1)) { + + if(num > 7) break; + if(msg[1].typeTag[1] == 'f') gOSC_CV[num] = msg[2].f * 3072.0; + if(msg[1].typeTag[1] == 'i') gOSC_CV[num] = msg[2].i * 3072.0; + + break; + } + + // address pattern GATE + if((strncmp(msg[0].address,"/kamui/gate",11)==0) && (num != -1)) { + + if(num > 3) break; + if(msg[2].i) gGATE |= (0x01 << num); + else gGATE &= ~(0x01 << num); + + break; + } + + // printf("undefined OSCmsg:%s %s\r\n",msg[0].address, msg[1].typeTag); + } + break; + } +}