STSW-STLKT01: Drivers/BSP/SensorTile/SensorTile_audio_out.c Source File

STSW-STLKT01

STSW-STLKT01
SensorTile_audio_out.c
Go to the documentation of this file.
1 
39 /* Includes ------------------------------------------------------------------*/
40 #include "stm32l4xx_hal.h"
41 #include "SensorTile_audio_out.h"
42 
76 #define SAIClockDivider(__FREQUENCY__) \
77 ((__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 12 \
78  : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 2 \
79  : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 6 \
80  : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 1 \
81  : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \
82  : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \
83  : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 2 : 1)
84 
93 static DrvContextTypeDef CODEC_Handle[CODEC_SENSORS_MAX_NUM ];
94 
95 
96 SAI_HandleTypeDef haudio_out_sai;
97 static void SAIx_MspInit(void);
98 static void SAIx_Init(uint32_t AudioFreq);
99 
100 
101 
109 static DrvStatusTypeDef BSP_PCM1774_CODEC_Init( void **handle, uint8_t Volume, uint32_t AudioFreq);
110 
129 uint8_t BSP_AUDIO_OUT_Init(CODEX_ID_t id, void **handle, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
130 {
131  if (AudioFreq != AUDIO_FREQUENCY_8K && AudioFreq != AUDIO_FREQUENCY_16K && AudioFreq && AudioFreq != AUDIO_FREQUENCY_32K && AudioFreq != AUDIO_FREQUENCY_48K)
132  return COMPONENT_ERROR;
133 
134  BSP_AUDIO_OUT_ClockConfig(AudioFreq, NULL);
135 
136  *handle = NULL;
137 
138  switch(id)
139  {
140  case CODEX_SENSORS_AUTO:
141  default:
142  {
143  /* Try to init the LSM6DSM before */
144  if(BSP_PCM1774_CODEC_Init(handle, Volume, AudioFreq) == COMPONENT_ERROR )
145  {
146  return COMPONENT_ERROR;
147  }
148  break;
149  }
150  case PCM1774_0:
151  {
152  if( BSP_PCM1774_CODEC_Init(handle, Volume, AudioFreq) == COMPONENT_ERROR )
153  {
154  return COMPONENT_ERROR;
155  }
156  break;
157  }
158  }
159 
160  /* SAI data transfer preparation:
161  Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
162  SAIx_Init(AudioFreq);
163 
164  return COMPONENT_OK;
165 }
166 
167 static DrvStatusTypeDef BSP_PCM1774_CODEC_Init( void **handle, uint8_t Volume, uint32_t AudioFreq)
168 {
169  AUDIO_DrvTypeDef *driver = NULL;
170 
171  if(CODEC_Handle[PCM1774_0].isInitialized == 1)
172  {
173  /* We have reached the max num of instance for this component */
174  return COMPONENT_ERROR;
175  }
176 
177  if (Sensor_IO_I2C_Init() == COMPONENT_ERROR )
178  {
179  return COMPONENT_ERROR;
180  }
181 
182  /* Setup handle. */
183  CODEC_Handle[PCM1774_0].who_am_i = 0;
184  CODEC_Handle[PCM1774_0].ifType = 0; // I2C interface
185  CODEC_Handle[PCM1774_0].address = PCM1774_CODEC_I2C_ADDRESS_LOW;
186  CODEC_Handle[PCM1774_0].instance = PCM1774_0;
187  CODEC_Handle[PCM1774_0].isInitialized = 0;
188  CODEC_Handle[PCM1774_0].isEnabled = 0;
189  CODEC_Handle[PCM1774_0].isCombo = 1;
190  CODEC_Handle[PCM1774_0].pData = ( void * )NULL;
191  CODEC_Handle[PCM1774_0].pVTable = ( void * )&PCM1774_drv;
192  CODEC_Handle[PCM1774_0].pExtVTable = 0;
193 
194  *handle = (void *)&CODEC_Handle[PCM1774_0];
195 
196  driver = ( AUDIO_DrvTypeDef * )((DrvContextTypeDef *)(*handle))->pVTable;
197 
198  if ( driver->Init == NULL )
199  {
200  memset((*handle), 0, sizeof(DrvContextTypeDef));
201  *handle = NULL;
202  return COMPONENT_ERROR;
203  }
204 
205  if (driver->Init( (DrvContextTypeDef *)(*handle), Volume, AudioFreq ) == COMPONENT_ERROR )
206  {
207  memset((*handle), 0, sizeof(DrvContextTypeDef));
208  *handle = NULL;
209  return COMPONENT_ERROR;
210  }
211 
212  return COMPONENT_OK;
213 }
214 
221 uint8_t BSP_AUDIO_OUT_Play(void *handle, uint16_t* pBuffer, uint32_t Size)
222 {
223  /* Start DMA transfer of PCM samples towards the serial audio interface */
224  if ( HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t *)pBuffer, DMA_MAX(Size))!= HAL_OK)
225  {
226  return AUDIO_ERROR;
227  }
228 
229  return AUDIO_OK;
230 }
231 
241 uint8_t BSP_AUDIO_OUT_Pause(void *handle)
242 {
243  /* Pause DMA transfer of PCM samples towards the serial audio interface */
244  if (HAL_SAI_DMAPause(&haudio_out_sai)!= HAL_OK)
245  {
246  return AUDIO_ERROR;
247  }
248 
249  return AUDIO_OK;
250 }
251 
260 uint8_t BSP_AUDIO_OUT_Resume(void *handle)
261 {
262  /* Call the Audio Codec Resume function */
263  /* Resume DMA transfer of PCM samples towards the serial audio interface */
264  if (HAL_SAI_DMAResume(&haudio_out_sai)!= HAL_OK)
265  {
266  return AUDIO_ERROR;
267  }
268  return AUDIO_OK;
269 }
270 
280 uint8_t BSP_AUDIO_OUT_Stop(void *handle, uint32_t Option)
281 {
282  DrvContextTypeDef *ctx = (DrvContextTypeDef *)handle;
283  AUDIO_DrvTypeDef *driver = NULL;
284 
285  if(ctx == NULL)
286  {
287  return COMPONENT_ERROR;
288  }
289 
290  driver = ( AUDIO_DrvTypeDef *)ctx->pVTable;
291 
292  if ( driver->Stop == NULL )
293  {
294  return COMPONENT_ERROR;
295  }
296 
297  if ( driver->Stop(ctx, Option ) == COMPONENT_ERROR )
298  {
299  return COMPONENT_ERROR;
300  }
301 
302  /* Stop DMA transfer of PCM samples towards the serial audio interface */
303  if (HAL_SAI_DMAStop(&haudio_out_sai)!= HAL_OK)
304  {
305  return COMPONENT_ERROR;
306  }
307  return COMPONENT_OK;
308 }
309 
317 uint8_t BSP_AUDIO_OUT_SetVolume(void *handle, uint8_t Volume)
318 {
319  DrvContextTypeDef *ctx = (DrvContextTypeDef *)handle;
320  AUDIO_DrvTypeDef *driver = NULL;
321 
322  if(ctx == NULL)
323  {
324  return COMPONENT_ERROR;
325  }
326 
327  driver = ( AUDIO_DrvTypeDef *)ctx->pVTable;
328 
329  if ( driver->SetVolume == NULL )
330  {
331  return COMPONENT_ERROR;
332  }
333 
334  if ( driver->SetVolume(ctx, Volume ) == COMPONENT_ERROR )
335  {
336  return COMPONENT_ERROR;
337  }
338 
339  return COMPONENT_OK;
340 }
341 
348 uint8_t BSP_AUDIO_OUT_SetMute(void *handle, uint32_t Cmd)
349 {
350  DrvContextTypeDef *ctx = (DrvContextTypeDef *)handle;
351  AUDIO_DrvTypeDef *driver = NULL;
352 
353  if(ctx == NULL)
354  {
355  return COMPONENT_ERROR;
356  }
357 
358  driver = ( AUDIO_DrvTypeDef *)ctx->pVTable;
359 
360  if ( driver->SetMute == NULL )
361  {
362  return COMPONENT_ERROR;
363  }
364 
365  if ( driver->SetMute(ctx, Cmd ) == COMPONENT_ERROR )
366  {
367  return COMPONENT_ERROR;
368  }
369 
370  return COMPONENT_OK;
371 }
372 
373 
382 __weak uint8_t BSP_AUDIO_OUT_ClockConfig(uint32_t AudioFreq, void *Params)
383 {
384  RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
385  HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct);
386 
387  /* SAI clock config
388  PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M
389  SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */
390  RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
391  RCC_ExCLKInitStruct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLSAI1;
392  RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 43;
393  RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = RCC_PLLP_DIV7;
394  RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1R = RCC_PLLR_DIV2;
395  RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1CFGR_PLLSAI1PEN;
396  HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct);
397 
398  return AUDIO_OK;
399 }
400 
408 uint8_t BSP_AUDIO_OUT_SetFrequency(void *handle, uint32_t AudioFreq)
409 {
410  BSP_AUDIO_OUT_ClockConfig(AudioFreq, NULL);
411  /* Disable SAI peripheral to allow access to SAI internal registers */
412  __HAL_SAI_DISABLE(&haudio_out_sai);
413 
414  /* Update the SAI audio frequency configuration */
415  haudio_out_sai.Init.Mckdiv = SAIClockDivider(AudioFreq);
416  HAL_SAI_Init(&haudio_out_sai);
417 
418  /* Enable SAI peripheral to generate MCLK */
419  __HAL_SAI_ENABLE(&haudio_out_sai);
420 
421  return AUDIO_OK;
422 }
423 
429 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
430 {
431  /* Manage the remaining file size and new address offset: This function
432  should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */
434 }
435 
441 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
442 {
443  /* Manage the remaining file size and new address offset: This function
444  should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */
446 }
447 
453 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
454 {
456 }
457 
463 {
464 }
465 
471 {
472 }
473 
479 {
480 }
481 
491 static void SAIx_MspInit(void)
492 {
493  static DMA_HandleTypeDef hdma_saiTx;
494  GPIO_InitTypeDef GPIO_InitStruct;
495  SAI_HandleTypeDef *hsai = &haudio_out_sai;
496 
497  /* Enable SAI clock */
498  AUDIO_SAIx_CLK_ENABLE();
499 
500  /* Enable GPIO clock */
501  AUDIO_SAIx_MCKB_SCKB_SDB_FSB_ENABLE();
502 
503  /* enable USB power for GPIOG */
504  HAL_PWREx_EnableVddIO2();
505 
506  /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
507  GPIO_InitStruct.Pin = AUDIO_SAIx_FSB_PIN | AUDIO_SAIx_SCKB_PIN | AUDIO_SAIx_SDB_PIN | AUDIO_SAIx_MCKB_PIN;
508  GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
509  GPIO_InitStruct.Pull = GPIO_NOPULL;
510  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
511  GPIO_InitStruct.Alternate = AUDIO_SAIx_MCKB_SCKB_SDB_FSB_AF;
512  HAL_GPIO_Init(AUDIO_SAIx_MCKB_SCKB_SDB_FSB_GPIO_PORT, &GPIO_InitStruct);
513 
514  /* Enable the DMA clock */
515  AUDIO_SAIx_DMAx_CLK_ENABLE();
516 
517  if(hsai->Instance == AUDIO_SAIx)
518  {
519  /* Configure the hdma_saiTx handle parameters */
520  hdma_saiTx.Init.Request = DMA_REQUEST_1;
521  hdma_saiTx.Init.Direction = DMA_MEMORY_TO_PERIPH;
522  hdma_saiTx.Init.PeriphInc = DMA_PINC_DISABLE;
523  hdma_saiTx.Init.MemInc = DMA_MINC_ENABLE;
524  hdma_saiTx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE;
525  hdma_saiTx.Init.MemDataAlignment = AUDIO_SAIx_DMAx_MEM_DATA_SIZE;
526  hdma_saiTx.Init.Mode = DMA_CIRCULAR;
527  hdma_saiTx.Init.Priority = DMA_PRIORITY_HIGH;
528 
529  hdma_saiTx.Instance = AUDIO_SAIx_DMAx_CHANNEL;
530 
531  /* Associate the DMA handle */
532  __HAL_LINKDMA(hsai, hdmatx, hdma_saiTx);
533 
534  /* Deinitialize the Stream for new transfer */
535  HAL_DMA_DeInit(&hdma_saiTx);
536 
537  /* Configure the DMA Stream */
538  HAL_DMA_Init(&hdma_saiTx);
539  }
540 
541  /* SAI DMA IRQ Channel configuration */
542  HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
543  HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ);
544 }
545 
553 static void SAIx_Init(uint32_t AudioFreq)
554 {
555  /* Initialize the haudio_out_sai Instance parameter */
556  haudio_out_sai.Instance = AUDIO_SAIx;
557 
558  /* Disable SAI peripheral to allow access to SAI internal registers */
559  __HAL_SAI_DISABLE(&haudio_out_sai);
560 
561  /* Configure SAI_Block_x
562  LSBFirst: Disabled
563  DataSize: 16 */
564  haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE;
565  haudio_out_sai.Init.Mckdiv = SAIClockDivider(AudioFreq);
566  haudio_out_sai.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
567  haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX;
568  haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
569  haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
570  haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
571  haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
572  haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
573  haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
574  haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
575  haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
576 
577  /* Configure SAI_Block_x Frame
578  Frame Length: 64
579  Frame active Length: 32
580  FS Definition: Start frame + Channel Side identification
581  FS Polarity: FS active Low
582  FS Offset: FS asserted one bit before the first bit of slot 0 */
583  haudio_out_sai.FrameInit.FrameLength = 32;
584  haudio_out_sai.FrameInit.ActiveFrameLength = 16;
585  haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
586  haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
587  haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
588 
589  /* Configure SAI Block_x Slot
590  Slot First Bit Offset: 0
591  Slot Size : 16
592  Slot Number: 4
593  Slot Active: All slot actives */
594  haudio_out_sai.SlotInit.FirstBitOffset = 0;
595  haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_16B;
596  haudio_out_sai.SlotInit.SlotNumber = 2;
597  haudio_out_sai.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
598 
599  /* Init the SAI */
600  SAIx_MspInit();
601 
602  HAL_SAI_Init(&haudio_out_sai);
603 
604  /* Enable SAI peripheral to generate MCLK */
605  __HAL_SAI_ENABLE(&haudio_out_sai);
606 }
607 /**************************/
608 
625 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
uint8_t BSP_AUDIO_OUT_SetVolume(void *handle, uint8_t Volume)
Controls the current audio volume level.
uint8_t BSP_AUDIO_OUT_Pause(void *handle)
This function Pauses the audio file stream. In case of using DMA, the DMA Pause feature is used...
uint8_t BSP_AUDIO_OUT_SetFrequency(void *handle, uint32_t AudioFreq)
Update the audio frequency.
__weak uint8_t BSP_AUDIO_OUT_ClockConfig(uint32_t AudioFreq, void *Params)
Clock Config.
void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
SAI error callbacks.
uint8_t BSP_AUDIO_OUT_Init(CODEX_ID_t id, void **handle, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
Configures the audio peripherals.
This file contains definitions for SensorTile_audio_out.c driver.
__weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
Manages the DMA Half Transfer complete event.
uint8_t BSP_AUDIO_OUT_SetMute(void *handle, uint32_t Cmd)
Enables or disables the MUTE mode by software.
void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
Tx Half Transfer completed callbacks.
static void SAIx_MspInit(void)
Initializes SAI MSP.
DrvStatusTypeDef Sensor_IO_I2C_Init(void)
Configures sensor SPI interface.
Definition: SensorTile.c:274
void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
Tx Transfer completed callbacks.
uint8_t BSP_AUDIO_OUT_Stop(void *handle, uint32_t Option)
Stops audio playing and Power down the Audio Codec.
__weak void BSP_AUDIO_OUT_Error_CallBack(void)
Manages the DMA FIFO error event.
uint8_t BSP_AUDIO_OUT_Resume(void *handle)
This function Resumes the audio file stream.
static void SAIx_Init(uint32_t AudioFreq)
Initializes the Audio Codec audio interface (SAI).
uint8_t BSP_AUDIO_OUT_Play(void *handle, uint16_t *pBuffer, uint32_t Size)
Starts playing audio stream from a data buffer for a determined size.
__weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
Manages the DMA full Transfer complete event.
Generated by   doxygen 1.8.13