Atsushi Shinbo / Mbed 2 deprecated CS8416_SPI

Dependencies:   mbed

Committer:
shinbo
Date:
Sun May 04 04:43:19 2014 +0000
Revision:
1:f468352a5408
Parent:
0:cb6ecbfcf585
Child:
2:849b0ab61874
-

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shinbo 0:cb6ecbfcf585 1 #include "mbed.h"
shinbo 0:cb6ecbfcf585 2
shinbo 1:f468352a5408 3 // this program control CS8416 in software mode(SPI) with LPC1114FN28.
shinbo 0:cb6ecbfcf585 4
shinbo 0:cb6ecbfcf585 5 // CS8416 : 192 kHz Digital Audio Interface Receiver
shinbo 0:cb6ecbfcf585 6 // http://www.cirrus.com/jp/pubs/proDatasheet/CS8416_F3.pdf
shinbo 0:cb6ecbfcf585 7
shinbo 0:cb6ecbfcf585 8 // FN1242A : 24bit/192KHz/2ch DAC
shinbo 0:cb6ecbfcf585 9 // http://akizukidenshi.com/download/ds/niigataseimitsu/FN1242Ajspec.pdf
shinbo 0:cb6ecbfcf585 10
shinbo 0:cb6ecbfcf585 11
shinbo 0:cb6ecbfcf585 12 // LPC1114FN28 connect to
shinbo 0:cb6ecbfcf585 13 // 1 MISO cs8416 / CDOUT
shinbo 0:cb6ecbfcf585 14 // 2 MOSI cs8416 / CDIN
shinbo 0:cb6ecbfcf585 15 // 3 SWCLK LPC-Link
shinbo 0:cb6ecbfcf585 16 // 4 PIO cs8416 / CS
shinbo 0:cb6ecbfcf585 17 // 6 SCK cs8416 / CCLK
shinbo 0:cb6ecbfcf585 18 // 7 AVIN 3.3V
shinbo 0:cb6ecbfcf585 19 // 8 AGND
shinbo 0:cb6ecbfcf585 20 // 9 PIO toggle switch : input source select.
shinbo 0:cb6ecbfcf585 21 // 12 SWDIO LPC-Link
shinbo 0:cb6ecbfcf585 22 // 14 PIO cs8416 / reset
shinbo 0:cb6ecbfcf585 23 // 15 PIO led1 : left
shinbo 0:cb6ecbfcf585 24 // 16 PIO led2
shinbo 0:cb6ecbfcf585 25 // 17 PIO led3
shinbo 0:cb6ecbfcf585 26 // 18 PIO led4 : right
shinbo 0:cb6ecbfcf585 27 // 21 VIN 3.3V
shinbo 0:cb6ecbfcf585 28 // 22 GND
shinbo 0:cb6ecbfcf585 29 // 23 RESET LPC-Link
shinbo 0:cb6ecbfcf585 30 // 24 PIO fn1242a / ML
shinbo 0:cb6ecbfcf585 31 // 25 PIO fn1242a / MD
shinbo 0:cb6ecbfcf585 32 // 26 PIO fn1242a / MC
shinbo 0:cb6ecbfcf585 33
shinbo 0:cb6ecbfcf585 34 // CS8416
shinbo 0:cb6ecbfcf585 35 // RXP0 : S/PDIF TOSLINK input
shinbo 0:cb6ecbfcf585 36 // RXP1 : S/PDIF COAX input
shinbo 0:cb6ecbfcf585 37 // OMCK : 11.2896 MHz
shinbo 0:cb6ecbfcf585 38
shinbo 0:cb6ecbfcf585 39 SPI spi(dp2, dp1, dp6); // mosi, miso, sclk
shinbo 0:cb6ecbfcf585 40 DigitalOut pin_cs (dp4);
shinbo 0:cb6ecbfcf585 41 DigitalOut pin_rst (dp14);
shinbo 0:cb6ecbfcf585 42 DigitalOut pin_led1(dp15);
shinbo 0:cb6ecbfcf585 43 DigitalOut pin_led2(dp16);
shinbo 0:cb6ecbfcf585 44 DigitalOut pin_led3(dp17);
shinbo 0:cb6ecbfcf585 45 DigitalOut pin_led4(dp18);
shinbo 0:cb6ecbfcf585 46 DigitalIn pin_tgl (dp9);
shinbo 0:cb6ecbfcf585 47 DigitalOut pin_ML (dp24);
shinbo 0:cb6ecbfcf585 48 DigitalOut pin_MD (dp25);
shinbo 0:cb6ecbfcf585 49 DigitalOut pin_MC (dp26);
shinbo 0:cb6ecbfcf585 50
shinbo 0:cb6ecbfcf585 51
shinbo 0:cb6ecbfcf585 52 const uint8_t DEF_REGVAL[10] = {
shinbo 1:f468352a5408 53 0x04, // [0] Control0
shinbo 1:f468352a5408 54 // TRUNC=1 - Incoming data is truncated according to the length specified in the channel status data.
shinbo 1:f468352a5408 55
shinbo 1:f468352a5408 56 0x80, // [1] Control1
shinbo 1:f468352a5408 57 // SWCLK=1 - Enable automatic clock switching on PLL unlock. OMCK clock input is automatically output on RMCK on PLL Unlock.
shinbo 1:f468352a5408 58 // MUTESAO=0 - SDOUT not muted.
shinbo 1:f468352a5408 59 // HOLD[1:0]=00 - hold last audio sample.
shinbo 1:f468352a5408 60
shinbo 1:f468352a5408 61 0x45, // [2] Control2
shinbo 1:f468352a5408 62 // EMPH_CNTL[2:0]=100 - deemphasis filter auto select.
shinbo 1:f468352a5408 63 // GPO0SEL[3:0]=0101 - RERR/Receiver Error
shinbo 1:f468352a5408 64
shinbo 1:f468352a5408 65 0x00, // [3] Control3
shinbo 1:f468352a5408 66
shinbo 1:f468352a5408 67 0x80, // [4] Control4
shinbo 1:f468352a5408 68 // RUN=1 - normal part operation
shinbo 1:f468352a5408 69
shinbo 1:f468352a5408 70 0x85, // [5] Serial Audio Data Format
shinbo 1:f468352a5408 71 // SOMS=1 - Serial audio output port is in master mode. OSCLK and OLRCK are outputs.
shinbo 1:f468352a5408 72 // SOSF=0 - OSCLK output frequency is 64*Fs.
shinbo 1:f468352a5408 73 // SORES[1:0]=00 - 24-bit resolution.
shinbo 1:f468352a5408 74 // SOJUST=0 - Left-Justified.
shinbo 1:f468352a5408 75 // SODEL=1 - second OSCLK period.
shinbo 1:f468352a5408 76 // SOSPOL=0 - SDOUT is sampled on rising edges of OSCLK.
shinbo 1:f468352a5408 77 // SOLRPOL=1 - right channel when OLRCK is high.
shinbo 1:f468352a5408 78
shinbo 0:cb6ecbfcf585 79 0x00, // 0x06 : Receiver Error Mask
shinbo 0:cb6ecbfcf585 80 0x00, // 0x07 : Interrupt Mask
shinbo 0:cb6ecbfcf585 81 0x00, // 0x08 : Interrupt Mode MSB
shinbo 0:cb6ecbfcf585 82 0x00 // 0x09 : Interrupt Mode LSB
shinbo 0:cb6ecbfcf585 83 };
shinbo 0:cb6ecbfcf585 84
shinbo 0:cb6ecbfcf585 85 uint32_t g_freq = 0;
shinbo 0:cb6ecbfcf585 86 uint8_t g_cur_frmt = 0;
shinbo 0:cb6ecbfcf585 87 uint32_t g_cur_tgl = 0;
shinbo 0:cb6ecbfcf585 88
shinbo 0:cb6ecbfcf585 89
shinbo 0:cb6ecbfcf585 90 void fn1242_write(uint16_t word) {
shinbo 0:cb6ecbfcf585 91
shinbo 0:cb6ecbfcf585 92 pin_ML = 1;
shinbo 0:cb6ecbfcf585 93
shinbo 0:cb6ecbfcf585 94 for (int iii = 0; iii < 16; iii++) {
shinbo 0:cb6ecbfcf585 95 pin_MC = 0;
shinbo 0:cb6ecbfcf585 96 pin_MD = (word & 0x8000) == 0 ? 0 : 1; // msb first
shinbo 0:cb6ecbfcf585 97 wait_us(10); // us
shinbo 0:cb6ecbfcf585 98
shinbo 0:cb6ecbfcf585 99 pin_MC = 1;
shinbo 0:cb6ecbfcf585 100 wait_us(10); // us
shinbo 0:cb6ecbfcf585 101
shinbo 0:cb6ecbfcf585 102 word = word << 1;
shinbo 0:cb6ecbfcf585 103 }
shinbo 0:cb6ecbfcf585 104
shinbo 0:cb6ecbfcf585 105 pin_MD = 0;
shinbo 0:cb6ecbfcf585 106 pin_MC = 0;
shinbo 0:cb6ecbfcf585 107 pin_ML = 0;
shinbo 0:cb6ecbfcf585 108 wait_us(10); // us
shinbo 0:cb6ecbfcf585 109
shinbo 0:cb6ecbfcf585 110 pin_ML = 1;
shinbo 0:cb6ecbfcf585 111 wait_us(10); // us
shinbo 0:cb6ecbfcf585 112 }
shinbo 0:cb6ecbfcf585 113
shinbo 0:cb6ecbfcf585 114 void fn1242_init() {
shinbo 0:cb6ecbfcf585 115
shinbo 0:cb6ecbfcf585 116 pin_ML = 1;
shinbo 0:cb6ecbfcf585 117 pin_MD = 0;
shinbo 0:cb6ecbfcf585 118 pin_MC = 0;
shinbo 0:cb6ecbfcf585 119 wait_us(10); // us
shinbo 0:cb6ecbfcf585 120
shinbo 0:cb6ecbfcf585 121 fn1242_write(
shinbo 0:cb6ecbfcf585 122 (2 << 11) // MODE2
shinbo 0:cb6ecbfcf585 123 | (0 << 9) // OM (default)
shinbo 0:cb6ecbfcf585 124 | (0 << 8) // RST (OFF/default)
shinbo 0:cb6ecbfcf585 125 | (2 << 6) // BIT (24bit)
shinbo 0:cb6ecbfcf585 126 | (0 << 4) // ZM (default)
shinbo 0:cb6ecbfcf585 127 | (0 << 3) // ATC (default)
shinbo 0:cb6ecbfcf585 128 | (0 << 2) // MUTE (OFF/default)
shinbo 0:cb6ecbfcf585 129 | (0 ) ); // EMPH (OFF/default)
shinbo 1:f468352a5408 130
shinbo 1:f468352a5408 131 wait_us(10); // us
shinbo 1:f468352a5408 132 fn1242_write(
shinbo 1:f468352a5408 133 (0 << 11) // MODE0
shinbo 1:f468352a5408 134 | (0 << 10) // LDL -> disable
shinbo 1:f468352a5408 135 | 1023); // 10bit
shinbo 1:f468352a5408 136 wait_us(10); // us
shinbo 1:f468352a5408 137 fn1242_write(
shinbo 1:f468352a5408 138 (1 << 11) // MODE1
shinbo 1:f468352a5408 139 | (0 << 10) // LDR -> disable
shinbo 1:f468352a5408 140 | 1023); // 10bit
shinbo 1:f468352a5408 141
shinbo 0:cb6ecbfcf585 142 }
shinbo 0:cb6ecbfcf585 143
shinbo 0:cb6ecbfcf585 144 void cs8416_write(uint8_t u8_addr, uint8_t u8_data) {
shinbo 0:cb6ecbfcf585 145 uint8_t u8_recv = 0;
shinbo 0:cb6ecbfcf585 146
shinbo 0:cb6ecbfcf585 147 pin_cs = 0;
shinbo 0:cb6ecbfcf585 148 wait_us(10); // us
shinbo 0:cb6ecbfcf585 149 u8_recv = spi.write(0x20);
shinbo 0:cb6ecbfcf585 150 u8_recv = spi.write(u8_addr);
shinbo 0:cb6ecbfcf585 151 u8_recv = spi.write(u8_data);
shinbo 0:cb6ecbfcf585 152 pin_cs = 1;
shinbo 0:cb6ecbfcf585 153 wait_us(10); // us
shinbo 0:cb6ecbfcf585 154 }
shinbo 0:cb6ecbfcf585 155
shinbo 0:cb6ecbfcf585 156
shinbo 0:cb6ecbfcf585 157 uint8_t cs8416_read(uint8_t u8_addr) {
shinbo 0:cb6ecbfcf585 158 uint8_t u8_recv = 0;
shinbo 0:cb6ecbfcf585 159
shinbo 0:cb6ecbfcf585 160 pin_cs = 0;
shinbo 0:cb6ecbfcf585 161 wait_us(10); // us
shinbo 0:cb6ecbfcf585 162 u8_recv = spi.write(0x20);
shinbo 0:cb6ecbfcf585 163 u8_recv = spi.write(u8_addr);
shinbo 0:cb6ecbfcf585 164 pin_cs = 1;
shinbo 0:cb6ecbfcf585 165 wait_us(10); // us
shinbo 0:cb6ecbfcf585 166
shinbo 0:cb6ecbfcf585 167 pin_cs = 0;
shinbo 0:cb6ecbfcf585 168 wait_us(10); // us
shinbo 0:cb6ecbfcf585 169 u8_recv = spi.write(0x21);
shinbo 0:cb6ecbfcf585 170 u8_recv = spi.write(0x00);
shinbo 0:cb6ecbfcf585 171 pin_cs = 1;
shinbo 0:cb6ecbfcf585 172 wait_us(10); // us
shinbo 0:cb6ecbfcf585 173
shinbo 0:cb6ecbfcf585 174 return u8_recv;
shinbo 0:cb6ecbfcf585 175 }
shinbo 0:cb6ecbfcf585 176
shinbo 0:cb6ecbfcf585 177
shinbo 0:cb6ecbfcf585 178 void cs8416_init() {
shinbo 0:cb6ecbfcf585 179
shinbo 0:cb6ecbfcf585 180 pin_rst = 0; // reset
shinbo 0:cb6ecbfcf585 181 wait_ms(100); // ms
shinbo 0:cb6ecbfcf585 182 pin_rst = 1;
shinbo 0:cb6ecbfcf585 183 wait_ms(1); // ms
shinbo 0:cb6ecbfcf585 184
shinbo 0:cb6ecbfcf585 185 // 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.
shinbo 0:cb6ecbfcf585 186 pin_cs = 1; wait_ms(1);
shinbo 0:cb6ecbfcf585 187 pin_cs = 0; wait_ms(1); // enter SPI mode
shinbo 0:cb6ecbfcf585 188 pin_cs = 1; wait_ms(1);
shinbo 0:cb6ecbfcf585 189
shinbo 0:cb6ecbfcf585 190 for (int iii = 0; iii < 10; iii++) {
shinbo 0:cb6ecbfcf585 191 uint8_t u8_addr = (uint8_t) iii;
shinbo 0:cb6ecbfcf585 192 uint8_t u8_data = DEF_REGVAL[iii];
shinbo 0:cb6ecbfcf585 193 cs8416_write(u8_addr, u8_data);
shinbo 0:cb6ecbfcf585 194 }
shinbo 0:cb6ecbfcf585 195 }
shinbo 0:cb6ecbfcf585 196
shinbo 0:cb6ecbfcf585 197
shinbo 0:cb6ecbfcf585 198 void decide_freq(uint8_t u8_addr18) {
shinbo 0:cb6ecbfcf585 199
shinbo 0:cb6ecbfcf585 200 switch (u8_addr18) {
shinbo 0:cb6ecbfcf585 201 case 0x59:
shinbo 0:cb6ecbfcf585 202 case 0x58:
shinbo 0:cb6ecbfcf585 203 case 0x57: g_freq = 32; break;
shinbo 0:cb6ecbfcf585 204
shinbo 0:cb6ecbfcf585 205 case 0x40:
shinbo 0:cb6ecbfcf585 206 case 0x3f: g_freq = 44; break;
shinbo 0:cb6ecbfcf585 207
shinbo 0:cb6ecbfcf585 208 case 0x3b:
shinbo 0:cb6ecbfcf585 209 case 0x3a: g_freq = 48; break;
shinbo 0:cb6ecbfcf585 210
shinbo 0:cb6ecbfcf585 211 case 0x20:
shinbo 0:cb6ecbfcf585 212 case 0x1f: g_freq = 88; break;
shinbo 0:cb6ecbfcf585 213
shinbo 0:cb6ecbfcf585 214 case 0x1d:
shinbo 0:cb6ecbfcf585 215 case 0x1c: g_freq = 96; break;
shinbo 0:cb6ecbfcf585 216
shinbo 0:cb6ecbfcf585 217 case 0x10:
shinbo 0:cb6ecbfcf585 218 case 0x0f: g_freq = 176; break;
shinbo 0:cb6ecbfcf585 219
shinbo 0:cb6ecbfcf585 220 case 0x0e: g_freq = 192; break;
shinbo 0:cb6ecbfcf585 221
shinbo 0:cb6ecbfcf585 222 default: g_freq = 0; break;
shinbo 0:cb6ecbfcf585 223 }
shinbo 0:cb6ecbfcf585 224 }
shinbo 0:cb6ecbfcf585 225
shinbo 0:cb6ecbfcf585 226
shinbo 0:cb6ecbfcf585 227 void set_led() {
shinbo 0:cb6ecbfcf585 228 uint32_t u32_val = 0;
shinbo 0:cb6ecbfcf585 229
shinbo 0:cb6ecbfcf585 230 switch (g_freq) {
shinbo 0:cb6ecbfcf585 231 case 32: u32_val = 0x01; break; // 0001
shinbo 0:cb6ecbfcf585 232 case 44: u32_val = 0x02; break; // 0010
shinbo 0:cb6ecbfcf585 233 case 48: u32_val = 0x03; break; // 0011
shinbo 0:cb6ecbfcf585 234 case 88: u32_val = 0x04; break; // 0100
shinbo 0:cb6ecbfcf585 235 case 96: u32_val = 0x05; break; // 0101
shinbo 0:cb6ecbfcf585 236 case 176: u32_val = 0x06; break; // 0110
shinbo 0:cb6ecbfcf585 237 case 192: u32_val = 0x07; break; // 0111
shinbo 0:cb6ecbfcf585 238 }
shinbo 0:cb6ecbfcf585 239
shinbo 0:cb6ecbfcf585 240 pin_led4 = (u32_val & 1); u32_val = u32_val >> 1;
shinbo 0:cb6ecbfcf585 241 pin_led3 = (u32_val & 1); u32_val = u32_val >> 1;
shinbo 0:cb6ecbfcf585 242 pin_led2 = (u32_val & 1); u32_val = u32_val >> 1;
shinbo 0:cb6ecbfcf585 243 }
shinbo 0:cb6ecbfcf585 244
shinbo 0:cb6ecbfcf585 245
shinbo 0:cb6ecbfcf585 246 void set_rmckf() {
shinbo 0:cb6ecbfcf585 247 uint8_t u8_data = 0;
shinbo 0:cb6ecbfcf585 248
shinbo 0:cb6ecbfcf585 249 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.
shinbo 0:cb6ecbfcf585 250 pin_led1 = 1;
shinbo 0:cb6ecbfcf585 251 u8_data = 0x02; // (01h)[1] RMCKF - Recovered Master Clock Frequency @ 1 : 128 Fs
shinbo 0:cb6ecbfcf585 252 } else {
shinbo 0:cb6ecbfcf585 253 pin_led1 = 0;
shinbo 0:cb6ecbfcf585 254 u8_data = 0x00; // (01h)[1] RMCKF - Recovered Master Clock Frequency @ 0 : 256 Fs
shinbo 0:cb6ecbfcf585 255 }
shinbo 1:f468352a5408 256
shinbo 1:f468352a5408 257 if (g_freq == 0) {
shinbo 1:f468352a5408 258 u8_data |= 0x40; // (01h)[6] MUTESAO - Mute control for the serial audio output port
shinbo 1:f468352a5408 259 }
shinbo 1:f468352a5408 260 cs8416_write(0x01, DEF_REGVAL[1] | u8_data); // (01h) : Control1
shinbo 0:cb6ecbfcf585 261 }
shinbo 0:cb6ecbfcf585 262
shinbo 0:cb6ecbfcf585 263
shinbo 0:cb6ecbfcf585 264 void set_source() {
shinbo 0:cb6ecbfcf585 265 uint8_t u8_data = 0;
shinbo 0:cb6ecbfcf585 266
shinbo 0:cb6ecbfcf585 267 if (g_cur_tgl & 1) {
shinbo 0:cb6ecbfcf585 268 u8_data = 0x08; // (04h)[5:3] RXSEL2:0
shinbo 0:cb6ecbfcf585 269 } else {
shinbo 0:cb6ecbfcf585 270 u8_data = 0x00; // (04h)[5:3] RXSEL2:0
shinbo 0:cb6ecbfcf585 271 }
shinbo 1:f468352a5408 272 cs8416_write(0x04, DEF_REGVAL[4] | u8_data); // (04h) : Control4
shinbo 0:cb6ecbfcf585 273 }
shinbo 0:cb6ecbfcf585 274
shinbo 0:cb6ecbfcf585 275
shinbo 0:cb6ecbfcf585 276 int main() {
shinbo 0:cb6ecbfcf585 277
shinbo 0:cb6ecbfcf585 278 spi.format(8, 3); // 8bit, mode3
shinbo 0:cb6ecbfcf585 279 spi.frequency(1000000); // 1MHz : default
shinbo 0:cb6ecbfcf585 280
shinbo 0:cb6ecbfcf585 281 cs8416_init();
shinbo 0:cb6ecbfcf585 282 fn1242_init();
shinbo 0:cb6ecbfcf585 283
shinbo 0:cb6ecbfcf585 284 while (1) {
shinbo 1:f468352a5408 285 uint32_t u32_freq = g_freq;
shinbo 1:f468352a5408 286
shinbo 0:cb6ecbfcf585 287 uint8_t u8_addr18 = cs8416_read(0x18); // (18h) : OMCK/RMCK Ratio
shinbo 0:cb6ecbfcf585 288 decide_freq(u8_addr18);
shinbo 0:cb6ecbfcf585 289 set_led();
shinbo 0:cb6ecbfcf585 290
shinbo 0:cb6ecbfcf585 291 uint8_t u8_addr0B = cs8416_read(0x0b); // (0Bh) : Format Detect Status
shinbo 1:f468352a5408 292 if ((g_cur_frmt != u8_addr0B) || (g_freq != u32_freq)) {
shinbo 0:cb6ecbfcf585 293 g_cur_frmt = u8_addr0B;
shinbo 0:cb6ecbfcf585 294 set_rmckf();
shinbo 0:cb6ecbfcf585 295 }
shinbo 0:cb6ecbfcf585 296
shinbo 0:cb6ecbfcf585 297 uint32_t u32_tgl = pin_tgl;
shinbo 0:cb6ecbfcf585 298 if (g_cur_tgl != u32_tgl) {
shinbo 0:cb6ecbfcf585 299 g_cur_tgl = u32_tgl;
shinbo 0:cb6ecbfcf585 300 set_source();
shinbo 0:cb6ecbfcf585 301 }
shinbo 0:cb6ecbfcf585 302
shinbo 0:cb6ecbfcf585 303 wait_ms(200); // ms
shinbo 0:cb6ecbfcf585 304 }
shinbo 1:f468352a5408 305
shinbo 0:cb6ecbfcf585 306 }