Teensy 4.1 + MAX98089

Myreauks

Active member
Hi!

I am trying to interface the MAX98089 audio codec with Teensy 4.1. Mainly I am interested in this codec, as it has integrated speaker amp and some more interfacing options compared to SGTL5000.
I have a custom board based on the evaluation board reference design of the MAX98089. I have managed to establish I2C connection between the Teensy and the audio codec. I can successfully read and write registers with the Wire library. Even the jack detection works correctly.
However, I am having trouble getting the i2S connection to work. When reading the status register from the audio codec it says: "Either digital audio interface is configured incorrectly or receiving invalid clocks."

This leads me to believe that I have not managed to configure the codec correctly so that it would interface with the Teensy as the master.
The connections should be correct MCLK, BCLK, LRCLK, DIN and DOUT.

I have found this project, which also interfaces Teensy with MAX98089, but here the Teensy is a slave, so it is not much of help for my issue.
https://gitlab.com/amesser-group/electronic-devices/radio-shield/-/tree/master

On page 85 of the datasheet of the MAX98089 it describes the process of setting up the clock source etc:
https://datasheets.maximintegrated.com/en/ds/MAX98089.pdf

Here are some of my settings related to the audio input:
0x10 (MCLK prescaler) -> 01 (as Teensy MCLK is 11.29MHz)
0x11 (Sample rate) -> 0x7(44.1KHz)
0x12 I have tried to enable PLL mode, but not exactly sure about the settings on this one.

Here is the full code where I setup all the registers: (For now, I am just trying to get output on headphones.)
Code:
#include <Audio.h>
#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include <SerialFlash.h>

// GUItool: begin automatically generated code
AudioSynthWaveformSine   sine1;          //xy=411,453
AudioOutputI2S           i2s1;           //xy=596,455
AudioConnection          patchCord1(sine1, 0, i2s1, 0);
AudioConnection          patchCord2(sine1, 0, i2s1, 1);
// GUItool: end automatically generated code

int chordnum=0;

void setup() {
  Serial.begin(9600);
  AudioMemory(15);
  
  sine1.amplitude(1.0);
  sine1.frequency(400);

  Wire.begin();
  delay(700);

  beginMAX98089();
}

void loop() {
//  Serial.print("Max CPU Usage = ");
//  Serial.print(AudioProcessorUsageMax(), 1);
//  Serial.println("%");
//  maxRead(0x00);
  delay(1000);
}

void beginMAX98089() {

  // Check that MAX98089 is connected by checking the revision number, should always be 0x40
  Wire.beginTransmission(0x10);
  Wire.write(0xFF);
  Wire.endTransmission(false);

  int n = Wire.requestFrom( 0x10, byte(1));
  if( n != 1) {
    Serial.println( "requestFrom failed");
  }
  else {
  while(Wire.available()) { // slave may send less than requested
      byte c = Wire.read();   // receive a byte as character
      Serial.print("0x");
      Serial.print(c, HEX);        // print the character
      Serial.print(" ");        // print the character
    }
  }
  
  Serial.println();

  Wire.endTransmission();

  /* Proper Startup sequence
   *  
  1   Ensure SHDN = 0                       0x51
  2   Configure Clocks                      0x10 to 0x13, 0x19 to 0x1B
  3   Configure digital audio interface     0x14 to 0x17, 0x1C to 0x1F
  4   Configure digital signal processing   0x18, 0x20, 0x3F to 0x46
  5   Load coefficients                     0x52 to 0xC9
  6   Configure mixers                      0x22 to 0x2D
  7   Configure gain and volume controls    0x2E to 0x3E
  8   Configure miscellaneous functions     0x47 to 0x4B
  9   Enable desired functions              0x4C, 0x50
  10  Set SHDN = 1                          0x51
  
  */

  // Ensure SHDN = 0
  if(maxWrite(0x51, 0x00)) { Serial.println("Device disabled"); };

  // Configure clocks
  if(maxWrite(0x10, 0x10)) { Serial.println("MCLK Prescaler set"); };
  if(maxWrite(0x11, 0x70)) { Serial.println("Sample rate set to 44.1 KHz"); };
  if(maxWrite(0x12, 0x80)) { Serial.println("Clock mode set"); };
  if(maxWrite(0x1A, 0x80)) { Serial.println("Clock mode set"); };
  if(maxWrite(0x13, 0x00)) { Serial.println("Clock mode set"); };
  if(maxWrite(0x1B, 0x00)) { Serial.println("Clock mode set"); };

  // Configure digital audio interface
  if(maxWrite(0x14, 0x10)) { Serial.println("DA1 Format set to I2S"); };
  if(maxWrite(0x15, 0x00)) { Serial.println("DA1 clock just in case"); };
  if(maxWrite(0x16, 0x41)) { Serial.println("S1 routed to DA1"); };
  if(maxWrite(0x17, 0x00)) { Serial.println("DA1 TDM Slots"); };
  if(maxWrite(0x1C, 0x10)) { Serial.println("DA2 Format set to I2S"); };
  
  // Configure digital signal processing
  if(maxWrite(0x18, 0x80)) { Serial.println("Set music mode"); };

  // Configure mixers
  if(maxWrite(0x22, 0x84)) { Serial.println("Routed DA1 to Headphones"); };
  if(maxWrite(0x27, 0x00)) { Serial.println("Bypass headphone mixer"); };

  //Configure gain and volume controls
  if(maxWrite(0x2F, 0x00)) { Serial.println("Config DA1 Vol"); };
  if(maxWrite(0x30, 0x00)) { Serial.println("Config DA1 EQ"); };
  if(maxWrite(0x39, 0x1A)) { Serial.println("Set headphone left output & volume"); };
  if(maxWrite(0x3A, 0x1A)) { Serial.println("Set headphone right output & volume"); };

  // Configure miscellaneous functions
  if(maxWrite(0x49, 0x00)) { Serial.println("DAI 1 EQ config"); };
  if(maxWrite(0x4B, 0x80)) { Serial.println("Jack detection enabled"); };

  // Enable desired functions
  if(maxWrite(0x4D, 0xC3)) { Serial.println("Enabled headphone & DAC output"); };
  if(maxWrite(0x4E, 0xF0)) { Serial.println("Top level bias set"); };
  if(maxWrite(0x50, 0x0F)) { Serial.println("Enabled DAI clock gen"); };

  
  
  
  // Set SHDN = 1
  if(maxWrite(0x51, 0xC0)) { Serial.println("Device enabled"); };
  
  delay(1500);
  maxRead(0x00);
  
}

bool maxWrite(unsigned int reg, unsigned int val) {
//  if (reg == CHIP_ANA_CTRL) ana_ctrl = val;
  Wire.beginTransmission(0x10);
  Wire.write(reg);
  Wire.write(val);
  if (Wire.endTransmission() == 0) return true;
  return false;
}

void maxRead(unsigned int reg) {
  Wire.beginTransmission(0x10);
  Wire.write(reg);
  Wire.endTransmission(false);

  int n = Wire.requestFrom( 0x10, byte(1));
  if( n != 1) {
    Serial.println( "requestFrom failed");
  }
  else {
  while(Wire.available()) { // slave may send less than requested
      byte c = Wire.read();   // receive a byte as character
      Serial.print("0x");
      Serial.print(c, HEX);        // print the character
      Serial.print(" ");        // print the character
    }
  }
  
  Serial.println();

}

Now, I am not very proficient with I2S standard yet. Maybe there are some more experienced heads here on the forums that can spot some obvious mistakes right away?

Best,
Miro
 
Sorry nobody helped. I was interested in this, as this chip is quite nice... But I couldn't come up with anything helpful. What was the issue?
 
Hi!
I hand-soldered the chip and turns out it had solder bridges just on the headphone-pins. It's quite a small chip so no wonder, a pretty big challenge to solder on a normal soldering iron. However, I managed to do it quite nicely with some solder paste.

I have now re-soldered the whole thing and have so far tested line-in, headphones, and speaker out connections to be working. Quite a big success, as my board is completely custom and I have no education in electronics engineering.
 
Back
Top