blob: ccd1ae19e3900958d2b77d94dfe65822f8c91bcc [file] [log] [blame]
/*
* Copyright (c) 2020 Antmicro <www.antmicro.com>
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/i2s.h>
#include <stdlib.h>
#include <string.h>
#define AUDIO_SAMPLE_FREQ (44100)
#define AUDIO_SAMPLES_PER_CH_PER_FRAME (128)
#define AUDIO_NUM_CHANNELS (2)
#define AUDIO_SAMPLES_PER_FRAME \
(AUDIO_SAMPLES_PER_CH_PER_FRAME * AUDIO_NUM_CHANNELS)
#define AUDIO_SAMPLE_BYTES (3)
#define AUDIO_SAMPLE_BIT_WIDTH (24)
#define AUDIO_FRAME_BUF_BYTES (AUDIO_SAMPLES_PER_FRAME * AUDIO_SAMPLE_BYTES)
#define I2S_PLAY_BUF_COUNT (500)
static const struct device *host_i2s_rx_dev;
static const struct device *host_i2s_tx_dev;
static struct k_mem_slab i2s_rx_mem_slab;
static struct k_mem_slab i2s_tx_mem_slab;
static char rx_buffers[AUDIO_FRAME_BUF_BYTES * I2S_PLAY_BUF_COUNT];
static char tx_buffer[AUDIO_FRAME_BUF_BYTES * I2S_PLAY_BUF_COUNT];
static struct i2s_config i2s_rx_cfg;
static struct i2s_config i2s_tx_cfg;
static int ret;
static void init(void)
{
/*configure rx device*/
host_i2s_rx_dev = device_get_binding("i2s_rx");
if (!host_i2s_rx_dev) {
printk("unable to find i2s_rx device\n");
exit(-1);
}
k_mem_slab_init(&i2s_rx_mem_slab, rx_buffers, AUDIO_FRAME_BUF_BYTES,
I2S_PLAY_BUF_COUNT);
/* configure i2s for audio playback */
i2s_rx_cfg.word_size = AUDIO_SAMPLE_BIT_WIDTH;
i2s_rx_cfg.channels = AUDIO_NUM_CHANNELS;
i2s_rx_cfg.format = I2S_FMT_DATA_FORMAT_I2S;
i2s_rx_cfg.options = I2S_OPT_FRAME_CLK_SLAVE;
i2s_rx_cfg.frame_clk_freq = AUDIO_SAMPLE_FREQ;
i2s_rx_cfg.block_size = AUDIO_FRAME_BUF_BYTES;
i2s_rx_cfg.mem_slab = &i2s_rx_mem_slab;
i2s_rx_cfg.timeout = -1;
ret = i2s_configure(host_i2s_rx_dev, I2S_DIR_RX, &i2s_rx_cfg);
if (ret != 0) {
printk("i2s_configure failed with %d error", ret);
exit(-1);
}
/*configure tx device*/
host_i2s_tx_dev = device_get_binding("i2s_tx");
if (!host_i2s_tx_dev) {
printk("unable to find i2s_tx device\n");
exit(-1);
}
k_mem_slab_init(&i2s_tx_mem_slab, tx_buffer, AUDIO_FRAME_BUF_BYTES,
I2S_PLAY_BUF_COUNT);
/* configure i2s for audio playback */
i2s_tx_cfg.word_size = AUDIO_SAMPLE_BIT_WIDTH;
i2s_tx_cfg.channels = AUDIO_NUM_CHANNELS;
i2s_tx_cfg.format = I2S_FMT_DATA_FORMAT_I2S;
i2s_tx_cfg.options = I2S_OPT_FRAME_CLK_SLAVE;
i2s_tx_cfg.frame_clk_freq = AUDIO_SAMPLE_FREQ;
i2s_tx_cfg.block_size = AUDIO_FRAME_BUF_BYTES;
i2s_tx_cfg.mem_slab = &i2s_tx_mem_slab;
i2s_tx_cfg.timeout = -1;
ret = i2s_configure(host_i2s_tx_dev, I2S_DIR_TX, &i2s_tx_cfg);
if (ret != 0) {
printk("i2s_configure failed with %d error\n", ret);
exit(-1);
}
}
void main(void)
{
init();
/* start i2s rx driver */
ret = i2s_trigger(host_i2s_rx_dev, I2S_DIR_RX, I2S_TRIGGER_START);
if (ret != 0) {
printk("i2s_trigger failed with %d error\n", ret);
exit(-1);
}
/* start i2s tx driver */
ret = i2s_trigger(host_i2s_tx_dev, I2S_DIR_TX, I2S_TRIGGER_START);
if (ret != 0) {
printk("i2s_trigger failed with %d error\n", ret);
exit(-1);
}
/* receive data */
void *rx_mem_block, *tx_mem_block;
size_t size;
while (true) {
k_mem_slab_alloc(&i2s_tx_mem_slab, &tx_mem_block, K_NO_WAIT);
i2s_read(host_i2s_rx_dev, &rx_mem_block, &size);
memcpy(tx_mem_block, rx_mem_block, size);
i2s_write(host_i2s_tx_dev, tx_mem_block, size);
k_mem_slab_free(&i2s_rx_mem_slab, &rx_mem_block);
}
}