mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
ports/stm32: Support setting audio module samples at runtime.
This commit is contained in:
parent
54104039b4
commit
40710a3573
@ -52,6 +52,7 @@ int32_t OMV_ATTR_SECTION(OMV_ATTR_ALIGNED(PDM_BUFFER[PDM_BUFFER_SIZE], 32), ".d2
|
||||
|
||||
static volatile uint32_t xfer_status = 0;
|
||||
static int g_channels = OMV_AUDIO_MAX_CHANNELS;
|
||||
static uint32_t g_pdm_buffer_size = 0;
|
||||
static mp_sched_node_t audio_task_sched_node;
|
||||
|
||||
#define DMA_XFER_NONE (0x00U)
|
||||
@ -79,7 +80,8 @@ void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_
|
||||
#endif
|
||||
{
|
||||
xfer_status |= DMA_XFER_HALF;
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *) (&PDM_BUFFER[0]), sizeof(PDM_BUFFER) / 2);
|
||||
uint32_t pdm_buffer_size_bytes = (sizeof(PDM_BUFFER[0]) * g_pdm_buffer_size);
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *) (&PDM_BUFFER[0]), pdm_buffer_size_bytes);
|
||||
if (MP_STATE_PORT(audio_callback) != mp_const_none) {
|
||||
mp_sched_schedule_node(&audio_task_sched_node, audio_task_callback);
|
||||
}
|
||||
@ -92,7 +94,8 @@ void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filt
|
||||
#endif
|
||||
{
|
||||
xfer_status |= DMA_XFER_FULL;
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *) (&PDM_BUFFER[PDM_BUFFER_SIZE / 2]), sizeof(PDM_BUFFER) / 2);
|
||||
uint32_t pdm_buffer_size_bytes = (sizeof(PDM_BUFFER[0]) * g_pdm_buffer_size);
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *) (&PDM_BUFFER[g_pdm_buffer_size]), pdm_buffer_size_bytes / 2);
|
||||
if (MP_STATE_PORT(audio_callback) != mp_const_none) {
|
||||
mp_sched_schedule_node(&audio_task_sched_node, audio_task_callback);
|
||||
}
|
||||
@ -114,12 +117,13 @@ static uint32_t get_decimation_factor(uint32_t decimation) {
|
||||
#endif
|
||||
|
||||
static mp_obj_t py_audio_init(uint n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) {
|
||||
enum { ARG_channels, ARG_frequency, ARG_gain_db, ARG_highpass };
|
||||
enum { ARG_channels, ARG_frequency, ARG_gain_db, ARG_highpass, ARG_samples };
|
||||
static const mp_arg_t allowed_args[] = {
|
||||
{ MP_QSTR_channels, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = OMV_AUDIO_MAX_CHANNELS } },
|
||||
{ MP_QSTR_frequency, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 16000 } },
|
||||
{ MP_QSTR_gain_db, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = 24 } },
|
||||
{ MP_QSTR_highpass, MP_ARG_OBJ | MP_ARG_KW_ONLY, {.u_rom_obj = MP_ROM_NONE} },
|
||||
{ MP_QSTR_samples, MP_ARG_INT | MP_ARG_KW_ONLY, {.u_int = -1 } },
|
||||
};
|
||||
|
||||
// Parse args.
|
||||
@ -143,14 +147,39 @@ static mp_obj_t py_audio_init(uint n_args, const mp_obj_t *pos_args, mp_map_t *k
|
||||
RAISE_OS_EXCEPTION("Invalid number of channels!");
|
||||
}
|
||||
|
||||
#if defined(OMV_SAI)
|
||||
// Default/max PDM buffer size;
|
||||
g_pdm_buffer_size = PDM_BUFFER_SIZE;
|
||||
|
||||
#if defined(OMV_DFSDM)
|
||||
uint32_t samples_per_channel = PDM_BUFFER_SIZE / 2; // Half a transfer
|
||||
#else
|
||||
uint32_t decimation_factor = OMV_SAI_FREQKHZ / (frequency / 1000);
|
||||
uint32_t decimation_factor_const = get_decimation_factor(decimation_factor);
|
||||
if (decimation_factor_const == 0) {
|
||||
RAISE_OS_EXCEPTION("This frequency is not supported!");
|
||||
}
|
||||
uint32_t samples_per_channel = (PDM_BUFFER_SIZE * 8) / (decimation_factor * g_channels * 2); // Half a transfer
|
||||
#endif // defined(OMV_DFSDM)
|
||||
|
||||
if (args[ARG_samples].u_int > 0) {
|
||||
if (args[ARG_samples].u_int % 16 != 0 ||
|
||||
args[ARG_samples].u_int > samples_per_channel) {
|
||||
mp_raise_msg_varg(&mp_type_ValueError,
|
||||
MP_ERROR_TEXT("Invalid number of samples." \
|
||||
"The number of samples must be a multiple of 16," \
|
||||
"and a maximum of %d"),
|
||||
samples_per_channel);
|
||||
}
|
||||
samples_per_channel = args[ARG_samples].u_int;
|
||||
// Recalculate the PDM buffer size for the requested samples.
|
||||
#if defined(OMV_DFSDM)
|
||||
g_pdm_buffer_size = samples_per_channel * 2;
|
||||
#else
|
||||
g_pdm_buffer_size = (samples_per_channel * decimation_factor * g_channels) / 4;
|
||||
#endif // defined(OMV_DFSDM)
|
||||
}
|
||||
|
||||
#if defined(OMV_SAI)
|
||||
hsai.Instance = OMV_SAI;
|
||||
hsai.Init.Protocol = SAI_FREE_PROTOCOL;
|
||||
hsai.Init.AudioMode = SAI_MODEMASTER_RX;
|
||||
@ -323,8 +352,6 @@ static mp_obj_t py_audio_init(uint n_args, const mp_obj_t *pos_args, mp_map_t *k
|
||||
|
||||
NVIC_SetPriority(OMV_DFSDM_FLT0_IRQ, IRQ_PRI_DMA21);
|
||||
HAL_NVIC_EnableIRQ(OMV_DFSDM_FLT0_IRQ);
|
||||
|
||||
uint32_t samples_per_channel = PDM_BUFFER_SIZE / 2; // Half a transfer
|
||||
#endif // defined(OMV_SAI)
|
||||
|
||||
// Allocate global PCM buffer.
|
||||
@ -395,7 +422,7 @@ static void audio_task_callback(mp_sched_node_t *node) {
|
||||
PDM_Filter(&((uint8_t *) PDM_BUFFER)[i], &pcmbuf[i], &PDM_FilterHandler[i]);
|
||||
}
|
||||
#elif defined(OMV_DFSDM)
|
||||
for (int i = 0; i < PDM_BUFFER_SIZE / 2; i++) {
|
||||
for (int i = 0; i < g_pdm_buffer_size / 2; i++) {
|
||||
pcmbuf[i] = SaturaLH((PDM_BUFFER[i] >> 8), -32768, 32767);
|
||||
}
|
||||
#endif
|
||||
@ -407,11 +434,11 @@ static void audio_task_callback(mp_sched_node_t *node) {
|
||||
#if defined(OMV_SAI)
|
||||
// Convert PDM samples to PCM.
|
||||
for (int i = 0; i < g_channels; i++) {
|
||||
PDM_Filter(&((uint8_t *) PDM_BUFFER)[PDM_BUFFER_SIZE / 2 + i], &pcmbuf[i], &PDM_FilterHandler[i]);
|
||||
PDM_Filter(&((uint8_t *) PDM_BUFFER)[g_pdm_buffer_size / 2 + i], &pcmbuf[i], &PDM_FilterHandler[i]);
|
||||
}
|
||||
#elif defined(OMV_DFSDM)
|
||||
for (int i = 0; i < PDM_BUFFER_SIZE / 2; i++) {
|
||||
pcmbuf[i] = SaturaLH((PDM_BUFFER[PDM_BUFFER_SIZE / 2 + i] >> 8), -32768, 32767);
|
||||
for (int i = 0; i < g_pdm_buffer_size / 2; i++) {
|
||||
pcmbuf[i] = SaturaLH((PDM_BUFFER[g_pdm_buffer_size / 2 + i] >> 8), -32768, 32767);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -432,13 +459,13 @@ static mp_obj_t py_audio_start_streaming(mp_obj_t callback_obj) {
|
||||
|
||||
#if defined(OMV_SAI)
|
||||
// Start DMA transfer
|
||||
if (HAL_SAI_Receive_DMA(&hsai, (uint8_t *) PDM_BUFFER, PDM_BUFFER_SIZE / g_channels) != HAL_OK) {
|
||||
if (HAL_SAI_Receive_DMA(&hsai, (uint8_t *) PDM_BUFFER, g_pdm_buffer_size / g_channels) != HAL_OK) {
|
||||
MP_STATE_PORT(audio_callback) = mp_const_none;
|
||||
RAISE_OS_EXCEPTION("SAI DMA transfer failed!");
|
||||
}
|
||||
#elif defined(OMV_DFSDM)
|
||||
// Start DMA transfer
|
||||
if (HAL_DFSDM_FilterRegularStart_DMA(&hdfsdm_filter[0], PDM_BUFFER, PDM_BUFFER_SIZE) != HAL_OK) {
|
||||
if (HAL_DFSDM_FilterRegularStart_DMA(&hdfsdm_filter[0], PDM_BUFFER, g_pdm_buffer_size) != HAL_OK) {
|
||||
RAISE_OS_EXCEPTION("DFSDM DMA transfer failed!");
|
||||
}
|
||||
#endif
|
||||
@ -481,7 +508,7 @@ static mp_obj_t py_audio_read_pdm(mp_obj_t buf_in) {
|
||||
xfer_status &= DMA_XFER_NONE;
|
||||
|
||||
// Start DMA transfer
|
||||
if (HAL_SAI_Receive_DMA(&hsai, (uint8_t *) PDM_BUFFER, PDM_BUFFER_SIZE / g_channels) != HAL_OK) {
|
||||
if (HAL_SAI_Receive_DMA(&hsai, (uint8_t *) PDM_BUFFER, g_pdm_buffer_size / g_channels) != HAL_OK) {
|
||||
RAISE_OS_EXCEPTION("SAI DMA transfer failed!");
|
||||
}
|
||||
|
||||
@ -500,7 +527,7 @@ static mp_obj_t py_audio_read_pdm(mp_obj_t buf_in) {
|
||||
|
||||
// Copy samples to pdm output buffer.
|
||||
// Note: samples are copied as bytes for 1 and 2 channels.
|
||||
uint32_t samples = OMV_MIN(n_samples, PDM_BUFFER_SIZE);
|
||||
uint32_t samples = OMV_MIN(n_samples, g_pdm_buffer_size);
|
||||
for (int i = 0; i < samples; i++, n_samples--, xfer_samples++) {
|
||||
((uint8_t *) pdmbuf.buf)[xfer_samples] = ((uint8_t *) PDM_BUFFER)[i];
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user