Head-Fi.org › Forums › Misc.-Category Forums › DIY (Do-It-Yourself) Discussions › Trying to communicate with WM8740 (Opus DAC), not going well...
New Posts  All Forums:Forum Nav:

Trying to communicate with WM8740 (Opus DAC), not going well...

post #1 of 6
Thread Starter 

Well, I now have a working Opus DAC module and have been playing with software control so that I can get an Arduino with rotary encoder and VFD to perform volume control and other control duties.

 

BUT, the Opus module I have is an older revision and uses the WM8740 chip and as such doesn't have I2C. I have been reading up on SPI and reading hifiduino for general info but I haven't been successful so far.

I have the DIFFHW and IWO switches pulled low on the DIP.

The Arduino is connected to the Opus using pins 8, 9 and 10 connected to MC, ML and MD (clock, latch, data).

 

Can anyone help point me in the right direction, tell me what I'm doing wrong, etc.

 

Maybe I'm not actually communicating right, or not passing the right setup commands to the Opus, or something just stupid; I'm a bit stuck...

 

The code I've written has been influenced by a number of sources (hifiduino included) and the bit I'm actually using to write to the DAC is as follows:

void opusWrite(byte addr, byte data)
{
  digitalWrite(OPUS_ML, LOW);
  spi_transfer(addr);
  spi_transfer(data);
  digitalWrite(OPUS_ML, HIGH);
}

void spi_transfer(byte working)
{
  for(int i = 1; i <= 8; i++) { // setup a loop of 8 iterations, one for each bit
    if (working > 127) { // test the most significant bit
      digitalWrite(OPUS_MD, HIGH); // if it is a 1 (ie. B1XXXXXXX), set the master out pin high
    }
    else {
      digitalWrite(OPUS_MD, LOW); // if it is not 1 (ie. B0XXXXXXX), set the master out pin low
    }
    digitalWrite(OPUS_MC, HIGH); // set clock high, rising edge will clock the bit in
    working = working << 1;
    digitalWrite(OPUS_MC, LOW); // set clock low
  }
}

 

I call opusWrite in the setup() function to set the format and attenuation setting:

opusWrite(REG2, 0x08); // Write to IW0(B3) bits in M2 (24-bit I2S)
opusWrite(REG3, 0x05); // Write to I2S(B0) and ATC(B2) bits in M3

 

And elsewhere to update the volume:

// Write volume with LDL bit set in addr byte
opusWrite(REG0 & 0x01, (byte) volume);
post #2 of 6
I wondering how you are clocking out the data? Looks like it could be an issue.
post #3 of 6
Thread Starter 

For each command I:

Set the latch low.

Set data to the value of each bit of the addr then data bytes starting with the most significant bit, followed by setting the clock high then low to commit each bit on the rising edge of the clock.

Set the latch high to commit the 16-bit word.

 

This was based off some sample code for SPI communication as well as this part of the WM8740 datasheet:

Screen shot 2010-05-27 at 12.54.54 AM.png

post #4 of 6

I'm not sure what you pin use is like, but you could try the built in SPI functionality.

 

You can read about an implementation here:

 

http://www.arduino.cc/en/Tutorial/SPIDigitalPot

 

I've used this method to drive some PGA2311 through SPI and it worked right off the bat.

post #5 of 6
Thread Starter 

Thanks for the link, I implemented the opusWrite command using the native SPI functionality, so I guess that should technically work fine.

But, it's still not working correctly. When I play music (from my MacBook to the TPA USB receiver -> SPDIF MUX module -> Opus as I2S) all I get is static noise. The noise is in time with playing and stopping audio from iTunes, so I'm guessing the Opus isn't being set up with the correct parameters and getting the format wrong?

 

New code (SLAVESELECT pin is connected to Opus ML):

void opusWrite(byte addr, byte data)
{
  digitalWrite(SLAVESELECT, LOW);
  spi_transfer(addr);
  spi_transfer(data);
  digitalWrite(SLAVESELECT, HIGH);
}

byte spi_transfer(volatile byte data)
{
  SPDR = data;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)));    // Wait the end of the transmission
  return SPDR;                    // return the received byte
}


 

Quote:
Originally Posted by cobaltmute View Post

I'm not sure what you pin use is like, but you could try the built in SPI functionality.

 

You can read about an implementation here:

 

http://www.arduino.cc/en/Tutorial/SPIDigitalPot

 

I've used this method to drive some PGA2311 through SPI and it worked right off the bat.

post #6 of 6
Thread Starter 

Bump.

Anyone else got any experience with WM8740 and SPI?

Documentation is sparse and implementation examples seem non-existent...


Edited by elliot42 - 5/28/10 at 7:27pm
New Posts  All Forums:Forum Nav:
  Return Home
Head-Fi.org › Forums › Misc.-Category Forums › DIY (Do-It-Yourself) Discussions › Trying to communicate with WM8740 (Opus DAC), not going well...