/* * Copyright (c) 2020 Antmicro * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include #include #include #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); } } int 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); } return 0; }