2022-04-25 07:12 PM
Hi,
This is my previous question(link).
I'm implementing 24bit, 44.1kHz audio out code using STM32H7B3-discovery.
In previous question, i set SAI(I2S format) buffer like below.
I set SAI_A block to output.
And, this is my SAI_A setting.
I set tx buffer to zero and BufferOutCtl.buff also filled zero.
This is my output waveform.
I thought that if I filled the buffer with 4 bytes of data and sent it to dma, it would be as below.But, I got noise waveform.
I checked clock.
This is main code.
#define FULL_TXRX_SIZE 256
#define HALF_TXRX_SIZE 128
ALIGN_32BYTES (static AUDIO_IN_BufferTypeDef BufferInCtl) __attribute__((section(".RAM_D3")));
ALIGN_32BYTES (static AUDIO_OUT_BufferTypeDef BufferOutCtl) __attribute__((section(".RAM_D3")));
int main(void) {
uint16_t b_cnt = 0, b_ptr = 0;
BSP_AUDIO_Init_t out_aduio;
BSP_AUDIO_Init_t in_aduio;
uint32_t pin_state = 0;
/* Configure the MPU attributes as Write Through for SDRAM*/
MPU_Config();
/* Enable the CPU Cache */
CPU_CACHE_Enable();
/* STM32H7xx HAL library initialization:
- Configure the Systick to generate an interrupt each 1 msec
- Set NVIC Group Priority to 4
- Low Level Initialization
*/
HAL_Init();
/* Configure the system clock to 280 MHz */
SystemClock_Config();
BSP_LED_Init(LED3);
BSP_LED_Init(LED2);
out_aduio.Device = AUDIO_OUT_DEVICE_HEADPHONE;
out_aduio.ChannelsNbr = 2;
out_aduio.SampleRate = AUDIO_FREQUENCY_44K;
out_aduio.BitsPerSample = AUDIO_RESOLUTION_24B;
out_aduio.Volume = 100;
in_aduio.Device = IN_DEVICE;
in_aduio.ChannelsNbr = 2;
in_aduio.SampleRate = AUDIO_FREQUENCY_44K;
in_aduio.BitsPerSample = AUDIO_RESOLUTION_24B;
in_aduio.Volume = 100;
/* -2- Configure EXTI15_10 (connected to PC.13 pin) in interrupt mode */
EXTI15_10_IRQHandler_Config();
BSP_AUDIO_IN_Init(AUDIO_INOUT_INSTANCE, &in_aduio);
//BSP_AUDIO_OUT_Init(AUDIO_INOUT_INSTANCE, &out_aduio);
/* Final Output double buffer structure */
BufferInCtl.state = PLAY_BUFFER_OFFSET_NONE;
BufferInCtl.fptr = 0;
BufferOutCtl.state = PLAY_BUFFER_OFFSET_NONE;
BufferOutCtl.fptr = 0;
#if CLEAN_DCACHE
/* Clean Data Cache to update the content of the SRAM */
SCB_InvalidateDCache_by_Addr((uint32_t*) &BufferInCtl.buff[0], FULL_TXRX_SIZE);
SCB_CleanDCache_by_Addr((uint32_t*) &BufferOutCtl.buff[0], FULL_TXRX_SIZE);
memset(&BufferInCtl.buff[0], 0x00, FULL_TXRX_SIZE);
memset(&BufferOutCtl.buff[0], 0x00, FULL_TXRX_SIZE);
#endif
BSP_AUDIO_OUT_Play(AUDIO_INOUT_INSTANCE, (uint8_t*) &BufferOutCtl.buff[0], FULL_TXRX_SIZE);
//BSP_AUDIO_IN_Record(AUDIO_INOUT_INSTANCE, (uint8_t*) &BufferInCtl.buff[0], FULL_TXRX_SIZE);
for (b_cnt = 0; b_cnt < FULL_TXRX_SIZE; b_cnt += 8) {
slotb[b_cnt] = 0x00;
slotb[b_cnt + 1] = 0x00;
slotb[b_cnt + 2] = 0x00;
slotb[b_cnt + 3] = 0;
slotb[b_cnt + 4] = 0;
slotb[b_cnt + 5] = 0;
slotb[b_cnt + 6] = 0;
slotb[b_cnt + 7] = 0;
}
p_bff = slotb;
/* Infinite loop */
while (1) {
if (rx_half_flag) {
SCB_InvalidateDCache_by_Addr((uint32_t*) &BufferInCtl.buff[0], HALF_TXRX_SIZE);
memcpy(rx_buffer, &BufferInCtl.buff[0], HALF_TXRX_SIZE);
rx_half_flag = 0;
}
if (rx_full_flag) {
SCB_InvalidateDCache_by_Addr((uint32_t*) &BufferInCtl.buff[HALF_TXRX_SIZE], HALF_TXRX_SIZE);
memcpy(rx_buffer + HALF_TXRX_SIZE, &BufferInCtl.buff[HALF_TXRX_SIZE], HALF_TXRX_SIZE);
rx_full_flag = 0;
}
if (tx_half_flag) {
SCB_CleanDCache_by_Addr((uint32_t*) &BufferOutCtl.buff[0], HALF_TXRX_SIZE);
memcpy(&BufferOutCtl.buff[0], p_bff, HALF_TXRX_SIZE);
tx_half_flag = 0;
}
if (tx_full_flag) {
SCB_CleanDCache_by_Addr((uint32_t*) &BufferOutCtl.buff[HALF_TXRX_SIZE], HALF_TXRX_SIZE);
memcpy(&BufferOutCtl.buff[HALF_TXRX_SIZE], p_bff + HALF_TXRX_SIZE, HALF_TXRX_SIZE);
tx_full_flag = 0;
}
}
}
And, This is my modified BSP_AUDIO_In_init().
int32_t BSP_AUDIO_IN_Init(uint32_t Instance, BSP_AUDIO_Init_t *AudioInit) {
uint32_t i;
int32_t ret = BSP_ERROR_NONE;
if (Instance >= AUDIO_IN_INSTANCES_NBR) {
ret = BSP_ERROR_WRONG_PARAM;
} else {
/* Store the audio record context */
Audio_In_Ctx[Instance].Device = AudioInit->Device;
Audio_In_Ctx[Instance].ChannelsNbr = AudioInit->ChannelsNbr;
Audio_In_Ctx[Instance].SampleRate = AudioInit->SampleRate;
Audio_In_Ctx[Instance].BitsPerSample = AudioInit->BitsPerSample;
Audio_In_Ctx[Instance].Volume = AudioInit->Volume;
Audio_In_Ctx[Instance].State = AUDIO_IN_STATE_RESET;
Audio_Out_Ctx[Instance].Device = AudioInit->Device;
Audio_Out_Ctx[Instance].Instance = Instance;
Audio_Out_Ctx[Instance].SampleRate = AudioInit->SampleRate;
Audio_Out_Ctx[Instance].BitsPerSample = AudioInit->BitsPerSample;
Audio_Out_Ctx[Instance].ChannelsNbr = AudioInit->ChannelsNbr;
Audio_Out_Ctx[Instance].Volume = AudioInit->Volume;
Audio_Out_Ctx[Instance].State = AUDIO_OUT_STATE_RESET;
if (Instance != 2U) {
/* Un-reset audio codec if not currently used by audio out instances */
if ((Audio_Out_Ctx[0].State == AUDIO_OUT_STATE_RESET) && (Audio_Out_Ctx[1].State == AUDIO_OUT_STATE_RESET)) {
(void) CS42L51_PowerUp();
/* Initialize the codec internal registers */
if (CS42L51_Probe() != BSP_ERROR_NONE) {
ret = BSP_ERROR_COMPONENT_FAILURE;
}
}
}
if (ret == BSP_ERROR_NONE) {
if (Instance == 0U) {
/* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
if (MX_SAI1_ClockConfig(&haudio_out_sai, AudioInit->SampleRate) != HAL_OK) {
ret = BSP_ERROR_CLOCK_FAILURE;
}
if (MX_SAI1_ClockConfig(&haudio_in_sai, AudioInit->SampleRate) != HAL_OK) {
ret = BSP_ERROR_CLOCK_FAILURE;
} else {
haudio_in_sai.Instance = AUDIO_IN_SAIx;
haudio_out_sai.Instance = AUDIO_OUT_SAIx;
SAI_MspInit(&haudio_in_sai);
SAI_MspInit(&haudio_out_sai);
MX_SAI_Config mx_config;
/* Prepare haudio_in_sai handle */
mx_config.AudioFrequency = Audio_In_Ctx[Instance].SampleRate;
mx_config.AudioMode = SAI_MODESLAVE_RX;
mx_config.ClockStrobing = SAI_CLOCKSTROBING_FALLINGEDGE;
mx_config.MonoStereoMode = (AudioInit->ChannelsNbr == 1U) ? SAI_MONOMODE : SAI_STEREOMODE;
mx_config.DataSize = SAI_DATASIZE_24;
mx_config.FrameLength = 64;
mx_config.ActiveFrameLength = 32;
mx_config.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
mx_config.Synchro = SAI_SYNCHRONOUS;
mx_config.SynchroExt = SAI_SYNCEXT_DISABLE;
mx_config.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
if (MX_SAI1_Block_B_Init(&haudio_in_sai, &mx_config) != HAL_OK) {
/* Return BSP_ERROR_PERIPH_FAILURE when operations are not correctly done */
ret = BSP_ERROR_PERIPH_FAILURE;
} else {
/* Prepare haudio_out_sai handle */
mx_config.AudioMode = SAI_MODEMASTER_TX;
mx_config.Synchro = SAI_ASYNCHRONOUS;
if (MX_SAI1_Block_A_Init(&haudio_out_sai, &mx_config) != HAL_OK) {
/* Return BSP_ERROR_PERIPH_FAILURE when operations are not correctly done */
ret = BSP_ERROR_PERIPH_FAILURE;
}
}
#if (USE_AUDIO_CODEC_CS42L51 == 1)
if (ret == BSP_ERROR_NONE) {
CS42L51_Init_t codec_init;
/* Fill codec_init structure */
codec_init.OutputDevice = ((Audio_Out_Ctx[0].State == AUDIO_OUT_STATE_RESET) && (Audio_Out_Ctx[1].State == AUDIO_OUT_STATE_RESET)) ? CS42L51_OUT_NONE : CS42L51_OUT_HEADPHONE;
codec_init.Frequency = AudioInit->SampleRate;
codec_init.Resolution = CS42L51_RESOLUTION_16b; /* Not used */
codec_init.Volume = AudioInit->Volume;
codec_init.InputDevice = CS42L51_IN_LINE1;
/* Initialize the codec internal registers */
if (Audio_Drv->Init(Audio_CompObj, &codec_init) < 0) {
ret = BSP_ERROR_COMPONENT_FAILURE;
} else {
/* Update audio in context state */
Audio_In_Ctx[Instance].State = AUDIO_IN_STATE_STOP;
Audio_Out_Ctx[Instance].State = AUDIO_OUT_STATE_STOP;
}
}
#endif /*USE_AUDIO_CODEC_CS42L51 == 1)*/
}
}
/* Update BSP AUDIO IN state */
Audio_In_Ctx[Instance].State = AUDIO_IN_STATE_STOP;
}
}
/* Return BSP status */
return ret;
}
Has anyone experienced these symptoms?
I attached my CS42L51 register setting.
Regards,
Youngjun
Solved! Go to Solution.
2022-04-26 02:05 AM
The problem has been resolved.
I missed below code.
HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*) pBuf, (uint16_t) (NbrOfBytes / (Audio_In_Ctx[Instance].BitsPerSample / 8U)))
My Audio_in_Ctx[Instance].BitPerSample was 24.
I modified this value to 32.
2022-04-25 08:19 PM
I attach more pictures.
I send input buffer data to output buffer.(100Hz 100mVpp sine wave from function generator)
while (1) {
if (rx_half_flag) {
SCB_InvalidateDCache_by_Addr((uint32_t*) &BufferInCtl.buff[0], HALF_TXRX_SIZE);
memcpy(rx_buffer, &BufferInCtl.buff[0], HALF_TXRX_SIZE);
rx_half_flag = 0;
}
if (rx_full_flag) {
SCB_InvalidateDCache_by_Addr((uint32_t*) &BufferInCtl.buff[HALF_TXRX_SIZE], HALF_TXRX_SIZE);
memcpy(rx_buffer + HALF_TXRX_SIZE, &BufferInCtl.buff[HALF_TXRX_SIZE], HALF_TXRX_SIZE);
rx_full_flag = 0;
}
if (tx_half_flag) {
SCB_CleanDCache_by_Addr((uint32_t*) &BufferOutCtl.buff[0], HALF_TXRX_SIZE);
memcpy(&BufferOutCtl.buff[0], rx_buffer, HALF_TXRX_SIZE);
tx_half_flag = 0;
}
if (tx_full_flag) {
SCB_CleanDCache_by_Addr((uint32_t*) &BufferOutCtl.buff[HALF_TXRX_SIZE], HALF_TXRX_SIZE);
memcpy(&BufferOutCtl.buff[HALF_TXRX_SIZE], rx_buffer + HALF_TXRX_SIZE, HALF_TXRX_SIZE);
tx_full_flag = 0;
}
}
when i set frame size to 16bit,
the waveform is clear.
This is 24bit frame size.
2022-04-26 02:05 AM
The problem has been resolved.
I missed below code.
HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*) pBuf, (uint16_t) (NbrOfBytes / (Audio_In_Ctx[Instance].BitsPerSample / 8U)))
My Audio_in_Ctx[Instance].BitPerSample was 24.
I modified this value to 32.