mirror of
https://github.com/openmv/openmv.git
synced 2025-11-04 14:49:50 +08:00
Merge pull request #1814 from openmv/audio_modules_sched
ports/All: Use static scheduler nodes for Audio modules.
This commit is contained in:
commit
afb26ddf72
@ -1 +1 @@
|
||||
Subproject commit c8ea7e65af10ddbe44d416fc2714057107906105
|
||||
Subproject commit fe89f40ff3726f4168eae70bf1a591198de2fbbe
|
||||
@ -14,7 +14,6 @@
|
||||
#include "py/nlr.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/binary.h"
|
||||
#include "pendsv.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#include "py_audio.h"
|
||||
@ -27,25 +26,24 @@
|
||||
#include "hal/nrf_gpio.h"
|
||||
|
||||
#if MICROPY_PY_AUDIO
|
||||
#define PDM_DEFAULT_GAIN 20
|
||||
#define PDM_IRQ_PRIORITY 7
|
||||
#define PDM_BUFFER_SIZE (256)
|
||||
#define PDM_DEFAULT_GAIN (20)
|
||||
#define PDM_IRQ_PRIORITY (7)
|
||||
#define PDM_BUFFER_SIZE (256)
|
||||
|
||||
#define NRF_PDM_FREQ_1280K (nrf_pdm_freq_t)(0x0A000000UL) ///< PDM_CLK= 1.280 MHz (32 MHz / 25) => Fs= 20000 Hz
|
||||
#define NRF_PDM_FREQ_2000K (nrf_pdm_freq_t)(0x10000000UL) ///< PDM_CLK= 2.000 MHz (32 MHz / 16) => Fs= 31250 Hz
|
||||
#define NRF_PDM_FREQ_2667K (nrf_pdm_freq_t)(0x15000000UL) ///< PDM_CLK= 2.667 MHz (32 MHz / 12) => Fs= 41667 Hz
|
||||
#define NRF_PDM_FREQ_3200K (nrf_pdm_freq_t)(0x19000000UL) ///< PDM_CLK= 3.200 MHz (32 MHz / 10) => Fs= 50000 Hz
|
||||
#define NRF_PDM_FREQ_4000K (nrf_pdm_freq_t)(0x20000000UL) ///< PDM_CLK= 4.000 MHz (32 MHz / 8) => Fs= 62500 Hz
|
||||
#define RAISE_OS_EXCEPTION(msg) mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT(msg))
|
||||
#define NRF_PDM_FREQ_1280K (nrf_pdm_freq_t)(0x0A000000UL) // PDM_CLK= 1.280 MHz (32 MHz / 25) => Fs= 20000 Hz
|
||||
#define NRF_PDM_FREQ_2000K (nrf_pdm_freq_t)(0x10000000UL) // PDM_CLK= 2.000 MHz (32 MHz / 16) => Fs= 31250 Hz
|
||||
#define NRF_PDM_FREQ_2667K (nrf_pdm_freq_t)(0x15000000UL) // PDM_CLK= 2.667 MHz (32 MHz / 12) => Fs= 41667 Hz
|
||||
#define NRF_PDM_FREQ_3200K (nrf_pdm_freq_t)(0x19000000UL) // PDM_CLK= 3.200 MHz (32 MHz / 10) => Fs= 50000 Hz
|
||||
#define NRF_PDM_FREQ_4000K (nrf_pdm_freq_t)(0x20000000UL) // PDM_CLK= 4.000 MHz (32 MHz / 8) => Fs= 62500 Hz
|
||||
#define RAISE_OS_EXCEPTION(msg) mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT(msg))
|
||||
|
||||
static mp_obj_array_t *g_pcmbuf = NULL;
|
||||
static mp_obj_t g_audio_callback = mp_const_none;
|
||||
static uint32_t g_channels = 1;
|
||||
static uint32_t g_buf_index = 0;
|
||||
static int16_t PDM_BUFFERS[2][PDM_BUFFER_SIZE];
|
||||
|
||||
// Pendsv dispatch callback.
|
||||
static void audio_pendsv_callback(void);
|
||||
static mp_sched_node_t audio_task_sched_node;
|
||||
static void audio_task_callback(mp_sched_node_t *node);
|
||||
|
||||
static void nrfx_pdm_event_handler(nrfx_pdm_evt_t const *evt)
|
||||
{
|
||||
@ -59,7 +57,7 @@ static void nrfx_pdm_event_handler(nrfx_pdm_evt_t const *evt)
|
||||
}
|
||||
if (evt->buffer_released && g_audio_callback != mp_const_none) {
|
||||
g_buf_index = (evt->buffer_released == PDM_BUFFERS[0]) ? 0 : 1;
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_AUDIO, audio_pendsv_callback);
|
||||
mp_sched_schedule_node(&audio_task_sched_node, audio_task_callback);
|
||||
}
|
||||
} else {
|
||||
// TODO
|
||||
@ -143,7 +141,7 @@ void py_audio_deinit()
|
||||
g_audio_callback = mp_const_none;
|
||||
}
|
||||
|
||||
static void audio_pendsv_callback(void)
|
||||
static void audio_task_callback(mp_sched_node_t *node)
|
||||
{
|
||||
memcpy(g_pcmbuf->items, PDM_BUFFERS[g_buf_index], PDM_BUFFER_SIZE * sizeof(int16_t));
|
||||
// Call user callback
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#include "py/nlr.h"
|
||||
#include "py/mphal.h"
|
||||
#include "py/binary.h"
|
||||
#include "pendsv.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#include "omv_boardconfig.h"
|
||||
@ -35,11 +34,6 @@
|
||||
#define PDM_DEFAULT_BUFFERS (128) // Number of PCM samples buffers.
|
||||
#define PDM_BUFFER_SIZE (512)
|
||||
#define PDM_TIME_CONV (0) // Enable to print average conversion time.
|
||||
|
||||
#ifndef MICROPY_PY_AUDIO_USE_SYNC_EVENTS
|
||||
#define MICROPY_PY_AUDIO_USE_SYNC_EVENTS (1)
|
||||
#endif
|
||||
|
||||
#define RAISE_OS_EXCEPTION(msg) mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT(msg))
|
||||
|
||||
typedef struct _audio_data_t {
|
||||
@ -65,20 +59,19 @@ typedef struct _audio_data_t {
|
||||
void (*pdm_filter_func) (uint8_t*, int16_t*, uint16_t, TPDMFilter_InitStruct*);
|
||||
} audio_data_t;
|
||||
|
||||
static bool audio_initialized = false;
|
||||
#define audio_data MP_STATE_PORT(audio_data)
|
||||
#define NEXT_BUFFER(x) (((x) + 1) % (audio_data->n_buffers))
|
||||
|
||||
#if MICROPY_PY_AUDIO_USE_SYNC_EVENTS
|
||||
volatile bool audio_task_scheduled = false;
|
||||
static const mp_obj_fun_builtin_fixed_t audio_task_obj;
|
||||
static mp_obj_t audio_task(mp_obj_t none_in)
|
||||
#else
|
||||
static void audio_pendsv_callback(void)
|
||||
#endif
|
||||
static bool audio_initialized = false;
|
||||
static mp_sched_node_t audio_task_sched_node;
|
||||
static volatile bool audio_task_scheduled = false;
|
||||
static bool irq_handler_installed = false;
|
||||
|
||||
static void audio_task_callback(mp_sched_node_t *node)
|
||||
{
|
||||
if (audio_data->streaming == false) {
|
||||
return mp_const_none;
|
||||
audio_task_scheduled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (audio_data->head != audio_data->tail) {
|
||||
@ -91,25 +84,17 @@ static void audio_pendsv_callback(void)
|
||||
// Call user callback.
|
||||
mp_call_function_1(audio_data->user_callback, MP_OBJ_FROM_PTR(audio_data->pcm_buffer_user));
|
||||
} else if (audio_data->overflow == true && audio_data->abort_on_overflow) {
|
||||
#if MICROPY_PY_AUDIO_USE_SYNC_EVENTS
|
||||
RAISE_OS_EXCEPTION("Audio buffer overflow.");
|
||||
#endif
|
||||
return mp_const_none;
|
||||
}
|
||||
|
||||
#if MICROPY_PY_AUDIO_USE_SYNC_EVENTS
|
||||
if (audio_data->head != audio_data->tail) {
|
||||
// Re-schedule function
|
||||
audio_task_scheduled = mp_sched_schedule(MP_OBJ_FROM_PTR(&audio_task_obj), mp_const_none);
|
||||
audio_task_scheduled = true;
|
||||
mp_sched_schedule_node(&audio_task_sched_node, audio_task_callback);
|
||||
} else {
|
||||
audio_task_scheduled = false;
|
||||
}
|
||||
return mp_const_none;
|
||||
#endif
|
||||
}
|
||||
#if MICROPY_PY_AUDIO_USE_SYNC_EVENTS
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(audio_task_obj, audio_task);
|
||||
#endif
|
||||
|
||||
static void dma_irq_handler()
|
||||
{
|
||||
@ -150,13 +135,10 @@ static void dma_irq_handler()
|
||||
|
||||
if (mp_obj_is_callable(audio_data->user_callback)) {
|
||||
// Schedule audio callback.
|
||||
#if MICROPY_PY_AUDIO_USE_SYNC_EVENTS
|
||||
if (audio_task_scheduled == false) {
|
||||
audio_task_scheduled = mp_sched_schedule(MP_OBJ_FROM_PTR(&audio_task_obj), mp_const_none);
|
||||
audio_task_scheduled = true;
|
||||
mp_sched_schedule_node(&audio_task_sched_node, audio_task_callback);
|
||||
}
|
||||
#else
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_AUDIO, audio_pendsv_callback);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -188,9 +170,7 @@ static mp_obj_t py_audio_init(uint n_args, const mp_obj_t *pos_args, mp_map_t *k
|
||||
RAISE_OS_EXCEPTION("Invalid frequency. Expected 16KHz, 32KHz or 48KHz.");
|
||||
}
|
||||
|
||||
#if MICROPY_PY_AUDIO_USE_SYNC_EVENTS
|
||||
audio_task_scheduled = false;
|
||||
#endif
|
||||
|
||||
// The decimation factor is set to keep the PDM datarate within min/max specs for the mic:
|
||||
// 16 KHz * 128 -> 2048 KHz
|
||||
@ -288,7 +268,6 @@ static mp_obj_t py_audio_init(uint n_args, const mp_obj_t *pos_args, mp_map_t *k
|
||||
// Clear DMA interrupts.
|
||||
dma_irqn_acknowledge_channel(PDM_DMA, audio_data->dma_channel);
|
||||
|
||||
static bool irq_handler_installed = false;
|
||||
if (!irq_handler_installed) {
|
||||
irq_handler_installed = true;
|
||||
// Install shared DMA IRQ handler.
|
||||
@ -349,18 +328,22 @@ static mp_obj_t py_audio_stop_streaming()
|
||||
if (audio_data->streaming) {
|
||||
// Disable PDM and IRQ
|
||||
dma_channel_abort(audio_data->dma_channel);
|
||||
//irq_set_enabled(PDM_DMA_IRQ, false);
|
||||
dma_irqn_set_channel_enabled(PDM_DMA, audio_data->dma_channel, false);
|
||||
|
||||
// Disable state machine.
|
||||
pio_sm_set_enabled(PDM_PIO, PDM_SM, false);
|
||||
pio_sm_clear_fifos(PDM_PIO, PDM_SM);
|
||||
|
||||
if (irq_handler_installed) {
|
||||
irq_handler_installed = false;
|
||||
irq_remove_handler(PDM_DMA_IRQ, dma_irq_handler);
|
||||
}
|
||||
|
||||
audio_data->streaming = false;
|
||||
#if MICROPY_PY_AUDIO_USE_SYNC_EVENTS
|
||||
for (mp_uint_t start = mp_hal_ticks_ms();
|
||||
audio_task_scheduled && (mp_hal_ticks_ms() - start) >= 1000;
|
||||
audio_task_scheduled && (mp_hal_ticks_ms() - start) < 1500;
|
||||
mp_hal_delay_ms(10));
|
||||
#endif
|
||||
|
||||
#if PDM_TIME_CONV
|
||||
mp_printf(&mp_plat_print, "Average conversion time:%ld us\n",
|
||||
@ -427,6 +410,7 @@ void py_audio_deinit()
|
||||
audio_data->overflow = false;
|
||||
audio_data->abort_on_overflow = false;
|
||||
audio_data->user_callback = mp_const_none;
|
||||
audio_data->pcm_buffer_user = NULL;
|
||||
|
||||
if (audio_data->dma_channel >= 0) {
|
||||
dma_channel_unclaim(audio_data->dma_channel);
|
||||
|
||||
@ -15,7 +15,6 @@
|
||||
#include "py/mphal.h"
|
||||
#include "py/binary.h"
|
||||
#include "systick.h"
|
||||
#include "pendsv.h"
|
||||
#include "runtime.h"
|
||||
|
||||
#include "py_audio.h"
|
||||
@ -54,14 +53,15 @@ static volatile uint32_t xfer_status = 0;
|
||||
static mp_obj_array_t *g_pcmbuf = NULL;
|
||||
static mp_obj_t g_audio_callback = mp_const_none;
|
||||
static int g_channels = AUDIO_MAX_CHANNELS;
|
||||
static mp_sched_node_t audio_task_sched_node;
|
||||
|
||||
#define DMA_XFER_NONE (0x00U)
|
||||
#define DMA_XFER_HALF (0x01U)
|
||||
#define DMA_XFER_FULL (0x04U)
|
||||
#define RAISE_OS_EXCEPTION(msg) mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT(msg))
|
||||
|
||||
// Pendsv dispatch callback.
|
||||
static void audio_pendsv_callback(void);
|
||||
// Scheduler callback.
|
||||
static void audio_task_callback(mp_sched_node_t *node);
|
||||
|
||||
#if defined(AUDIO_SAI)
|
||||
void AUDIO_SAI_DMA_IRQHandler(void)
|
||||
@ -89,7 +89,7 @@ void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_
|
||||
xfer_status |= DMA_XFER_HALF;
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *)(&PDM_BUFFER[0]), sizeof(PDM_BUFFER) / 2);
|
||||
if (g_audio_callback != mp_const_none) {
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_AUDIO, audio_pendsv_callback);
|
||||
mp_sched_schedule_node(&audio_task_sched_node, audio_task_callback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,7 +102,7 @@ void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filt
|
||||
xfer_status |= DMA_XFER_FULL;
|
||||
SCB_InvalidateDCache_by_Addr((uint32_t *)(&PDM_BUFFER[PDM_BUFFER_SIZE / 2]), sizeof(PDM_BUFFER) / 2);
|
||||
if (g_audio_callback != mp_const_none) {
|
||||
pendsv_schedule_dispatch(PENDSV_DISPATCH_AUDIO, audio_pendsv_callback);
|
||||
mp_sched_schedule_node(&audio_task_sched_node, audio_task_callback);
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,7 +376,7 @@ void py_audio_deinit()
|
||||
g_audio_callback = mp_const_none;
|
||||
}
|
||||
|
||||
static void audio_pendsv_callback(void)
|
||||
static void audio_task_callback(mp_sched_node_t *node)
|
||||
{
|
||||
// Check for half transfer complete.
|
||||
if ((xfer_status & DMA_XFER_HALF)) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user