1 /*
2 * Copyright (c) 2020 Antmicro <www.antmicro.com>
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/sys/printk.h>
9 #include <zephyr/drivers/i2s.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #define AUDIO_SAMPLE_FREQ (44100)
13 #define AUDIO_SAMPLES_PER_CH_PER_FRAME (128)
14 #define AUDIO_NUM_CHANNELS (2)
15 #define AUDIO_SAMPLES_PER_FRAME \
16 (AUDIO_SAMPLES_PER_CH_PER_FRAME * AUDIO_NUM_CHANNELS)
17 #define AUDIO_SAMPLE_BYTES (3)
18 #define AUDIO_SAMPLE_BIT_WIDTH (24)
19
20 #define AUDIO_FRAME_BUF_BYTES (AUDIO_SAMPLES_PER_FRAME * AUDIO_SAMPLE_BYTES)
21
22 #define I2S_PLAY_BUF_COUNT (500)
23
24 static const struct device *host_i2s_rx_dev;
25 static const struct device *host_i2s_tx_dev;
26 static struct k_mem_slab i2s_rx_mem_slab;
27 static struct k_mem_slab i2s_tx_mem_slab;
28 static char rx_buffers[AUDIO_FRAME_BUF_BYTES * I2S_PLAY_BUF_COUNT];
29 static char tx_buffer[AUDIO_FRAME_BUF_BYTES * I2S_PLAY_BUF_COUNT];
30 static struct i2s_config i2s_rx_cfg;
31 static struct i2s_config i2s_tx_cfg;
32 static int ret;
33
init(void)34 static void init(void)
35 {
36 /*configure rx device*/
37 host_i2s_rx_dev = device_get_binding("i2s_rx");
38 if (!host_i2s_rx_dev) {
39 printk("unable to find i2s_rx device\n");
40 exit(-1);
41 }
42 k_mem_slab_init(&i2s_rx_mem_slab, rx_buffers, AUDIO_FRAME_BUF_BYTES,
43 I2S_PLAY_BUF_COUNT);
44
45 /* configure i2s for audio playback */
46 i2s_rx_cfg.word_size = AUDIO_SAMPLE_BIT_WIDTH;
47 i2s_rx_cfg.channels = AUDIO_NUM_CHANNELS;
48 i2s_rx_cfg.format = I2S_FMT_DATA_FORMAT_I2S;
49 i2s_rx_cfg.options = I2S_OPT_FRAME_CLK_SLAVE;
50 i2s_rx_cfg.frame_clk_freq = AUDIO_SAMPLE_FREQ;
51 i2s_rx_cfg.block_size = AUDIO_FRAME_BUF_BYTES;
52 i2s_rx_cfg.mem_slab = &i2s_rx_mem_slab;
53 i2s_rx_cfg.timeout = -1;
54 ret = i2s_configure(host_i2s_rx_dev, I2S_DIR_RX, &i2s_rx_cfg);
55
56 if (ret != 0) {
57 printk("i2s_configure failed with %d error", ret);
58 exit(-1);
59 }
60
61 /*configure tx device*/
62 host_i2s_tx_dev = device_get_binding("i2s_tx");
63 if (!host_i2s_tx_dev) {
64 printk("unable to find i2s_tx device\n");
65 exit(-1);
66 }
67 k_mem_slab_init(&i2s_tx_mem_slab, tx_buffer, AUDIO_FRAME_BUF_BYTES,
68 I2S_PLAY_BUF_COUNT);
69
70 /* configure i2s for audio playback */
71 i2s_tx_cfg.word_size = AUDIO_SAMPLE_BIT_WIDTH;
72 i2s_tx_cfg.channels = AUDIO_NUM_CHANNELS;
73 i2s_tx_cfg.format = I2S_FMT_DATA_FORMAT_I2S;
74 i2s_tx_cfg.options = I2S_OPT_FRAME_CLK_SLAVE;
75 i2s_tx_cfg.frame_clk_freq = AUDIO_SAMPLE_FREQ;
76 i2s_tx_cfg.block_size = AUDIO_FRAME_BUF_BYTES;
77 i2s_tx_cfg.mem_slab = &i2s_tx_mem_slab;
78 i2s_tx_cfg.timeout = -1;
79 ret = i2s_configure(host_i2s_tx_dev, I2S_DIR_TX, &i2s_tx_cfg);
80 if (ret != 0) {
81 printk("i2s_configure failed with %d error\n", ret);
82 exit(-1);
83 }
84 }
85
main(void)86 int main(void)
87 {
88 init();
89
90 /* start i2s rx driver */
91 ret = i2s_trigger(host_i2s_rx_dev, I2S_DIR_RX, I2S_TRIGGER_START);
92 if (ret != 0) {
93 printk("i2s_trigger failed with %d error\n", ret);
94 exit(-1);
95 }
96
97 /* start i2s tx driver */
98 ret = i2s_trigger(host_i2s_tx_dev, I2S_DIR_TX, I2S_TRIGGER_START);
99 if (ret != 0) {
100 printk("i2s_trigger failed with %d error\n", ret);
101 exit(-1);
102 }
103
104 /* receive data */
105 void *rx_mem_block, *tx_mem_block;
106 size_t size;
107
108 while (true) {
109 k_mem_slab_alloc(&i2s_tx_mem_slab, &tx_mem_block, K_NO_WAIT);
110 i2s_read(host_i2s_rx_dev, &rx_mem_block, &size);
111 memcpy(tx_mem_block, rx_mem_block, size);
112 i2s_write(host_i2s_tx_dev, tx_mem_block, size);
113 k_mem_slab_free(&i2s_rx_mem_slab, &rx_mem_block);
114 }
115 return 0;
116 }
117