ES9039Q2M S/PDIF DAC design

A bit of success, the amanero arrived from italy and I got the DAC working with I2S in software mode 🙂
It seems I have to send the registers for every start of the DAC, otherwise I get no output.

I changed these registers:

C++:
 // Register 1: SYS MODE CONFIG (default 0b10110001 = hex B1)
  // Enable SPDIF decode (bit 3 = 1), keep other defaults
  // New value for spdif: 0x89 (0b10001001)
  //for i2s: default, hex B1
  writeRegister(0x01, 0xB1);

  // Register 57: INPUT SELECTION (default 0b01000000 = hex 40)
  // SPDIF:        0b01000110 = 0x46 (INPUT_SEL = 3 = SPDIF, AUTO_INPUT_SEL = 0)
  // I2S (Amanero):0b01000001 = 0x41 (INPUT_SEL = 0 = PCM, AUTO_INPUT_SEL = 1)

  writeRegister(0x39, 0x41);

Its working with both crystals, sound quality is not mindblowing atm, there is a bit of a crackle/noise (maybe coming from the +-15V SMPS, I will investigate).
 
Working on the similar project, testing I2C configuring ES9039Q2M and now stuck with no analog output with SPDIF input.
Is it enough to startup with SPDIF enabled ?
Code:
#include <Wire.h>
#define DAC_ADDR 0x48;
void writeDACRegister(uint8_t reg, uint8_t val);
void applyStartupConfig() {
  writeDACRegister(0x09, 0x01);        // SPDIF input select
  writeDACRegister(0x39, 0b00000100);  // SPDIF, auto detect off
  writeDACRegister(0x89, 0b01000000);  // SPDIF_SEL = GPIO4
  writeDACRegister(0x88, 0b00010000);  // Enable GPIO4 as SPDIF input
  writeDACRegister(0x01, 0b00000010);// Enable DAC analog output
  writeDACRegister(0x02, 0x00);// Unmute
  uint8_t reg3; // Set ASRC mode
  readDACRegister(0x03, &reg3);
  reg3 &= ~0x80;  // Clear SYNC bit (bit7 = 0 -> Async)
  writeDACRegister(0x03, reg3);
  writeDACRegister(123, 0x00);  // Disable automute
}
and to call once during boot applyStartupConfig() or it is it is absolutely necessary to do hardware reset CHIP_EN for SPDIF even if we boot with such settings, not switch from I2S to SPDIF during work or I miss something ?
 
Ok. Leave that SPDIF and go with I2S, is it enough to play analog out with 3 wire I2S in and onboard XO, need help with debug what is the reason of silence (in HW mode it works well) ? Is it enough to set this registers to play sound with ASRC and I2S input ?
Code:
#include <Wire.h>
#define I2C_ADDRESS 0x48
void setup() {
Wire.begin();
writeRegister(0x00, 0x02);
writeRegister(0x01, 0xB1);
writeRegister(0x39, 0x41);
writeRegister(0x56, 0x00);
writeRegister(0x7B, 0x00);
void loop() {
}
bool writeRegister(uint8_t reg, uint8_t value) {
  Wire.beginTransmission(I2C_ADDRESS);
  Wire.write(reg);
  Wire.write(value);
  return Wire.endTransmission() == 0;
}
 
Arduino IDE with Arduino Nano, <Wire.h>, all is well with I2C bus, writing and reading registers. I can read them after writing and check, but something is missing to get sound from DAC (or it is hardware problem at board). Pin29 (mode) at GND, pin19 and 20 are at GND to configure I2C address 0x48.
 
IMHO, its too much trouble to sort through your code and the datasheet. Why don't you annotate you register programming lines with the settings you intend them to make? Then we can read what you are trying to do in something closer to English.

You should also be reading out status bits such as Lock status, and tell us what status information you are getting back.
 
Solved, it was AI mistake in other part of сode to set some registers which should not have been touched at all with errors. Only these register settings are enough to play 3 wire I2S with onboard clock:
Code:
writeRegister(0x00, 0x80); // Register 0 Bit 7 to 1 Reset digital core (all settings are set to default)  - on the off-chance
writeRegister(0x00, 0x02); // Register 0 Bit 1=1 Set DAC_MODE to enable DAC analog output

Is it necessary to do some kind of restart procedure or something else for the changes to take effect immediately for ex with changing digital filters?
 
Last edited:
If you would ever need a premade i2s card to measure against, this is made according to the eval. I have used it in hw mode and it measures extremly well with non perfect surrounding components.
1750861340061.png
 
What is strugling me in the docs from ESS is they put in // two Rf resistor in the fedbackloop. I don't see why, the noise figure should be the same than one resistor with half the value and it adds parasitic capacitance exposure and longer path !

Btw layout wise, should the resistors not be the nearest from the op amp and VS the capacitor ?

What am I missing ? Thanks.

1750863196703.png
 
If you would ever need a premade i2s card to measure against, this is made according to the eval. I have used it in hw mode and it measures extremly well with non perfect surrounding components.
I have exactly the same board, it works fine in HW mode, but I want to have UI and almost done it with Arduino (even with chosing SPDIF/I2S input). Now solved to run SPDIF in SW mode. It is enough to set just these register settings to play SPDIF with ES9039Q2M:
Code:
writeRegister(0x00, 0x80); // Register 0 Bit 7 to 1 Reset digital core (all settings are set to default) - on the off-chance
writeRegister(0x39, 0x01); // INPUT SELECTION [0] 1'b1: Automatically determine the input data format
writeRegister(0x59, 0x64); // Select GPIO4 as SPDIF IN
writeRegister(0x2A, 0x08); // GPIO4_SDB Enables GPIO4 input
uint8_t val = readRegister(0x01); // SYS MODE CONFIG > ENABLE_SPDIF_DECODE set only bit 3 to 1
val |= 0x08;
writeRegister(0x01, val);
writeRegister(0x00, 0x02);// SYSTEM CONFIG Register 0 Bit 1=1 Set DAC_MODE to enable DAC analog output

@diyiggy it was here about it
 
Last edited:
  • Like
Reactions: florian911
Found easy way to switch between sources. I2S input works fine even with connected active SPDIF signal and with other needed SPDIF settings, just with disabling GPIO4_SDB, so this will be universal code for both inputs, just set register 0x2A to 0x00 anytime to swtich to I2S input without reboot/restart and without CHIP_EN touching.
Code:
writeRegister(0x00, 0x80); // Register 0 Bit 7 to 1 Reset digital core (all settings are set to default) - on the off-chance
writeRegister(0x39, 0x01); // INPUT SELECTION [0] 1'b1: Automatically determine the input data format
writeRegister(0x59, 0x64); // Select GPIO4 as SPDIF IN
writeRegister(0x2A, 0x08); // GPIO4_SDB Enables GPIO4 input (SPDIF IN ACTIVE) or writeRegister(0x2A, 0x00); // I2S IN ACTIVE
uint8_t val = readRegister(0x01); // SYS MODE CONFIG > ENABLE_SPDIF_DECODE set only bit 3 to 1
val |= 0x08;
writeRegister(0x01, val);
writeRegister(0x00, 0x02); // SYSTEM CONFIG Register 0 Bit 1=1 Set DAC_MODE to enable DAC analog output

Next question is how to autoplay DSD via I2S. If USB processor has DSDon output, is it just trigger with high/low logic level ? And we need to put it on some ESS GPIO port and watch high level to setup right DSD settings ?
 
Last edited:
The switching is very interesting.
Do you measure with high resolution ADC? Wondering if there are a difference in distortion between I2S and SPDIF?
I send I2S without masterclock, and get really low THD. Seems like the PLL is really good with the onboard clock
 
I think it also depends on SPDIF/I2S source, for me at now it is just an option to have both inputs in device. Also it will be usefull to all members with universal code and menu for any ES9039Q2M. Usually I use USB-I2S. Also I want to make an option to chose between ASRC and external clock. It remains to come up with a simple switching circuit between two clock lines to the MCLK pin of the DAC.
 
  • Like
Reactions: torgeirs
Traditionally I2S with masterclock is best.
Se that external masterclock is not really needed for this solution as I see it.
So wondered if should try just using spdif. Lots of mcus or dsps has spdif or i2s on outputs. Spdif is just 2 wires and can have a cable in between so there are some benefits if degradation is minimal
 
My usecase is 2 or more synced 9039 boards and DSP or DSP enhanced MCU as source. Eg ADAU 1452 or STM32H series. I have a feeling the boards will be pretty well synced even with SPDIF
The ranking versus time syncronisation:
TDM
I2S with masterclock
I2S without masterclock (PLL)
SPDIF(PLL)

But now I wonder if the SPDIF PLL is so good that it is neglible difference as long at sourse channels are synced