| /* |
| * 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); |
| } |
| } |
| |
| 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; |
| } |