1
6
7
16
17
19
25
26
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
49
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
88
89
90
91
100
101
102
103
104
105
106
107
110
111
112
113
117
118
119
125
126
127
128
129
130
131
132
133
138
139
140
143
144
145
146
147
148
149
150
151
152
153
154
157
158
159
160
161
162
166
167
168
169
170
171
172
173
174
175
176
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
202
203
204
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
/* ... */
#include <stdint.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s_tdm.h"
#include "driver/gpio.h"
#include "esp_check.h"
#include "sdkconfig.h"
#include "i2s_example_pins.h"9 includes
/* ... */
#define EXAMPLE_I2S_DUPLEX_MODE 1
#define EXAMPLE_TDM_BCLK_IO1 EXAMPLE_I2S_BCLK_IO1
#define EXAMPLE_TDM_WS_IO1 EXAMPLE_I2S_WS_IO1
#define EXAMPLE_TDM_DOUT_IO1 EXAMPLE_I2S_DOUT_IO1
#define EXAMPLE_TDM_DIN_IO1 EXAMPLE_I2S_DIN_IO1 5 defines
#if !EXAMPLE_I2S_DUPLEX_MODE
#define EXAMPLE_TDM_BCLK_IO2 EXAMPLE_I2S_BCLK_IO2
#define EXAMPLE_TDM_WS_IO2 EXAMPLE_I2S_WS_IO2
#define EXAMPLE_TDM_DOUT_IO2 EXAMPLE_I2S_DOUT_IO2
#define EXAMPLE_TDM_DIN_IO2 EXAMPLE_I2S_DIN_IO2 /* ... */
#endif
#define EXAMPLE_BUFF_SIZE 2048
static i2s_chan_handle_t tx_chan;
static i2s_chan_handle_t rx_chan;
static void i2s_example_read_task(void *args)
{
uint8_t *r_buf = (uint8_t *)calloc(1, EXAMPLE_BUFF_SIZE);
assert(r_buf);
size_t r_bytes = 0;
ESP_ERROR_CHECK(i2s_channel_enable(rx_chan));
/* ... */
while (1) {
if (i2s_channel_read(rx_chan, r_buf, EXAMPLE_BUFF_SIZE, &r_bytes, 1000) == ESP_OK) {
printf("Read Task: i2s read %d bytes\n-----------------------------------\n", r_bytes);
printf("[0] %x [1] %x [2] %x [3] %x\n[4] %x [5] %x [6] %x [7] %x\n\n",
r_buf[0], r_buf[1], r_buf[2], r_buf[3], r_buf[4], r_buf[5], r_buf[6], r_buf[7]);
}{...} else {
printf("Read Task: i2s read failed\n");
}{...}
vTaskDelay(pdMS_TO_TICKS(200));
}{...}
free(r_buf);
vTaskDelete(NULL);
}{ ... }
static void i2s_example_write_task(void *args)
{
uint8_t *w_buf = (uint8_t *)calloc(1, EXAMPLE_BUFF_SIZE);
assert(w_buf);
for (int i = 0; i < EXAMPLE_BUFF_SIZE; i += 8) {
w_buf[i] = 0x12;
w_buf[i + 1] = 0x34;
w_buf[i + 2] = 0x56;
w_buf[i + 3] = 0x78;
w_buf[i + 4] = 0x9A;
w_buf[i + 5] = 0xBC;
w_buf[i + 6] = 0xDE;
w_buf[i + 7] = 0xF0;
}{...}
size_t w_bytes = EXAMPLE_BUFF_SIZE;
while (w_bytes == EXAMPLE_BUFF_SIZE) {
ESP_ERROR_CHECK(i2s_channel_preload_data(tx_chan, w_buf, EXAMPLE_BUFF_SIZE, &w_bytes));
}{...}
ESP_ERROR_CHECK(i2s_channel_enable(tx_chan));
while (1) {
if (i2s_channel_write(tx_chan, w_buf, EXAMPLE_BUFF_SIZE, &w_bytes, 1000) == ESP_OK) {
printf("Write Task: i2s write %d bytes\n", w_bytes);
}{...} else {
printf("Write Task: i2s write failed\n");
}{...}
vTaskDelay(pdMS_TO_TICKS(200));
}{...}
free(w_buf);
vTaskDelete(NULL);
}{ ... }
#if EXAMPLE_I2S_DUPLEX_MODE
static void i2s_example_init_tdm_duplex(void)
{
/* ... */
i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_chan, &rx_chan));
/* ... */
i2s_tdm_config_t tdm_cfg = {
.clk_cfg = I2S_TDM_CLK_DEFAULT_CONFIG(16000),
/* ... */
.slot_cfg = I2S_TDM_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO,
I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3),
.gpio_cfg = {
.mclk = I2S_GPIO_UNUSED,
.bclk = EXAMPLE_TDM_BCLK_IO1,
.ws = EXAMPLE_TDM_WS_IO1,
.dout = EXAMPLE_TDM_DOUT_IO1,
.din = EXAMPLE_TDM_DOUT_IO1,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
}{...},
}{...},
}{...};
/* ... */
tdm_cfg.clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_512;
ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(tx_chan, &tdm_cfg));
ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(rx_chan, &tdm_cfg));
}{ ... }
/* ... */#else
static void i2s_example_init_tdm_simplex(void)
{
/* ... */
i2s_chan_config_t tx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&tx_chan_cfg, &tx_chan, NULL));
i2s_chan_config_t rx_chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM_AUTO, I2S_ROLE_MASTER);
ESP_ERROR_CHECK(i2s_new_channel(&rx_chan_cfg, NULL, &rx_chan));
/* ... */
i2s_tdm_config_t tx_tdm_cfg = {
.clk_cfg = I2S_TDM_CLK_DEFAULT_CONFIG(16000),
.slot_cfg = I2S_TDM_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_32BIT, I2S_SLOT_MODE_STEREO,
I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3),
.gpio_cfg = {
.mclk = I2S_GPIO_UNUSED,
.bclk = EXAMPLE_TDM_BCLK_IO1,
.ws = EXAMPLE_TDM_WS_IO1,
.dout = EXAMPLE_TDM_DOUT_IO1,
.din = EXAMPLE_TDM_DIN_IO1,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
}{...},
}{...},
}{...};
tx_tdm_cfg.clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_512;
ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(tx_chan, &tx_tdm_cfg));
i2s_tdm_config_t rx_tdm_cfg = {
.clk_cfg = I2S_TDM_CLK_DEFAULT_CONFIG(44100),
.slot_cfg = I2S_TDM_MSB_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_MONO,
I2S_TDM_SLOT0 | I2S_TDM_SLOT1 | I2S_TDM_SLOT2 | I2S_TDM_SLOT3 |
I2S_TDM_SLOT4 | I2S_TDM_SLOT5 | I2S_TDM_SLOT6 | I2S_TDM_SLOT7),
.gpio_cfg = {
.mclk = I2S_GPIO_UNUSED,
.bclk = EXAMPLE_TDM_BCLK_IO2,
.ws = EXAMPLE_TDM_WS_IO2,
.dout = EXAMPLE_TDM_DOUT_IO2,
.din = EXAMPLE_TDM_DIN_IO2,
.invert_flags = {
.mclk_inv = false,
.bclk_inv = false,
.ws_inv = false,
}{...},
}{...},
}{...};
/* ... */
rx_tdm_cfg.clk_cfg.mclk_multiple = I2S_MCLK_MULTIPLE_512;
ESP_ERROR_CHECK(i2s_channel_init_tdm_mode(rx_chan, &rx_tdm_cfg));
}{...}
/* ... */#endif
void app_main(void)
{
#if EXAMPLE_I2S_DUPLEX_MODE
i2s_example_init_tdm_duplex();
#else
i2s_example_init_tdm_simplex();
#endif
xTaskCreate(i2s_example_read_task, "i2s_example_read_task", 4096, NULL, 5, NULL);
xTaskCreate(i2s_example_write_task, "i2s_example_write_task", 4096, NULL, 5, NULL);
}{ ... }