21 #include "PinConfigured.h"
22 #include "stm32-config-i2s.h"
23 #include "stm32f4xx_hal.h"
25 extern uint32_t g_anOutputPinConfigured[MAX_NB_PORT];
31 extern "C" void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s);
32 extern "C" void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s);
33 extern "C" void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s);
34 extern "C" void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s);
35 extern "C" void DMA1_Stream0_IRQHandler(
void);
36 extern "C" void DMA1_Stream5_IRQHandler(
void);
37 extern "C" void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s);
38 extern "C" void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s);
39 extern "C" void Report_Error();
40 extern "C" void STM32_LOG(
const char *fmt, ...);
41 extern bool stm32_i2s_is_error;
66 pin_function(pin, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, altFunction));
74 #if (defined(HAL_DAC_MODULE_ENABLED) && !defined(HAL_DAC_MODULE_ONLY)) || \
75 (defined(HAL_TIM_MODULE_ENABLED) && !defined(HAL_TIM_MODULE_ONLY))
76 if (is_pin_configured(p, g_anOutputPinConfigured)) {
77 #if defined(HAL_DAC_MODULE_ENABLED) && !defined(HAL_DAC_MODULE_ONLY)
78 if (pin_in_pinmap(p, PinMap_DAC)) {
82 #if defined(HAL_TIM_MODULE_ENABLED) && !defined(HAL_TIM_MODULE_ONLY)
83 if (pin_in_pinmap(p, PinMap_TIM)) {
87 { reset_pin_configured(p, g_anOutputPinConfigured); }
100 IRQn_Type irq1 = DMA1_Stream0_IRQn;
101 IRQn_Type irq2 = DMA1_Stream5_IRQn;
104 uint32_t pllm = PLLM;
106 uint32_t plln = PLLN;
107 uint32_t pllr = PLLR;
109 DMA_Stream_TypeDef *rx_instance = DMA1_Stream0;
110 uint32_t rx_channel = DMA_CHANNEL_3;
111 uint32_t rx_direction = DMA_PERIPH_TO_MEMORY;
113 DMA_Stream_TypeDef *tx_instance = DMA1_Stream5;
114 uint32_t tx_channel = DMA_CHANNEL_0;
115 uint32_t tx_direction = DMA_MEMORY_TO_PERIPH;
117 I2SPin pins[5] = STM_I2S_PINS;
119 int buffer_size = 512;
132 uint32_t mode = I2S_MODE_MASTER_TX;
133 uint32_t standard = I2S_STANDARD_PHILIPS;
134 uint32_t fullduplexmode = I2S_FULLDUPLEXMODE_ENABLE;
135 uint32_t sample_rate = I2S_AUDIOFREQ_44K;
136 uint32_t data_format = I2S_DATAFORMAT_16B;
148 friend void DMA1_Stream0_IRQHandler(
void);
149 friend void DMA1_Stream5_IRQHandler(
void);
150 friend void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s);
151 friend void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s);
152 friend void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s);
153 friend void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s);
154 friend void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s);
155 friend void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s);
160 this->use_dma =
false;
161 this->settings = settings;
162 this->hw = settings.hardware_config;
163 int buffer_size = hw.buffer_size;
170 if (!transmit && !receive) {
175 if (transmit && !receive) {
176 if (HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dma_buffer_tx,
177 buffer_size) != HAL_OK) {
178 STM32_LOG(
"error HAL_I2S_Transmit_DMA");
184 if (receive && !transmit) {
185 if (HAL_I2S_Receive_DMA(&hi2s3, (uint16_t *)dma_buffer_rx,
186 buffer_size) != HAL_OK) {
187 STM32_LOG(
"error: HAL_I2S_Receive_DMA");
193 if (receive && transmit) {
194 if (HAL_I2SEx_TransmitReceive_DMA(&hi2s3, (uint16_t *)dma_buffer_tx,
195 (uint16_t *)dma_buffer_rx,
196 buffer_size) != HAL_OK) {
197 STM32_LOG(
"error HAL_I2SEx_TransmitReceive_DMA");
209 void (*readToTransmit)(uint8_t *buffer, uint16_t byteCount,
210 void *ref) =
nullptr) {
211 this->use_dma =
true;
212 this->settings = settings;
213 this->hw = settings.hardware_config;
214 int buffer_size = hw.buffer_size;
215 readToTransmitCB = readToTransmit;
216 if (dma_buffer_tx ==
nullptr) dma_buffer_tx =
new byte[buffer_size];
222 if (HAL_I2S_Transmit_DMA(&hi2s3, (uint16_t *)dma_buffer_tx, buffer_size) !=
224 STM32_LOG(
"error HAL_I2S_Transmit_DMA");
233 void (*writeFromReceive)(uint8_t *buffer,
235 void *ref) =
nullptr) {
236 this->use_dma =
true;
237 this->settings = settings;
238 this->hw = settings.hardware_config;
239 int buffer_size = hw.buffer_size;
241 writeFromReceiveCB = writeFromReceive;
242 if (dma_buffer_rx ==
nullptr) dma_buffer_rx =
new byte[buffer_size];
247 if (HAL_I2S_Receive_DMA(&hi2s3, (uint16_t *)dma_buffer_rx, buffer_size) !=
249 STM32_LOG(
"error: HAL_I2S_Transmit_DMA");
258 void (*readToTransmit)(uint8_t *buffer,
261 void (*writeFromReceive)(uint8_t *buffer,
264 this->use_dma =
true;
265 this->settings = settings;
266 this->hw = settings.hardware_config;
267 int buffer_size = hw.buffer_size;
269 readToTransmitCB = readToTransmit;
270 writeFromReceiveCB = writeFromReceive;
272 if (dma_buffer_tx ==
nullptr) dma_buffer_tx =
new byte[buffer_size];
274 if (dma_buffer_rx ==
nullptr) dma_buffer_rx =
new byte[buffer_size];
279 if (HAL_I2SEx_TransmitReceive_DMA(&hi2s3, (uint16_t *)dma_buffer_tx,
280 (uint16_t *)dma_buffer_rx,
281 buffer_size) != HAL_OK) {
282 STM32_LOG(
"error HAL_I2SEx_TransmitReceive_DMA");
290 if (use_dma) HAL_I2S_DMAStop(&hi2s3);
291 HAL_I2S_DeInit(&hi2s3);
292 HAL_I2S_MspDeInit(&hi2s3);
293 if (dma_buffer_tx != NULL) {
294 delete[] (dma_buffer_tx);
296 if (dma_buffer_rx != NULL) {
297 delete[] (dma_buffer_rx);
305 size_t write(
const uint8_t *data,
size_t bytes) {
306 HAL_StatusTypeDef rc = HAL_OK;
307 if (!this->use_dma) {
308 int samples = bytes / getBytes();
309 HAL_StatusTypeDef rc =
310 HAL_I2S_Transmit(&hi2s3, (uint16_t *)data, samples, HAL_MAX_DELAY);
312 return rc == HAL_OK ? bytes : 0;
320 HAL_StatusTypeDef rc = HAL_OK;
321 if (!this->use_dma) {
322 int samples = bytes / getBytes();
323 HAL_StatusTypeDef rc =
324 HAL_I2S_Receive(&hi2s3, (uint16_t *)data, samples, HAL_MAX_DELAY);
326 return rc == HAL_OK ? bytes : 0;
331 I2S_HandleTypeDef hi2s3;
332 byte *dma_buffer_tx =
nullptr;
333 byte *dma_buffer_rx =
nullptr;
334 void (*readToTransmitCB)(uint8_t *buffer, uint16_t byteCount,
void *ref);
335 void (*writeFromReceiveCB)(uint8_t *buffer, uint16_t byteCount,
void *ref);
336 DMA_HandleTypeDef hdma_i2s3_ext_rx;
337 DMA_HandleTypeDef hdma_i2s3_ext_tx;
339 bool use_dma =
false;
342 if (settings.data_format == I2S_DATAFORMAT_16B)
return 2;
343 if (settings.data_format == I2S_DATAFORMAT_24B)
return 4;
344 if (settings.data_format == I2S_DATAFORMAT_32B)
return 4;
345 STM32_LOG(
"unsuppoted data_format");
353 uint8_t *dma_buffer_tx = (uint8_t *)hi2s->pTxBuffPtr;
354 uint8_t *dma_buffer_rx = (uint8_t *)hi2s->pRxBuffPtr;
355 uint16_t buffer_size_tx = hi2s->TxXferSize * 2;
356 uint16_t buffer_size_rx = hi2s->RxXferSize * 2;
357 if (readToTransmitCB != NULL)
358 readToTransmitCB(&(dma_buffer_tx[buffer_size_tx / 2]), buffer_size_tx / 2,
360 if (writeFromReceiveCB != NULL)
361 writeFromReceiveCB(&(dma_buffer_rx[buffer_size_rx / 2]),
362 buffer_size_rx / 2, settings.ref);
369 uint8_t *dma_buffer_tx = (uint8_t *)hi2s->pTxBuffPtr;
370 uint8_t *dma_buffer_rx = (uint8_t *)hi2s->pRxBuffPtr;
371 uint16_t buffer_size_tx = hi2s->TxXferSize * 2;
372 uint16_t buffer_size_rx = hi2s->RxXferSize * 2;
373 if (readToTransmitCB != NULL)
374 readToTransmitCB(&(dma_buffer_tx[0]), buffer_size_tx / 2, settings.ref);
375 if (writeFromReceiveCB != NULL)
376 writeFromReceiveCB(&(dma_buffer_rx[0]), buffer_size_rx / 2, settings.ref);
380 inline void cb_dmaIrqRx() { HAL_DMA_IRQHandler(&hdma_i2s3_ext_rx); }
383 inline void cb_dmaIrqTx() { HAL_DMA_IRQHandler(&hdma_i2s3_ext_tx); }
397 stm32_i2s_is_error =
false;
398 if (settings.sample_rate == 0) {
399 STM32_LOG(
"sample_rate must not be 0");
402 STM32_LOG(
"use_dma: %s", use_dma ?
"true" :
"false");
403 stm32_i2s_is_error =
false;
414 return !stm32_i2s_is_error;
425 __HAL_RCC_GPIOH_CLK_ENABLE();
428 for (
I2SPin &pin : hw.pins) {
438 __HAL_RCC_DMA1_CLK_ENABLE();
442 HAL_NVIC_SetPriority(hw.irq1, 0, 0);
443 HAL_NVIC_EnableIRQ(hw.irq1);
445 HAL_NVIC_SetPriority(hw.irq2, 0, 0);
446 HAL_NVIC_EnableIRQ(hw.irq2);
455 hi2s3.Instance = SPI_INSTANCE_FOR_I2S;
456 hi2s3.Init.Mode = settings.mode;
457 hi2s3.Init.Standard = settings.standard;
458 hi2s3.Init.FullDuplexMode = settings.fullduplexmode;
459 hi2s3.Init.AudioFreq = settings.sample_rate;
460 hi2s3.Init.DataFormat = settings.data_format;
461 hi2s3.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE;
462 hi2s3.Init.CPOL = I2S_CPOL_LOW;
463 hi2s3.Init.ClockSource = I2S_CLOCK_PLL;
464 if (HAL_I2S_Init(&hi2s3) != HAL_OK) {
476 RCC_PeriphCLKInitTypeDef PeriphClkInitStruct = {0};
480 PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_I2S;
482 PeriphClkInitStruct.PLLI2S.PLLI2SM = hw.pllm;
485 PeriphClkInitStruct.PLLI2S.PLLI2SN = hw.plln;
488 PeriphClkInitStruct.PLLI2S.PLLI2SR = hw.pllr;
490 if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
495 __HAL_RCC_SPI3_CLK_ENABLE();
500 if (dma_buffer_rx !=
nullptr) {
501 setupDMA(hdma_i2s3_ext_rx, hw.rx_instance, hw.rx_channel,
503 __HAL_LINKDMA(hi2s, hdmarx, hdma_i2s3_ext_rx);
506 if (dma_buffer_tx !=
nullptr) {
507 setupDMA(hdma_i2s3_ext_tx, hw.tx_instance, hw.tx_channel,
509 __HAL_LINKDMA(hi2s, hdmatx, hdma_i2s3_ext_tx);
518 void setupDMA(DMA_HandleTypeDef &dma, DMA_Stream_TypeDef *instance,
519 uint32_t channel, uint32_t direction) {
520 dma.Instance = instance;
521 dma.Init.Channel = channel;
522 dma.Init.Direction = direction;
523 dma.Init.PeriphInc = DMA_PINC_DISABLE;
524 dma.Init.MemInc = DMA_MINC_ENABLE;
525 dma.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
526 dma.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
527 dma.Init.Mode = DMA_CIRCULAR;
528 dma.Init.Priority = DMA_PRIORITY_HIGH;
529 dma.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
530 dma.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
531 dma.Init.MemBurst = DMA_PBURST_INC4;
532 dma.Init.PeriphBurst = DMA_PBURST_INC4;
533 if (HAL_DMA_Init(&dma) != HAL_OK) {
545 if (hi2s->Instance == SPI3) {
547 __HAL_RCC_SPI3_CLK_DISABLE();
550 HAL_DMA_DeInit(hi2s->hdmarx);
551 HAL_DMA_DeInit(hi2s->hdmatx);
557 extern Stm32I2sClass I2S;
I2S API for STM32.
Definition: stm32-i2s.h:147
virtual void MX_I2S3_Init(void)
I2S3 Initialization Function.
Definition: stm32-i2s.h:454
bool beginReadDMA(I2SSettingsSTM32 settings, void(*writeFromReceive)(uint8_t *buffer, uint16_t byteCount, void *ref)=nullptr)
Start to receive I2S data.
Definition: stm32-i2s.h:232
bool beginWriteDMA(I2SSettingsSTM32 settings, void(*readToTransmit)(uint8_t *buffer, uint16_t byteCount, void *ref)=nullptr)
Start to transmit I2S data.
Definition: stm32-i2s.h:208
size_t write(const uint8_t *data, size_t bytes)
Write method which needs to be called when ansync mode is disabled.
Definition: stm32-i2s.h:305
void cb_HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s)
Callback I2S de-intitialization.
Definition: stm32-i2s.h:391
virtual void cb_i2s_MspInit(I2S_HandleTypeDef *hi2s)
I2S MSP Initialization This function configures the hardware resources used in this example.
Definition: stm32-i2s.h:475
virtual void MX_GPIO_Init(void)
GPIO Initialization Function for I2S pins.
Definition: stm32-i2s.h:423
void cb_TxRxComplete(I2S_HandleTypeDef *hi2s)
Callback for double buffer.
Definition: stm32-i2s.h:351
void cb_dmaIrqTx()
Callback for DMA interrupt request.
Definition: stm32-i2s.h:383
virtual void MX_DMA_Init(void)
Definition: stm32-i2s.h:436
size_t readBytes(uint8_t *data, size_t bytes)
Read method which needs to be called when ansync mode is disabled.
Definition: stm32-i2s.h:319
virtual void cb_i2s_MspDeInit(I2S_HandleTypeDef *hi2s)
I2S MSP De-Initialization This function freeze the hardware resources used in this example.
Definition: stm32-i2s.h:544
void cb_TxRxHalfComplete(I2S_HandleTypeDef *hi2s)
Callback for double buffer.
Definition: stm32-i2s.h:367
void cb_HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s)
Callback I2S intitialization.
Definition: stm32-i2s.h:386
bool begin(I2SSettingsSTM32 settings, bool transmit, bool receive)
start I2S w/o DMA: use write and readBytes
Definition: stm32-i2s.h:159
bool beginReadWriteDMA(I2SSettingsSTM32 settings, void(*readToTransmit)(uint8_t *buffer, uint16_t byteCount, void *)=nullptr, void(*writeFromReceive)(uint8_t *buffer, uint16_t byteCount, void *)=nullptr)
Start to receive and transmit I2S data.
Definition: stm32-i2s.h:257
bool i2s_begin()
Starts the i2s processing.
Definition: stm32-i2s.h:396
void setupDMA(DMA_HandleTypeDef &dma, DMA_Stream_TypeDef *instance, uint32_t channel, uint32_t direction)
DMA Initialization This function configures and initializes the DMA.
Definition: stm32-i2s.h:518
void cb_dmaIrqRx()
Callback for DMA interrupt request.
Definition: stm32-i2s.h:380
I2SPinFunction
i2s pin function used as documentation
Definition: stm32-i2s.h:44
Processor specific settings that are needed to set up I2S.
Definition: stm32-i2s.h:99
Define individual Pin. This is used to set up processor specific arrays with all I2S pins and to setu...
Definition: stm32-i2s.h:53
void end()
Undo the current pin function.
Definition: stm32-i2s.h:70
Currently supported parameters.
Definition: stm32-i2s.h:131