TLV320AIC3110 Codec breakout

Status
Not open for further replies.
After soliciting wisdom in this post about a codec to try, suitable for a small speaker, microphone and headphones, I made a breakout for the Texas Instruments TLV320AIC3110.

I managed to assemble it yesterday and decided to use the Teensy Audio tutorial materials as a way to start testing it.
IMG_20210119_142835198.jpg

So far the main hardware error I have found is that the reset pin was not connected to anything. Thus, when I scanned the I2C bus I got no response. However, I greenwired to Teensy pin 16/A2 and set it up as a reset pin (pull to ground for a millisecond, pull up for the rest of the time). This allowed me to find the codec at 0x18 on the I2C bus.

I am totally naive when it comes to codecs so I had hoped that the device would default to some kind of enabled state but sadly no output was on headphones or speaker terminals when I uploaded Part_1_02_Hardware_Test with the reset pin code added in and the SGTL5000 elements commented out.

Fortunately, the TLV320AIC3110 datasheet has pseudocode for an example output mode initialisation, so I converted to Arduino and it is nicely beeping away on both headphones and stereo speakers and updating the serial monitor when I move the potentiometer.

Code:
const uint8_t resetPin = 16; // Teensy 3.2 codec shield reset pin v1.0 hardware
const uint8_t codecAddress = 0x18; // TLV320AIC3110

void setup() {
  pinMode(resetPin, OUTPUT); // comment out if not Teensy diy audio codec
  digitalWrite(resetPin, LOW); // comment out if not Teensy diy audio codec
  delay(1);
  digitalWrite(resetPin, HIGH); // comment out if not Teensy diy audio codec

  init_codec(); // start up the codec
...


void init_codec()
{
  Wire.begin();
  writeCodec(0x0, 0x0); //  select page 0
  writeCodec(0x01, 0x01); // soft reset
  writeCodec(0x04, 0x03); // pll clock in
  writeCodec(0x05, 0x91); // pll power up
  writeCodec(0x06, 0x08); // j = 8
  writeCodecDual(0x07, 0x0, 0x0); // D = 0000
  writeCodec(0x1B, 0x0); //  i2s, wordlength 16
  writeCodec(0x0B, 0x84); // NDAC is powered and set to 4
  writeCodec(0x0C, 0x84); // MDAC is powered and set to 4
  writeCodecDual(0x0D, 0x0, 0x80); // DOSR = 128, DOSR(9:8) = 0, DOSR(7:0) = 128

  writeCodec(0x74, 0x0); //  DAC -> volume control thru pin disable
  writeCodec(0x44, 0x0); // DAC -> DRC disable
  writeCodec(0x41, 0xD4); // DAC -> -22dB gain left
  writeCodec(0x42, 0xD4); // DAC -> -22dB gain right

  writeCodec(0x0, 0x01); // Select page 1
  writeCodec(0x21, 0x4E); // De-pop, power on = 800 ms, step time = 4ms
  writeCodec(0x1F, 0xC2); // HPL and HPR powered up
  writeCodec(0x23, 0x44); // LDAC routed to HPL, RDAC routed to HPR
  writeCodec(0x28, 0x06); // HPL unmute annd gain = 0dB
  writeCodec(0x29, 0x06); // HPR unmute annd gain = 0dB
  writeCodec(0x2A, 0x1C); // unmute class D left
  writeCodec(0x2B, 0x1C); // unmute class D right
  writeCodec(0x20, 0xC6); // power up class D drivers
  writeCodec(0x24, 0x92); // enables HPL output analog volume, set = -9 dB
  writeCodec(0x25, 0x92); // enables HPR output analog volume, set = -9 dB
  writeCodec(0x26, 0x92); // enables HPL output analog volume, set = -9 dB
  writeCodec(0x27, 0x92); // enables HPR output analog volume, set = -9 dB

  writeCodec(0x0, 0x0); // select page 0
  // select DAC DSP Processing Block PRB_P11
  writeCodec(0x3C, 0x0B); //
  writeCodec(0x00, 0x08); //
  writeCodec(0x01, 0x04); //
  writeCodec(0x00, 0x00); //
  writeCodec(0x3F, 0xD6); // power up DAC left and right channels (soft step disable)
  writeCodec(0x40, 0x0); // unmute DAC left and right channels
  Wire.end();

}

void writeCodec(uint8_t registerVal, uint8_t dataVal)
{
  Wire.beginTransmission(codecAddress);
  Wire.write(registerVal); // set the address to write to
  Wire.write(dataVal); // set the data to write
  Wire.endTransmission(); // end
}

void writeCodecDual(uint8_t registerVal, uint8_t data0Val, uint8_t data1Val)
{
  Wire.beginTransmission(codecAddress);
  Wire.write(registerVal); // set the address to write to
  Wire.write(data0Val); // set the data to write
  Wire.write(data1Val); // set the data to write
  Wire.endTransmission(); // end
}

I will try and play some music from the SD card next.
 
I made some more progress, thanks to the contributors who have already written Audio library code for the TLV320AIC3206. Many of the register names and sequences appear to be the same or have similarities with the TLV320AIC3110. I only adapted the DAC side of things but after #including control_tlv320aic3110.h in audio.h, I am able to use the following without any of my in-sketch code from above:

Code:
AudioControlTLV320AIC3110  TLV320AIC3110;
...

void setup() {
  Serial.begin(9600);
  AudioMemory(8);
  TLV320AIC3110.enable();
  TLV320AIC3110.volume(0.5);
  ...

And WAV playback from SD works fine! Not tested volume controls but it's great how quickly new hardware can be integrated with this library. WIP header and c++ files hopefully attached for anyone interested. Once ADC is incorporated and it's all a bit better tested I can fork and PR, if the code gets tidy enough and that would be desirable to others.
View attachment control_tlv320aic3110.cpp
View attachment control_tlv320aic3110.h
 
Pretty sure the TLV320AIC3206 driver (and board) uses pin 22 for reset. I noticed that on your schematic when you posted earlier. I meant to check to see if the reset pin was required, so I could warn you, and I forgot! Sorry! Glad you figured it out.
 
JayShoe, thanks! I just picked a free gpio near where I could route my greenwire to. For ease of routing I will use a pin on the other side of the I2C pins when I revise the board. I think the TLV320AIC3206 uses 21, which is a possibility.
 
Status
Not open for further replies.
Back
Top