KAMUI DIN-SYNC Example

Dependencies:   TextLCD mbed

main.cpp

Committer:
radiojunkbox
Date:
2012-05-05
Revision:
0:e3174b02ec81

File content as of revision 0:e3174b02ec81:

//-------------------------------------------------------------
// KAMUI DIN SYNC Example
// Copyright (C) 2012 RJB RadioJunkBox
// Released under the MIT License: http://mbed.org/license/mit
//-------------------------------------------------------------

#include "mbed.h"
#include "TextLCD.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     50      // 50us
#define SW_WATCH_INTERVAL   (25000/UPDATE_INTERVAL) // 25ms

#define UPDATE_MODE0        0       // Update Interval CV ch1-6 600us, ch7,8 200us
#define UPDATE_MODE1        1       // Update Interval CV ch1-6 N/A, ch7,8 100us

#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

#define TBASE               (60*1000000/(48*UPDATE_INTERVAL))

//-------------------------------------------------------------
// Functions

void InitKamui(void);
void UpdateCV(void);
void DinSync(unsigned char);
unsigned char CheckSW(unsigned char);

//-------------------------------------------------------------
// Global Variables

int gUpdateMode;
unsigned short gCV[8];
unsigned char  gGATE;
unsigned char  gSYNC;
unsigned short gT1,gT2;

union {
    unsigned short    WORD;    
    struct {
        unsigned char L;
        unsigned char H; 
    } BYTE;
} gDAC;

//-------------------------------------------------------------
// 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;

//-------------------------------------------------------------
// main

int main() {

    unsigned int pot1, pot2, pot3, pot4;
    unsigned int tempo;
    unsigned int t,s;

    InitKamui();    

    while(1) {

        // POT1 Tempo 40 - 220 bpm
        // POT2 Suffle Rate
        // POT3 CV1 - CV4     0V - +10V
        // POT4 CV5 - CV8   -10V - +10V
        
        pot1 = gAIN1.read_u16();
        pot2 = gAIN2.read_u16() / 0x0400;
        pot3 = gAIN3.read_u16() / 2 + 0x8000;
        pot4 = gAIN4.read_u16();
        
        tempo = pot1 / 364 + 40;
        t = TBASE / tempo;
        s = t * pot2 / 127; 
        
        gT1 = t + s;
        gT2 = t - s;
        
        gCV[0] = pot3; 
        gCV[1] = pot3; 
        gCV[2] = pot3;
        gCV[3] = pot3;
        gCV[4] = pot4;
        gCV[5] = pot4;
        gCV[6] = pot4;
        gCV[7] = pot4;
        
        gLCD.locate( 0, 1 );
        gLCD.printf("TEMPO=%03d SFL=%02d", tempo, pot2);    
    }
}

//-------------------------------------------------------------
// 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("DIN-SyncExample");
}

//-------------------------------------------------------------
// Update CV, GATE, SYNC

void UpdateCV()
{ 
    unsigned char rcv,sw,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;

    // 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;

    sw = CheckSW(rcv);
    DinSync(sw);
}

//-------------------------------------------------------------
// DIN Sync

void DinSync(unsigned char sw) {

    static unsigned int   cnt;
    static unsigned char  cnt48;
    static unsigned char  _cnt48;

    // BEAT COUNTER
    if((cnt48 % 24) < 12) {
        if( cnt >= gT1) {
            cnt = 0;
            cnt48++;
        }
    } 
    else {
        if( cnt >= gT2) {
            cnt = 0;
            cnt48++;
        }
    }
    if(cnt48 >= 48) cnt48 = 0;

    // START/STOP
    if(sw & (SW1 | SW2)) {
        if( !(gSYNC & (SYNC1RUN | SYNC2RUN))){
            cnt   = 0;
            cnt48 = 0;
            gGATE = 0;
        }
        if(sw & SW1) gSYNC ^= SYNC1RUN;
        if(sw & SW2) gSYNC ^= SYNC2RUN;
    }

    // TOGGLE SYNC CLOCK
    if(cnt48 & 0x01) {
        gSYNC &= ~(SYNC1CLK | SYNC2CLK);
    }
    else {
        gSYNC |= (SYNC1CLK | SYNC2CLK);
    }

    // SYNC LED
    gLED1 = gSYNC & SYNC1RUN ? 1 : 0;
    gLED2 = gSYNC & SYNC2RUN ? 1 : 0;
    gLED4 = cnt48 < 8 ? 1 : 0;

    // TOGGLE GATE OUT
    if(gSYNC & (SYNC1RUN | SYNC2RUN)) {
        if(cnt48 != _cnt48) {
            if((cnt48 %  6) == 0) gGATE ^= GATE1;
            if((cnt48 % 12) == 0) gGATE ^= GATE2;
            if((cnt48 % 24) == 0) gGATE ^= GATE3;
            if((cnt48 % 48) == 0) gGATE ^= GATE4;
        }
    }
    else gGATE = 0;
    _cnt48 = cnt48;        

    cnt++;
}

//-------------------------------------------------------------
// 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;
}