arduino-audio-tools
Loading...
Searching...
No Matches
I2SDriverESP32.h
Go to the documentation of this file.
1#pragma once
2
3#include "AudioToolsConfig.h"
4#if defined(ESP32) && USE_LEGACY_I2S || defined(DOXYGEN)
5
9
10#include "driver/i2s.h"
11#include "esp_system.h"
12
13#ifndef I2S_MCLK_MULTIPLE_DEFAULT
14# define I2S_MCLK_MULTIPLE_DEFAULT ((i2s_mclk_multiple_t)0)
15#endif
16
17#define IS_I2S_IMPLEMENTED
18
19namespace audio_tools {
20
29 friend class AnalogAudio;
30 friend class AudioKitStream;
31
32 public:
35 I2SConfigESP32 c(mode);
36 return c;
37 }
38
41 // nothing to do
42 if (is_started) {
43 if (info.equals(cfg)) return true;
44 if (info.equalsExSampleRate(cfg)) {
46 LOGI("i2s_set_sample_rates: %d", info.sample_rate);
48 }
49 } else {
50 LOGE("not started");
51 }
52 return false;
53 }
54
56 bool begin(RxTxMode mode) { return begin(defaultConfig(mode)); }
57
60 bool begin() { return !is_started ? begin(cfg) : true; }
61
64 TRACED();
65 this->cfg = cfg;
66 switch (cfg.rx_tx_mode) {
67 case TX_MODE:
69 case RX_MODE:
70 // usually we expet cfg.pin_data but if the used assinged rx we might
71 // consider this one
72 return begin(
75 default:
77 }
78 LOGE("Did not expect go get here");
79 }
80
83
86
88 void end() {
89 TRACED();
91 is_started = false;
92 }
93
96
98 size_t writeBytes(const void *src, size_t size_bytes) {
99 TRACED();
100
101 size_t result = 0;
103 if (i2s_write(i2s_num, src, size_bytes, &result, ticks_to_wait_write) !=
104 ESP_OK) {
105 TRACEE();
106 }
107 LOGD("i2s_write %d -> %d bytes", size_bytes, result);
108 } else {
109 result =
111 }
112 return result;
113 }
114
115 size_t readBytes(void *dest, size_t size_bytes) {
116 size_t result = 0;
118 if (i2s_read(i2s_num, dest, size_bytes, &result, ticks_to_wait_read) !=
119 ESP_OK) {
120 TRACEE();
121 }
122 } else if (cfg.channels == 1) {
123 // I2S has always 2 channels. We support to reduce it to 1
124 uint8_t temp[size_bytes * 2];
125 if (i2s_read(i2s_num, temp, size_bytes * 2, &result,
127 TRACEE();
128 }
129 // convert to 1 channel
130 switch (cfg.bits_per_sample) {
131 case 16: {
133 result = reducer16.convert((uint8_t *)dest, temp, result);
134 } break;
135 case 24: {
137 result = reducer24.convert((uint8_t *)dest, temp, result);
138 } break;
139 case 32: {
141 result = reducer32.convert((uint8_t *)dest, temp, result);
142 } break;
143 default:
144 LOGE("invalid bits_per_sample: %d", cfg.bits_per_sample);
145 break;
146 }
147 } else {
148 LOGE("Invalid channels: %d", cfg.channels);
149 }
150 return result;
151 }
152
159
160 protected:
164 bool is_started = false;
167
169 if (cfg.channels == 2) return true;
171 return true;
173 return true;
175 return true;
177 return true;
178 return false;
179 }
180
183 TRACED();
184 cfg.logInfo();
185 this->cfg = cfg;
186 this->i2s_num = (i2s_port_t)cfg.port_no;
188
190 .mode = toMode(cfg),
192 .bits_per_sample = (i2s_bits_per_sample_t)cfg.bits_per_sample,
193 .channel_format = (i2s_channel_fmt_t)cfg.channel_format,
194 .communication_format = toCommFormat(cfg.i2s_format),
195 .intr_alloc_flags = 0, // default interrupt priority
196 .dma_buf_count = cfg.buffer_count,
197 .dma_buf_len = cfg.buffer_size,
198 .use_apll = (bool)cfg.use_apll,
199 .tx_desc_auto_clear = cfg.auto_clear,
201 .fixed_mclk = (int)(cfg.fixed_mclk > 0 ? cfg.fixed_mclk : 0),
202 .mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT,
204#endif
205 };
207
208 // We make sure that we can reconfigure
209 if (is_started) {
210 end();
211 LOGD("%s", "I2S restarting");
212 }
213
214 // setup config
215 LOGD("i2s_driver_install");
217 LOGE("%s - %s", __func__, "i2s_driver_install");
218 }
219
220 // setup pin config
221 if (this->cfg.signal_type == Digital || this->cfg.signal_type == PDM) {
223#if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 4, 0)
224 .mck_io_num = cfg.pin_mck,
225#endif
226 .bck_io_num = cfg.pin_bck,
227 .ws_io_num = cfg.pin_ws,
228 .data_out_num = txPin,
229 .data_in_num = rxPin};
230
231 LOGD("i2s_set_pin");
233 LOGE("%s - %s", __func__, "i2s_set_pin");
234 }
235 } else {
236 LOGD("Using built in DAC");
237 // for internal DAC, this will enable both of the internal channels
239 }
240
241 // clear initial buffer
242 LOGD("i2s_zero_dma_buffer");
244
245 is_started = true;
246 LOGD("%s - %s", __func__, "started");
247 return true;
248 }
249
250 // update the cfg.i2s.channel_format based on the number of channels
251 void setChannels(int channels) { cfg.channels = channels; }
252
254 size_t writeExpandChannel(i2s_port_t i2s_num, const int bits_per_sample,
255 const void *src, size_t size_bytes) {
256 size_t result = 0;
257 int j;
258 switch (bits_per_sample) {
259 case 8:
260 for (j = 0; j < size_bytes; j++) {
261 int8_t frame[2];
262 int8_t *data = (int8_t *)src;
263 frame[0] = data[j];
264 frame[1] = data[j];
265 size_t result_call = 0;
266 if (i2s_write(i2s_num, frame, sizeof(int8_t) * 2, &result_call,
268 TRACEE();
269 } else {
270 result += result_call;
271 }
272 }
273 break;
274
275 case 16:
276 for (j = 0; j < size_bytes / 2; j++) {
277 int16_t frame[2];
278 int16_t *data = (int16_t *)src;
279 frame[0] = data[j];
280 frame[1] = data[j];
281 size_t result_call = 0;
282 if (i2s_write(i2s_num, frame, sizeof(int16_t) * 2, &result_call,
284 TRACEE();
285 } else {
286 result += result_call;
287 }
288 }
289 break;
290
291 case 24:
292 for (j = 0; j < size_bytes / 4; j++) {
293 int24_t frame[2];
294 int24_t *data = (int24_t *)src;
295 frame[0] = data[j];
296 frame[1] = data[j];
297 size_t result_call = 0;
298 if (i2s_write(i2s_num, frame, sizeof(int24_t) * 2, &result_call,
300 TRACEE();
301 } else {
302 result += result_call;
303 }
304 }
305 break;
306
307 case 32:
308 for (j = 0; j < size_bytes / 4; j++) {
309 int32_t frame[2];
310 int32_t *data = (int32_t *)src;
311 frame[0] = data[j];
312 frame[1] = data[j];
313 size_t result_call = 0;
314 if (i2s_write(i2s_num, frame, sizeof(int32_t) * 2, &result_call,
316 TRACEE();
317 } else {
318 result += result_call;
319 }
320 }
321 break;
322 }
323 return size_bytes;
324 }
325
326#pragma GCC diagnostic push
327#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
328
329 // determines the i2s_comm_format_t - by default we use
330 // I2S_COMM_FORMAT_STAND_I2S
352#pragma GCC diagnostic pop
353
355 int i2s_format = cfg.is_master ? I2S_MODE_MASTER : I2S_MODE_SLAVE;
356 int i2s_rx_tx = 0;
357 switch (cfg.rx_tx_mode) {
358 case TX_MODE:
360 break;
361 case RX_MODE:
363 break;
364 case RXTX_MODE:
366 break;
367 default:
368 LOGE("Undefined rx_tx_mode: %d", cfg.rx_tx_mode);
369 }
370 return (i2s_format | i2s_rx_tx);
371 }
372
373 // determines the i2s_format_t
376 switch (cfg.signal_type) {
377 case Digital:
379 break;
380
381 case PDM:
383 break;
384
385 case Analog:
386#if defined(USE_ANALOG)
389#else
390 LOGE("mode not supported");
391#endif
392 break;
393
394 default:
395 LOGW("signal_type undefined");
397 break;
398 }
399 return mode;
400 }
401};
402
404
405} // namespace audio_tools
406
407#endif
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define TRACEE()
Definition AudioLoggerIDF.h:34
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define I2S_BUFFER_SIZE
Definition AudioToolsConfig.h:112
#define I2S_BUFFER_COUNT
Definition AudioToolsConfig.h:116
#define I2S_MCLK_MULTIPLE_DEFAULT
Definition I2SDriverESP32.h:14
#define portMAX_DELAY
Definition QueueZephyr.h:14
#define pdMS_TO_TICKS(ms)
Definition QueueZephyr.h:17
uint32_t TickType_t
Definition QueueZephyr.h:11
AudioKit Stream which uses the https://github.com/pschatzmann/arduino-audiokit library.
Definition AudioKit.h:189
We combine a datastream which consists of multiple channels into less channels. E....
Definition BaseConverter.h:434
Configuration for ESP32 legacy i2s.
Definition I2SConfigESP32.h:24
int buffer_count
Definition I2SConfigESP32.h:70
int pin_mck
Definition I2SConfigESP32.h:69
RxTxMode rx_tx_mode
public settings
Definition I2SConfigESP32.h:60
int pin_ws
Definition I2SConfigESP32.h:65
bool auto_clear
Definition I2SConfigESP32.h:72
I2SSignalType signal_type
Definition I2SConfigESP32.h:62
int pin_data
Definition I2SConfigESP32.h:67
int pin_data_rx
Definition I2SConfigESP32.h:68
bool use_apll
Definition I2SConfigESP32.h:73
bool is_master
Definition I2SConfigESP32.h:63
int pin_bck
Definition I2SConfigESP32.h:66
int channel_format
Definition I2SConfigESP32.h:75
I2SFormat i2s_format
Definition I2SConfigESP32.h:61
uint32_t fixed_mclk
Definition I2SConfigESP32.h:74
void logInfo(const char *source="")
Definition I2SConfigESP32.h:77
int port_no
Definition I2SConfigESP32.h:64
int buffer_size
Definition I2SConfigESP32.h:71
Definition I2SDriverBase.h:7
Basic I2S API - for the ESP32. If we receive 1 channel, we expand the result to 2 channels.
Definition I2SDriverESP32.h:28
friend class AnalogAudio
Definition I2SDriverESP32.h:29
bool isNoChannelConversion(I2SConfigESP32 cfg)
Definition I2SDriverESP32.h:168
i2s_port_t i2s_num
Definition I2SDriverESP32.h:162
void setWaitTimeWriteMs(TickType_t ms)
Definition I2SDriverESP32.h:156
bool begin(I2SConfigESP32 cfg)
starts the DAC
Definition I2SDriverESP32.h:63
I2SConfigESP32 cfg
Definition I2SDriverESP32.h:161
TickType_t ticks_to_wait_read
Definition I2SDriverESP32.h:165
void setWaitTimeReadMs(TickType_t ms)
Definition I2SDriverESP32.h:153
int available()
we assume the data is already available in the buffer
Definition I2SDriverESP32.h:82
bool is_started
Definition I2SDriverESP32.h:164
bool begin()
Definition I2SDriverESP32.h:60
bool setAudioInfo(AudioInfo info)
Potentially updates the sample rate (if supported)
Definition I2SDriverESP32.h:40
size_t writeExpandChannel(i2s_port_t i2s_num, const int bits_per_sample, const void *src, size_t size_bytes)
writes the data by making sure that we send 2 channels
Definition I2SDriverESP32.h:254
int availableForWrite()
We limit the write size to the buffer size.
Definition I2SDriverESP32.h:85
I2SConfigESP32 config()
provides the actual configuration
Definition I2SDriverESP32.h:95
i2s_config_t i2s_config
Definition I2SDriverESP32.h:163
i2s_comm_format_t toCommFormat(I2SFormat mode)
Definition I2SDriverESP32.h:331
void end()
stops the I2C and unistalls the driver
Definition I2SDriverESP32.h:88
void setChannels(int channels)
Definition I2SDriverESP32.h:251
bool begin(RxTxMode mode)
starts the DAC with the default config
Definition I2SDriverESP32.h:56
I2SConfigESP32 defaultConfig(RxTxMode mode)
Provides the default configuration.
Definition I2SDriverESP32.h:34
i2s_mode_t toMode(I2SConfigESP32 &cfg)
Definition I2SDriverESP32.h:374
TickType_t ticks_to_wait_write
Definition I2SDriverESP32.h:166
int getModeDigital(I2SConfigESP32 &cfg)
Definition I2SDriverESP32.h:354
size_t writeBytes(const void *src, size_t size_bytes)
writes the data to the I2S interface
Definition I2SDriverESP32.h:98
size_t readBytes(void *dest, size_t size_bytes)
Definition I2SDriverESP32.h:115
bool begin(I2SConfigESP32 cfg, int txPin, int rxPin)
starts the DAC
Definition I2SDriverESP32.h:182
24bit integer which is used for I2S sound processing. The values are represented as int32_t,...
Definition Int24_4bytes_t.h:22
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:26
@ RXTX_MODE
Definition AudioTypes.h:26
@ TX_MODE
Definition AudioTypes.h:26
@ RX_MODE
Definition AudioTypes.h:26
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
@ Digital
Definition AudioTypes.h:438
@ PDM
Definition AudioTypes.h:440
@ Analog
Definition AudioTypes.h:439
I2SFormat
I2S Formats.
Definition AudioTypes.h:416
@ I2S_STD_FORMAT
Definition AudioTypes.h:417
@ I2S_PHILIPS_FORMAT
Definition AudioTypes.h:420
@ I2S_LSB_FORMAT
Definition AudioTypes.h:418
@ I2S_LEFT_JUSTIFIED_FORMAT
Definition AudioTypes.h:422
@ I2S_RIGHT_JUSTIFIED_FORMAT
Definition AudioTypes.h:421
@ I2S_MSB_FORMAT
Definition AudioTypes.h:419
@ I2S_PCM
Definition AudioTypes.h:423
int i2s_port_t
Definition I2SDriverESP32V1.h:19
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:508
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:51
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:53
bool equals(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:83
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:55
bool equalsExSampleRate(AudioInfo alt)
Checks if only the sample rate is different.
Definition AudioTypes.h:86
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:57