ARMEBS4  revision-26.06.2015
audio_stm32.c
Go to the documentation of this file.
1 /************************************************************************//**
2  * \file heivs/audio_stm32.c
3  * \brief ARMEBS4 audio for stm32
4  * \author marc dot pignat at hevs dot ch & Pascal Sartoretti (sap at hevs dot ch)
5  ***************************************************************************/
6 
7 #include "heivs/audio_stm32.h"
8 #include "heivs/bsp.h"
9 #include "stm32/stm32f4xx_rcc.h"
10 #include "stm32/stm32f4xx_spi.h"
11 #include "stm32/stm32f4xx_dma.h"
12 #include "stm32/stm32f4xx_misc.h"
13 #include "heivs/stm32_gpio.h"
14 
15 #include "heivs/config.h"
16 #if USE_FREERTOS
17 #include "freertos/FreeRTOS.h"
18 #endif
19 
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
24 
25 /**
26  * \brief Predefined audio setup
27  */
29 {
30  uint32_t fs;
31  uint32_t fs_i2s;
32  uint32_t pll_sn;
33  uint32_t pll_sr;
34  uint32_t sample_size;
35  uint32_t byte_per_sample;
36 };
37 
38 /**
39  * \brief Table of all currently supported setups
40  */
41 static const struct audio_setup_t audio_setups[] =
42 {
43  {
44  .fs = 48000,
45  .fs_i2s = I2S_AudioFreq_48k,
46  .pll_sn = 258,
47  .pll_sr = 3,
48  },
49  {
50  .fs = 44100,
51  .fs_i2s = I2S_AudioFreq_44k,
52  .pll_sn = 271,
53  .pll_sr = 2,
54  },
55  {
56  .fs = 96000,
57  .fs_i2s = I2S_AudioFreq_96k,
58  .pll_sn = 344,
59  .pll_sr = 2,
60  },
61  {
62  .fs = 32000,
63  .fs_i2s = I2S_AudioFreq_32k,
64  .pll_sn = 213,
65  .pll_sr = 2,
66  },
67  {
68  .fs = 16000,
69  .fs_i2s = I2S_AudioFreq_16k,
70  .pll_sn = 213,
71  .pll_sr = 2,
72  },
73  {
74  .fs = 8000,
75  .fs_i2s = I2S_AudioFreq_8k,
76  .pll_sn = 256,
77  .pll_sr = 5,
78  },
79 };
80 
81 /**
82  * \brief DMA transfer
83  */
84 static struct dma_xfer_t dma_play_xfer;
85 static struct dma_xfer_t dma_record_xfer;
86 
87 /**
88  * The current audio setup
89  */
90 static struct audio_setup_t setup;
91 
92 /**
93  * \brief Description of a DMA transfer
94  */
95 struct dma_xfer_t
96 {
97  uint32_t tx_zeroes;
98 
99  void (*done)(const void *); ///< Handler called at the end of Audio_DMA_Play
100  void *data[2]; ///< Buffers
101  uint32_t length;
102  volatile void *next_buffer;
103  volatile uint32_t buffer_needed;
104 };
105 
106 /**
107  * \brief Find the correct setup
108  *
109  * \param fs, the sampling frequency
110  *
111  * \return a pointer to the configuration or NULL if the frequency is not supported
112  */
113 static status_e audio_setup_selection(struct audio_setup_t *setup, uint32_t fs, uint32_t sample_size)
114 {
115  size_t i;
116  int32_t found = -1;
117 
118  for (i = 0 ; i < ARRAY_SIZE(audio_setups); i++)
119  {
120  if (audio_setups[i].fs == fs)
121  {
122  found = i;
123  break;
124  }
125  }
126 
127  if (found == -1)
128  {
129  return ERROR_BAD_PARAM;
130  }
131 
132  memcpy(setup, &audio_setups[i], sizeof(*setup));
133 
134  switch (sample_size)
135  {
136  case 16:
137  setup->sample_size = I2S_DataFormat_16bextended;
138  setup->byte_per_sample = 2;
139  break;
140  case 24:
141  setup->sample_size = I2S_DataFormat_24b;
142  setup->byte_per_sample = 3;
143  break;
144  case 32:
145  setup->sample_size = I2S_DataFormat_32b;
146  setup->byte_per_sample = 4;
147  break;
148 
149  default:
150  return ERROR_BAD_PARAM;
151  }
152 
153  return NO_ERROR;
154 }
155 
156 
157 
158 static const uint16_t nop[4];
159 static void tx_zeroes(void)
160 {
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);
163 
164  DMA_Stream_TX->NDTR = ARRAY_SIZE(nop);
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);
168 
169  /* Enable the I2S DMA Stream */
170  DMA_Cmd(DMA_Stream_TX, ENABLE);
171 }
172 
173 static void i2s_dma_tx_irq_handler(void)
174 {
175  /* FIFO Error interrupt */
176  if (DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_FEIF4) != RESET)
177  {
178  /* Clear the Interrupt flag */
179  DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_FEIF4);
180  }
181 
182  /* Transfer error interrupt */
183  if (DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_DMEIF4) || DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_TEIF4))
184  {
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);
187 
188  /* Clear the Interrupt flag */
189  DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_DMEIF4);
190  DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_TEIF4);
191  }
192 
193  if (DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_HTIF4) != RESET)
194  {
195  switch (DMA_GetCurrentMemoryTarget(DMA_Stream_TX))
196  {
197  case 0:
198  dma_play_xfer.next_buffer = dma_play_xfer.data[0];
199  break;
200 
201  case 1:
202  dma_play_xfer.next_buffer = dma_play_xfer.data[1];
203  break;
204 
205  default:
207  break;
208  }
209 
210  // Clear the flag
211  DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_HTIF4);
212  }
213 
214  // Xfer complete
215  if (DMA_GetFlagStatus(DMA_Stream_TX, DMA_FLAG_TCIF4) != RESET)
216  {
217  dma_play_xfer.buffer_needed = 1;
218 
219  if (dma_play_xfer.done)
220  {
221  dma_play_xfer.done((void *)dma_play_xfer.next_buffer);
222  }
223 
224  // Clear the flag
225  DMA_ClearFlag(DMA_Stream_TX, DMA_FLAG_TCIF4);
226  }
227 }
228 
229 static void i2s_dma_rx_irq_handler(void)
230 {
231  /* FIFO Error interrupt */
232  if (DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_FEIF3) != RESET)
233  {
234  /* Clear the Interrupt flag */
235  DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_FEIF3);
236  }
237 
238  /* Transfer error interrupt */
239  if (DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_DMEIF3) || DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_TEIF3))
240  {
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);
243 
244  /* Clear the Interrupt flag */
245  DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_DMEIF3);
246  DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_TEIF3);
247  }
248  if (DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_HTIF3) != RESET)
249  {
250  switch (DMA_GetCurrentMemoryTarget(DMA_Stream_RX))
251  {
252  case 0:
253  dma_record_xfer.next_buffer = dma_record_xfer.data[0];
254  break;
255 
256  case 1:
257  dma_record_xfer.next_buffer = dma_record_xfer.data[1];
258  break;
259 
260  default:
262  break;
263  }
264 
265  DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_HTIF3);
266  }
267 
268  // Xfer complete
269  if (DMA_GetFlagStatus(DMA_Stream_RX, DMA_FLAG_TCIF3) != RESET)
270  {
271  dma_record_xfer.done((void*)dma_record_xfer.next_buffer);
272 
273  // Clear the flag
274  DMA_ClearFlag(DMA_Stream_RX, DMA_FLAG_TCIF3);
275  }
276 }
277 
278 status_e AudioSTM32_Init(uint32_t fs, uint32_t sample_size)
279 {
280  I2S_InitTypeDef i2sStruct;
281  status_e status;
282  status = audio_setup_selection(&setup, fs, sample_size);
283  if (status != NO_ERROR)
284  {
285  return status;
286  }
287 
288  // Setup pins
289  const struct gpio_t pins[] =
290  {
291  GPIO_I2S2_MCK_PC6,
292  GPIO_I2S2_WS_PB12,
293  GPIO_I2S2_CK_PB13,
294  GPIO_I2S2ext_SD_PI2,
295  GPIO_I2S2_SD_PI3,
296  };
297  gpio_setup_list(pins, ARRAY_SIZE(pins));
298 
299  //---------------------------------------------------------------------------
300  // ensure de init I2S from previous states
301  SPI_I2S_DeInit(SPI2);
302  //---------------------------------------------------------------------------
303  // setup clock for I2S (on SPI 2)
304  RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S);
305  RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
306  RCC_PLLI2SConfig(setup.pll_sn, setup.pll_sr); // setup PLL freq
307  RCC_PLLI2SCmd(ENABLE);
308  while(RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY)!= SET)
309  {}
310  //---------------------------------------------------------------------------
311  // setup I2S working mode
312  i2sStruct.I2S_Mode = I2S_Mode_MasterTx;
313  i2sStruct.I2S_Standard = I2S_Standard_Phillips; // I2S standard
314  i2sStruct.I2S_DataFormat = setup.sample_size;
315  i2sStruct.I2S_MCLKOutput = I2S_MCLKOutput_Enable; // enable MCK
316  i2sStruct.I2S_CPOL = I2S_CPOL_Low;
317  i2sStruct.I2S_AudioFreq = setup.fs_i2s; // set sample freq
318 
319  I2S_Init(SPI2, &i2sStruct);
320  I2S_FullDuplexConfig(I2S2ext, &i2sStruct); // use recording too
321 
322  I2S_Cmd(SPI2, ENABLE); // enable output
323  I2S_Cmd(I2S2ext, ENABLE); // enable input
324 
325  // DMA output
326  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
327  DMA_InitTypeDef DMA_InitStructure;
328  DMA_StructInit(&DMA_InitStructure);
329 
330  DMA_Cmd(DMA_Stream_TX, DISABLE);
331  DMA_DeInit(DMA_Stream_TX);
332  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
333  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR;
334  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;
335  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
336  DMA_InitStructure.DMA_BufferSize = (uint32_t)0xFFFE;
337  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
338  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
339  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
340  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
341  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
342  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
343  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
344  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
345  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
346  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
347  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
348  DMA_Init(DMA_Stream_TX, &DMA_InitStructure);
349 
350  /* I2S DMA IRQ Channel configuration */
351  NVIC_InitTypeDef NVIC_InitStructure;
352  NVIC_InitStructure.NVIC_IRQChannel = DMA_Stream_TX_IRQn;
353  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
354  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
355  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
356  NVIC_InitStructure.NVIC_Handler = i2s_dma_tx_irq_handler;
357  NVIC_Init(&NVIC_InitStructure);
358 
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);
361 
362  SPI_I2S_DMACmd(SPI2, SPI_I2S_DMAReq_Tx, ENABLE);
363 
364  // DMA input
365  DMA_StructInit(&DMA_InitStructure);
366 
367  DMA_Cmd(DMA_Stream_RX, DISABLE);
368  DMA_DeInit(DMA_Stream_RX);
369  DMA_InitStructure.DMA_Channel = DMA_Channel_3;
370  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&I2S2ext->DR;
371  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;
372  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
373  DMA_InitStructure.DMA_BufferSize = (uint32_t)0xFFFE;
374  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
375  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
376  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
377  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
378  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
379  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
380  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
381  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
382  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
383  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
384  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
385  DMA_Init(DMA_Stream_RX, &DMA_InitStructure);
386 
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);
389 
390  /* I2S DMA IRQ Channel configuration */
391  NVIC_InitStructure.NVIC_IRQChannel = DMA_Stream_RX_IRQn;
392  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
393  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
394  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
395  NVIC_InitStructure.NVIC_Handler = i2s_dma_rx_irq_handler;
396  NVIC_Init(&NVIC_InitStructure);
397 
398  SPI_I2S_DMACmd(I2S2ext, SPI_I2S_DMAReq_Rx, ENABLE);
399 
400  return NO_ERROR;
401 }
402 
403 status_e AudioSTM32_Stream_Play_Init(uint32_t length, void *buffer0, void *buffer1, void (*done)(const void *))
404 {
405  if (length & 1)
406  {
407  return ERROR_BAD_PARAM;
408  }
409 
410  length /=2;
411 
412  if (length > DMA_MAX_XFER_COUNT)
413  {
414  return ERROR_BAD_PARAM;
415  }
416 
417  if (buffer0 == buffer1)
418  {
419  return ERROR_BAD_PARAM;
420  }
421 
422  if (((uint32_t)buffer0 & 1) || ((uint32_t)buffer1 & 1))
423  {
424  return ERROR_BAD_ALIGN;
425  }
426 
427  if (DMA_GetCmdStatus(DMA_Stream_TX))
428  {
429  return ERROR_BAD_STATE;
430  }
431 
432  memset(&dma_play_xfer, 0x0, sizeof(dma_play_xfer));
433  dma_play_xfer.data[0] = buffer0;
434  dma_play_xfer.data[1] = buffer1;
435  dma_play_xfer.length = length;
436 
437  DMA_Stream_TX->NDTR = length;
438  DMA_Stream_TX->M0AR = (uint32_t)dma_play_xfer.data[0];
439  DMA_Stream_TX->M1AR = (uint32_t)dma_play_xfer.data[1];
440  dma_play_xfer.done = done;
441  DMA_DoubleBufferModeCmd(DMA_Stream_TX, ENABLE);
442 
443  AudioSTM32_Stream_Play_Pause();
444 
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);
447 
448  /* Enable the I2S DMA Stream */
449  DMA_Cmd(DMA_Stream_TX, ENABLE);
450 
451  return NO_ERROR;
452 }
453 
454 status_e AudioSTM32_Stream_Play_Pause(void)
455 {
456  memset(dma_play_xfer.data[0], 0x0, dma_play_xfer.length * 2);
457  memset(dma_play_xfer.data[1], 0x0, dma_play_xfer.length * 2);
458 
459  return NO_ERROR;
460 }
461 
463 {
464  DMA_Cmd(DMA_Stream_TX, DISABLE);
465 
466  return NO_ERROR;
467 }
468 
470 {
471  if (dma_play_xfer.buffer_needed == 0)
472  {
473  return ERROR_AGAIN;
474  }
475 
476  return NO_ERROR;
477 }
478 
480 {
481  status_e status;
482 
483  while (1)
484  {
486  if (status == NO_ERROR)
487  {
488  // Ready for next buffer
489  break;
490  }
491 
492  if (status == ERROR_AGAIN)
493  {
494  // Should wait
495  #if USE_FREERTOS
496  // FIXME : use something like an event
497  vTaskDelay(1);
498  #else
499  // Stream will be changed in interrupt, so wait for it
500  __WFI();
501  #endif
502  }
503  else
504  {
505  // Another error
506  return status;
507  }
508  }
509 
510  // Copy the buffer
511  memcpy((void *)dma_play_xfer.next_buffer, data, dma_play_xfer.length * 2);
512  dma_play_xfer.buffer_needed = 0;
513 
514  return NO_ERROR;
515 }
516 
517 static void send_when_ready(uint16_t data)
518 {
519  while (SPI_I2S_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET){}
520  SPI_I2S_SendData(SPI2, data);
521 }
522 
523 status_e AudioSTM32_Play(const int16_t *src, uint32_t length)
524 {
525  uint32_t i;
526 
527  length /=2;
528  for (i = 0 ; i < length; i++)
529  {
530  send_when_ready(src[i]);
531  }
532 
533  return NO_ERROR;
534 }
535 
536 status_e AudioSTM32_Record(int16_t *dst, uint32_t length)
537 {
538  length /= 2;
539  uint32_t counter=0;
540 
541  // send a dummy byte more -> so it works !!!
542  while (SPI_I2S_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET){}
543  SPI_I2S_SendData(SPI2, 0);
544 
545  do
546  {
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);
551  counter++;
552  }while(counter < length);
553  return NO_ERROR;
554 }
555 
556 status_e AudioSTM32_Stream_Record_Init(uint32_t length, void *buffer0, void *buffer1, void(*done)(const void *))
557 {
558  if (!length || !done)
559  {
560  return ERROR_BAD_PARAM;
561  }
562 
563  if (length & 1)
564  {
565  return ERROR_BAD_PARAM;
566  }
567 
568  length /=2;
569 
570  if (length > DMA_MAX_XFER_COUNT)
571  {
572  return ERROR_BAD_PARAM;
573  }
574 
575  if (!buffer0 || !buffer1)
576  {
577  return ERROR_BAD_PARAM;
578  }
579 
580  if (buffer0 == buffer1)
581  {
582  return ERROR_BAD_PARAM;
583  }
584 
585  if (((uint32_t)buffer0 & 1) || ((uint32_t)buffer1 & 1))
586  {
587  return ERROR_BAD_ALIGN;
588  }
589 
590 
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;
596 
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);
601 
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);
604 
605  /* Send zeros if DMA output is disable */
606  if (!DMA_GetCmdStatus(DMA_Stream_TX))
607  {
608  dma_record_xfer.tx_zeroes = 1;
609  tx_zeroes();
610  }
611 
612  /* Enable the I2S DMA Stream */
613  DMA_Cmd(DMA_Stream_RX, ENABLE);
614 
615  return NO_ERROR;
616 }
617 
618 status_e AudioSTM32_Stream_Record_Stop(void)
619 {
620  DMA_Cmd(DMA_Stream_RX, DISABLE);
621 
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);
624 
625  if (dma_record_xfer.tx_zeroes)
626  {
627  DMA_Cmd(DMA_Stream_TX, DISABLE);
628  }
629 
630  return NO_ERROR;
631 }
This file contains all the functions prototypes for the RCC firmware library.
uint32_t DMA_MemoryInc
Definition: stm32f4xx_dma.h:70
status_e AudioSTM32_Stream_Play_Status(void)
Is AudioSTM32_Stream_Play ready for the next buffer?
Definition: audio_stm32.c:469
void * data[2]
Buffers.
Definition: audio_stm32.c:100
uint32_t DMA_Channel
Definition: stm32f4xx_dma.h:50
BSP - Board Support Package.
void(* done)(const void *)
Handler called at the end of Audio_DMA_Play.
Definition: audio_stm32.c:99
status_e AudioSTM32_Stream_Play_Stop(void)
Audio stream stop.
Definition: audio_stm32.c:462
DMA Init structure definition.
Definition: stm32f4xx_dma.h:48
uint8_t NVIC_IRQChannel
uint32_t DMA_MemoryBurst
Definition: stm32f4xx_dma.h:95
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.
Definition: audio_stm32.c:113
static struct audio_setup_t setup
Definition: audio_stm32.c:90
void * memcpy(void *dest, const void *src, size_t n)
void * memset(void *dest, int n, size_t n)
uint16_t I2S_Standard
Definition: stm32f4xx_spi.h:91
uint32_t DMA_MemoryDataSize
Definition: stm32f4xx_dma.h:76
libheivs configuration file
void bsp_fatal(status_e status)
fatal error
Definition: bsp.c:123
uint8_t NVIC_IRQChannelSubPriority
uint32_t DMA_DIR
Definition: stm32f4xx_dma.h:59
static const struct audio_setup_t audio_setups[]
Table of all currently supported setups.
Definition: audio_stm32.c:41
Pointer with wrong alignment.
Definition: error.h:75
uint32_t DMA_PeripheralInc
Definition: stm32f4xx_dma.h:67
uint16_t I2S_Mode
Definition: stm32f4xx_spi.h:88
NVIC Init Structure definition.
Function called at bad time.
Definition: error.h:67
uint32_t DMA_PeripheralDataSize
Definition: stm32f4xx_dma.h:73
uint32_t DMA_PeripheralBurst
uint32_t I2S_AudioFreq
uint16_t I2S_MCLKOutput
Definition: stm32f4xx_spi.h:97
Parameter unsupported.
Definition: error.h:56
This file contains all the functions prototypes for the DMA firmware library.
Impossible switch value.
Definition: error.h:63
board specific defines
uint32_t DMA_PeripheralBaseAddr
Definition: stm32f4xx_dma.h:53
Predefined audio setup.
Definition: audio_stm32.c:28
uint32_t DMA_Memory0BaseAddr
Definition: stm32f4xx_dma.h:55
static struct dma_xfer_t dma_play_xfer
DMA transfer.
Definition: audio_stm32.c:84
GPIO control structure.
Definition: stm32_gpio.h:96
uint32_t DMA_FIFOThreshold
Definition: stm32f4xx_dma.h:92
status_e AudioSTM32_Stream_Play(const void *data)
Audio stream play buffer.
Definition: audio_stm32.c:479
FunctionalState NVIC_IRQChannelCmd
status_e AudioSTM32_Stream_Play_Init(uint32_t length, void *buffer0, void *buffer1, void(*done)(const void *))
Audio stream initialization.
Definition: audio_stm32.c:403
Retry later.
Definition: error.h:49
uint8_t NVIC_IRQChannelPreemptionPriority
uint32_t DMA_FIFOMode
Definition: stm32f4xx_dma.h:87
I2S Init structure definition.
Definition: stm32f4xx_spi.h:85
uint32_t DMA_Mode
Definition: stm32f4xx_dma.h:79
uint16_t I2S_DataFormat
Definition: stm32f4xx_spi.h:94
status_e gpio_setup_list(const struct gpio_t gpio[], size_t len)
Setup an array of gpio.
Definition: stm32_gpio.c:47
uint32_t DMA_BufferSize
Definition: stm32f4xx_dma.h:63
status_e
Known errors.
Definition: error.h:21
#define ARRAY_SIZE(x)
Number of elements in the array.
Definition: utils.h:19
uint32_t DMA_Priority
Definition: stm32f4xx_dma.h:84
status_e AudioSTM32_Play(const int16_t *src, uint32_t length)
Play a sound (polling mode)
Definition: audio_stm32.c:523
No error.
Definition: error.h:28
Description of a DMA transfer.
Definition: audio_stm32.c:95