cs3318 and arduino

Linuxworks, I am still fighting to justify the use of cs3318 for pure stereo preamp (with that PITA soldering and carrier board ;-). I have no use for all the channels in my setup, no HT, no XO. What if I use the 8 channels as 4x stereo input selector controlled via sw - just control volume of the selected input and mute the rest? The datasheet reports 120 dB Inter-Channel Isolation - does it make sense or is it too much crazy? So I could spare the input relays and make an all-in-one preamp board.
 
No... I meant to hardwire the 4 stereo inputs directly to the 8 channels of the cirrus chip and fake the input selector in 3318 via sw control: to mute 3 stereo inputs fully and let the "selected input" pass through to volume control...already obsolete (or overcomplicated) due to input buffer habit ;-)
 
so you want to sum all the 8 channels and just mute the inputs you don't want?

you'll pay a summed noise tax, I would guess.

muting is pretty clean on this chip, but you are still summing 4 pairs to select and I'm not sure that's going to give the best results.

relays are so simple and so clean. they are low-tech but so what? ;)
 
Nothing against relays...as mentioned, it was more a twist of mind to justify the six high-end channels lying idle in the chip in pure stereo setup :). But I cannot find device of similar sonic quality as 3318 with two channels only. I may come back to R-2R ladder...if I sacrifice fade-out/in while muting. I am still scared of soldering so small SMD...or I keep waiting until you finish your development and offer the 3318 module board as kit...;-))
 
Anybody have any Arduino code for this IC?

Is this how you set a register?

Code:
Wire.beginTransmission(CSAddr);     // Begin I2C
Wire.write(B10000000);                 // Chip Address and R/W bit
Wire.write(0x00);                         // select the register
Wire.write(0x99);                         // set register

Here is what I've got but the device just seems to stay muted after bringing RESET high.

Code:
#include "Wire.h"

#define CSAddr 64 // 64 or 1000000b or 0x40
#define CIRRUS_RESET    8
#define CIRRUS_DISABLE_PDN_ALL B00000000  // the only bit we care about is b0=0
#define CIRRUS_MASTER_POWER 0x0e
int vol_level = 0;

void setup()
{
  Serial.begin(9600);
  
  // Power up sequence from Page 16, point 1.
  pinMode(CIRRUS_RESET, OUTPUT);
  digitalWrite(CIRRUS_RESET, LOW);
  delay(5000);
  // Power up sequence from Page 16, point 2, bring reset high
  Serial.println ("Starting powerup...");
  digitalWrite(CIRRUS_RESET, HIGH);   // disable reset (bring chip out of sleep)
  delay(5000);
  
  // Errata from http://www.digikey.com/Web%20Export/Supplier%20Content/Cirrus_598/PDF/Cirrus_PCN_CS3308-18_B0_C0.pdf?redirected=1
  Serial.println ("Applying errata thing...");
  Wire.beginTransmission(CSAddr);     // Begin I2C
  Wire.write(B10000000);              // Chip Address and R/W bit
  Wire.write(0x00);                   // select the register
  Wire.write(0x99);                   // set register
  Wire.write(B10000000);              // Chip Address and R/W bit
  Wire.write(0x1D);                   // select the register
  Wire.write(0x86);                   // set register 
  Wire.write(B10000000);              // Chip Address and R/W bit
  Wire.write(0x1F);                   // select the register
  Wire.write(0x02);                   // set register
  Wire.write(B10000000);              // Chip Address and R/W bit
  Wire.write(0x00);                   // select the register
  Wire.write(0x00);                   // set register 
  delay(5000);
  
  // Unmute by setting PDN_ALL, from page 15.
  Serial.println ("Unmuting...");
  Wire.write(B10000000);              // chip_addr and r/w bit
  Wire.write(CIRRUS_MASTER_POWER);    // select the register
  Wire.write(CIRRUS_DISABLE_PDN_ALL); // set register

}


void loop()
{
  
  Wire.write(B10000000);              // chip_addr and r/w bit
  Wire.write(0x11);                   // select Master 1 Vol-ume
  Wire.write(vol_level);              // send volume
  
  Wire.write(B10000000);              // chip_addr and r/w bit
  Wire.write(0x14);                   // select Master 2 Vol-ume
  Wire.write(vol_level);              // send volume
  
  Wire.write(B10000000);              // chip_addr and r/w bit
  Wire.write(0x17);                   // select Master 3 Vol-ume
  Wire.write(vol_level);              // send volume
  
  delay(100);
  
  if (vol_level < 254) {
    vol_level = vol_level + 1;
  }
  
  if (vol_level == 253) {
    vol_level = 1;
  }
  
  Serial.println (vol_level);
}
 
Take a look at this example: Arduino - WireWrite

Yeah I've read that. I've used other I2C devices without issues but they were all 5V. This time I'm using one of these to change the level. Do I put the pull up resistors on the arduino to 5V or on the CS3318 side to 3.3V?

I've updated my code a bit but still the IC is mute...


Code:
#include "Wire.h"

#define CSAddr 64 // 64 or 1000000b or 0x40
#define CIRRUS_RESET    8
#define CIRRUS_DISABLE_PDN_ALL B00000000  // the only bit we care about is b0=0
#define CIRRUS_MASTER_POWER 0x0e
#define CIRRUS_CHANNEL_POWER 0x0d
byte vol_level = 0;

void setup()
{
  Serial.begin(9600);
  
  // Power up sequence from Page 16, point 1.
  pinMode(CIRRUS_RESET, OUTPUT);
  digitalWrite(CIRRUS_RESET, LOW);
  delay(7000);
  // Power up sequence from Page 16, point 2, bring reset high
  Serial.println ("Starting powerup...");
  digitalWrite(CIRRUS_RESET, HIGH);   // disable reset (bring chip out of sleep)
  delay(5000);
  Wire.begin(); // join i2c bus
  delay(1000);
  
  // Errata from http://www.digikey.com/Web%20Export/Supplier%20Content/Cirrus_598/PDF/Cirrus_PCN_CS3308-18_B0_C0.pdf?redirected=1
  Serial.println ("Applying errata thing...");
  Wire.beginTransmission(CSAddr);     // Begin I2C
  Wire.write(B10000000);              // Chip Address and R/W bit
  Wire.write(0x00);                   // select the register
  Wire.write(0x99);                   // set register
  Wire.endTransmission();
  Wire.beginTransmission(CSAddr);
  Wire.write(B10000000);              // Chip Address and R/W bit
  Wire.write(0x1D);                   // select the register
  Wire.write(0x86);                   // set register 
  Wire.endTransmission();
  Wire.beginTransmission(CSAddr);
  Wire.write(B10000000);              // Chip Address and R/W bit
  Wire.write(0x1F);                   // select the register
  Wire.write(0x02);                   // set register
  Wire.endTransmission();
  Wire.beginTransmission(CSAddr);
  Wire.write(B10000000);              // Chip Address and R/W bit
  Wire.write(0x00);                   // select the register
  Wire.write(0x00);                   // set register
  Wire.endTransmission(); 
  delay(5000);
  
  // Unmute by setting PDN_ALL, from page 15.
  Serial.println ("Unmuting...");
  Wire.beginTransmission(CSAddr);
  Wire.write(B10000000);              // chip_addr and r/w bit
  Wire.write(CIRRUS_MASTER_POWER);    // select the register
  Wire.write(CIRRUS_DISABLE_PDN_ALL); // set register
  Wire.endTransmission();
  Wire.beginTransmission(CSAddr);
  Wire.write(B10000000);              // chip_addr and r/w bit
  Wire.write(CIRRUS_CHANNEL_POWER);    // select the register
  Wire.write(CIRRUS_DISABLE_PDN_ALL); // set register
  Wire.endTransmission();
}


void loop()
{
  Wire.beginTransmission(CSAddr);
  Wire.write(B10000000);              // chip_addr and r/w bit
  Wire.write(0x02);                   // select Master 1 Vol-ume
  Wire.write(vol_level);              // send volume
  Wire.endTransmission();
  
  Wire.beginTransmission(CSAddr);
  Wire.write(B10000000);              // chip_addr and r/w bit
  Wire.write(0x03);                   // select Master 2 Vol-ume
  Wire.write(vol_level);              // send volume
  Wire.endTransmission();

  delay(100);
  
  if (vol_level < 254) {
    vol_level = vol_level + 1;
  }
  
  if (vol_level == 253) {
    vol_level = 1;
  }
  
  Serial.println (vol_level);
}
 
Is that ALL the code?

...because it won't do anything. Unless there's something about Arduino C that is radically different from all the C I've ever come across.

You need a main() routine, and you need to call those routines...

int main(void)
{
setup();
loop();
}

Otherwise show us all of the code, it's impossible to debug fragmentary code.

...and there's something strange about the last few lines in the loop() routine, when the volume gets to 253, it resets to one.

I'd expect to see a bit (pin) test in a neverending loop in main and an associated upcount routine and a second bit test with an associated downcount routine.

For test purposes I'd bit-bang the serial comms in assembler, whitewire across a spare pin or two if the serial port pins won't let you use them like that. Once you've verified that the hardware works you can move on to using the built-in serial comms. Stuff like that can be really hard to debug, because all you need is a slightly incorrect setup and it all falls over. You need to work up the functionality from absolutely basic if you don't have code that you've verified previously.
 
Yeah I've read that. I've used other I2C devices without issues but they were all 5V. This time I'm using one of these to change the level. Do I put the pull up resistors on the arduino to 5V or on the CS3318 side to 3.3V?

The board already has 10K pull ups. But you can use smaller pull ups if you wish. You need them on both sides.

Regarding your code:

Wire.beginTransmission(CSAddr); // Begin I2C
Wire.write(B10000000); // Chip Address and R/W bit
Wire.write(0x00); // select the register
Wire.write(0x99); // set register
Wire.endTransmission();


Wire.begin is for the chip address
Wire.write is to select the register address
The next write is for the value you want to write into the register
Wire.end sends the data and releases the bus

Try writing one register at a time.
 
Is that ALL the code?

...because it won't do anything. Unless there's something about Arduino C that is radically different from all the C I've ever come across.

You need a main() routine, and you need to call those routines...

int main(void)
{
setup();
loop();
}

Otherwise show us all of the code, it's impossible to debug fragmentary code.

Yes, that is all the code. I don't think there is a main() routine in the Arduino IDE.

The board already has 10K pull ups. But you can use smaller pull ups if you wish. You need them on both sides.

Regarding your code:

Wire.beginTransmission(CSAddr); // Begin I2C
Wire.write(B10000000); // Chip Address and R/W bit
Wire.write(0x00); // select the register
Wire.write(0x99); // set register
Wire.endTransmission();


Wire.begin is for the chip address
Wire.write is to select the register address
The next write is for the value you want to write into the register
Wire.end sends the data and releases the bus

Try writing one register at a time.

Thanks glt, this solved it. The first wire.write was not required. I put it in due to this being in the datasheet:
"The first byte sent to the CS3318 after a Start condition consists of a 7-bit chip address field and a R/W
bit", but I guess that part is taken care of in the Wire.beginTransmission.

Anyway, I got it going, then fried the chip. Not sure how but hey ho, learn as I go :)
 
No real deal breakers but just a few things that make it a bit more tricky for DIY:
- It's expensive
- It's hard to solder (0.65mm pin pitch)
- 3.3V. Not a huge problem these days as there are more 3.3V device now but a couple years back options were more limited.
- Easy to destroy the IC. If one supply rail is connected but not the other it goes up in smoke. I think everyone who played with the CS3318 has fried at least one.
 
AX tech editor
Joined 2002
Paid Member
Hi guys.

After not manage to fix the PGA2310 clicks issue cause of the low resolution i searched the web and got to this post.
I saw in the first page that linuxworks used a pcb for the CS3318, i couldn't find anywhere to buy this pcb, is it available somewhere?

Regards,
Isak.

If you have the click issue with the PGA you will also have it with the CS. It is not caused by resolution but by having some DC offset on the signal. When switching the DC offset changes and that sounds as clicking. Because of the DC, the zero=volt switching of the PGA will not work.
Get rid of that and you get rid of the clicking.

Jan