From 540b17e8e6d41b6ee386ea281d7f5851f9de57f7 Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Mon, 2 Nov 2020 00:14:23 +0200 Subject: [PATCH] Fix audio 1 channel mode. --- src/omv/boards/PORTENTA/omv_boardconfig.h | 2 + src/omv/py/py_audio.c | 60 +++++++++++++---------- 2 files changed, 37 insertions(+), 25 deletions(-) diff --git a/src/omv/boards/PORTENTA/omv_boardconfig.h b/src/omv/boards/PORTENTA/omv_boardconfig.h index 130e3a2c4..373b29b23 100644 --- a/src/omv/boards/PORTENTA/omv_boardconfig.h +++ b/src/omv/boards/PORTENTA/omv_boardconfig.h @@ -273,6 +273,7 @@ // SCKx frequency = SAI_KER_CK / MCKDIV / 2 #define AUDIO_SAI_MCKDIV (12) #define AUDIO_SAI_FREQKHZ (2048U) // 2048KHz +#define AUDIO_SAI_NBR_CHANNELS (2) // Default number of channels. #define AUDIO_SAI_CK_PORT (GPIOE) #define AUDIO_SAI_CK_PIN (GPIO_PIN_2) @@ -296,6 +297,7 @@ // #define AUDIO_SAI (SAI1_Block_A) // #define AUDIO_SAI_MCKDIV (12) // #define AUDIO_SAI_FREQKHZ (2048U) // 2048KHz +// #define AUDIO_SAI_NBR_CHANNELS (2) // Default number of channels. // // #define AUDIO_SAI_CK_PORT (GPIOE) // #define AUDIO_SAI_CK_PIN (GPIO_PIN_2) diff --git a/src/omv/py/py_audio.c b/src/omv/py/py_audio.c index 2088376b9..4579ae622 100644 --- a/src/omv/py/py_audio.c +++ b/src/omv/py/py_audio.c @@ -28,7 +28,7 @@ static CRC_HandleTypeDef hcrc; static SAI_HandleTypeDef hsai; static DMA_HandleTypeDef hdma_sai_rx; -static const int n_channels = 2; +static int n_channels = AUDIO_SAI_NBR_CHANNELS; static PDM_Filter_Handler_t PDM_FilterHandler[2]; static PDM_Filter_Config_t PDM_FilterConfig[2]; @@ -58,12 +58,18 @@ void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai) SCB_InvalidateDCache_by_Addr((uint32_t *)(&PDM_BUFFER[PDM_BUFFER_SIZE / 2]), PDM_BUFFER_SIZE / 2); } -static mp_obj_t py_audio_init() +static mp_obj_t py_audio_init(uint n_args, const mp_obj_t *args, mp_map_t *kw_args) { + n_channels = py_helper_keyword_int(n_args, args, 0, kw_args, MP_OBJ_NEW_QSTR(MP_QSTR_channels), 2); + + if (n_channels != 1 && n_channels != 2) { + RAISE_OS_EXCEPTION("Invalid number of channels! Expected 1 or 2."); + } + hsai.Instance = AUDIO_SAI; hsai.Init.Protocol = SAI_FREE_PROTOCOL; hsai.Init.AudioMode = SAI_MODEMASTER_RX; - hsai.Init.DataSize = SAI_DATASIZE_16; + hsai.Init.DataSize = (n_channels == 1) ? SAI_DATASIZE_8 : SAI_DATASIZE_16; hsai.Init.FirstBit = SAI_FIRSTBIT_LSB; hsai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; hsai.Init.Synchro = SAI_ASYNCHRONOUS; @@ -72,7 +78,7 @@ static mp_obj_t py_audio_init() hsai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; hsai.Init.SynchroExt = SAI_SYNCEXT_DISABLE; hsai.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV; - hsai.Init.MonoStereoMode = SAI_STEREOMODE; + hsai.Init.MonoStereoMode = (n_channels == 1) ? SAI_MONOMODE: SAI_STEREOMODE; hsai.Init.CompandingMode = SAI_NOCOMPANDING; hsai.Init.TriState = SAI_OUTPUT_RELEASED; @@ -95,8 +101,8 @@ static mp_obj_t py_audio_init() hsai.SlotInit.FirstBitOffset = 0; hsai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; - hsai.SlotInit.SlotNumber = 1; - hsai.SlotInit.SlotActive = SAI_SLOTACTIVE_0; + hsai.SlotInit.SlotNumber = (n_channels == 1) ? 2 : 1; + hsai.SlotInit.SlotActive = (n_channels == 1) ? (SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1) : SAI_SLOTACTIVE_0; // Initialize the SAI HAL_SAI_DeInit(&hsai); @@ -113,8 +119,8 @@ static mp_obj_t py_audio_init() hdma_sai_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_sai_rx.Init.PeriphInc = DMA_PINC_DISABLE; hdma_sai_rx.Init.MemInc = DMA_MINC_ENABLE; - hdma_sai_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; - hdma_sai_rx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + hdma_sai_rx.Init.PeriphDataAlignment = (n_channels == 1) ? DMA_PDATAALIGN_BYTE : DMA_PDATAALIGN_HALFWORD; + hdma_sai_rx.Init.MemDataAlignment = (n_channels == 1) ? DMA_MDATAALIGN_BYTE : DMA_MDATAALIGN_HALFWORD; hdma_sai_rx.Init.Mode = DMA_CIRCULAR; hdma_sai_rx.Init.Priority = DMA_PRIORITY_HIGH; hdma_sai_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; @@ -154,18 +160,19 @@ static mp_obj_t py_audio_read_pdm(mp_obj_t buf_in) mp_get_buffer_raise(buf_in, &pdmbuf, MP_BUFFER_WRITE); size_t typesize = mp_binary_get_size('@', pdmbuf.typecode, NULL); uint32_t xfer_samples = 0; - uint32_t n_samples = pdmbuf.len / typesize; + // Note: samples are copied as bytes for 1 and 2 channels. + uint32_t n_samples = pdmbuf.len; - if (typesize != 2) { - // Make sure the buffer is 16-Bits array. - RAISE_OS_EXCEPTION("Wrong data type, expected 16-Bits array!"); + if (typesize != n_channels) { + // Make sure the buffer type matches the number of channels. + RAISE_OS_EXCEPTION("Buffer data type does not match the number of channels!"); } // Clear DMA buffer status xfer_status &= DMA_XFER_NONE; // Start DMA transfer - if (HAL_SAI_Receive_DMA(&hsai, (uint8_t*) PDM_BUFFER, PDM_BUFFER_SIZE / 2) != HAL_OK) { + if (HAL_SAI_Receive_DMA(&hsai, (uint8_t*) PDM_BUFFER, PDM_BUFFER_SIZE / n_channels) != HAL_OK) { RAISE_OS_EXCEPTION("SAI DMA transfer failed!"); } @@ -183,9 +190,10 @@ static mp_obj_t py_audio_read_pdm(mp_obj_t buf_in) xfer_status &= DMA_XFER_NONE; // Copy samples to pdm output buffer. - uint32_t samples = SAI_MIN(n_samples, PDM_BUFFER_SIZE/2); + // Note: samples are copied as bytes for 1 and 2 channels. + uint32_t samples = SAI_MIN(n_samples, PDM_BUFFER_SIZE); for (int i=0; i