4 #include "AudioTools/CoreAudio/AudioI2S/I2SConfig.h"
8 #define IS_I2S_IMPLEMENTED
24 class I2SDriverSTM32 {
25 friend class I2SStream;
29 I2SConfigStd defaultConfig(
RxTxMode mode = TX_MODE) {
35 bool setAudioInfo(AudioInfo) {
return false;}
38 bool begin(
RxTxMode mode = TX_MODE) {
40 return begin(defaultConfig(mode));
44 bool begin(I2SConfigStd cfg) {
49 LOGI(
"buffer_size: %d", cfg.buffer_size);
50 LOGI(
"buffer_count: %d", cfg.buffer_count);
52 if (cfg.channels > 2 || cfg.channels <= 0) {
53 LOGE(
"Channels not supported: %d", cfg.channels);
57 setupDefaultI2SParameters();
59 result = use_dma ? startI2SDMA() : startI2S();
60 this->active = result;
74 if (!active)
return 0;
75 if (use_dma && p_rx_buffer ==
nullptr)
return 0;
76 return cfg.buffer_size;
80 int availableForWrite() {
81 if (!active)
return 0;
82 if (use_dma && p_tx_buffer ==
nullptr)
return 0;
83 return cfg.buffer_size;
87 I2SConfigStd config() {
return cfg; }
90 size_t writeBytes(
const void *src,
size_t size_bytes) {
94 result = i2s.write((uint8_t *)src, size_bytes);
97 if (p_dma_in !=
nullptr) {
104 result = writeBytesDMA(src, size_bytes);
110 size_t readBytes(
void *dest,
size_t size_bytes) {
113 return i2s.readBytes((uint8_t *)dest, size_bytes);
115 if (cfg.channels == 2) {
116 return p_rx_buffer->readArray((uint8_t *)dest, size_bytes);
118 return readBytesDMA(dest, size_bytes);
125 static void writeFromReceive(uint8_t *buffer, uint16_t byteCount,
void *ref) {
126 I2SDriverSTM32 *
self = (I2SDriverSTM32 *)ref;
127 uint16_t written = 0;
128 if (self->p_dma_out !=
nullptr)
129 written =
self->p_dma_out->write(buffer, byteCount);
131 written =
self->p_rx_buffer->writeArray(buffer, byteCount);
134 if (written != byteCount) {
135 LOGW(
"Buffer overflow: written %d of %d", written, byteCount);
141 static void readToTransmit(uint8_t *buffer, uint16_t byteCount,
void *ref) {
142 I2SDriverSTM32 *
self = (I2SDriverSTM32 *)ref;
143 static size_t count = 0;
145 if (self->p_dma_in !=
nullptr) {
147 if (self->isWriteTimedOut()) {
152 read =
self->p_dma_in->readBytes(buffer, byteCount);
156 if (self->stm32_write_active) {
157 read =
self->p_tx_buffer->readArray(buffer, byteCount);
160 memset(buffer+read, 0, byteCount-read);
164 if (read != byteCount) {
165 LOGW(
"Buffer underflow at %lu: %d for %d", count, read, byteCount);
170 bool isWriteTimedOut() {
171 return last_write_ms != 0 && last_write_ms + 500 <
millis();
175 void setDMAActive(
bool flag) { use_dma = flag; }
178 void setDMAInputStream(Stream &in) {
184 void setDMAOutput(Print &out) {
190 stm32_i2s::Stm32I2sClass i2s;
191 stm32_i2s::I2SSettingsSTM32 i2s_stm32;
195 BaseBuffer<uint8_t> *p_tx_buffer =
nullptr;
196 BaseBuffer<uint8_t> *p_rx_buffer =
nullptr;
197 volatile bool stm32_write_active =
false;
199 Print *p_dma_out =
nullptr;
200 Stream *p_dma_in =
nullptr;
201 uint32_t last_write_ms = 0;
203 size_t writeBytesDMA(
const void *src,
size_t size_bytes) {
206 int open = size_bytes;
208 int actual_written = writeBytesExt(src, size_bytes);
209 result += actual_written;
210 open -= actual_written;
212 stm32_write_active =
true;
218 if (!stm32_write_active && p_tx_buffer->availableForWrite() == 0) {
219 stm32_write_active =
true;
220 LOGI(
"Buffer is full->starting i2s output");
226 size_t readBytesDMA(
void *dest,
size_t size_bytes) {
228 int req_bytes = size_bytes * 2;
229 uint8_t tmp[req_bytes];
230 int16_t *tmp_16 = (int16_t *)tmp;
231 int eff_bytes = p_rx_buffer->readArray((uint8_t *)tmp, req_bytes);
233 int16_t *dest_16 = (int16_t *)dest;
234 int16_t eff_samples = eff_bytes / 2;
236 for (
int j = 0; j < eff_samples; j += 2) {
237 dest_16[idx++] =
static_cast<float>(tmp_16[j]) + tmp_16[j + 1] / 2.0;
239 return eff_bytes / 2;
243 switch (cfg.rx_tx_mode) {
245 result = i2s.begin(i2s_stm32,
false,
true);
248 result = i2s.begin(i2s_stm32,
true,
false);
252 result = i2s.begin(i2s_stm32,
true,
true);
259 switch (cfg.rx_tx_mode) {
261 if (use_dma && p_rx_buffer ==
nullptr)
262 p_rx_buffer = allocateBuffer();
263 result = i2s.beginReadDMA(i2s_stm32, writeFromReceive);
266 stm32_write_active =
false;
267 if (use_dma && p_tx_buffer ==
nullptr)
268 p_tx_buffer = allocateBuffer();
269 result = i2s.beginWriteDMA(i2s_stm32, readToTransmit);
274 stm32_write_active =
false;
275 if (p_rx_buffer ==
nullptr)
276 p_rx_buffer = allocateBuffer();
277 if (p_tx_buffer ==
nullptr)
278 p_tx_buffer = allocateBuffer();
280 result = i2s.beginReadWriteDMA(
281 i2s_stm32, readToTransmit, writeFromReceive);
285 LOGE(
"Unsupported mode");
291 uint32_t toDataFormat(
int bits_per_sample) {
292 switch (bits_per_sample) {
294 return I2S_DATAFORMAT_16B;
296 return I2S_DATAFORMAT_24B;
298 return I2S_DATAFORMAT_32B;
300 return I2S_DATAFORMAT_16B;
303 void deleteBuffers() {
304 if (p_rx_buffer !=
nullptr) {
306 p_rx_buffer =
nullptr;
308 if (p_tx_buffer !=
nullptr) {
310 p_tx_buffer =
nullptr;
314 void setupDefaultI2SParameters() {
315 i2s_stm32.sample_rate = getSampleRate(cfg);
316 i2s_stm32.data_format = toDataFormat(cfg.bits_per_sample);
317 i2s_stm32.mode = getMode(cfg);
318 i2s_stm32.standard = getStandard(cfg);
319 i2s_stm32.fullduplexmode = cfg.rx_tx_mode == RXTX_MODE
320 ? I2S_FULLDUPLEXMODE_ENABLE
321 : I2S_FULLDUPLEXMODE_DISABLE;
322 i2s_stm32.hardware_config.buffer_size = cfg.buffer_size;
324 i2s_stm32.ref =
this;
328 if (cfg.pin_bck == -1 || cfg.pin_ws == -1 || cfg.pin_data == -1) {
329 LOGW(
"pins ignored: used from stm32-i2s");
331 LOGI(
"setting up pins for stm32-i2s");
332 i2s_stm32.hardware_config.pins[0].function = stm32_i2s::mclk;
333 i2s_stm32.hardware_config.pins[0].pin = digitalPinToPinName(cfg.pin_mck);
334 i2s_stm32.hardware_config.pins[0].altFunction = cfg.pin_alt_function;
336 i2s_stm32.hardware_config.pins[1].function = stm32_i2s::bck;
337 i2s_stm32.hardware_config.pins[1].pin = digitalPinToPinName(cfg.pin_bck);
338 i2s_stm32.hardware_config.pins[1].altFunction = cfg.pin_alt_function;
340 i2s_stm32.hardware_config.pins[2].function = stm32_i2s::ws;
341 i2s_stm32.hardware_config.pins[2].pin = digitalPinToPinName(cfg.pin_ws);
342 i2s_stm32.hardware_config.pins[2].altFunction = cfg.pin_alt_function;
344 switch (cfg.rx_tx_mode) {
346 i2s_stm32.hardware_config.pins[3].function = stm32_i2s::data_out;
347 i2s_stm32.hardware_config.pins[3].pin = digitalPinToPinName(cfg.pin_data);
348 i2s_stm32.hardware_config.pins[3].altFunction = cfg.pin_alt_function;
351 i2s_stm32.hardware_config.pins[4].function = stm32_i2s::data_in;
352 i2s_stm32.hardware_config.pins[4].pin = digitalPinToPinName(cfg.pin_data);
353 i2s_stm32.hardware_config.pins[4].altFunction = cfg.pin_alt_function;
356 i2s_stm32.hardware_config.pins[3].function = stm32_i2s::data_out;
357 i2s_stm32.hardware_config.pins[3].pin = digitalPinToPinName(cfg.pin_data);
358 i2s_stm32.hardware_config.pins[3].altFunction = cfg.pin_alt_function;
360 i2s_stm32.hardware_config.pins[4].function = stm32_i2s::data_in;
361 i2s_stm32.hardware_config.pins[4].pin = digitalPinToPinName(cfg.pin_data);
362 i2s_stm32.hardware_config.pins[4].altFunction = cfg.pin_alt_function;
369 uint32_t getMode(I2SConfigStd &cfg) {
371 switch (cfg.rx_tx_mode) {
373 return I2S_MODE_MASTER_RX;
375 return I2S_MODE_MASTER_TX;
377 LOGE(
"RXTX_MODE not supported");
378 return I2S_MODE_MASTER_TX;
381 switch (cfg.rx_tx_mode) {
383 return I2S_MODE_SLAVE_RX;
385 return I2S_MODE_SLAVE_TX;
387 LOGE(
"RXTX_MODE not supported");
388 return I2S_MODE_SLAVE_TX;
393 uint32_t getStandard(I2SConfigStd &cfg) {
395 switch (cfg.i2s_format) {
396 case I2S_PHILIPS_FORMAT:
397 return I2S_STANDARD_PHILIPS;
400 case I2S_RIGHT_JUSTIFIED_FORMAT:
401 return I2S_STANDARD_MSB;
403 case I2S_LEFT_JUSTIFIED_FORMAT:
404 return I2S_STANDARD_LSB;
406 return I2S_STANDARD_PHILIPS;
409 uint32_t getSampleRate(I2SConfigStd &cfg) {
410 switch (cfg.sample_rate) {
411 case I2S_AUDIOFREQ_192K:
412 case I2S_AUDIOFREQ_96K:
413 case I2S_AUDIOFREQ_48K:
414 case I2S_AUDIOFREQ_44K:
415 case I2S_AUDIOFREQ_32K:
416 case I2S_AUDIOFREQ_22K:
417 case I2S_AUDIOFREQ_16K:
418 case I2S_AUDIOFREQ_11K:
419 case I2S_AUDIOFREQ_8K:
420 return cfg.sample_rate;
422 LOGE(
"Unsupported sample rate: %u", cfg.sample_rate);
423 return cfg.sample_rate;
427 size_t writeBytesExt(
const void *src,
size_t size_bytes) {
429 if (cfg.channels == 2) {
430 result = p_tx_buffer->writeArray((uint8_t *)src, size_bytes);
433 int samples = size_bytes / 2;
434 int16_t *src_16 = (int16_t *)src;
437 for (
int j = 0; j < samples; j++) {
440 if (p_tx_buffer->availableForWrite() >= 4) {
441 p_tx_buffer->writeArray((uint8_t *)tmp, 4);
449 LOGD(
"writeBytesExt: %u", result)
453 BaseBuffer<uint8_t>* allocateBuffer() {
455 return new NBuffer<uint8_t>(cfg.buffer_size, cfg.buffer_count);
459 using I2SDriver = I2SDriverSTM32;
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition: AudioTypes.h:28