2023-05-05 04:17 AM
Hi,
Having STM32F723 DISCO with simple play/record example. Need to process sound by 20ms periods, so I've calculated PCM buffer size as :
```
#define AUDIO_CHANNELS 2
#define AUDIO_PCM_BIT_RESOLUTION 16
#define AUDIO_SAMPLE_LENGTH_MS 20
#define AUDIO_SAMPLE_SIZE (AUDIO_CHANNELS * (SAMPLE_RATE/1000) * AUDIO_SAMPLE_LENGTH_MS)
#define AUDIO_PERIODS 2
#define AUDIO_BUFFER_SIZE (AUDIO_SAMPLE_SIZE * AUDIO_PERIODS)
```
So I'm expect the HAL_SAI_TxHalfCpltCallback & HAL_SAI_TxCpltCallback to trigger each 20ms, but it triggers each 10ms:
```
[0000:00:00:00.000] Firmware v1.0 started, h/w rev: 0x1000
[0000:00:00:00.000] System clock: 216 MHz, HCLK/AHB clock: 216 MHz, PCLK1/APB1 clock: 54 MHz, PCLK2/APB2 clock: 108 MHz
[0000:00:00:00.655] SAI clock: 49.142856 MHz
[0000:00:00:00.655] Audio inited: Sample rate: 16000, channels: 2, period length: 20 ms, AUDIO_PCM16BIT_SAMPLE_SIZE: 640, doubled AUDIO_PCM16BIT_BUFFER_SIZE: 1280
[0000:00:00:00.655] Board inited
[0000:00:00:00.655] App started
[0000:00:00:00.655] Generating sine table for 200Hz
[0000:00:00:00.832] Sine table gen completed
[0000:00:00:00.833] Audio started
[0000:00:00:00.843] BSP_AUDIO_OUT_HalfTransfer_CallBack
[0000:00:00:00.853] BSP_AUDIO_OUT_TransferComplete_CallBack
[0000:00:00:00.863] BSP_AUDIO_OUT_HalfTransfer_CallBack
[0000:00:00:00.873] BSP_AUDIO_OUT_TransferComplete_CallBack
```
What can be the problem ?
2023-05-05 05:09 AM
you set for 20ms chunk 1280 Byte (320 int16 x 2 ch) , ok.
but for half.. and cplt... callback each buffer needs to be 1280 B.
then each half plays 20ms , as you expect. 🙂
2023-05-05 05:13 AM
Not bytes. 1280 is PCM16BIT - this is uint16_t type which 2 bytes long
2023-05-05 05:16 AM
Some additional code where types are visible:
```
...
typedef struct {
uint16_t buff[AUDIO_BUFFER_SIZE];
volatile BUFFER_StateTypeDef state;
} AUDIO_BufferTypeDef;
...
static AUDIO_BufferTypeDef play_data;
...
AUDIO_ErrorTypeDef AUDIO_OUT_Start(void) {
// fill first half of buf
gen(play_data.buff, AUDIO_BUFFER_SIZE / 2); // size in shorts
playback_state = AUDIO_STATE_PLAYING;
play_data.state = BUFFER_FIRST_PLAYING;
// plays data from both buffers, making interrupt in half
return BSP_AUDIO_OUT_Play(play_data.buff, AUDIO_BUFFER_SIZE * 2); // size in bytes
}
```
2023-05-05 05:19 AM
look with scope...wordclk is 16k ?
2023-05-05 05:24 AM
Can you please clarify the "wordclk" ? Anyway I can't look with scope as both chips (STM32F723IEK & WM8994) are BGA. The BSP code (stm32f723e_discovery_audio.c) taken unchanged from STM32F7Cube
2023-05-05 05:41 AM
Found some test points at devkit, measured:
TP7 (SAI2_SCK_A) - 1.025MHz
TP11 (SAI2_FS_A) - 16.03KHz
TP6 (SAI2_MCLK_A) - 4.098MHz
2023-05-05 06:34 AM
ok, wordclk = frame fs , 16k - ok.
but bitclk 1 M , should be 16k x 2 ch x 16 bit -> 512k .
so now we know: you send 4 words/frame or 2 words 32 bit data in 16 bit data slot ...?
2023-05-05 07:29 AM
Yes, you are right. I suspect that original ST BSP code from stm32f723e_discovery_audio.c is buggy - if anybody try to use their stock Audio_playback_and_record example then wrong playback speed will be noticeable.
The actual code there is:
```
static void SAIx_Out_Init(uint32_t AudioFreq)
{
/* Initialize the haudio_out_sai Instance parameter */
haudio_out_sai.Instance = AUDIO_OUT_SAIx;
/* Disable SAI peripheral to allow access to SAI internal registers */
__HAL_SAI_DISABLE(&haudio_out_sai);
/* Configure SAI_Block_x
LSBFirst: Disabled
DataSize: 16 */
haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
haudio_out_sai.Init.AudioFrequency = AudioFreq;
haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX;
haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLE;
haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
haudio_out_sai.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
haudio_out_sai.Init.CompandingMode = SAI_NOCOMPANDING;
haudio_out_sai.Init.TriState = SAI_OUTPUT_NOTRELEASED;
haudio_out_sai.Init.Mckdiv = 0;
/* Configure SAI_Block_x Frame
Frame Length: 64
Frame active Length: 32
FS Definition: Start frame + Channel Side identification
FS Polarity: FS active Low
FS Offset: FS asserted one bit before the first bit of slot 0 */
haudio_out_sai.FrameInit.FrameLength = 64;
haudio_out_sai.FrameInit.ActiveFrameLength = 32;
haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
/* Configure SAI Block_x Slot
Slot First Bit Offset: 0
Slot Size : 16
Slot Number: 4
Slot Active: All slot actives */
haudio_out_sai.SlotInit.FirstBitOffset = 0;
haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
haudio_out_sai.SlotInit.SlotNumber = 4;
haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123;
HAL_SAI_Init(&haudio_out_sai);
/* Enable SAI peripheral to generate MCLK */
__HAL_SAI_ENABLE(&haudio_out_sai);
```
I suspect that FrameInit.FrameLength & ActiveFrameLength are incorrect, right ?
2023-05-05 07:58 AM
depends....what it should be. 64b frame + 32b active : looks like 16b in 32b frames (some dacs use this).
BUT : slot no. 4 -> is 4 channel output ...thats wrong, if there is stereo dac.
slot must be 2 . for stereo. try.
and your dac setting is 16b in 32b frame ? left just. ?
and : freeprotocol ??? not I2S ? i use SAI_I2S_STANDARD .
ok, i looked... you send to WM8994 ? is 4 ch dac, what mode is it programmed to?