arduino-audio-tools
Loading...
Searching...
No Matches
I2SESP32.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
7#include "driver/i2s.h"
8#include "esp_system.h"
9
10#ifndef I2S_MCLK_MULTIPLE_DEFAULT
11# define I2S_MCLK_MULTIPLE_DEFAULT ((i2s_mclk_multiple_t)0)
12#endif
13
14#define IS_I2S_IMPLEMENTED
15
16namespace audio_tools {
17
26 friend class AnalogAudio;
27 friend class AudioKitStream;
28
29 public:
32 I2SConfigESP32 c(mode);
33 return c;
34 }
35
38 // nothing to do
39 if (is_started) {
40 if (info.equals(cfg)) return true;
41 if (info.equalsExSampleRate(cfg)) {
43 LOGI("i2s_set_sample_rates: %d", info.sample_rate);
45 }
46 } else {
47 LOGE("not started");
48 }
49 return false;
50 }
51
53 bool begin(RxTxMode mode) { return begin(defaultConfig(mode)); }
54
57 bool begin() { return !is_started ? begin(cfg) : true; }
58
61 TRACED();
62 this->cfg = cfg;
63 switch (cfg.rx_tx_mode) {
64 case TX_MODE:
66 case RX_MODE:
67 // usually we expet cfg.pin_data but if the used assinged rx we might
68 // consider this one
69 return begin(
72 default:
74 }
75 LOGE("Did not expect go get here");
76 }
77
80
83
85 void end() {
86 TRACED();
88 is_started = false;
89 }
90
93
95 size_t writeBytes(const void *src, size_t size_bytes) {
96 TRACED();
97
98 size_t result = 0;
100 if (i2s_write(i2s_num, src, size_bytes, &result, ticks_to_wait_write) !=
101 ESP_OK) {
102 TRACEE();
103 }
104 LOGD("i2s_write %d -> %d bytes", size_bytes, result);
105 } else {
106 result =
108 }
109 return result;
110 }
111
112 size_t readBytes(void *dest, size_t size_bytes) {
113 size_t result = 0;
115 if (i2s_read(i2s_num, dest, size_bytes, &result, ticks_to_wait_read) !=
116 ESP_OK) {
117 TRACEE();
118 }
119 } else if (cfg.channels == 1) {
120 // I2S has always 2 channels. We support to reduce it to 1
121 uint8_t temp[size_bytes * 2];
122 if (i2s_read(i2s_num, temp, size_bytes * 2, &result,
124 TRACEE();
125 }
126 // convert to 1 channel
127 switch (cfg.bits_per_sample) {
128 case 16: {
130 result = reducer16.convert((uint8_t *)dest, temp, result);
131 } break;
132 case 24: {
134 result = reducer24.convert((uint8_t *)dest, temp, result);
135 } break;
136 case 32: {
138 result = reducer32.convert((uint8_t *)dest, temp, result);
139 } break;
140 default:
141 LOGE("invalid bits_per_sample: %d", cfg.bits_per_sample);
142 break;
143 }
144 } else {
145 LOGE("Invalid channels: %d", cfg.channels);
146 }
147 return result;
148 }
149
156
157 protected:
161 bool is_started = false;
164
166 if (cfg.channels == 2) return true;
168 return true;
170 return true;
172 return true;
174 return true;
175 return false;
176 }
177
180 TRACED();
181 cfg.logInfo();
182 this->cfg = cfg;
183 this->i2s_num = (i2s_port_t)cfg.port_no;
185
187 .mode = toMode(cfg),
189 .bits_per_sample = (i2s_bits_per_sample_t)cfg.bits_per_sample,
190 .channel_format = (i2s_channel_fmt_t)cfg.channel_format,
191 .communication_format = toCommFormat(cfg.i2s_format),
192 .intr_alloc_flags = 0, // default interrupt priority
193 .dma_buf_count = cfg.buffer_count,
194 .dma_buf_len = cfg.buffer_size,
195 .use_apll = (bool)cfg.use_apll,
196 .tx_desc_auto_clear = cfg.auto_clear,
198 .fixed_mclk = (int)(cfg.fixed_mclk > 0 ? cfg.fixed_mclk : 0),
199 .mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT,
201#endif
202 };
204
205 // We make sure that we can reconfigure
206 if (is_started) {
207 end();
208 LOGD("%s", "I2S restarting");
209 }
210
211 // setup config
212 LOGD("i2s_driver_install");
214 LOGE("%s - %s", __func__, "i2s_driver_install");
215 }
216
217 // setup pin config
218 if (this->cfg.signal_type == Digital || this->cfg.signal_type == PDM) {
220#if ESP_IDF_VERSION > ESP_IDF_VERSION_VAL(4, 4, 0)
221 .mck_io_num = cfg.pin_mck,
222#endif
223 .bck_io_num = cfg.pin_bck,
224 .ws_io_num = cfg.pin_ws,
225 .data_out_num = txPin,
226 .data_in_num = rxPin};
227
228 LOGD("i2s_set_pin");
230 LOGE("%s - %s", __func__, "i2s_set_pin");
231 }
232 } else {
233 LOGD("Using built in DAC");
234 // for internal DAC, this will enable both of the internal channels
236 }
237
238 // clear initial buffer
239 LOGD("i2s_zero_dma_buffer");
241
242 is_started = true;
243 LOGD("%s - %s", __func__, "started");
244 return true;
245 }
246
247 // update the cfg.i2s.channel_format based on the number of channels
248 void setChannels(int channels) { cfg.channels = channels; }
249
251 size_t writeExpandChannel(i2s_port_t i2s_num, const int bits_per_sample,
252 const void *src, size_t size_bytes) {
253 size_t result = 0;
254 int j;
255 switch (bits_per_sample) {
256 case 8:
257 for (j = 0; j < size_bytes; j++) {
258 int8_t frame[2];
259 int8_t *data = (int8_t *)src;
260 frame[0] = data[j];
261 frame[1] = data[j];
262 size_t result_call = 0;
263 if (i2s_write(i2s_num, frame, sizeof(int8_t) * 2, &result_call,
265 TRACEE();
266 } else {
267 result += result_call;
268 }
269 }
270 break;
271
272 case 16:
273 for (j = 0; j < size_bytes / 2; j++) {
274 int16_t frame[2];
275 int16_t *data = (int16_t *)src;
276 frame[0] = data[j];
277 frame[1] = data[j];
278 size_t result_call = 0;
279 if (i2s_write(i2s_num, frame, sizeof(int16_t) * 2, &result_call,
281 TRACEE();
282 } else {
283 result += result_call;
284 }
285 }
286 break;
287
288 case 24:
289 for (j = 0; j < size_bytes / 4; j++) {
290 int24_t frame[2];
291 int24_t *data = (int24_t *)src;
292 frame[0] = data[j];
293 frame[1] = data[j];
294 size_t result_call = 0;
295 if (i2s_write(i2s_num, frame, sizeof(int24_t) * 2, &result_call,
297 TRACEE();
298 } else {
299 result += result_call;
300 }
301 }
302 break;
303
304 case 32:
305 for (j = 0; j < size_bytes / 4; j++) {
306 int32_t frame[2];
307 int32_t *data = (int32_t *)src;
308 frame[0] = data[j];
309 frame[1] = data[j];
310 size_t result_call = 0;
311 if (i2s_write(i2s_num, frame, sizeof(int32_t) * 2, &result_call,
313 TRACEE();
314 } else {
315 result += result_call;
316 }
317 }
318 break;
319 }
320 return size_bytes;
321 }
322
323#pragma GCC diagnostic push
324#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
325
326 // determines the i2s_comm_format_t - by default we use
327 // I2S_COMM_FORMAT_STAND_I2S
349#pragma GCC diagnostic pop
350
352 int i2s_format = cfg.is_master ? I2S_MODE_MASTER : I2S_MODE_SLAVE;
353 int i2s_rx_tx = 0;
354 switch (cfg.rx_tx_mode) {
355 case TX_MODE:
357 break;
358 case RX_MODE:
360 break;
361 case RXTX_MODE:
363 break;
364 default:
365 LOGE("Undefined rx_tx_mode: %d", cfg.rx_tx_mode);
366 }
367 return (i2s_format | i2s_rx_tx);
368 }
369
370 // determines the i2s_format_t
373 switch (cfg.signal_type) {
374 case Digital:
376 break;
377
378 case PDM:
380 break;
381
382 case Analog:
383#if defined(USE_ANALOG)
386#else
387 LOGE("mode not supported");
388#endif
389 break;
390
391 default:
392 LOGW("signal_type undefined");
394 break;
395 }
396 return mode;
397 }
398};
399
401
402} // namespace audio_tools
403
404#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:102
#define I2S_BUFFER_COUNT
Definition AudioToolsConfig.h:106
#define I2S_MCLK_MULTIPLE_DEFAULT
Definition I2SESP32.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:433
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
Basic I2S API - for the ESP32. If we receive 1 channel, we expand the result to 2 channels.
Definition I2SESP32.h:25
friend class AnalogAudio
Definition I2SESP32.h:26
bool isNoChannelConversion(I2SConfigESP32 cfg)
Definition I2SESP32.h:165
i2s_port_t i2s_num
Definition I2SESP32.h:159
void setWaitTimeWriteMs(TickType_t ms)
Definition I2SESP32.h:153
bool begin(I2SConfigESP32 cfg)
starts the DAC
Definition I2SESP32.h:60
I2SConfigESP32 cfg
Definition I2SESP32.h:158
TickType_t ticks_to_wait_read
Definition I2SESP32.h:162
void setWaitTimeReadMs(TickType_t ms)
Definition I2SESP32.h:150
int available()
we assume the data is already available in the buffer
Definition I2SESP32.h:79
bool is_started
Definition I2SESP32.h:161
bool begin()
Definition I2SESP32.h:57
bool setAudioInfo(AudioInfo info)
Potentially updates the sample rate (if supported)
Definition I2SESP32.h:37
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 I2SESP32.h:251
int availableForWrite()
We limit the write size to the buffer size.
Definition I2SESP32.h:82
I2SConfigESP32 config()
provides the actual configuration
Definition I2SESP32.h:92
i2s_config_t i2s_config
Definition I2SESP32.h:160
i2s_comm_format_t toCommFormat(I2SFormat mode)
Definition I2SESP32.h:328
void end()
stops the I2C and unistalls the driver
Definition I2SESP32.h:85
void setChannels(int channels)
Definition I2SESP32.h:248
bool begin(RxTxMode mode)
starts the DAC with the default config
Definition I2SESP32.h:53
I2SConfigESP32 defaultConfig(RxTxMode mode)
Provides the default configuration.
Definition I2SESP32.h:31
i2s_mode_t toMode(I2SConfigESP32 &cfg)
Definition I2SESP32.h:371
TickType_t ticks_to_wait_write
Definition I2SESP32.h:163
int getModeDigital(I2SConfigESP32 &cfg)
Definition I2SESP32.h:351
size_t writeBytes(const void *src, size_t size_bytes)
writes the data to the I2S interface
Definition I2SESP32.h:95
size_t readBytes(void *dest, size_t size_bytes)
Definition I2SESP32.h:112
bool begin(I2SConfigESP32 cfg, int txPin, int rxPin)
starts the DAC
Definition I2SESP32.h:179
24bit integer which is used for I2S sound processing. The values are represented as int32_t,...
Definition Int24_4bytes_t.h:16
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:30
@ RXTX_MODE
Definition AudioTypes.h:30
@ TX_MODE
Definition AudioTypes.h:30
@ RX_MODE
Definition AudioTypes.h:30
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
@ Digital
Definition AudioTypes.h:442
@ PDM
Definition AudioTypes.h:444
@ Analog
Definition AudioTypes.h:443
I2SFormat
I2S Formats.
Definition AudioTypes.h:420
@ I2S_STD_FORMAT
Definition AudioTypes.h:421
@ I2S_PHILIPS_FORMAT
Definition AudioTypes.h:424
@ I2S_LSB_FORMAT
Definition AudioTypes.h:422
@ I2S_LEFT_JUSTIFIED_FORMAT
Definition AudioTypes.h:426
@ I2S_RIGHT_JUSTIFIED_FORMAT
Definition AudioTypes.h:425
@ I2S_MSB_FORMAT
Definition AudioTypes.h:423
@ I2S_PCM
Definition AudioTypes.h:427
size_t writeData(Print *p_out, T *data, int samples, int maxSamples=512)
Definition AudioTypes.h:512
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
bool equals(AudioInfo alt)
Returns true if alt values are the same like the current values.
Definition AudioTypes.h:87
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
bool equalsExSampleRate(AudioInfo alt)
Checks if only the sample rate is different.
Definition AudioTypes.h:90
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:61