Skip to content

Commit

Permalink
Add support for I2S slave in ASR audio playback
Browse files Browse the repository at this point in the history
  • Loading branch information
lucianomartin committed Jul 25, 2024
1 parent 7de7d04 commit ab8617e
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 40 deletions.
2 changes: 1 addition & 1 deletion examples/ffd/ffd_i2s_input_cyberon.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ set(APP_COMPILE_DEFINITIONS
QSPI_FLASH_CALIBRATION_ADDRESS=${CALIBRATION_PATTERN_START_ADDRESS}
ASR_CYBERON=1
appconfUSE_I2S_INPUT=1
appconfAUDIO_PLAYBACK_ENABLED=0
appconfAUDIO_PLAYBACK_ENABLED=1
appconfI2S_MODE=appconfI2S_MODE_SLAVE
appconfI2S_AUDIO_SAMPLE_RATE=48000
appconfI2S_ENABLED=1
Expand Down
19 changes: 12 additions & 7 deletions examples/ffd/src/app_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,6 @@
#define appconfAUDIO_PLAYBACK_ENABLED 1
#endif

#if appconfUSE_I2S_INPUT==1 && appconfAUDIO_PLAYBACK_ENABLED==1
#error "I2S audio input cannot be used with audio playback"
#endif

/* Intent Engine Configuration */
#define appconfINTENT_FRAME_BUFFER_MULT (8*2) /* total buffer size is this value * MIC_ARRAY_CONFIG_SAMPLES_PER_FRAME */
#define appconfINTENT_SAMPLE_BLOCK_LENGTH 240
Expand Down Expand Up @@ -95,6 +91,18 @@
#define appconfI2S_ENABLED 1
#endif

#ifndef appconfI2S_MODE_MASTER
#define appconfI2S_MODE_MASTER 0
#endif

#ifndef appconfI2S_MODE_SLAVE
#define appconfI2S_MODE_SLAVE 1
#endif

#ifndef appconfI2S_MODE
#define appconfI2S_MODE appconfI2S_MODE_MASTER
#endif

#ifndef appconfAUDIO_PIPELINE_SKIP_IC_AND_VNR
#define appconfAUDIO_PIPELINE_SKIP_IC_AND_VNR 0
#endif
Expand All @@ -111,9 +119,6 @@
#define appconfI2S_AUDIO_SAMPLE_RATE appconfAUDIO_PIPELINE_SAMPLE_RATE
#endif

#define appconfI2S_MODE_MASTER 0
#define appconfI2S_MODE_SLAVE 1

/* I/O and interrupt cores for Tile 0 */

/* I/O and interrupt cores for Tile 1 */
Expand Down
53 changes: 39 additions & 14 deletions examples/ffd/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,46 @@
#endif

#if appconfI2S_ENABLED && (appconfI2S_MODE == appconfI2S_MODE_SLAVE)
void i2s_slave_intertile(void *args) {
(void) args;
void i2s_slave_intertile()
{
int32_t tmp[appconfAUDIO_PIPELINE_FRAME_ADVANCE][appconfAUDIO_PIPELINE_CHANNELS];
while(1) {
#if ON_TILE(1) && appconfRECOVER_MCLK_I2S_APP_PLL
memset(tmp, 0x00, sizeof(tmp));

size_t bytes_received = 0;
bytes_received = rtos_intertile_rx_len(
intertile_ctx,
appconfI2S_OUTPUT_SLAVE_PORT,
portMAX_DELAY);

xassert(bytes_received == sizeof(tmp));

rtos_intertile_rx_data(
intertile_ctx,
tmp,
bytes_received);

rtos_i2s_tx(i2s_ctx,
(int32_t*) tmp,
appconfAUDIO_PIPELINE_FRAME_ADVANCE,
portMAX_DELAY);
}
}
#endif

#if appconfRECOVER_MCLK_I2S_APP_PLL
void sw_pll(void *args)
{

while(1)
{
sw_pll_ctx_t* i2s_callback_args = (sw_pll_ctx_t*) args;
port_clear_buffer(i2s_callback_args->p_bclk_count);
port_in(i2s_callback_args->p_bclk_count); // Block until BCLK transition to synchronise. Will consume up to 1/64 of a LRCLK cycle
uint16_t mclk_pt = port_get_trigger_time(i2s_callback_args->p_mclk_count); // Immediately sample mclk_count
uint16_t bclk_pt = port_get_trigger_time(i2s_callback_args->p_bclk_count); // Now grab bclk_count (which won't have changed)

sw_pll_do_control(i2s_callback_args->sw_pll, mclk_pt, bclk_pt);
#endif

}
}
#endif
Expand Down Expand Up @@ -91,6 +118,7 @@ void audio_pipeline_input(void *input_app_data,
xassert(frame_count == appconfAUDIO_PIPELINE_FRAME_ADVANCE);
int32_t tmp[appconfAUDIO_PIPELINE_FRAME_ADVANCE][appconfAUDIO_PIPELINE_CHANNELS];
int32_t *tmpptr = (int32_t *)input_audio_frames;

/* I2S provides sample channel format */
size_t rx_count =
rtos_i2s_rx(i2s_ctx,
Expand All @@ -100,7 +128,6 @@ void audio_pipeline_input(void *input_app_data,


for (int i=0; i<frame_count; i++) {
//printintln(tmp[i][0]);
*(tmpptr + i) = tmp[i][0];
*(tmpptr + i + frame_count) = tmp[i][1];
}
Expand Down Expand Up @@ -227,19 +254,17 @@ void startup_task(void *arg)

#if ON_TILE(1) && appconfI2S_ENABLED && (appconfI2S_MODE == appconfI2S_MODE_SLAVE)

// Use sw_pll_ctx only if the MCLK recovery is enabled
#if appconfRECOVER_MCLK_I2S_APP_PLL
xTaskCreate((TaskFunction_t) i2s_slave_intertile,
"i2s_slave_intertile",
RTOS_THREAD_STACK_SIZE(i2s_slave_intertile),
sw_pll_ctx,
NULL,
appconfAUDIO_PIPELINE_TASK_PRIORITY,
NULL);
#else
xTaskCreate((TaskFunction_t) i2s_slave_intertile,
"i2s_slave_intertile",
RTOS_THREAD_STACK_SIZE(i2s_slave_intertile),
NULL,
#if appconfRECOVER_MCLK_I2S_APP_PLL
xTaskCreate((TaskFunction_t) sw_pll,
"sw_pll",
RTOS_THREAD_STACK_SIZE(sw_pll),
sw_pll_ctx,
appconfAUDIO_PIPELINE_TASK_PRIORITY,
NULL);
#endif
Expand Down
10 changes: 0 additions & 10 deletions examples/ffva/bsp_config/XK_VOICE_L71/platform/platform_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,16 +132,6 @@
#define appconfSPI_OUTPUT_ENABLED 0
#endif /* appconfSPI_OUTPUT_ENABLED */

#ifndef appconfI2S_MODE_MASTER
#define appconfI2S_MODE_MASTER 0
#endif /* appconfI2S_MODE_MASTER */
#ifndef appconfI2S_MODE_SLAVE
#define appconfI2S_MODE_SLAVE 1
#endif /* appconfI2S_MODE_SLAVE */
#ifndef appconfI2S_MODE
#define appconfI2S_MODE appconfI2S_MODE_MASTER
#endif /* appconfI2S_MODE */

/*
* This option sends all 6 16 KHz channels (two channels of processed audio,
* stereo reference audio, and stereo microphone audio) out over a single
Expand Down
18 changes: 18 additions & 0 deletions examples/ffva/src/app_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,8 +170,14 @@
#define appconfI2S_TDM_ENABLED 0
#endif

#ifndef appconfI2S_MODE_MASTER
#define appconfI2S_MODE_MASTER 0
#endif

#ifndef appconfI2S_MODE_SLAVE
#define appconfI2S_MODE_SLAVE 1
#endif

#ifndef appconfI2S_MODE
#define appconfI2S_MODE appconfI2S_MODE_MASTER
#endif
Expand Down Expand Up @@ -232,6 +238,18 @@
#define appconfINTENT_MODEL_RUNNER_TASK_PRIORITY (configMAX_PRIORITIES - 2)
#define appconfLED_TASK_PRIORITY (configMAX_PRIORITIES / 2 - 1)

#ifndef appconfI2S_MODE_MASTER
#define appconfI2S_MODE_MASTER 0
#endif

#ifndef appconfI2S_MODE_SLAVE
#define appconfI2S_MODE_SLAVE 1
#endif

#ifndef appconfI2S_MODE
#define appconfI2S_MODE appconfI2S_MODE_MASTER
#endif

/* Software PLL settings for mclk recovery configurations */
/* see fractions.h and register_setup.h for other pll settings */
#define appconfLRCLK_NOMINAL_HZ appconfI2S_AUDIO_SAMPLE_RATE
Expand Down
26 changes: 18 additions & 8 deletions modules/asr/intent_handler/audio_response/audio_response.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ static const char *audio_files_en[] = {

#define NUM_FILES (sizeof(audio_files_en) / sizeof(char *))

static int16_t file_audio[appconfAUDIO_PIPELINE_FRAME_ADVANCE * sizeof(int16_t)];
static int32_t i2s_audio[2*(appconfAUDIO_PIPELINE_FRAME_ADVANCE * sizeof(int32_t))];
static int16_t file_audio[appconfAUDIO_PIPELINE_FRAME_ADVANCE];
static int32_t i2s_audio[2*(appconfAUDIO_PIPELINE_FRAME_ADVANCE)];
static drwav *wav_files = NULL;

#pragma stackfunction 3000
Expand Down Expand Up @@ -95,12 +95,22 @@ void audio_response_play(int32_t id) {
i2s_audio[(2*i)+0] = (int32_t) file_audio[i] << 16;
i2s_audio[(2*i)+1] = (int32_t) file_audio[i] << 16;
}

rtos_i2s_tx(i2s_ctx,
(int32_t*) i2s_audio,
appconfAUDIO_PIPELINE_FRAME_ADVANCE,
portMAX_DELAY);

if (appconfI2S_MODE == appconfI2S_MODE_MASTER)
{
rtos_i2s_tx(i2s_ctx,
(int32_t*) i2s_audio,
appconfAUDIO_PIPELINE_FRAME_ADVANCE,
portMAX_DELAY);
} else if (appconfI2S_MODE == appconfI2S_MODE_SLAVE)
{
rtos_intertile_tx(intertile_ctx,
appconfI2S_OUTPUT_SLAVE_PORT,
i2s_audio,
sizeof(i2s_audio));
} else {
// Invalid I2S mode
xassert(0);
}
if (framesRead != appconfAUDIO_PIPELINE_FRAME_ADVANCE) {
drwav_seek_to_pcm_frame(&tmp, 0);
break;
Expand Down

0 comments on commit ab8617e

Please sign in to comment.