I'm trying to setup a I2S module by referring the I2S module given in the nrf5340-audio application. This is my audio_i2s.c file.
/*
* Copyright (c) 2021, PACKETCRAFT, INC.
*
* SPDX-License-Identifier: LicenseRef-PCFT
*/
#include "audio_i2s.h"
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/pinctrl.h>
#include <nrfx_i2s.h>
#include <nrfx_clock.h>
#include <audio_module/audio_module.h>
#define I2S_NL DT_NODELABEL(i2s0)
#define HFCLKAUDIO_12_288_MHZ 0x9BAE
enum audio_i2s_state {
AUDIO_I2S_STATE_UNINIT,
AUDIO_I2S_STATE_IDLE,
AUDIO_I2S_STATE_STARTED,
};
static enum audio_i2s_state state = AUDIO_I2S_STATE_UNINIT;
PINCTRL_DT_DEFINE(I2S_NL);
#if CONFIG_AUDIO_SAMPLE_RATE_16000_HZ
#define CONFIG_AUDIO_RATIO NRF_I2S_RATIO_384X
#elif CONFIG_AUDIO_SAMPLE_RATE_24000_HZ
#define CONFIG_AUDIO_RATIO NRF_I2S_RATIO_256X
#elif CONFIG_AUDIO_SAMPLE_RATE_48000_HZ
#define CONFIG_AUDIO_RATIO NRF_I2S_RATIO_128X
#else
#error "Current AUDIO_SAMPLE_RATE_HZ setting not supported"
#endif
static nrfx_i2s_t i2s_inst = NRFX_I2S_INSTANCE(0);
static nrfx_i2s_config_t cfg = {
/* Pins are configured by pinctrl. */
.skip_gpio_cfg = true,
.skip_psel_cfg = true,
.irq_priority = DT_IRQ(I2S_NL, priority),
.mode = NRF_I2S_MODE_MASTER,
.format = NRF_I2S_FORMAT_I2S,
.alignment = NRF_I2S_ALIGN_LEFT,
.ratio = CONFIG_AUDIO_RATIO,
.mck_setup = 0x66666000,
#if (CONFIG_AUDIO_BIT_DEPTH_16)
.sample_width = NRF_I2S_SWIDTH_16BIT,
#elif (CONFIG_AUDIO_BIT_DEPTH_32)
.sample_width = NRF_I2S_SWIDTH_32BIT,
#else
#error Invalid bit depth selected
#endif /* (CONFIG_AUDIO_BIT_DEPTH_16) */
.channels = NRF_I2S_CHANNELS_STEREO,
.clksrc = NRF_I2S_CLKSRC_ACLK,
.enable_bypass = false,
};
static i2s_blk_comp_callback_t i2s_blk_comp_callback;
static void i2s_comp_handler(nrfx_i2s_buffers_t const *released_bufs, uint32_t status)
{
uint32_t frame_start_ts = audio_sync_timer_capture_get();
if ((status == NRFX_I2S_STATUS_NEXT_BUFFERS_NEEDED) && released_bufs &&
i2s_blk_comp_callback && (released_bufs->p_rx_buffer || released_bufs->p_tx_buffer)) {
i2s_blk_comp_callback(frame_start_ts, released_bufs->p_rx_buffer,
released_bufs->p_tx_buffer);
}
}
void audio_i2s_set_next_buf(const uint8_t *tx_buf, uint32_t *rx_buf)
{
__ASSERT_NO_MSG(state == AUDIO_I2S_STATE_STARTED);
if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL) || (CONFIG_AUDIO_DEV == GATEWAY)) {
__ASSERT_NO_MSG(rx_buf != NULL);
}
if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL) || (CONFIG_AUDIO_DEV == HEADSET)) {
__ASSERT_NO_MSG(tx_buf != NULL);
}
const nrfx_i2s_buffers_t i2s_buf = { .p_rx_buffer = rx_buf,
.p_tx_buffer = (uint32_t *)tx_buf };
nrfx_err_t ret;
ret = nrfx_i2s_next_buffers_set(&i2s_inst, &i2s_buf);
__ASSERT_NO_MSG(ret == NRFX_SUCCESS);
}
void audio_i2s_start(const uint8_t *tx_buf, uint32_t *rx_buf)
{
__ASSERT_NO_MSG(state == AUDIO_I2S_STATE_IDLE);
if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL) || (CONFIG_AUDIO_DEV == GATEWAY)) {
__ASSERT_NO_MSG(rx_buf != NULL);
}
if (IS_ENABLED(CONFIG_STREAM_BIDIRECTIONAL) || (CONFIG_AUDIO_DEV == HEADSET)) {
__ASSERT_NO_MSG(tx_buf != NULL);
}
const nrfx_i2s_buffers_t i2s_buf = { .p_rx_buffer = rx_buf,
.p_tx_buffer = (uint32_t *)tx_buf };
nrfx_err_t ret;
/* Buffer size in 32-bit words */
ret = nrfx_i2s_start(&i2s_inst, &i2s_buf, I2S_SAMPLES_NUM, 0);
__ASSERT_NO_MSG(ret == NRFX_SUCCESS);
state = AUDIO_I2S_STATE_STARTED;
}
void audio_i2s_stop(void)
{
__ASSERT_NO_MSG(state == AUDIO_I2S_STATE_STARTED);
nrfx_i2s_stop(&i2s_inst);
state = AUDIO_I2S_STATE_IDLE;
}
void audio_i2s_blk_comp_cb_register(i2s_blk_comp_callback_t blk_comp_callback)
{
i2s_blk_comp_callback = blk_comp_callback;
}
void audio_i2s_init(void)
{
__ASSERT_NO_MSG(state == AUDIO_I2S_STATE_UNINIT);
nrfx_err_t ret;
nrfx_clock_hfclkaudio_config_set(HFCLKAUDIO_12_288_MHZ);
NRF_CLOCK->TASKS_HFCLKAUDIOSTART = 1;
/* Wait for ACLK to start */
while (!NRF_CLOCK_EVENT_HFCLKAUDIOSTARTED) {
k_sleep(K_MSEC(1));
}
ret = pinctrl_apply_state(PINCTRL_DT_DEV_CONFIG_GET(I2S_NL), PINCTRL_STATE_DEFAULT);
__ASSERT_NO_MSG(ret == 0);
IRQ_CONNECT(DT_IRQN(I2S_NL), DT_IRQ(I2S_NL, priority), nrfx_isr, nrfx_i2s_0_irq_handler, 0);
irq_enable(DT_IRQN(I2S_NL));
ret = nrfx_i2s_init(&i2s_inst, &cfg, i2s_comp_handler);
__ASSERT_NO_MSG(ret == NRFX_SUCCESS);
state = AUDIO_I2S_STATE_IDLE;
}
Now when I'm building this, I'm getting this weird error
gen_isr_tables.py: error: multiple registrations at table_index 40 for irq 40 (0x28)Existing handler 0x22407, new handler 0x22407Has IRQ_CONNECT or IRQ_DIRECT_CONNECT accidentally been invoked on the same irq multiple times?ninja: build stopped: subcommand failed.I went through the Global Search to find if there are multiple instances of IRQ_CONNECT, but I found only 1 instance that is present in the audio_i2s_init() function in the code file which I have mentioned above. What could possibly cause this error and how do I fix it?
Also is there any other simpler way of setting up I2S service with both the CS47L63 Codec and the LC3 Codec?