Hello all,
I am trying to get the WM8904 audio codec eval board (AC328904) working with a Teensy 4.1, but I can't seem to get any signs of life from the ADCs or DACs.
I can communicate over I2C just fine (set and read back config registers correctly). I probed the I2S lines and see the Teensy correctly giving the MCLK, BCLK, and LRCLK signals to the WM8904, but there's no activity on ADCDAT or DACDAT. Also, I try putting the CODEC in loopback mode, but don't see anything on either DAC when inputting a 1kHz 0.5Vpk sine wave onto both ADC inputs.
Any ideas on what could be happening? Here's my test code:
I am trying to get the WM8904 audio codec eval board (AC328904) working with a Teensy 4.1, but I can't seem to get any signs of life from the ADCs or DACs.
I can communicate over I2C just fine (set and read back config registers correctly). I probed the I2S lines and see the Teensy correctly giving the MCLK, BCLK, and LRCLK signals to the WM8904, but there's no activity on ADCDAT or DACDAT. Also, I try putting the CODEC in loopback mode, but don't see anything on either DAC when inputting a 1kHz 0.5Vpk sine wave onto both ADC inputs.
Any ideas on what could be happening? Here's my test code:
Code:
#include <Arduino.h>
#include <Audio.h>
#include "Wire.h"
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#define LED_PIN 13
#define BUTTON 12
#define WM8904_I2C_ADDRESS 0x1A //0x34
#define SDCARD_CS_PIN BUILTIN_SDCARD
#define SDCARD_MOSI_PIN 11 // not actually used
#define SDCARD_SCK_PIN 13 // not actually used
//I2S Setup
AudioInputI2S i2s2; //xy=105,63
AudioAnalyzePeak peak1; //xy=278,108
AudioRecordQueue queue1; //xy=281,63
AudioPlaySdRaw playRaw1; //xy=302,157
AudioOutputI2S i2s1; //xy=470,120
AudioConnection patchCord1(i2s2, 0, queue1, 0);
AudioConnection patchCord2(i2s2, 0, peak1, 0);
AudioConnection patchCord3(playRaw1, 0, i2s1, 0);
AudioConnection patchCord4(playRaw1, 0, i2s1, 1);
// The file where data is recorded
File frec;
bool recordingActive = false;
bool loopbackMode = true;
void setup()
{
Serial.begin(9600);
// Audio connections require memory, and the record queue
// uses this memory to buffer incoming audio.
AudioMemory(60);
Wire2.begin();
//Enable CODEC
CodecEnable();
//Check CODEC ID
uint16_t codecId = 0;
CodecRead(0, &codecId);
Serial.print("Codec ID: ");
Serial.println(codecId, HEX);
// Initialize the SD card
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
if (!(SD.begin(SDCARD_CS_PIN))) {
// stop here if no SD card, but print a message
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
if (loopbackMode)
{
//Put CODEC in loopback mode
uint16_t loopbackReg = 0;
CodecRead(0x18, &loopbackReg);
loopbackReg = (loopbackReg & 0xFEFF) + (1 << 8);
CodecWrite(0x18, loopbackReg);
}
else
{
//Log ADC data to SD card
StartRecording();
}
}
void loop()
{
if (recordingActive)
{
ContinueRecording();
}
}
void CodecEnable()
{
//reset
Serial.println("Resetting");
CodecWrite(0x00, 0x0000);
delay(10);
//Automatic startup sequence
Serial.println("Beginning auto startup sequence");
CodecWrite(0x6F, 0x0100);
delay(500);
//Enable ADCs and DACs
Serial.println("Enabling ADCs and DACs");
CodecWrite(0x12, 0x000F);
delay(10);
}
int CodecWrite(uint8_t reg, uint16_t value)
{
uint8_t data[3];
data[0] = reg; // Register address
data[1] = (value >> 8) & 0xFF; // Data MSB
data[2] = value & 0xFF; // Data LSB
Wire2.beginTransmission(WM8904_I2C_ADDRESS);
Wire2.write(data, (uint8_t)3);
return Wire2.endTransmission();
}
int CodecRead(uint8_t reg, uint16_t *value)
{
uint8_t data[10];
Wire2.beginTransmission(WM8904_I2C_ADDRESS);
Wire2.write(reg);
Wire2.endTransmission();
Wire2.requestFrom(WM8904_I2C_ADDRESS, 2);
data[0] = Wire2.read();
data[1] = Wire2.read();
*value = (data[0] << 8) | data[1];
return 0;
}
void StartRecording()
{
/*
Serial.println("Starting recording");
//Delete old file if present
if (SD.exsists("RECORD.RAW"))
{
SD.remove("RECORD.RAW");
}
frec = SD.open("RECORD.RAW", FILE_WRITE);
if (frec)
{
queue1.begin();
recordingActive = true;
}
*/
queue1.begin();
recordingActive = true;
}
void ContinueRecording()
{
if (queue1.available() >= 2)
{
byte buffer[512];
// Fetch 2 blocks from the audio library and copy
// into a 512 byte buffer. The Arduino SD library
// is most efficient when full 512 byte sector size
// writes are used.
memcpy(buffer, queue1.readBuffer(), 256);
queue1.freeBuffer();
memcpy(buffer+256, queue1.readBuffer(), 256);
queue1.freeBuffer();
// write all 512 bytes to the SD card
//elapsedMicros usec = 0;
//frec.write(buffer, 512);
Serial.print(buffer[0]);
Serial.print(",");
Serial.print(buffer[1]);
Serial.print(",");
Serial.println(buffer[2]);
}
}