Trying to communicate with WM8740 (Opus DAC), not going well...
May 26, 2010 at 10:34 AM Thread Starter Post #1 of 6

elliot42

500+ Head-Fier
Joined
Jul 18, 2008
Posts
924
Likes
12
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:
Code:
 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:
Code:
 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:
Code:
 // Write volume with LDL bit set in addr byte opusWrite(REG0 & 0x01, (byte) volume);
 
May 26, 2010 at 11:00 AM Post #3 of 6
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:

 
May 26, 2010 at 11:48 PM Post #5 of 6
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):
Code:
 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:
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.



 

Users who are viewing this thread

Back
Top