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