Atsushi Shinbo / Mbed 2 deprecated CS8416_SPI

Dependencies:   mbed

Revision:
0:cb6ecbfcf585
Child:
1:f468352a5408
diff -r 000000000000 -r cb6ecbfcf585 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Mar 30 19:34:20 2014 +0000
@@ -0,0 +1,267 @@
+#include "mbed.h"
+
+// this program control CS8416 in software mode(SPI) with LPC1114FN2.
+
+// CS8416 : 192 kHz Digital Audio Interface Receiver
+// http://www.cirrus.com/jp/pubs/proDatasheet/CS8416_F3.pdf
+
+// FN1242A : 24bit/192KHz/2ch DAC
+// http://akizukidenshi.com/download/ds/niigataseimitsu/FN1242Ajspec.pdf
+
+
+// LPC1114FN28      connect to
+//  1  MISO         cs8416 / CDOUT
+//  2  MOSI         cs8416 / CDIN
+//  3  SWCLK        LPC-Link
+//  4  PIO          cs8416 / CS
+//  6  SCK          cs8416 / CCLK
+//  7  AVIN 3.3V
+//  8  AGND
+//  9  PIO          toggle switch : input source select.
+// 12  SWDIO        LPC-Link
+// 14  PIO          cs8416 / reset
+// 15  PIO          led1 : left
+// 16  PIO          led2 
+// 17  PIO          led3
+// 18  PIO          led4 : right
+// 21  VIN 3.3V
+// 22  GND
+// 23  RESET        LPC-Link
+// 24  PIO          fn1242a / ML
+// 25  PIO          fn1242a / MD
+// 26  PIO          fn1242a / MC
+
+// CS8416
+// RXP0 : S/PDIF TOSLINK input
+// RXP1 : S/PDIF COAX input
+// OMCK : 11.2896 MHz
+
+SPI        spi(dp2, dp1, dp6);      // mosi, miso, sclk
+DigitalOut pin_cs  (dp4);
+DigitalOut pin_rst (dp14);
+DigitalOut pin_led1(dp15);
+DigitalOut pin_led2(dp16);
+DigitalOut pin_led3(dp17);
+DigitalOut pin_led4(dp18);
+DigitalIn  pin_tgl (dp9);
+DigitalOut pin_ML  (dp24);
+DigitalOut pin_MD  (dp25);
+DigitalOut pin_MC  (dp26);
+
+
+const uint8_t DEF_REGVAL[10] = {
+    0x00,   // 0x00 : Control0
+    0x00,   // 0x01 : Control1
+    0x48,   // 0x02 : Control2                  // EMPH_CNTL[2:0]=deemphasis filter auto select, GPO0SEL[3:0]=(96KHZ)
+    0x00,   // 0x03 : Control3
+    0x80,   // 0x04 : Control4                  // RUN=normal part operation
+    0x85,   // 0x05 : Serial Audio Data Format  // SOMS=master mode, SODEL=second OSCLK period, SOLRPOL=right channel when OLRCK is high.
+    0x00,   // 0x06 : Receiver Error Mask
+    0x00,   // 0x07 : Interrupt Mask
+    0x00,   // 0x08 : Interrupt Mode MSB
+    0x00    // 0x09 : Interrupt Mode LSB
+};
+
+uint32_t g_freq = 0;
+uint8_t  g_cur_frmt = 0;
+uint32_t g_cur_tgl = 0;
+
+
+void fn1242_write(uint16_t word) {
+    
+    pin_ML = 1;
+    
+    for (int iii = 0; iii < 16; iii++) {
+        pin_MC = 0;
+        pin_MD = (word & 0x8000) == 0 ? 0 : 1;      // msb first
+        wait_us(10);            // us
+        
+        pin_MC = 1;
+        wait_us(10);            // us
+        
+        word = word << 1;
+    }
+    
+    pin_MD = 0;
+    pin_MC = 0;
+    pin_ML = 0;
+    wait_us(10);                // us
+    
+    pin_ML = 1;
+    wait_us(10);                // us
+}
+
+void fn1242_init() {
+    
+    pin_ML = 1;
+    pin_MD = 0;
+    pin_MC = 0;
+    wait_us(10);                // us
+    
+    fn1242_write(
+              (2 << 11)     // MODE2
+            | (0 <<  9)     // OM  (default)
+            | (0 <<  8)     // RST (OFF/default)
+            | (2 <<  6)     // BIT (24bit)
+            | (0 <<  4)     // ZM  (default)
+            | (0 <<  3)     // ATC (default)
+            | (0 <<  2)     // MUTE (OFF/default)
+            | (0      ) );  // EMPH (OFF/default)
+}
+
+void cs8416_write(uint8_t u8_addr, uint8_t u8_data) {
+    uint8_t u8_recv = 0;
+    
+    pin_cs = 0;
+    wait_us(10);                    // us
+    u8_recv = spi.write(0x20);
+    u8_recv = spi.write(u8_addr);
+    u8_recv = spi.write(u8_data);
+    pin_cs = 1;
+    wait_us(10);                    // us
+}
+
+
+uint8_t cs8416_read(uint8_t u8_addr) {
+    uint8_t u8_recv = 0;
+    
+    pin_cs = 0;
+    wait_us(10);                    // us
+    u8_recv = spi.write(0x20);
+    u8_recv = spi.write(u8_addr);
+    pin_cs = 1;
+    wait_us(10);                    // us
+    
+    pin_cs = 0;
+    wait_us(10);                    // us
+    u8_recv = spi.write(0x21);
+    u8_recv = spi.write(0x00);
+    pin_cs = 1;
+    wait_us(10);                    // us
+    
+    return u8_recv;
+}
+
+
+void cs8416_init() {
+    
+    pin_rst = 0;                    // reset
+    wait_ms(100);                   // ms
+    pin_rst = 1;
+    wait_ms(1);                     // ms
+    
+    // SPI Mode is selected if there is a high to low transition on the AD0/CS pin, after the RST pin has been brought high.
+    pin_cs = 1; wait_ms(1);     
+    pin_cs = 0; wait_ms(1);         // enter SPI mode
+    pin_cs = 1; wait_ms(1);
+    
+    for (int iii = 0; iii < 10; iii++) {
+        uint8_t u8_addr = (uint8_t) iii;
+        uint8_t u8_data = DEF_REGVAL[iii];
+        cs8416_write(u8_addr, u8_data);
+    }
+}
+
+
+void decide_freq(uint8_t u8_addr18) {
+       
+    switch (u8_addr18) {
+        case 0x59:
+        case 0x58:
+        case 0x57:  g_freq =  32; break;
+        
+        case 0x40:
+        case 0x3f:  g_freq =  44; break;
+        
+        case 0x3b:
+        case 0x3a:  g_freq =  48; break;
+        
+        case 0x20:
+        case 0x1f:  g_freq =  88; break;
+        
+        case 0x1d:
+        case 0x1c:  g_freq =  96; break;
+        
+        case 0x10:
+        case 0x0f:  g_freq = 176; break;
+        
+        case 0x0e:  g_freq = 192; break;
+        
+        default:    g_freq =   0; break;
+    }
+}
+
+
+void set_led() {
+    uint32_t u32_val = 0;
+    
+    switch (g_freq) {
+        case  32: u32_val = 0x01; break;     // 0001
+        case  44: u32_val = 0x02; break;     // 0010
+        case  48: u32_val = 0x03; break;     // 0011
+        case  88: u32_val = 0x04; break;     // 0100
+        case  96: u32_val = 0x05; break;     // 0101
+        case 176: u32_val = 0x06; break;     // 0110
+        case 192: u32_val = 0x07; break;     // 0111
+    }
+    
+    pin_led4 = (u32_val & 1); u32_val = u32_val >> 1;
+    pin_led3 = (u32_val & 1); u32_val = u32_val >> 1;
+    pin_led2 = (u32_val & 1); u32_val = u32_val >> 1;
+}
+
+
+void set_rmckf() {
+    uint8_t u8_data = 0;
+    
+    if (g_cur_frmt & 1) {           // (0Bh)[0] 96KHZ - If the input sample rate is <= 48 kHz, outputs a "0". Outputs a "1" if the sample rate is >= 88.1 kHz. Otherwise the output is indeterminate.
+        pin_led1 = 1;
+        u8_data = 0x02;             // (01h)[1] RMCKF - Recovered Master Clock Frequency @ 1 : 128 Fs
+    } else {
+        pin_led1 = 0;
+        u8_data = 0x00;             // (01h)[1] RMCKF - Recovered Master Clock Frequency @ 0 : 256 Fs
+    }
+    cs8416_write(0x01, DEF_REGVAL[1] + u8_data);    // (01h) : Control1
+}
+
+
+void set_source() {
+    uint8_t u8_data = 0;
+    
+    if (g_cur_tgl & 1) {
+        u8_data = 0x08;             // (04h)[5:3] RXSEL2:0
+    } else {
+        u8_data = 0x00;             // (04h)[5:3] RXSEL2:0
+    }
+    cs8416_write(0x04, DEF_REGVAL[4] + u8_data);    // (04h) : Control4
+}
+
+
+int main() {
+    
+    spi.format(8, 3);               // 8bit, mode3
+    spi.frequency(1000000);         // 1MHz : default
+    
+    cs8416_init();
+    fn1242_init();
+    
+    while (1) {
+        uint8_t u8_addr18 = cs8416_read(0x18);  // (18h) : OMCK/RMCK Ratio
+        decide_freq(u8_addr18);
+        set_led();
+        
+        uint8_t u8_addr0B = cs8416_read(0x0b);  // (0Bh) : Format Detect Status
+        if (g_cur_frmt != u8_addr0B) {
+            g_cur_frmt = u8_addr0B;
+            set_rmckf();
+        }
+        
+        uint32_t u32_tgl = pin_tgl;
+        if (g_cur_tgl != u32_tgl) {
+            g_cur_tgl = u32_tgl;
+            set_source();
+        }
+        
+        wait_ms(200);               // ms
+    }
+}