Very quiet output from external codec

Hi there,

I’ve set up a Seed (rev 4) with an external wm8731 in the same way as the seed rev 5 schematic (see page 4) but connected to SAI2 and I2C1.

For some reason the audio out of the codec is extremely quiet (the internal outs have good volume). I’ve tried a second wm8731 and it has exactly the same issue.

I’ve referenced the patch code in libDaisy for how to inititalise both codecs and the seed code for how to initialise the wm8731. This just outputs a tone to all outs.

#include "daisy_seed.h"
#include "daisysp.h"

using namespace daisy;
using namespace daisysp;

DaisySeed hw;
static Oscillator osc;

void AudioCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size)
{
	float sig;
    for(size_t i = 0; i < size; i++)
    {
        sig = osc.Process();
        // Output the same audio to all 4 outs.
        out[0][i] = sig;
        out[1][i] = sig;
        out[2][i] = sig;
        out[3][i] = sig;
    }
}

// Init the audio like the patch:
// https://github.com/electro-smith/libDaisy/blob/master/src/daisy_patch.cpp#L170
void InitAudio()
{
    // Handle Seed Audio as-is and then
    SaiHandle::Config sai_config[2];
    // Internal Codec
    if(hw.CheckBoardVersion() == DaisySeed::BoardVersion::DAISY_SEED_1_1)
    {
        sai_config[0].pin_config.sa = {DSY_GPIOE, 6};
        sai_config[0].pin_config.sb = {DSY_GPIOE, 3};
        sai_config[0].a_dir         = SaiHandle::Config::Direction::RECEIVE;
        sai_config[0].b_dir         = SaiHandle::Config::Direction::TRANSMIT;
    }
    else
    {
        sai_config[0].pin_config.sa = {DSY_GPIOE, 6};
        sai_config[0].pin_config.sb = {DSY_GPIOE, 3};
        sai_config[0].a_dir         = SaiHandle::Config::Direction::TRANSMIT;
        sai_config[0].b_dir         = SaiHandle::Config::Direction::RECEIVE;
    }
    sai_config[0].periph          = SaiHandle::Config::Peripheral::SAI_1;
    sai_config[0].sr              = SaiHandle::Config::SampleRate::SAI_48KHZ;
    sai_config[0].bit_depth       = SaiHandle::Config::BitDepth::SAI_24BIT;
    sai_config[0].a_sync          = SaiHandle::Config::Sync::MASTER;
    sai_config[0].b_sync          = SaiHandle::Config::Sync::SLAVE;
    sai_config[0].pin_config.fs   = {DSY_GPIOE, 4};
    sai_config[0].pin_config.mclk = {DSY_GPIOE, 2};
    sai_config[0].pin_config.sck  = {DSY_GPIOE, 5};

    // External Codec
    // Set up like Seed rev 5:
    // https://github.com/electro-smith/libDaisy/blob/master/src/daisy_seed.cpp#L269
    sai_config[1].periph          = SaiHandle::Config::Peripheral::SAI_2;
    sai_config[1].sr              = SaiHandle::Config::SampleRate::SAI_48KHZ;
    sai_config[1].bit_depth       = SaiHandle::Config::BitDepth::SAI_24BIT;
    sai_config[1].a_sync          = SaiHandle::Config::Sync::MASTER;
    sai_config[1].b_sync          = SaiHandle::Config::Sync::SLAVE;
    sai_config[1].a_dir           = SaiHandle::Config::Direction::RECEIVE;
    sai_config[1].b_dir           = SaiHandle::Config::Direction::TRANSMIT;
    sai_config[1].pin_config.fs   = hw.GetPin(27);
    sai_config[1].pin_config.mclk = hw.GetPin(24);
    sai_config[1].pin_config.sck  = hw.GetPin(28);
    sai_config[1].pin_config.sb   = hw.GetPin(25);
    sai_config[1].pin_config.sa   = hw.GetPin(26);
	I2CHandle::Config i2c_config;
	i2c_config.mode           = I2CHandle::Config::Mode::I2C_MASTER;
	i2c_config.periph         = I2CHandle::Config::Peripheral::I2C_1;
	i2c_config.speed          = I2CHandle::Config::Speed::I2C_400KHZ;
	i2c_config.pin_config.scl = hw.GetPin(11);
	i2c_config.pin_config.sda = hw.GetPin(12);
	I2CHandle i2c_handle;
	i2c_handle.Init(i2c_config);
	Wm8731::Config codec_cfg;
	codec_cfg.Defaults();
	Wm8731 codec;
	codec.Init(codec_cfg, i2c_handle);

    SaiHandle sai_handle[2];
    sai_handle[0].Init(sai_config[0]);
    sai_handle[1].Init(sai_config[1]);

    // Reinit Audio for _both_ codecs...
    AudioHandle::Config cfg;
    cfg.blocksize  = 48;
    cfg.samplerate = SaiHandle::Config::SampleRate::SAI_48KHZ;
    // cfg.postgain   = 0.5f;
    cfg.postgain   = 1.f;
    hw.audio_handle.Init(cfg, sai_handle[0], sai_handle[1]);
}

int main(void)
{
	float sample_rate;
	hw.Init();
    // Re-init the audio with the external codec.
    InitAudio();
	hw.SetAudioBlockSize(4); // number of samples handled per callback
	hw.SetAudioSampleRate(SaiHandle::Config::SampleRate::SAI_48KHZ);
    sample_rate = hw.AudioSampleRate();
    osc.Init(sample_rate);

    // Set parameters for oscillator
    osc.SetWaveform(osc.WAVE_SIN);
    osc.SetFreq(440);
    osc.SetAmp(1);
	hw.StartAudio(AudioCallback);
	while(1) {}
}

Am I missing something obvious with how I’m initialising the codec/audio?

1 Like

Ah, it looks like the quiet audio is a red herring! I flashed one of the examples (so nothing was setting up the codec) and I could still hear the noise so there must be some bleed through the circuit somehow…

Unfortunately I’m no closer to figuring this one out.

Setting up just the codec returns OK from codec.Init() but I’m not going any audio from the codec line outs.

This is what I ran:

#include "daisysp.h"
#include "daisy_seed.h"

using namespace daisysp;
using namespace daisy;

static DaisySeed  hw;
static Oscillator osc;

void ConfigureAudio()
{
    // SAI2 -- Peripheral
    // Configure
    SaiHandle::Config sai_config;
    sai_config.periph          = SaiHandle::Config::Peripheral::SAI_2;
    sai_config.sr              = SaiHandle::Config::SampleRate::SAI_48KHZ;
    sai_config.bit_depth       = SaiHandle::Config::BitDepth::SAI_24BIT;
    sai_config.a_sync          = SaiHandle::Config::Sync::MASTER;
    sai_config.b_sync          = SaiHandle::Config::Sync::SLAVE;
    sai_config.pin_config.fs   = hw.GetPin(27);
    sai_config.pin_config.mclk = hw.GetPin(24);
    sai_config.pin_config.sck  = hw.GetPin(28);
    // Data Line Directions
    sai_config.a_dir         = SaiHandle::Config::Direction::RECEIVE;
    sai_config.pin_config.sa = hw.GetPin(26);
    sai_config.b_dir         = SaiHandle::Config::Direction::TRANSMIT;
    sai_config.pin_config.sb = hw.GetPin(25);
    I2CHandle::Config i2c_config;
    I2CHandle i2c_handle;
    Wm8731::Config codec_cfg;
    Wm8731 codec;
    i2c_config.mode           = I2CHandle::Config::Mode::I2C_MASTER;
    i2c_config.periph         = I2CHandle::Config::Peripheral::I2C_1;
    i2c_config.speed          = I2CHandle::Config::Speed::I2C_400KHZ;
    i2c_config.pin_config.scl = hw.GetPin(11);
    i2c_config.pin_config.sda = hw.GetPin(12);
    i2c_handle.Init(i2c_config);
    codec_cfg.Defaults();
    codec.Init(codec_cfg, i2c_handle);

    // Then Initialize
    SaiHandle sai_2_handle;
    sai_2_handle.Init(sai_config);

    // Audio
    AudioHandle::Config audio_config;
    audio_config.blocksize  = 48;
    audio_config.samplerate = SaiHandle::Config::SampleRate::SAI_48KHZ;
    audio_config.postgain   = .5f;
    hw.audio_handle.Init(audio_config, sai_2_handle);
}

static void AudioCallback(AudioHandle::InterleavingInputBuffer  in,
                          AudioHandle::InterleavingOutputBuffer out,
                          size_t                                size)
{
    float sig;
    for(size_t i = 0; i < size; i += 2)
    {
        sig = osc.Process();

        // left out
        out[i] = sig;

        // right out
        out[i + 1] = sig;
    }
}

int main(void)
{
    // initialize seed hardware and oscillator daisysp module
    float sample_rate;
    hw.Configure();
    hw.Init();
    ConfigureAudio();
    hw.SetAudioBlockSize(4);
    sample_rate = hw.AudioSampleRate();
    osc.Init(sample_rate);

    // Set parameters for oscillator
    osc.SetWaveform(osc.WAVE_SIN);
    osc.SetFreq(440);
    osc.SetAmp(0.5);

    // start callback
    hw.StartAudio(AudioCallback);

    while(1) {}
}

I’ve torn down and rebuilt my breadboard. Swapped out all components (including a different seed and a different wm8731). I’ve tried both the Seed rev 5 schematic and the wm8731 reference schematic. I’ve also tried adding 220ohm resistors to the mclk, scl and sda lines.

For anyone curious or trying to get an external wm8731 working, it turns out I had a_sync and b_sync back to front.

I changed it to this and it worked:

sai_config[1].a_sync = SaiHandle::Config::Sync::SLAVE;
sai_config[1].b_sync = SaiHandle::Config::Sync::MASTER;
5 Likes