Resources needed for STM32H743 SAI1 + PCM3060 (hardware control mode) integration using STM32CubeIDE

Hi everyone,

I’m working on a project where I need to interface an STM32H743 microcontroller with a PCM3060 audio codec from scratch using STM32CubeIDE. The PCM3060 is wired in hardware control mode, and I plan to use the SAI1 peripheral for audio data transfer.

What I’m trying to achieve:

  • Interface with PCM3060 audio codec in hardware control mode
  • Configure STM32H743 SAI1 peripheral for audio data transfer
  • Set up proper clock domains and SAI timing
  • Handle audio data flow (ADC/DAC) through SAI1
  • Build the project from the ground up in STM32CubeIDE

What I’m looking for:

  • Reference designs or application notes for PCM3060 in hardware mode
  • STM32H7 SAI1 configuration examples for audio applications
  • Code examples showing SAI1 setup, DMA configuration, and data handling
  • Documentation on SAI clock configuration and PLL setup for audio
  • SAI1 timing requirements and PCM3060 synchronization
  • CubeMX configuration tips for SAI1 audio projects
  • Any gotchas or common pitfalls to avoid

My current experience level:
i am not a beginner but i’m sure i can build something with a few indications

Since the codec is in hardware control mode, I mainly need help with the STM32 SAI1 configuration and audio data flow implementation.

Any help, links to resources, or guidance would be greatly appreciated!

Thanks in advance!

Daisy Seed uses PCM3060 in hardware control mode, that should help you with the code.
The hardware pins look easy to figure out.

hello
i am able to get some sound from my output. i can hear kind of hear my guitar when i play the strings but it’s still very distorted. there’s a lot of noise

i was able to get a clean signal from the codec. I just implemented a pass through for now. I’'ll see what i can add to this

hsai_BlockA1.Instance = SAI1_Block_A;
  hsai_BlockA1.Init.AudioMode = SAI_MODEMASTER_TX;
  hsai_BlockA1.Init.Synchro = SAI_ASYNCHRONOUS;
  hsai_BlockA1.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
  hsai_BlockA1.Init.NoDivider = SAI_MCK_OVERSAMPLING_DISABLE;
  hsai_BlockA1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_DISABLE;
  hsai_BlockA1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
  hsai_BlockA1.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K;
  hsai_BlockA1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
  hsai_BlockA1.Init.MonoStereoMode = SAI_STEREOMODE;
  hsai_BlockA1.Init.CompandingMode = SAI_NOCOMPANDING;
  hsai_BlockA1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
  if (HAL_SAI_InitProtocol(&hsai_BlockA1, SAI_I2S_MSBJUSTIFIED, SAI_PROTOCOL_DATASIZE_24BIT, 2) != HAL_OK)
  {
    Error_Handler();
  }
  hsai_BlockB1.Instance = SAI1_Block_B;
  hsai_BlockB1.Init.AudioMode = SAI_MODESLAVE_RX;
  hsai_BlockB1.Init.Synchro = SAI_SYNCHRONOUS;
  hsai_BlockB1.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
  hsai_BlockB1.Init.MckOverSampling = SAI_MCK_OVERSAMPLING_ENABLE;
  hsai_BlockB1.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
  hsai_BlockB1.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
  hsai_BlockB1.Init.MonoStereoMode = SAI_STEREOMODE;
  hsai_BlockB1.Init.CompandingMode = SAI_NOCOMPANDING;
  hsai_BlockB1.Init.TriState = SAI_OUTPUT_NOTRELEASED;
  if (HAL_SAI_InitProtocol(&hsai_BlockB1, SAI_I2S_MSBJUSTIFIED, SAI_PROTOCOL_DATASIZE_24BIT, 2) != HAL_OK)
  {
    Error_Handler();
  }

this is my init sequence, is there something i should change?

the clean sound work just great. but i noticed that when i try to add effects to it the signal just gets distorted. a lot

any ideas on how to prevent this

#include "tremolo.h"
#include <math.h>

#define TWO_PI (2.0f * 3.1415926535f)
#define MIN_RATE 0.1f
#define MAX_RATE 10.0f
#define MIN_DEPTH 0.0f
#define MAX_DEPTH 0.95f  // Leave some headroom

void Tremolo_Init(Tremolo* trem, uint32_t sample_rate) 
{
    trem->rate_hz = 2.0f;  // Default 2Hz
    trem->depth = 0.5f;    // Default 50% depth
    trem->phase = 0.0f;
    trem->sample_rate = sample_rate;
    trem->phase_inc = TWO_PI * trem->rate_hz / (float)sample_rate;
    trem->smoothed_lfo = 1.0f;  // Start at unity gain
}

void Tremolo_SetRate(Tremolo* trem, float rate_hz) 
{
    // Constrain rate and convert to phase increment
    trem->rate_hz = (rate_hz < MIN_RATE) ? MIN_RATE : 
                   ((rate_hz > MAX_RATE) ? MAX_RATE : rate_hz);
    trem->phase_inc = TWO_PI * trem->rate_hz / (float)trem->sample_rate;
}

void Tremolo_SetDepth(Tremolo* trem, float depth) 
{
    // Constrain depth to safe range
    trem->depth = (depth < MIN_DEPTH) ? MIN_DEPTH : 
                 ((depth > MAX_DEPTH) ? MAX_DEPTH : depth);
}

float Tremolo_Process(Tremolo* trem, float input) 
{
    // Generate triangle wave LFO (smoother than sine for tremolo)
    float lfo_pos = fmodf(trem->phase / TWO_PI, 1.0f);
    float raw_lfo = 1.0f - trem->depth * (1.0f - fabsf(2.0f * lfo_pos - 1.0f));
    
    // Smooth LFO transitions to prevent clicks
    trem->smoothed_lfo = 0.25f * raw_lfo + 0.75f * trem->smoothed_lfo;
    
    // Update phase
    trem->phase += trem->phase_inc;
    if (trem->phase > TWO_PI * 4.0f) {  // Keep phase bounded
        trem->phase -= TWO_PI * 4.0f;
    }
    
    // Apply modulation with 10% minimum gain to avoid silence
    return input * (0.1f + 0.8f * trem->smoothed_lfo);
}

this is what the tremolo code would look like and i would apply it like this

void GuitarPedal_ProcessAudio(...) {
    if(tremolo_enabled) {
        float in_sample = (float)input[i].left / 8388608.0f; // 24-bit to float
        float out_sample = Tremolo_Process(&tremolo, in_sample);
        output[i].left = (int32_t)(out_sample * 8388608.0f);
    }
}

but i always get distorted sound like very distorted, not pleasant to hear

i also want to know what is the default sample rate when the pcm3060 is used in hardware mode

In case other community members come across this, I’ll share the thread where you were able to resolve it with tele_player :slight_smile:

1 Like