7 #include "heivs/audio_stm32.h"
12 #include "stm32/stm32f4xx_misc.h"
17 #include "freertos/FreeRTOS.h"
20 #define DMA_Stream_RX DMA1_Stream3
21 #define DMA_Stream_TX DMA1_Stream4
22 #define DMA_Stream_RX_IRQn DMA1_Stream3_IRQn
23 #define DMA_Stream_TX_IRQn DMA1_Stream4_IRQn
35 uint32_t byte_per_sample;
45 .fs_i2s = I2S_AudioFreq_48k,
51 .fs_i2s = I2S_AudioFreq_44k,
57 .fs_i2s = I2S_AudioFreq_96k,
63 .fs_i2s = I2S_AudioFreq_32k,
69 .fs_i2s = I2S_AudioFreq_16k,
75 .fs_i2s = I2S_AudioFreq_8k,
99 void (*
done)(
const void *);
102 volatile void *next_buffer;
103 volatile uint32_t buffer_needed;
118 for (i = 0 ; i <
ARRAY_SIZE(audio_setups); i++)
120 if (audio_setups[i].fs == fs)
132 memcpy(setup, &audio_setups[i],
sizeof(*setup));
137 setup->sample_size = I2S_DataFormat_16bextended;
138 setup->byte_per_sample = 2;
141 setup->sample_size = I2S_DataFormat_24b;
142 setup->byte_per_sample = 3;
145 setup->sample_size = I2S_DataFormat_32b;
146 setup->byte_per_sample = 4;
158 static const uint16_t nop[4];
159 static void tx_zeroes(
void)
161 DMA_ITConfig(DMA_Stream_TX, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_DME, DISABLE);
162 DMA_ITConfig(DMA_Stream_TX, DMA_IT_FE, DISABLE);
165 DMA_Stream_TX->M0AR = (uint32_t)&nop[0];
166 DMA_Stream_TX->M1AR = (uint32_t)&nop[0];
167 DMA_DoubleBufferModeCmd(DMA_Stream_TX, ENABLE);
170 DMA_Cmd(DMA_Stream_TX, ENABLE);
173 static void i2s_dma_tx_irq_handler(
void)
176 if (DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_FEIF4) != RESET)
179 DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_FEIF4);
183 if (DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_DMEIF4) || DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_TEIF4))
185 DMA_ITConfig(DMA_Stream_TX, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_DME, DISABLE);
186 DMA_ITConfig(DMA_Stream_TX, DMA_IT_FE, DISABLE);
189 DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_DMEIF4);
190 DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_TEIF4);
193 if (DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_HTIF4) != RESET)
195 switch (DMA_GetCurrentMemoryTarget(DMA_Stream_TX))
211 DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_HTIF4);
215 if (DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_TCIF4) != RESET)
225 DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_TCIF4);
229 static void i2s_dma_rx_irq_handler(
void)
232 if (DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_FEIF3) != RESET)
235 DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_FEIF3);
239 if (DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_DMEIF3) || DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_TEIF3))
241 DMA_ITConfig(DMA_Stream_RX, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_DME, DISABLE);
242 DMA_ITConfig(DMA_Stream_RX, DMA_IT_FE, DISABLE);
245 DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_DMEIF3);
246 DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_TEIF3);
248 if (DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_HTIF3) != RESET)
250 switch (DMA_GetCurrentMemoryTarget(DMA_Stream_RX))
253 dma_record_xfer.next_buffer = dma_record_xfer.
data[0];
257 dma_record_xfer.next_buffer = dma_record_xfer.
data[1];
265 DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_HTIF3);
269 if (DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_TCIF3) != RESET)
271 dma_record_xfer.
done((
void*)dma_record_xfer.next_buffer);
274 DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_TCIF3);
278 status_e AudioSTM32_Init(uint32_t fs, uint32_t sample_size)
289 const struct gpio_t pins[] =
301 SPI_I2S_DeInit(SPI2);
304 RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
305 RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
307 RCC_PLLI2SCmd(ENABLE);
308 while(RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY)!= SET)
312 i2sStruct.
I2S_Mode = I2S_Mode_MasterTx;
319 I2S_Init(SPI2, &i2sStruct);
320 I2S_FullDuplexConfig(I2S2ext, &i2sStruct);
322 I2S_Cmd(SPI2, ENABLE);
323 I2S_Cmd(I2S2ext, ENABLE);
326 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
328 DMA_StructInit(&DMA_InitStructure);
330 DMA_Cmd(DMA_Stream_TX, DISABLE);
331 DMA_DeInit(DMA_Stream_TX);
335 DMA_InitStructure.
DMA_DIR = DMA_DIR_MemoryToPeripheral;
341 DMA_InitStructure.
DMA_Mode = DMA_Mode_Circular;
342 DMA_InitStructure.
DMA_Mode = DMA_Mode_Normal;
348 DMA_Init(DMA_Stream_TX, &DMA_InitStructure);
356 NVIC_InitStructure.NVIC_Handler = i2s_dma_tx_irq_handler;
357 NVIC_Init(&NVIC_InitStructure);
359 DMA_ITConfig(DMA_Stream_TX, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_DME, ENABLE);
360 DMA_ITConfig(DMA_Stream_TX, DMA_IT_FE, ENABLE);
362 SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
365 DMA_StructInit(&DMA_InitStructure);
367 DMA_Cmd(DMA_Stream_RX, DISABLE);
368 DMA_DeInit(DMA_Stream_RX);
372 DMA_InitStructure.
DMA_DIR = DMA_DIR_PeripheralToMemory;
378 DMA_InitStructure.
DMA_Mode = DMA_Mode_Circular;
379 DMA_InitStructure.
DMA_Mode = DMA_Mode_Normal;
385 DMA_Init(DMA_Stream_RX, &DMA_InitStructure);
387 DMA_ITConfig(DMA_Stream_RX, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_DME, ENABLE);
388 DMA_ITConfig(DMA_Stream_RX, DMA_IT_FE, ENABLE);
395 NVIC_InitStructure.NVIC_Handler = i2s_dma_rx_irq_handler;
396 NVIC_Init(&NVIC_InitStructure);
398 SPI_I2S_DMACmd(I2S2ext, SPI_I2S_DMAReq_Rx, ENABLE);
412 if (length > DMA_MAX_XFER_COUNT)
417 if (buffer0 == buffer1)
422 if (((uint32_t)buffer0 & 1) || ((uint32_t)buffer1 & 1))
427 if (DMA_GetCmdStatus(DMA_Stream_TX))
437 DMA_Stream_TX->NDTR = length;
441 DMA_DoubleBufferModeCmd(DMA_Stream_TX, ENABLE);
443 AudioSTM32_Stream_Play_Pause();
445 DMA_ITConfig(DMA_Stream_TX, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_DME, ENABLE);
446 DMA_ITConfig(DMA_Stream_TX, DMA_IT_FE, ENABLE);
449 DMA_Cmd(DMA_Stream_TX, ENABLE);
454 status_e AudioSTM32_Stream_Play_Pause(
void)
464 DMA_Cmd(DMA_Stream_TX, DISABLE);
517 static void send_when_ready(uint16_t data)
519 while (SPI_I2S_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET){}
520 SPI_I2S_SendData(SPI2, data);
528 for (i = 0 ; i < length; i++)
530 send_when_ready(src[i]);
536 status_e AudioSTM32_Record(int16_t *dst, uint32_t length)
542 while (SPI_I2S_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET){}
543 SPI_I2S_SendData(SPI2, 0);
547 while (SPI_I2S_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET){}
548 SPI_I2S_SendData(SPI2,0);
549 while (SPI_I2S_GetFlagStatus(I2S2ext, SPI_FLAG_RXNE) == RESET){}
550 dst[counter] = SPI_I2S_ReceiveData(I2S2ext);
552 }
while(counter < length);
556 status_e AudioSTM32_Stream_Record_Init(uint32_t length,
void *buffer0,
void *buffer1,
void(*done)(
const void *))
558 if (!length || !done)
570 if (length > DMA_MAX_XFER_COUNT)
575 if (!buffer0 || !buffer1)
580 if (buffer0 == buffer1)
585 if (((uint32_t)buffer0 & 1) || ((uint32_t)buffer1 & 1))
591 memset(&dma_record_xfer, 0x0,
sizeof(dma_record_xfer));
592 dma_record_xfer.
done = done;
593 dma_record_xfer.length = length;
594 dma_record_xfer.
data[0] = buffer0;
595 dma_record_xfer.
data[1] = buffer1;
597 DMA_Stream_RX->NDTR = dma_record_xfer.length;
598 DMA_Stream_RX->M0AR = (uint32_t)dma_record_xfer.
data[0];
599 DMA_Stream_RX->M1AR = (uint32_t)dma_record_xfer.
data[1];
600 DMA_DoubleBufferModeCmd(DMA_Stream_RX, ENABLE);
602 DMA_ITConfig(DMA_Stream_RX, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_DME, ENABLE);
603 DMA_ITConfig(DMA_Stream_RX, DMA_IT_FE, ENABLE);
606 if (!DMA_GetCmdStatus(DMA_Stream_TX))
608 dma_record_xfer.tx_zeroes = 1;
613 DMA_Cmd(DMA_Stream_RX, ENABLE);
618 status_e AudioSTM32_Stream_Record_Stop(
void)
620 DMA_Cmd(DMA_Stream_RX, DISABLE);
622 DMA_ITConfig(DMA_Stream_RX, DMA_IT_TC | DMA_IT_HT | DMA_IT_TE | DMA_IT_DME, DISABLE);
623 DMA_ITConfig(DMA_Stream_RX, DMA_IT_FE, DISABLE);
625 if (dma_record_xfer.tx_zeroes)
627 DMA_Cmd(DMA_Stream_TX, DISABLE);
This file contains all the functions prototypes for the RCC firmware library.
status_e AudioSTM32_Stream_Play_Status(void)
Is AudioSTM32_Stream_Play ready for the next buffer?
BSP - Board Support Package.
void(* done)(const void *)
Handler called at the end of Audio_DMA_Play.
status_e AudioSTM32_Stream_Play_Stop(void)
Audio stream stop.
DMA Init structure definition.
This file contains all the functions prototypes for the SPI firmware library.
static status_e audio_setup_selection(struct audio_setup_t *setup, uint32_t fs, uint32_t sample_size)
Find the correct setup.
static struct audio_setup_t setup
void * memcpy(void *dest, const void *src, size_t n)
void * memset(void *dest, int n, size_t n)
uint32_t DMA_MemoryDataSize
libheivs configuration file
void bsp_fatal(status_e status)
fatal error
uint8_t NVIC_IRQChannelSubPriority
static const struct audio_setup_t audio_setups[]
Table of all currently supported setups.
Pointer with wrong alignment.
uint32_t DMA_PeripheralInc
NVIC Init Structure definition.
Function called at bad time.
uint32_t DMA_PeripheralDataSize
uint32_t DMA_PeripheralBurst
This file contains all the functions prototypes for the DMA firmware library.
uint32_t DMA_PeripheralBaseAddr
uint32_t DMA_Memory0BaseAddr
static struct dma_xfer_t dma_play_xfer
DMA transfer.
uint32_t DMA_FIFOThreshold
status_e AudioSTM32_Stream_Play(const void *data)
Audio stream play buffer.
FunctionalState NVIC_IRQChannelCmd
status_e AudioSTM32_Stream_Play_Init(uint32_t length, void *buffer0, void *buffer1, void(*done)(const void *))
Audio stream initialization.
uint8_t NVIC_IRQChannelPreemptionPriority
I2S Init structure definition.
status_e gpio_setup_list(const struct gpio_t gpio[], size_t len)
Setup an array of gpio.
#define ARRAY_SIZE(x)
Number of elements in the array.
status_e AudioSTM32_Play(const int16_t *src, uint32_t length)
Play a sound (polling mode)
Description of a DMA transfer.