Driving 16 bit DAC

I’m experimenting with the DAC TDA1543 that uses I2S communication (the name looks like I2C, but it’s not the same).
The datasheet is here: http://www.datasheetcatalog.org/datasheet/philips/TDA1543.pdf

Since the communication protocol looked for me quite similar to the shiftout function, I’ve modified the following code to drive it:

void mishiftOut(word val, boolean wsSel)
// if wsSel is HIGH, RIGHT channel is selected.

{
	uint8_t i;
        digitalWrite(WSPIN, wsSel);
	for (i = 0; i < 16; i++)  {
		digitalWrite(CLOCKPIN, HIGH);
                digitalWrite(DATAPIN, !!(val & (1 << (15 - i)))); //MSB FIRST
		digitalWrite(CLOCKPIN, LOW);
	}
        digitalWrite(WSPIN, !wsSel);
}

The wiring is prettey simple, 3 pins of the arduino are used to connect with the ICs data, clock and WS pins.
I’ve tested it, trying to get different DC voltages in the Analog Outputs (measuring with a multimeter), so far without success. Voltage does not change.
As far as I understand from the datasheet, once the signal is sent, the output should be latched. I’m not using a high frecuency, just sending a stream every 2 seconds.
As far as I understand from the datasheet, I should get an output between 1.8 and 3.8V (5V - 1.2V)
Does anyone have experience with this IC? Is the code I’ve written right?
Regards

The code is probably fine. I would have suggested two SPI transfers per channel, or two shiftouts per channel, which you've basically duplicated. How is your output wired up? Try adding a 10K pullup resistor, the output is a current sink, so you should see that wiggle some.

Looking at fig 5, page 8 of the datasheet I think you need to add one more clock pulse after the WS change at the end of your function. So I think you have to shift out 15 bits, toggle WS and then send the LSB. At least give it a try. Even then I’m not sure all is setup correctly for the next call to the function? This seems to really want both channels to be clocked out as a set, as best I can tell.

void mishiftOut(word val, boolean wsSel)
// if wsSel is HIGH, RIGHT channel is selected.

{
	uint8_t i;
        digitalWrite(WSPIN, wsSel);
	for (i = 0; i < 15; i++)  {
		digitalWrite(CLOCKPIN, HIGH);
                digitalWrite(DATAPIN, !!(val & (1 << (14 - i)))); //MSB FIRST, do 15 bits only
		digitalWrite(CLOCKPIN, LOW);
	}
        digitalWrite(WSPIN, !wsSel);
        digitalWrite(DATAPIN, bitRead(val, 0)  // get LSB of val
        digitalWrite(CLOCKPIN, HIGH);
        digitalWrite(CLOCKPIN, LOW);

}

Lefty

Tried both approches with no result. Maybe I wasn't meassuring the right way. Wired the output to an LM358 OpAmp, the way it´s shown in the TDA datasheet, and this way I can get a range between 2,2 and 3,4V, inputing values from 58000 to 32000. So that´s a nice start. At leas I believe that the code works. Now, is there a way to wire the OpAmp to get a range from 0 to 5V? I'm just starting to learn something about OpAmps, and I hae to confess that is not an easy road... Should i start supplying the LM358 with 12V instead of the actual 5V?

Still didn't have the guts to test the Opamp with 12V. But at least tweaking the feedback resistor I was able to get a consistent value between 1V and almost 0V, but only with 15-bits. Something is wrong with the last bit. I'll have to try retroleftys idea again.

Got it finally!

void mishiftOut(int val, boolean wsSel)
// Si wsSel es HIGH va a ir al canal RIGHT

{
	uint8_t i;
        digitalWrite(WSPIN, wsSel);
	for (i = 0; i < 16; i++)  {
		digitalWrite(CLOCKPIN, HIGH);
                digitalWrite(DATAPIN, !!(val & (1 << (15 - i)))); //MSB FIRST
                //delay(ESPERA);
               
		digitalWrite(CLOCKPIN, LOW);
	}
        digitalWrite(WSPIN, !wsSel);
}

I learned about negative binary handling and that was it.

In general I2S devices require a stable continuous multiple synchronous clocks (sometimes 3 clocks!) and can’t be given individual samples like this - typical devices use the clock to drive internal decimation filters and suchlike - although the datasheet is a bit sparse it looks like this one is a pretty-much standard D/A interfaced as “pseudo I2S”. So don’t immediately expect it to be as easy/possible on other I2S chips.