CS8416 in Software Mode

Is anyone here using the CS8416 in "Software Mode"?
If so, I have some questions.

I have built a DAC board with the CS8416 and the MAX9850. I have the I2C bus working nicely (connected to a PIC 18F2550) and I can read/write commands to either chip. But, so far - the only sound output is a few clicks.

Please share your init sequence. Here is mine (function I2C_W2 writes 2 bytes on the I2C bus):
Code:
r = I2C_W2(RXI2S_A, RXI2S_SADFMT, 0b10000000);	// set audio output port to Master mode
r = I2C_W2(RXI2S_A, I2SDAC_LRCLKH, 0b10001011);	// set Integer mode, DLY, 24 bit
r = I2C_W2(RXI2S_A, I2SDAC_DAUDIO, 0b00001000);	// set I2S data
r = I2C_W2(RXI2S_A, RXI2S_CNTRL2, 0b00000011);	// set GPO-0, red, to C bit
r = I2C_W2(RXI2S_A, RXI2S_CNTRL3, 0b01100000);	// set GPO-1, green, to NVERR

r = I2C_W2(RXI2S_A, RXI2S_CNTRL4, 0b10000000);	// set RUN

a) which of the 16 choices for GPOn best describes if the CS8416 is decoding a valid stream? I have tried the C (channel status) and NVERR, but they are always 0 (so far).

b) I have my CS8416 in Master Mode and the DAC in Slave Mode, does that make sense?

Thanks,
Jake
 
cs8416 init via SPI

You might want to do a cross check with (part of) my SPI init code.

This is confirmed to work (also by reading status registers, eg the receiver error (0C) register and the version register (7F).

Code:
int control4_reg = 0x8b; // 0x8b = coax 1 default, 0xb2 = coax 2, 0xba = coax 3, 0xa3 = opt1, 0xaa = opt2, 
 
void cs8416_init(void) {
 cs8416_rst = 0;     // put device in reset
 DelayMs(1);       // delay 1 ms
 cs8416_rst = 1;     // wake device
 DelayMs(1);       // delay 1 ms
 cs8416_cs = 1;     // enter SPI mode by setting cs high 
 cs8416_write(control4, control4_reg);   // send run state, RXP0 on, RXP2 (not connected on PCB) to TX
 
 cs8416_write(rem, 0xff);       // unmask all receiver error bits
 
 cs8416_write(int_mask, 0xff);       // unmask all IRQ
 
 cs8416_write(sadf, 0b10100101);  // set master mode (1)
                  // OSCLK is 64*Fs (0)
                  // 16-bit resolution (10)
                  // left-justified (0)
                  // MSB on second clock period (1)
                  // sampled on rising edges of OSCLK (0)
                  // right channel when OLRCK is high (1)
 
 
 cs8416_setpdur(1);
 
} //end cs8416_init

You might want to try reading the 7F register (should read 0b00101111 if you have a version E). First argument of the cs8416_write function is the register's friendly name (defined in include file, but you'll recognize from the datasheet).

Now, the trouble I am having is I am not getting anything useful out of the 0x19 - 0x22 (channel status registers, would love to read the sample rate, bit depth from the S/PDIF stream)... Can anyone help, please?
 
Now, the trouble I am having is I am not getting anything useful out of the 0x19 - 0x22 (channel status registers, would love to read the sample rate, bit depth from the S/PDIF stream)... Can anyone help, please?

To answer my own query: I managed to read the channel status registers. Problem turned out to be I have LSB/MSB mixed up. Bit depth, BTW, seems to be set to 24 bits all the time, at least in all the sources I have used so far (on board sound card, EMU0404PCIE card...)

Cheers!!
 
Code:
cs8416_write(sadf, 0b10100101);  // set master mode (1)
                  // OSCLK is 64*Fs (0)
                  // 16-bit resolution (10)
                  // left-justified (0)
                  // MSB on second clock period (1)
                  // sampled on rising edges of OSCLK (0)
                  // right channel when OLRCK is high (1)
 
 
 cs8416_setpdur(1);

Thanks for the example. Can you offer any insight on how you choose those init values;
Why MSB on second clock period?
Why right channel on ...?

Also, what does CS8416_setpdur(1) do?


You might want to try reading the 7F register (should read 0b00101111 if you have a version E).
When I read register 7F, I do indeed get 0x2F.

Jake
 
Thanks for the example. Can you offer any insight on how you choose those init values;
Why MSB on second clock period?
Why right channel on ...?

Also, what does CS8416_setpdur(1) do?



When I read register 7F, I do indeed get 0x2F.

Jake

Init values are mostly as per I2S bus specs / datasheet of your DAC IC. I believe you are also configured to use I2S, so possibly you should stick to the init values I have?

CS8416_setpdur(1) sets the PDUR bit. For the functionality of the PDUR bit, please search the datasheet of the CS8416. I can't explain it any better than that.
 
I have made some progress and got something out of my DAC. The sound is distorted, but recognizable.

Meanwhile I still can't get the GPO LEDs to change. For example the AUDIO bit should be high when a proper SPDIF/PCM stream is detected, but it stays low all the time (although it does flicker a bit when I disconnect the SPDIF input).
 
... For example the AUDIO bit should be high when a proper SPDIF/PCM stream is detected, ...

Are you sure? Datasheet says about the !AUDIO pin 15 in hardware mode "When low, a valid linear PCM audio stream is indicated." (an exclamation mark in front of or a 'overlined' pinnname is an active low indicator)

So when valid PCM is detected pin is low, not high. Still doesn't explain the flickering when you disconnect input, though, LED should be solid on. Time to check the electrical connections, then? Or maybe resetting the part in some while loop?...

Good luck!
 
I've now got this working. The problem was in the init code for the DAC.

Here is the init code for the CS8416 (SPDIF inputs - I2S outputs), in Software mode, with the CS8416 operating as the clock master:
Code:
I2C_W2(RXI2S_A, RXI2S_SADFMT, 0b10000101);		// Master, 24 bit, SODEL, SOLRPOL
I2C_W2(RXI2S_A, RXI2S_CNTRL0, 0b00001100);	// PDUR, TRUNC
I2C_W2(RXI2S_A, RXI2S_CNTRL1, 0b00000000);	// 
I2C_W2(RXI2S_A, RXI2S_CNTRL2, 0b01001001);	// Auto de-emphasis; GPO-0 (red-led) to non-AUDIO
I2C_W2(RXI2S_A, RXI2S_CNTRL3, 0b00110000);	// GPO-1 (green-led) to C bit
I2C_W2(RXI2S_A, RXI2S_RXEMSK, 0b01111111);	// unmask all errors
...
I2C_W2(RXI2S_A, RXI2S_CNTRL4, 0b10000000);

and for anyone who wants it, here is the init code for the MAX9850 (I2S inputs - audio outputs), operating as the clock slave:
Code:
I2C_W2(I2SDAC_B, I2SDAC_DAUDIO, 0b00001011);	// set to Slave mode, DLY, 24 bit
I2C_W2(I2SDAC_B, I2SDAC_LRCLKL, 0b00010000);	// divide iclk by 16 * 16 (typ 44.1 or 48 kHz)
I2C_W2(I2SDAC_B, I2SDAC_LRCLKH, 0b10000000);	// Integer mode,
I2C_W2(I2SDAC_B, I2SDAC_VOLUME, 0b00001111);	// volume to mid-range
I2C_W2(I2SDAC_B, I2SDAC_GENPUR, 0b00100001);	// ZDEN, GPD out, GPO=0
I2C_W2(I2SDAC_B, I2SDAC_CHGPMP, 0b01000000);	// Slew 125 ms, CP internal
...
I2C_W2(I2SDAC_B, I2SDAC_ENABLE, 0b11111101);

I plan to do some further experimenting with the various registers, and then get my ADC card working (based on CS4265).

Jake
 
Congrats!

WRT the left/right polarity of the LRCK: it seems the datasheet is not consistent with 'reality':

I have a piece of music where my transport indicates (via VU meter on screen) that a sound is on the left-channel only. Now, If I configure the CS8416 according the the I2S specs and the datasheet (so SOLRPOL = 1, SDOUT data is valid for the right channel when OLRCK is high), I hear the sound on the RIGHT channel.

So I guess SOLRPOL = 0 is the correct setting, after all??

Anyhow, glad you got it working!
 
FYI - I got the GPOs sorted out too. Here is what I use to set up the outputs that drive the LEDs:
Code:
I2C_W2(RXI2S_A, RXI2S_CNTRL2, 0b01000001);	// Auto de-emphasis; GPO-0 (red-led) to !EPMPH
I2C_W2(RXI2S_A, RXI2S_CNTRL3, 0b01100000);	// GPO-1 (green-led) to NVERR
The LEDs are fed from +5v, and then into the GPOs; so a low voltage on the GPO pin turns on the LED. So, the Green LED comes on when there is no error, and the red LED comes on when there is no de-emphasis. During normal music, the green led is on and red is off. If I unplug the SPDIF coax, the green goes out and the red comes on.
 
To answer my own query: I managed to read the channel status registers. Problem turned out to be I have LSB/MSB mixed up. Bit depth, BTW, seems to be set to 24 bits all the time, at least in all the sources I have used so far (on board sound card, EMU0404PCIE card...)

Cheers!!

Hi all folks!

I began to work on CS8416 recently. I was sucessful basicly at least it sounded well. However, by reading the datasheet, I found out the register 18h (OMCK/RMCK Ratio (18h)) can be used to get input frequency like 44.1 48 khz..etc. But I get all 00000000 valus from this register.
Does anyone have experienced in using/reading this register?
Thanks!
 
Hi all folks!

I began to work on CS8416 recently. I was sucessful basicly at least it sounded well. However, by reading the datasheet, I found out the register 18h (OMCK/RMCK Ratio (18h)) can be used to get input frequency like 44.1 48 khz..etc. But I get all 00000000 valus from this register.
Does anyone have experienced in using/reading this register?
Thanks!

Are you actually applying a clock on OMCK pin? (FWIW: I am reading the sample frequency from the S/PDIF channel data, e.g. from register 19h; works fine if the source is sending this information).
 
Are you actually applying a clock on OMCK pin? (FWIW: I am reading the sample frequency from the S/PDIF channel data, e.g. from register 19h; works fine if the source is sending this information).

I just checked my code: I am using channelA_stat3 an channelA_stat4 registers.

Some of the bits in those registers represent sample frequency and word length. According to IEC 60958-3-2006.
 
Koen,

Thanks a lot.
Now I get from channelA_stat3 with frequency incomming and seems to be correct according to IEC 60958-3.
As for channelA_stat4, I always read 0000 0000 which means …"word length not indicate (default)". Have you get correct word length from channelA_stat4? and in what condition (cd, dvd or .wav..)
 
Koen,

Thanks a lot.
Now I get from channelA_stat3 with frequency incomming and seems to be correct according to IEC 60958-3.
As for channelA_stat4, I always read 0000 0000 which means …"word length not indicate (default)". Have you get correct word length from channelA_stat4? and in what condition (cd, dvd or .wav..)

Yes, I am successfully reading word length, too. Possibly you are trying to read the metadata before it has all been decoded from the S/PDIF stream?

Here's a the bit of code I have to handle this. Notice the delay after the receiver has acquired the lock to allow channel decoding. One second is probably way too long, but I feel it is kind of classy when the LCD is updated after a while. Like my receiver has done a really hard job decoding the channel metadata. :)

BTW, I believe the actual metadata is not dependent on the actual source but on the implementation of the S/PDIF transmitter and it's drivers. For example: my computer and satellite receiver always display 24 bits word length, even when playing 16-bit material. It is not until I explicitly set the soundcard to 16-bit wordlength that 16 bit wordlength is indicated. But then 24-bit source material is truncated.

Also see section 11.1, 5th paragraph of the CS8416 datasheet on how to use an interrupt to detect when channel data has been decoded.

Code:
if (!cs8416_rerr && !islocked) { // receiver acquired lock
  __delay32(fcy);		// delay 1s for metadata
  // get stream metadata
  sample_rate = (cs8416_read(channelA_stat3) & 0b00001111);
  bit_depth = (cs8416_read(channelA_stat4) & 0b00001111);
  switch(bit_depth) {         // send bit depth to LCD
    // put your switches here
  }
 
Hi Koen,

Thank you very much for your help again.
I have two inputs hook up into CS8416.
1. CD Player, in this device I can read 1C (channelA_stat3), Q-Channel sub code correctly.
2. USB input, in this device I can only read 1C (channelA_stat3), but can not read Q-Channel sub code (00000000).

I still can not read correct 1D (channelA_stat4), in both devices.

I checked the rerr, metadata possibility, but still nothing.

Maybe I have some configuation's problems.

Will work on this issue further.

Thanks again.