STM32L476G_EVAL BSP User Manual
|
stm32l476g_eval_audio.c
Go to the documentation of this file.
00001 /** 00002 ****************************************************************************** 00003 * @file stm32l476g_eval_audio.c 00004 * @author MCD Application Team 00005 * @version $VERSION$ 00006 * @date $DATE$ 00007 * @brief This file provides the Audio driver for the STM32L476G-EVAL evaluation board. 00008 ****************************************************************************** 00009 * @attention 00010 * 00011 * <h2><center>© COPYRIGHT(c) 2015 STMicroelectronics</center></h2> 00012 * 00013 * Redistribution and use in source and binary forms, with or without modification, 00014 * are permitted provided that the following conditions are met: 00015 * 1. Redistributions of source code must retain the above copyright notice, 00016 * this list of conditions and the following disclaimer. 00017 * 2. Redistributions in binary form must reproduce the above copyright notice, 00018 * this list of conditions and the following disclaimer in the documentation 00019 * and/or other materials provided with the distribution. 00020 * 3. Neither the name of STMicroelectronics nor the names of its contributors 00021 * may be used to endorse or promote products derived from this software 00022 * without specific prior written permission. 00023 * 00024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 00025 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00026 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00027 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 00028 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00029 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 00030 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 00031 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00032 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 00033 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00034 * 00035 ****************************************************************************** 00036 */ 00037 00038 /*============================================================================== 00039 User NOTES 00040 00041 1. How To use this driver: 00042 -------------------------- 00043 + This driver supports STM32L4xx devices on STM32L476G-EVAL (MB1144) Evaluation boards. 00044 a) to play an audio file (all functions names start by BSP_AUDIO_OUT_xxx) 00045 b) to record an audio file through MP34DT01TR, ST MEMS (all functions names start by BSP_AUDIO_IN_xxx) 00046 00047 a) PLAY A FILE: 00048 ============== 00049 + Call the function BSP_AUDIO_OUT_Init( 00050 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 00051 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH) 00052 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%) 00053 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...) 00054 this parameter is relative to the audio file/stream type. 00055 ) 00056 This function configures all the hardware required for the audio application (codec, I2C, SAI, 00057 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK. 00058 If the returned value is different from AUDIO_OK or the function is stuck then the communication with 00059 the codec or the IOExpander has failed (try to un-plug the power or reset device in this case). 00060 - OUTPUT_DEVICE_SPEAKER : only speaker will be set as output for the audio stream. 00061 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream. 00062 - OUTPUT_DEVICE_BOTH : both Speaker and Headphone are used as outputs for the audio stream 00063 at the same time. 00064 + Call the function BSP_AUDIO_OUT_Play( 00065 pBuffer: pointer to the audio data file address 00066 Size : size of the buffer to be sent in Bytes 00067 ) 00068 to start playing (for the first time) from the audio file/stream. 00069 + Call the function BSP_AUDIO_OUT_Pause() to pause playing 00070 + Call the function BSP_AUDIO_OUT_Resume() to resume playing. 00071 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called 00072 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case). 00073 Note. This function should be called only when the audio file is played or paused (not stopped). 00074 + For each mode, you may need to implement the relative callback functions into your code. 00075 The Callback functions are named BSP_AUDIO_OUT_XXXCallBack() and only their prototypes are declared in 00076 the stm32l476g_eval_audio.h file. (refer to the example for more details on the callbacks implementations) 00077 + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 00078 the device output mode, the mute, the audio configuratio or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 00079 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(), 00080 BSP_AUDIO_OUT_SetMute(), BSP_AUDIO_OUT_ChangeAudioConfig() and BSP_AUDIO_OUT_Stop(). 00081 + The driver API and the callback functions are at the end of the stm32l476g_eval_audio.h file. 00082 00083 Driver architecture: 00084 -------------------- 00085 + This driver provide the High Audio Layer: consists of the function API exported in the stm32l476g_eval_audio.h file 00086 (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...) 00087 + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/ 00088 providing the audio file/stream. These functions are also included as local functions into 00089 the stm32l476g_eval_audio_codec.c file (SAIx_MspInit() and SAIx_Init()) 00090 00091 Known Limitations: 00092 ------------------ 00093 1- When using the Speaker, if the audio file quality is not high enough, the speaker output 00094 may produce high and uncomfortable noise level. To avoid this issue, to use speaker 00095 output properly, try to increase audio file sampling rate (typically higher than 48KHz). 00096 This operation will lead to larger file size. 00097 2- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some 00098 user interrupt routines (in this case, interrupts could be disabled just before the start of 00099 communication then re-enabled when it is over). Note that this communication is only done at 00100 the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is 00101 performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()). 00102 When the audio data is played, no communication is required with the audio codec. 00103 3- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 00104 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file. 00105 4- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 00106 Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams. 00107 5- Supports only Stereo audio streaming. 00108 6- Supports only 16-bits audio data size. 00109 00110 b) RECORD A FILE: 00111 ================ 00112 + Call the function BSP_AUDIO_IN_Init( 00113 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...) 00114 ) 00115 This function configures all the hardware required for the audio application (SAI, 00116 GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK. 00117 00118 + Call the function BSP_AUDIO_IN_Record( 00119 pbuf Main buffer pointer for the recorded data storing 00120 size Current size of the recorded buffer 00121 ) 00122 to start recording from the microphones. 00123 00124 + User needs to implement user callbacks to follow the process of data recorded in the record buffer 00125 (BSP_AUDIO_IN_HalfTransfer_CallBack()/BSP_AUDIO_IN_TransferComplete_CallBack() 00126 00127 + Call the function AUDIO_IN_STOP() to stop recording 00128 ==============================================================================*/ 00129 00130 /* Includes ------------------------------------------------------------------*/ 00131 #include "stm32l476g_eval_audio.h" 00132 00133 /** @addtogroup BSP 00134 * @{ 00135 */ 00136 00137 /** @addtogroup STM32L476G_EVAL 00138 * @{ 00139 */ 00140 00141 /** @defgroup STM32L476G_EVAL_AUDIO STM32L476G_EVAL AUDIO 00142 * @brief This file includes the low layer driver for wm8994 Audio Codec 00143 * available on STM32L476G-EVAL evaluation board(MB1144). 00144 * @{ 00145 */ 00146 00147 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Types Private Types 00148 * @{ 00149 */ 00150 typedef struct 00151 { 00152 uint32_t Frequency; /* Record Frequency */ 00153 uint32_t BitResolution; /* Record bit resolution */ 00154 uint32_t ChannelNbr; /* Record Channel Number */ 00155 uint16_t *pRecBuf; /* Pointer to record user buffer */ 00156 uint32_t RecSize; /* Size to record in mono, double size to record in stereo */ 00157 }AUDIOIN_TypeDef; 00158 /** 00159 * @} 00160 */ 00161 00162 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Constants Private Constants 00163 * @{ 00164 */ 00165 /** 00166 * @} 00167 */ 00168 00169 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Macros Private Macros 00170 * @{ 00171 */ 00172 /*### PLAY ###*/ 00173 /* SCK(kHz) = SAI_CK_x/(SAIClockDivider*2*256) */ 00174 #define SAIClockDivider(__FREQUENCY__) \ 00175 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 12 \ 00176 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 2 \ 00177 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 6 \ 00178 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 1 \ 00179 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \ 00180 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \ 00181 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 2 : 1 \ 00182 00183 /*### RECORD ###*/ 00184 #define DFSDMOverSampling(__FREQUENCY__) \ 00185 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 256 \ 00186 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \ 00187 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \ 00188 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \ 00189 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \ 00190 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64 \ 00191 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 16 \ 00192 00193 #define DFSDMClockDivider(__FREQUENCY__) \ 00194 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \ 00195 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \ 00196 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \ 00197 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \ 00198 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \ 00199 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4 \ 00200 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 32 \ 00201 00202 #define DFSDMFilterOrder(__FREQUENCY__) \ 00203 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? DFSDM_FILTER_SINC3_ORDER \ 00204 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \ 00205 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \ 00206 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \ 00207 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \ 00208 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC4_ORDER \ 00209 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC5_ORDER \ 00210 00211 #define DFSDMRightBitShift(__FREQUENCY__) \ 00212 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 3 \ 00213 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 3 \ 00214 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 0 \ 00215 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 0 \ 00216 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \ 00217 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 3 \ 00218 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 0 : 0 \ 00219 00220 /* Saturate the record PCM sample */ 00221 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N))) 00222 00223 /** 00224 * @} 00225 */ 00226 00227 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Variables Private Variables 00228 * @{ 00229 */ 00230 /*### PLAY ###*/ 00231 AUDIO_DrvTypeDef *audio_drv; 00232 SAI_HandleTypeDef haudio_out_sai; 00233 00234 /*### RECORD ###*/ 00235 AUDIOIN_TypeDef audio_in_context; 00236 00237 DFSDM_Channel_HandleTypeDef haudio_in_dfsdm_leftchannel; 00238 DFSDM_Channel_HandleTypeDef haudio_in_dfsdm_rightchannel; 00239 DFSDM_Filter_HandleTypeDef haudio_in_dfsdm_leftfilter; 00240 DFSDM_Filter_HandleTypeDef haudio_in_dfsdm_rightfilter; 00241 DMA_HandleTypeDef hdma_dfsdm_left; 00242 DMA_HandleTypeDef hdma_dfsdm_right; 00243 00244 /* Buffers for right and left samples */ 00245 int32_t LeftRecBuff[INTERNAL_BUFF_SIZE]; 00246 int32_t RightRecBuff[INTERNAL_BUFF_SIZE]; 00247 00248 /* Buffers status flags */ 00249 uint32_t DmaLeftRecHalfBuffCplt = 0; 00250 uint32_t DmaLeftRecBuffCplt = 0; 00251 uint32_t DmaRightRecHalfBuffCplt = 0; 00252 uint32_t DmaRightRecBuffCplt = 0; 00253 00254 /* Application Buffer Trigger */ 00255 __IO uint32_t AppBuffTrigger = 0; 00256 uint32_t __IO AppBuffHalf = 0; 00257 00258 /* Default record volume */ 00259 uint16_t __IO AudioInVolume = DEFAULT_AUDIO_IN_VOLUME; 00260 00261 /** 00262 * @} 00263 */ 00264 00265 /** @defgroup STM32L476G_EVAL_AUDIO_Private_Functions Private Functions 00266 * @{ 00267 */ 00268 static void CODEC_Reset(void); 00269 static void SAIx_MspInit(void); 00270 static void SAIx_Init(uint32_t AudioFreq); 00271 static void DFSDMx_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); 00272 static void DFSDMx_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); 00273 static void DFSDMx_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel); 00274 static void DFSDMx_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter); 00275 static uint8_t DFSDMx_Init(uint32_t AudioFreq); 00276 static uint8_t DFSDMx_DeInit(void); 00277 /** 00278 * @} 00279 */ 00280 00281 /** @addtogroup STM32L476G_EVAL_AUDIO_Exported_Functions 00282 * @{ 00283 */ 00284 00285 /** 00286 * @brief Configures the audio peripherals. 00287 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE, 00288 * or OUTPUT_DEVICE_BOTH. 00289 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max)) 00290 * @param AudioFreq: Audio frequency used to play the audio stream. 00291 * @note The SAI PLL input clock must be done in the user application. 00292 * @retval AUDIO_OK if correct communication, else wrong communication 00293 */ 00294 uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq) 00295 { 00296 uint8_t ret = AUDIO_ERROR; 00297 uint32_t deviceid = 0x00; 00298 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct; 00299 00300 HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct); 00301 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00302 { 00303 /* Configure PLLSAI prescalers */ 00304 /* SAI clock config 00305 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 00306 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */ 00307 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00308 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 24; 00309 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 17; 00310 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 00311 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 00312 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00313 } 00314 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 00315 { 00316 /* SAI clock config 00317 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 00318 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */ 00319 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00320 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 43; 00321 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 7; 00322 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 00323 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 00324 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00325 } 00326 00327 /* SAI data transfer preparation: 00328 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00329 SAIx_Init(AudioFreq); 00330 00331 /* wm8994 codec initialization */ 00332 deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS); 00333 00334 /* Reset the Codec Registers */ 00335 CODEC_Reset(); 00336 00337 if((deviceid) == WM8994_ID) 00338 { 00339 /* Initialize the audio driver structure */ 00340 audio_drv = &wm8994_drv; 00341 ret = AUDIO_OK; 00342 } 00343 else 00344 { 00345 ret = AUDIO_ERROR; 00346 } 00347 00348 if(ret == AUDIO_OK) 00349 { 00350 /* Initialize the codec internal registers */ 00351 audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq); 00352 } 00353 00354 /* Set the request volume */ 00355 BSP_AUDIO_OUT_SetVolume(Volume); 00356 00357 return ret; 00358 } 00359 00360 /** 00361 * @brief Starts playing audio stream from a data buffer for a determined size. 00362 * @param pBuffer: Pointer to the buffer 00363 * @param Size: Number of audio data BYTES. 00364 * @retval AUDIO_OK if correct communication, else wrong communication 00365 */ 00366 uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size) 00367 { 00368 /* Call the audio Codec Play function */ 00369 if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0) 00370 { 00371 return AUDIO_ERROR; 00372 } 00373 else 00374 { 00375 /* Update the Media layer and enable it for play */ 00376 HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t *)pBuffer, DMA_MAX(Size)); 00377 00378 return AUDIO_OK; 00379 } 00380 } 00381 00382 /** 00383 * @brief Sends n-Bytes on the SAI interface. 00384 * @param pData: pointer on data address 00385 * @param Size: number of data to be written 00386 * @retval AUDIO_OK if correct communication, else wrong communication 00387 */ 00388 uint8_t BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size) 00389 { 00390 return (HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t *)pData, Size)); 00391 } 00392 00393 /** 00394 * @brief This function Pauses the audio file stream. In case 00395 * of using DMA, the DMA Pause feature is used. 00396 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00397 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00398 * function for resume could lead to unexpected behavior). 00399 * @retval AUDIO_OK if correct communication, else wrong communication 00400 */ 00401 uint8_t BSP_AUDIO_OUT_Pause(void) 00402 { 00403 /* Call the Audio Codec Pause/Resume function */ 00404 if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0) 00405 { 00406 return AUDIO_ERROR; 00407 } 00408 else 00409 { 00410 /* Call the Media layer pause function */ 00411 HAL_SAI_DMAPause(&haudio_out_sai); 00412 00413 /* Return AUDIO_OK when all operations are correctly done */ 00414 return AUDIO_OK; 00415 } 00416 } 00417 00418 /** 00419 * @brief This function Resumes the audio file stream. 00420 * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only 00421 * BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 00422 * function for resume could lead to unexpected behavior). 00423 * @retval AUDIO_OK if correct communication, else wrong communication 00424 */ 00425 uint8_t BSP_AUDIO_OUT_Resume(void) 00426 { 00427 /* Call the Audio Codec Pause/Resume function */ 00428 if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0) 00429 { 00430 return AUDIO_ERROR; 00431 } 00432 else 00433 { 00434 /* Call the Media layer pause/resume function */ 00435 HAL_SAI_DMAResume(&haudio_out_sai); 00436 00437 /* Return AUDIO_OK when all operations are correctly done */ 00438 return AUDIO_OK; 00439 } 00440 } 00441 00442 /** 00443 * @brief Stops audio playing and Power down the Audio Codec. 00444 * @param Option: could be one of the following parameters 00445 * - CODEC_PDWN_SW: for software power off (by writing registers). 00446 * Then no need to reconfigure the Codec after power on. 00447 * - CODEC_PDWN_HW: completely shut down the codec (physically). 00448 * Then need to reconfigure the Codec after power on. 00449 * @retval AUDIO_OK if correct communication, else wrong communication 00450 */ 00451 uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option) 00452 { 00453 /* Call the Media layer stop function */ 00454 HAL_SAI_DMAStop(&haudio_out_sai); 00455 00456 /* Call Audio Codec Stop function */ 00457 if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0) 00458 { 00459 return AUDIO_ERROR; 00460 } 00461 else 00462 { 00463 if(Option == CODEC_PDWN_HW) 00464 { 00465 /* Wait at least 100us */ 00466 HAL_Delay(1); 00467 00468 /* Power Down the codec */ 00469 HAL_GPIO_WritePin(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, GPIO_PIN_RESET); 00470 00471 } 00472 /* Return AUDIO_OK when all operations are correctly done */ 00473 return AUDIO_OK; 00474 } 00475 } 00476 00477 /** 00478 * @brief Controls the current audio volume level. 00479 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 00480 * Mute and 100 for Max volume level). 00481 * @retval AUDIO_OK if correct communication, else wrong communication 00482 */ 00483 uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume) 00484 { 00485 /* Call the codec volume control function with converted volume value */ 00486 if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0) 00487 { 00488 return AUDIO_ERROR; 00489 } 00490 else 00491 { 00492 /* Return AUDIO_OK when all operations are correctly done */ 00493 return AUDIO_OK; 00494 } 00495 } 00496 00497 /** 00498 * @brief Enables or disables the MUTE mode by software 00499 * @param Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 00500 * unmute the codec and restore previous volume level. 00501 * @retval AUDIO_OK if correct communication, else wrong communication 00502 */ 00503 uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd) 00504 { 00505 /* Call the Codec Mute function */ 00506 if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0) 00507 { 00508 return AUDIO_ERROR; 00509 } 00510 else 00511 { 00512 /* Return AUDIO_OK when all operations are correctly done */ 00513 return AUDIO_OK; 00514 } 00515 } 00516 00517 /** 00518 * @brief Switch dynamically (while audio file is played) the output target 00519 * (speaker or headphone). 00520 * @param Output: The audio output target: OUTPUT_DEVICE_SPEAKER, 00521 * OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH 00522 * @retval AUDIO_OK if correct communication, else wrong communication 00523 */ 00524 uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output) 00525 { 00526 /* Call the Codec output device function */ 00527 if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0) 00528 { 00529 return AUDIO_ERROR; 00530 } 00531 else 00532 { 00533 /* Return AUDIO_OK when all operations are correctly done */ 00534 return AUDIO_OK; 00535 } 00536 } 00537 00538 /** 00539 * @brief Update the audio frequency. 00540 * @param AudioFreq: Audio frequency used to play the audio stream. 00541 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00542 * audio frequency. 00543 * @retval None 00544 */ 00545 void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq) 00546 { 00547 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct; 00548 00549 HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct); 00550 00551 /* Update the PLL configuration according to the new frequency */ 00552 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00553 { 00554 /* Configure PLLSAI prescalers */ 00555 /* SAI clock config 00556 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 00557 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */ 00558 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00559 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 24; 00560 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 17; 00561 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 00562 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 00563 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00564 } 00565 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 00566 { 00567 /* SAI clock config 00568 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 00569 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */ 00570 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00571 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 43; 00572 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 7; 00573 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 00574 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 00575 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00576 } 00577 /* Disable SAI peripheral to allow access to SAI internal registers */ 00578 __HAL_SAI_DISABLE(&haudio_out_sai); 00579 00580 /* Update the SAI audio frequency configuration */ 00581 haudio_out_sai.Init.Mckdiv = SAIClockDivider(AudioFreq); 00582 HAL_SAI_Init(&haudio_out_sai); 00583 00584 /* Enable SAI peripheral to generate MCLK */ 00585 __HAL_SAI_ENABLE(&haudio_out_sai); 00586 } 00587 00588 /** 00589 * @brief Updates the Audio frame slot configuration. 00590 * @param AudioFrameSlot: specifies the audio Frame slot 00591 * This parameter can be any value of @ref CODEC_AudioFrame_SLOT_TDMMode 00592 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00593 * audio frame slot. 00594 * @retval None 00595 */ 00596 void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot) 00597 { 00598 /* Disable SAI peripheral to allow access to SAI internal registers */ 00599 __HAL_SAI_DISABLE(&haudio_out_sai); 00600 00601 /* Update the SAI audio frame slot configuration */ 00602 haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot; 00603 HAL_SAI_Init(&haudio_out_sai); 00604 00605 /* Enable SAI peripheral to generate MCLK */ 00606 __HAL_SAI_ENABLE(&haudio_out_sai); 00607 } 00608 00609 /** 00610 * @brief Changes the Audio Out Configuration. 00611 * @param AudioOutOption: specifies the audio out new configuration 00612 * This parameter can be any value of @ref BSP_Audio_Out_Option 00613 * @note This API should be called after the BSP_AUDIO_OUT_Init() to adjust the 00614 * audio out configuration. 00615 * @retval None 00616 */ 00617 void BSP_AUDIO_OUT_ChangeAudioConfig(uint32_t AudioOutOption) 00618 { 00619 /********** Playback Buffer circular/normal mode **********/ 00620 if(AudioOutOption & BSP_AUDIO_OUT_CIRCULARMODE) 00621 { 00622 /* Deinitialize the Stream to update DMA mode */ 00623 HAL_DMA_DeInit(haudio_out_sai.hdmatx); 00624 00625 /* Update the SAI audio Transfer DMA mode */ 00626 haudio_out_sai.hdmatx->Init.Mode = DMA_CIRCULAR; 00627 00628 /* Configure the DMA Stream with new Transfer DMA mode */ 00629 HAL_DMA_Init(haudio_out_sai.hdmatx); 00630 } 00631 else /* BSP_AUDIO_OUT_NORMALMODE */ 00632 { 00633 /* Deinitialize the Stream to update DMA mode */ 00634 HAL_DMA_DeInit(haudio_out_sai.hdmatx); 00635 00636 /* Update the SAI audio Transfer DMA mode */ 00637 haudio_out_sai.hdmatx->Init.Mode = DMA_NORMAL; 00638 00639 /* Configure the DMA Stream with new Transfer DMA mode */ 00640 HAL_DMA_Init(haudio_out_sai.hdmatx); 00641 } 00642 00643 /********** Playback Buffer stereo/mono mode **********/ 00644 if(AudioOutOption & BSP_AUDIO_OUT_STEREOMODE) 00645 { 00646 /* Disable SAI peripheral to allow access to SAI internal registers */ 00647 __HAL_SAI_DISABLE(&haudio_out_sai); 00648 00649 /* Update the SAI audio frame slot configuration */ 00650 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 00651 HAL_SAI_Init(&haudio_out_sai); 00652 00653 /* Enable SAI peripheral to generate MCLK */ 00654 __HAL_SAI_ENABLE(&haudio_out_sai); 00655 } 00656 else /* BSP_AUDIO_OUT_MONOMODE */ 00657 { 00658 /* Disable SAI peripheral to allow access to SAI internal registers */ 00659 __HAL_SAI_DISABLE(&haudio_out_sai); 00660 00661 /* Update the SAI audio frame slot configuration */ 00662 haudio_out_sai.Init.MonoStereoMode = SAI_MONOMODE; 00663 HAL_SAI_Init(&haudio_out_sai); 00664 00665 /* Enable SAI peripheral to generate MCLK */ 00666 __HAL_SAI_ENABLE(&haudio_out_sai); 00667 } 00668 } 00669 00670 /** 00671 * @brief Tx Transfer completed callbacks. 00672 * @param hsai: SAI handle 00673 * @retval None 00674 */ 00675 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai) 00676 { 00677 /* Manage the remaining file size and new address offset: This function 00678 should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */ 00679 BSP_AUDIO_OUT_TransferComplete_CallBack(); 00680 } 00681 00682 /** 00683 * @brief Tx Half Transfer completed callbacks. 00684 * @param hsai: SAI handle 00685 * @retval None 00686 */ 00687 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai) 00688 { 00689 /* Manage the remaining file size and new address offset: This function 00690 should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */ 00691 BSP_AUDIO_OUT_HalfTransfer_CallBack(); 00692 } 00693 00694 /** 00695 * @brief SAI error callbacks. 00696 * @param hsai: SAI handle 00697 * @retval None 00698 */ 00699 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai) 00700 { 00701 BSP_AUDIO_OUT_Error_CallBack(); 00702 } 00703 00704 /** 00705 * @brief Manages the DMA full Transfer complete event. 00706 * @retval None 00707 */ 00708 __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void) 00709 { 00710 } 00711 00712 /** 00713 * @brief Manages the DMA Half Transfer complete event. 00714 * @retval None 00715 */ 00716 __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void) 00717 { 00718 } 00719 00720 /** 00721 * @brief Manages the DMA FIFO error event. 00722 * @retval None 00723 */ 00724 __weak void BSP_AUDIO_OUT_Error_CallBack(void) 00725 { 00726 } 00727 00728 /** 00729 * @} 00730 */ 00731 00732 /** @addtogroup STM32L476G_EVAL_AUDIO_Private_Functions 00733 * @{ 00734 */ 00735 00736 /******************************************************************************* 00737 Static Functions 00738 *******************************************************************************/ 00739 /** 00740 * @brief Initializes SAI MSP. 00741 * @retval None 00742 */ 00743 static void SAIx_MspInit(void) 00744 { 00745 static DMA_HandleTypeDef hdma_saiTx; 00746 GPIO_InitTypeDef GPIO_InitStruct; 00747 SAI_HandleTypeDef *hsai = &haudio_out_sai; 00748 00749 /* Enable SAI clock */ 00750 AUDIO_SAIx_CLK_ENABLE(); 00751 00752 /* Enable GPIO clock */ 00753 AUDIO_SAIx_MCKB_SCKB_SDB_FSB_ENABLE(); 00754 00755 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ 00756 GPIO_InitStruct.Pin = AUDIO_SAIx_FSB_PIN | AUDIO_SAIx_SCKB_PIN | AUDIO_SAIx_SDB_PIN | AUDIO_SAIx_MCKB_PIN; 00757 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 00758 GPIO_InitStruct.Pull = GPIO_NOPULL; 00759 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 00760 GPIO_InitStruct.Alternate = AUDIO_SAIx_MCKB_SCKB_SDB_FSB_AF; 00761 HAL_GPIO_Init(AUDIO_SAIx_MCKB_SCKB_SDB_FSB_GPIO_PORT, &GPIO_InitStruct); 00762 00763 /* Enable the DMA clock */ 00764 AUDIO_SAIx_DMAx_CLK_ENABLE(); 00765 00766 if(hsai->Instance == AUDIO_SAIx) 00767 { 00768 /* Configure the hdma_saiTx handle parameters */ 00769 hdma_saiTx.Init.Request = DMA_REQUEST_1; 00770 hdma_saiTx.Init.Direction = DMA_MEMORY_TO_PERIPH; 00771 hdma_saiTx.Init.PeriphInc = DMA_PINC_DISABLE; 00772 hdma_saiTx.Init.MemInc = DMA_MINC_ENABLE; 00773 hdma_saiTx.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE; 00774 hdma_saiTx.Init.MemDataAlignment = AUDIO_SAIx_DMAx_MEM_DATA_SIZE; 00775 hdma_saiTx.Init.Mode = DMA_NORMAL; 00776 hdma_saiTx.Init.Priority = DMA_PRIORITY_HIGH; 00777 00778 hdma_saiTx.Instance = AUDIO_SAIx_DMAx_CHANNEL; 00779 00780 /* Associate the DMA handle */ 00781 __HAL_LINKDMA(hsai, hdmatx, hdma_saiTx); 00782 00783 /* Deinitialize the Stream for new transfer */ 00784 HAL_DMA_DeInit(&hdma_saiTx); 00785 00786 /* Configure the DMA Stream */ 00787 HAL_DMA_Init(&hdma_saiTx); 00788 } 00789 00790 /* SAI DMA IRQ Channel configuration */ 00791 HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 00792 HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ); 00793 } 00794 00795 /** 00796 * @brief Initializes the Audio Codec audio interface (SAI). 00797 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00798 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 00799 * and user can update this configuration using 00800 * @retval None 00801 */ 00802 static void SAIx_Init(uint32_t AudioFreq) 00803 { 00804 /* Initialize the haudio_out_sai Instance parameter */ 00805 haudio_out_sai.Instance = AUDIO_SAIx; 00806 00807 /* Disable SAI peripheral to allow access to SAI internal registers */ 00808 __HAL_SAI_DISABLE(&haudio_out_sai); 00809 00810 /* Configure SAI_Block_x 00811 LSBFirst: Disabled 00812 DataSize: 16 */ 00813 haudio_out_sai.Init.MonoStereoMode = SAI_STEREOMODE; 00814 haudio_out_sai.Init.Mckdiv = SAIClockDivider(AudioFreq); 00815 haudio_out_sai.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV; 00816 haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX; 00817 haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE; 00818 haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL; 00819 haudio_out_sai.Init.DataSize = SAI_DATASIZE_16; 00820 haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB; 00821 haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; 00822 haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS; 00823 haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; 00824 haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; 00825 00826 /* Configure SAI_Block_x Frame 00827 Frame Length: 64 00828 Frame active Length: 32 00829 FS Definition: Start frame + Channel Side identification 00830 FS Polarity: FS active Low 00831 FS Offset: FS asserted one bit before the first bit of slot 0 */ 00832 haudio_out_sai.FrameInit.FrameLength = 64; 00833 haudio_out_sai.FrameInit.ActiveFrameLength = 32; 00834 haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION; 00835 haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW; 00836 haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; 00837 00838 /* Configure SAI Block_x Slot 00839 Slot First Bit Offset: 0 00840 Slot Size : 16 00841 Slot Number: 4 00842 Slot Active: All slot actives */ 00843 haudio_out_sai.SlotInit.FirstBitOffset = 0; 00844 haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE; 00845 haudio_out_sai.SlotInit.SlotNumber = 4; 00846 haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123; 00847 00848 /* Init the SAI */ 00849 SAIx_MspInit(); 00850 00851 HAL_SAI_Init(&haudio_out_sai); 00852 00853 /* Enable SAI peripheral to generate MCLK */ 00854 __HAL_SAI_ENABLE(&haudio_out_sai); 00855 } 00856 00857 /** 00858 * @brief Resets the audio codec. It restores the default configuration of the 00859 * codec (this function shall be called before initializing the codec). 00860 * @retval None 00861 */ 00862 static void CODEC_Reset(void) 00863 { 00864 /* Initialize the audio driver structure */ 00865 audio_drv = &wm8994_drv; 00866 00867 audio_drv->Reset(AUDIO_I2C_ADDRESS); 00868 } 00869 00870 /** 00871 * @} 00872 */ 00873 00874 /** @addtogroup STM32L476G_EVAL_AUDIO_Exported_Functions 00875 * @{ 00876 */ 00877 00878 /** 00879 * @brief Initializes wave recording. 00880 * @note This function assumes that the SAI input clock (through PLL_M) 00881 * is already configured and ready to be used. 00882 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral. 00883 * @param BitRes: Audio frequency to be configured for the SAI peripheral. 00884 * @param ChnlNbr: Audio frequency to be configured for the SAI peripheral. 00885 * @retval AUDIO_OK if correct communication, else wrong communication 00886 */ 00887 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr) 00888 { 00889 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct; 00890 uint32_t ret = AUDIO_ERROR; 00891 00892 /* Store the audio record context */ 00893 audio_in_context.Frequency = AudioFreq; 00894 audio_in_context.BitResolution = BitRes; 00895 audio_in_context.ChannelNbr = ChnlNbr; 00896 00897 /* Update the PLL configuration according to the new frequency */ 00898 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00899 { 00900 /* Configure PLLSAI prescalers */ 00901 /* SAI clock config 00902 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 00903 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */ 00904 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00905 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 24; 00906 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 17; 00907 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 00908 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 00909 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00910 } 00911 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 00912 { 00913 /* SAI clock config 00914 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 00915 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */ 00916 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 00917 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 43; 00918 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 7; 00919 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 00920 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 00921 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 00922 } 00923 00924 /* SAI data transfer preparation: 00925 Prepare the Media to be used for the audio transfer from memory to SAI peripheral */ 00926 ret = DFSDMx_Init(AudioFreq); 00927 00928 /* Return AUDIO_OK when all operations are correctly done */ 00929 return ret; 00930 } 00931 00932 /** 00933 * @brief DeInitializes the audio peripheral. 00934 * @retval None 00935 */ 00936 void BSP_AUDIO_IN_DeInit(void) 00937 { 00938 DFSDMx_DeInit(); 00939 } 00940 00941 /** 00942 * @brief Starts audio recording. 00943 * @param pbuf: Main buffer pointer for the recorded data storing 00944 * @param size: Current size of the recorded buffer 00945 * @note The Right channel is start at first with synchro on start of Left channel 00946 * @retval AUDIO_OK if correct communication, else wrong communication 00947 */ 00948 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size) 00949 { 00950 uint8_t ret = AUDIO_ERROR; 00951 00952 audio_in_context.pRecBuf = pbuf; 00953 audio_in_context.RecSize = size; 00954 /* Reset Application Buffer Trigger */ 00955 AppBuffTrigger = 0; 00956 AppBuffHalf = 0; 00957 00958 if(audio_in_context.ChannelNbr == 2) 00959 { 00960 /* Call the Media layer start function for right channel */ 00961 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_rightfilter, (int32_t*)RightRecBuff, INTERNAL_BUFF_SIZE)) 00962 { 00963 return ret; 00964 } 00965 } 00966 00967 /* Call the Media layer start function for left channel */ 00968 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_leftfilter, (int32_t*)LeftRecBuff, INTERNAL_BUFF_SIZE)) 00969 { 00970 return ret; 00971 } 00972 00973 /* Return AUDIO_OK when all operations are correctly done */ 00974 ret = AUDIO_OK; 00975 00976 return ret; 00977 } 00978 00979 /** 00980 * @brief Updates the audio frequency. 00981 * @param AudioFreq: Audio frequency used to record the audio stream. 00982 * @note This API should be called after the BSP_AUDIO_IN_Init() to adjust the 00983 * audio frequency. 00984 * @retval AUDIO_OK if correct communication, else wrong communication 00985 */ 00986 uint8_t BSP_AUDIO_IN_SetFrequency(uint32_t AudioFreq) 00987 { 00988 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct; 00989 00990 HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct); 00991 00992 /* Update the PLL configuration according to the new frequency */ 00993 if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K)) 00994 { 00995 /* Configure PLLSAI prescalers */ 00996 /* SAI clock config 00997 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M 00998 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */ 00999 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 01000 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 24; 01001 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 17; 01002 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 01003 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 01004 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 01005 } 01006 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */ 01007 { 01008 /* SAI clock config 01009 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M 01010 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */ 01011 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1; 01012 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 43; 01013 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 7; 01014 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK; 01015 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1; 01016 HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct); 01017 } 01018 01019 /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */ 01020 if(AUDIO_OK != DFSDMx_DeInit()) 01021 { 01022 return AUDIO_ERROR; 01023 } 01024 01025 /* Initializes the Digital Filter for Sigma-Delta Modulators interface */ 01026 if(AUDIO_OK != DFSDMx_Init(AudioFreq)) 01027 { 01028 return AUDIO_ERROR; 01029 } 01030 01031 /* Return AUDIO_OK when all operations are correctly done */ 01032 return AUDIO_OK; 01033 } 01034 01035 /** 01036 * @brief Regular conversion complete callback. 01037 * @note In interrupt mode, user has to read conversion value in this function 01038 using HAL_DFSDM_FilterGetRegularValue. 01039 * @param hdfsdm_filter : DFSDM filter handle. 01040 * @retval None 01041 */ 01042 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01043 { 01044 uint32_t index; 01045 01046 /* Stereo Channels treatment */ 01047 if(audio_in_context.ChannelNbr == 2) 01048 { 01049 if(hdfsdm_filter == &haudio_in_dfsdm_leftfilter) 01050 { 01051 DmaLeftRecBuffCplt = 1; 01052 } 01053 else 01054 { 01055 DmaRightRecBuffCplt = 1; 01056 } 01057 01058 if((DmaRightRecBuffCplt == 1) && (DmaLeftRecBuffCplt == 1)) 01059 { 01060 if(AppBuffTrigger >= audio_in_context.RecSize) 01061 AppBuffTrigger = 0; 01062 01063 for(index = (INTERNAL_BUFF_SIZE/2) ; index < INTERNAL_BUFF_SIZE; index++) 01064 { 01065 audio_in_context.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((LeftRecBuff[index] >> 8), -32760, 32760)); 01066 audio_in_context.pRecBuf[AppBuffTrigger + 1] = (uint16_t)(SaturaLH((RightRecBuff[index] >> 8), -32760, 32760)); 01067 AppBuffTrigger += 2; 01068 } 01069 DmaRightRecBuffCplt = DmaLeftRecBuffCplt = 0; 01070 } 01071 } 01072 else /* Mono Channel treatment */ 01073 { 01074 for(index = (INTERNAL_BUFF_SIZE/2); index < INTERNAL_BUFF_SIZE; index++) 01075 { 01076 audio_in_context.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((LeftRecBuff[index] >> 8), -32760, 32760)); 01077 AppBuffTrigger++; 01078 } 01079 } 01080 01081 /* Update Trigger with Remaining Byte before callback if necessary */ 01082 if(AppBuffTrigger >= audio_in_context.RecSize) 01083 { 01084 /* Reset Application Buffer Trigger */ 01085 AppBuffTrigger = 0; 01086 AppBuffHalf = 0; 01087 01088 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01089 BSP_AUDIO_IN_TransferComplete_CallBack(); 01090 } 01091 else if((AppBuffTrigger >= audio_in_context.RecSize/2)) 01092 { 01093 if(AppBuffHalf == 0) 01094 { 01095 AppBuffHalf = 1; 01096 /* Manage the remaining file size and new address offset: This function 01097 should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */ 01098 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01099 } 01100 } 01101 } 01102 01103 /** 01104 * @brief Half regular conversion complete callback. 01105 * @param hdfsdm_filter : DFSDM filter handle. 01106 * @retval None 01107 */ 01108 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01109 { 01110 uint32_t index; 01111 01112 /* Stereo Channels treatment */ 01113 if(audio_in_context.ChannelNbr == 2) 01114 { 01115 if(hdfsdm_filter == &haudio_in_dfsdm_leftfilter) 01116 { 01117 DmaLeftRecHalfBuffCplt = 1; 01118 } 01119 else 01120 { 01121 DmaRightRecHalfBuffCplt = 1; 01122 } 01123 01124 if((DmaRightRecHalfBuffCplt == 1) && (DmaLeftRecHalfBuffCplt == 1)) 01125 { 01126 if(AppBuffTrigger >= audio_in_context.RecSize) 01127 AppBuffTrigger = 0; 01128 01129 for(index = 0; index < INTERNAL_BUFF_SIZE/2; index++) 01130 { 01131 audio_in_context.pRecBuf[AppBuffTrigger] = (int16_t)(SaturaLH((LeftRecBuff[index] >> 8), -32760, 32760)); 01132 audio_in_context.pRecBuf[AppBuffTrigger + 1] = (int16_t)(SaturaLH((RightRecBuff[index] >> 8), -32760, 32760)); 01133 AppBuffTrigger += 2; 01134 } 01135 DmaRightRecHalfBuffCplt = DmaLeftRecHalfBuffCplt = 0; 01136 } 01137 } 01138 else /* Mono Channel treatment */ 01139 { 01140 for(index = 0; index < (INTERNAL_BUFF_SIZE/2); index++) 01141 { 01142 audio_in_context.pRecBuf[AppBuffTrigger] = (uint16_t)(SaturaLH((LeftRecBuff[index] >> 8), -32760, 32760)); 01143 AppBuffTrigger++; 01144 } 01145 } 01146 01147 /* Update Trigger with Remaining Byte before callback if necessary */ 01148 if(AppBuffTrigger >= audio_in_context.RecSize) 01149 { 01150 /* Reset Application Buffer Trigger */ 01151 AppBuffTrigger = 0; 01152 AppBuffHalf = 0; 01153 01154 /* Call the record update function to get the next buffer to fill and its size (size is ignored) */ 01155 BSP_AUDIO_IN_TransferComplete_CallBack(); 01156 } 01157 else if((AppBuffTrigger >= audio_in_context.RecSize/2)) 01158 { 01159 if(AppBuffHalf == 0) 01160 { 01161 AppBuffHalf = 1; 01162 /* Manage the remaining file size and new address offset: This function 01163 should be coded by user (its prototype is already declared in stm32l476g_eval_audio.h) */ 01164 BSP_AUDIO_IN_HalfTransfer_CallBack(); 01165 } 01166 } 01167 } 01168 01169 /** 01170 * @brief Stops audio recording. 01171 * @retval AUDIO_OK if correct communication, else wrong communication 01172 */ 01173 uint8_t BSP_AUDIO_IN_Stop(void) 01174 { 01175 uint32_t ret = AUDIO_ERROR; 01176 01177 AppBuffTrigger = 0; 01178 AppBuffHalf = 0; 01179 01180 if(audio_in_context.ChannelNbr == 2) 01181 { 01182 /* Call the Media layer stop function for right channel */ 01183 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_rightfilter)) 01184 { 01185 return ret; 01186 } 01187 } 01188 01189 /* Call the Media layer stop function for left channel */ 01190 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_leftfilter)) 01191 { 01192 return ret; 01193 } 01194 01195 /* Return AUDIO_OK when all operations are correctly done */ 01196 ret = AUDIO_OK; 01197 01198 return ret; 01199 } 01200 01201 /** 01202 * @brief Pauses the audio file stream. 01203 * @retval AUDIO_OK if correct communication, else wrong communication 01204 */ 01205 uint8_t BSP_AUDIO_IN_Pause(void) 01206 { 01207 if(audio_in_context.ChannelNbr == 2) 01208 { 01209 /* Call the Media layer stop function */ 01210 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_rightfilter)) 01211 { 01212 return AUDIO_ERROR; 01213 } 01214 } 01215 01216 /* Call the Media layer stop function */ 01217 if(HAL_OK != HAL_DFSDM_FilterRegularStop_DMA(&haudio_in_dfsdm_leftfilter)) 01218 { 01219 return AUDIO_ERROR; 01220 } 01221 01222 /* Return AUDIO_OK when all operations are correctly done */ 01223 return AUDIO_OK; 01224 } 01225 01226 /** 01227 * @brief Resumes the audio file stream. 01228 * @note The Right channel is start a first with synchro on start Left channel 01229 * @retval AUDIO_OK if correct communication, else wrong communication 01230 */ 01231 uint8_t BSP_AUDIO_IN_Resume(void) 01232 { 01233 uint8_t ret = AUDIO_ERROR; 01234 01235 if(audio_in_context.ChannelNbr == 2) 01236 { 01237 /* Call the Media layer start function for right channel */ 01238 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_rightfilter, (int32_t*)RightRecBuff, (audio_in_context.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR))) 01239 { 01240 return ret; 01241 } 01242 } 01243 01244 /* Call the Media layer start function for left channel */ 01245 if(HAL_OK != HAL_DFSDM_FilterRegularStart_DMA(&haudio_in_dfsdm_leftfilter, (int32_t*)LeftRecBuff, (audio_in_context.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR))) 01246 { 01247 return ret; 01248 } 01249 01250 /* Return AUDIO_OK when all operations are correctly done */ 01251 return AUDIO_OK; 01252 } 01253 01254 /** 01255 * @brief Controls the audio in volume level. 01256 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for 01257 * Mute and 100 for Max volume level). 01258 * @retval AUDIO_OK if correct communication, else wrong communication 01259 */ 01260 uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume) 01261 { 01262 /* Set the Global variable AudioInVolume */ 01263 AudioInVolume = Volume; 01264 01265 /* Return AUDIO_OK when all operations are correctly done */ 01266 return AUDIO_OK; 01267 } 01268 01269 /** 01270 * @brief User callback when record buffer is filled. 01271 * @retval None 01272 */ 01273 __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void) 01274 { 01275 /* This function should be implemented by the user application. 01276 It is called into this driver when the current buffer is filled 01277 to prepare the next buffer pointer and its size. */ 01278 } 01279 01280 /** 01281 * @brief Manages the DMA Half Transfer complete event. 01282 * @retval None 01283 */ 01284 __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void) 01285 { 01286 /* This function should be implemented by the user application. 01287 It is called into this driver when the current buffer is filled 01288 to prepare the next buffer pointer and its size. */ 01289 } 01290 01291 /** 01292 * @brief Audio IN Error callback function. 01293 * @retval None 01294 */ 01295 __weak void BSP_AUDIO_IN_Error_Callback(void) 01296 { 01297 /* This function is called when an Interrupt due to transfer error on or peripheral 01298 error occurs. */ 01299 } 01300 01301 /** 01302 * @} 01303 */ 01304 01305 /** @addtogroup STM32L476G_EVAL_AUDIO_Private_Functions 01306 * @{ 01307 */ 01308 01309 /******************************************************************************* 01310 Static Functions 01311 *******************************************************************************/ 01312 /** 01313 * @brief Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01314 * @param AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral. 01315 * @retval AUDIO_OK if correct communication, else wrong communication 01316 */ 01317 static uint8_t DFSDMx_Init(uint32_t AudioFreq) 01318 { 01319 /*####CHANNEL 4####*/ 01320 haudio_in_dfsdm_leftchannel.Init.OutputClock.Activation = ENABLE; 01321 haudio_in_dfsdm_leftchannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01322 /* Set the DFSDM clock OUT audio frequency configuration */ 01323 haudio_in_dfsdm_leftchannel.Init.OutputClock.Divider = DFSDMClockDivider(AudioFreq); 01324 haudio_in_dfsdm_leftchannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01325 haudio_in_dfsdm_leftchannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01326 haudio_in_dfsdm_leftchannel.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS; 01327 /* Request to sample stable data for LEFT micro on Rising edge */ 01328 haudio_in_dfsdm_leftchannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING; 01329 haudio_in_dfsdm_leftchannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01330 haudio_in_dfsdm_leftchannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_SINC1_ORDER; 01331 haudio_in_dfsdm_leftchannel.Init.Awd.Oversampling = 10; 01332 haudio_in_dfsdm_leftchannel.Init.Offset = 0; 01333 haudio_in_dfsdm_leftchannel.Init.RightBitShift = DFSDMRightBitShift(AudioFreq); 01334 01335 haudio_in_dfsdm_leftchannel.Instance = DFSDM_Channel4; 01336 if(HAL_DFSDM_ChannelGetState(&haudio_in_dfsdm_leftchannel) == HAL_DFSDM_CHANNEL_STATE_RESET) 01337 { 01338 /* Init the DFSDM Channel */ 01339 DFSDMx_ChannelMspInit(&haudio_in_dfsdm_leftchannel); 01340 } 01341 01342 if(HAL_OK != HAL_DFSDM_ChannelInit(&haudio_in_dfsdm_leftchannel)) 01343 { 01344 return AUDIO_ERROR; 01345 } 01346 01347 /*####CHANNEL 3####*/ 01348 haudio_in_dfsdm_rightchannel.Init.OutputClock.Activation = ENABLE; 01349 haudio_in_dfsdm_rightchannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO; 01350 /* Set the DFSDM clock OUT audio frequency configuration */ 01351 haudio_in_dfsdm_rightchannel.Init.OutputClock.Divider = DFSDMClockDivider(AudioFreq); 01352 haudio_in_dfsdm_rightchannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS; 01353 haudio_in_dfsdm_rightchannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE; 01354 haudio_in_dfsdm_rightchannel.Init.Input.Pins = DFSDM_CHANNEL_FOLLOWING_CHANNEL_PINS; 01355 /* Request to sample stable data for RIGHT micro on Falling edge */ 01356 haudio_in_dfsdm_rightchannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_FALLING; 01357 haudio_in_dfsdm_rightchannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL; 01358 haudio_in_dfsdm_rightchannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_SINC1_ORDER; 01359 haudio_in_dfsdm_rightchannel.Init.Awd.Oversampling = 10; 01360 haudio_in_dfsdm_rightchannel.Init.Offset = 0; 01361 haudio_in_dfsdm_rightchannel.Init.RightBitShift = DFSDMRightBitShift(AudioFreq); 01362 01363 haudio_in_dfsdm_rightchannel.Instance = DFSDM_Channel3; 01364 01365 if(HAL_DFSDM_ChannelGetState(&haudio_in_dfsdm_rightchannel) == HAL_DFSDM_CHANNEL_STATE_RESET) 01366 { 01367 /* Init the DFSDM Channel */ 01368 DFSDMx_ChannelMspInit(&haudio_in_dfsdm_rightchannel); 01369 } 01370 01371 if(HAL_OK != HAL_DFSDM_ChannelInit(&haudio_in_dfsdm_rightchannel)) 01372 { 01373 return AUDIO_ERROR; 01374 } 01375 01376 /*####FILTER 0####*/ 01377 haudio_in_dfsdm_leftfilter.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01378 haudio_in_dfsdm_leftfilter.Init.RegularParam.FastMode = ENABLE; 01379 haudio_in_dfsdm_leftfilter.Init.RegularParam.DmaMode = ENABLE; 01380 haudio_in_dfsdm_leftfilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01381 haudio_in_dfsdm_leftfilter.Init.InjectedParam.ScanMode = DISABLE; 01382 haudio_in_dfsdm_leftfilter.Init.InjectedParam.DmaMode = DISABLE; 01383 haudio_in_dfsdm_leftfilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO; 01384 haudio_in_dfsdm_leftfilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES; 01385 haudio_in_dfsdm_leftfilter.Init.FilterParam.SincOrder = DFSDMFilterOrder(AudioFreq); 01386 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01387 haudio_in_dfsdm_leftfilter.Init.FilterParam.Oversampling = DFSDMOverSampling(AudioFreq); 01388 haudio_in_dfsdm_leftfilter.Init.FilterParam.IntOversampling = 1; 01389 01390 haudio_in_dfsdm_leftfilter.Instance = AUDIO_DFSDMx_LEFT_FILTER; 01391 01392 if(HAL_DFSDM_FilterGetState(&haudio_in_dfsdm_leftfilter) == HAL_DFSDM_FILTER_STATE_RESET) 01393 { 01394 /* Init the DFSDM Filter */ 01395 DFSDMx_FilterMspInit(&haudio_in_dfsdm_leftfilter); 01396 } 01397 01398 if(HAL_OK != HAL_DFSDM_FilterInit(&haudio_in_dfsdm_leftfilter)) 01399 { 01400 return AUDIO_ERROR; 01401 } 01402 01403 /* Configure injected channel */ 01404 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&haudio_in_dfsdm_leftfilter, DFSDM_CHANNEL_4, DFSDM_CONTINUOUS_CONV_ON)) 01405 { 01406 return AUDIO_ERROR; 01407 } 01408 01409 /*####FILTER 1####*/ 01410 haudio_in_dfsdm_rightfilter.Init.RegularParam.Trigger = DFSDM_FILTER_SYNC_TRIGGER; 01411 haudio_in_dfsdm_rightfilter.Init.RegularParam.FastMode = ENABLE; 01412 haudio_in_dfsdm_rightfilter.Init.RegularParam.DmaMode = ENABLE; 01413 haudio_in_dfsdm_rightfilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER; 01414 haudio_in_dfsdm_rightfilter.Init.InjectedParam.ScanMode = DISABLE; 01415 haudio_in_dfsdm_rightfilter.Init.InjectedParam.DmaMode = DISABLE; 01416 haudio_in_dfsdm_rightfilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO; 01417 haudio_in_dfsdm_rightfilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES; 01418 haudio_in_dfsdm_rightfilter.Init.FilterParam.SincOrder = DFSDMFilterOrder(AudioFreq); 01419 /* Set the DFSDM Filters Oversampling to have correct sample rate */ 01420 haudio_in_dfsdm_rightfilter.Init.FilterParam.Oversampling = DFSDMOverSampling(AudioFreq); 01421 haudio_in_dfsdm_rightfilter.Init.FilterParam.IntOversampling = 1; 01422 01423 haudio_in_dfsdm_rightfilter.Instance = AUDIO_DFSDMx_RIGHT_FILTER; 01424 01425 if(HAL_DFSDM_FilterGetState(&haudio_in_dfsdm_rightfilter) == HAL_DFSDM_FILTER_STATE_RESET) 01426 { 01427 /* Init the DFSDM Filter */ 01428 DFSDMx_FilterMspInit(&haudio_in_dfsdm_rightfilter); 01429 } 01430 01431 if(HAL_OK != HAL_DFSDM_FilterInit(&haudio_in_dfsdm_rightfilter)) 01432 { 01433 return AUDIO_ERROR; 01434 } 01435 01436 /* Configure injected channel */ 01437 if(HAL_OK != HAL_DFSDM_FilterConfigRegChannel(&haudio_in_dfsdm_rightfilter, DFSDM_CHANNEL_3, DFSDM_CONTINUOUS_CONV_ON)) 01438 { 01439 return AUDIO_ERROR; 01440 } 01441 01442 return AUDIO_OK; 01443 } 01444 01445 /** 01446 * @brief De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM). 01447 * @retval AUDIO_OK if correct communication, else wrong communication 01448 */ 01449 static uint8_t DFSDMx_DeInit(void) 01450 { 01451 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */ 01452 if(HAL_OK != HAL_DFSDM_FilterDeInit(&haudio_in_dfsdm_leftfilter)) 01453 { 01454 return AUDIO_ERROR; 01455 } 01456 01457 if(HAL_OK != HAL_DFSDM_FilterDeInit(&haudio_in_dfsdm_rightfilter)) 01458 { 01459 return AUDIO_ERROR; 01460 } 01461 01462 DFSDMx_FilterMspDeInit(&haudio_in_dfsdm_leftfilter); 01463 DFSDMx_FilterMspDeInit(&haudio_in_dfsdm_rightfilter); 01464 01465 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */ 01466 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&haudio_in_dfsdm_leftchannel)) 01467 { 01468 return AUDIO_ERROR; 01469 } 01470 01471 if(HAL_OK != HAL_DFSDM_ChannelDeInit(&haudio_in_dfsdm_rightchannel)) 01472 { 01473 return AUDIO_ERROR; 01474 } 01475 01476 DFSDMx_ChannelMspDeInit(&haudio_in_dfsdm_leftchannel); 01477 DFSDMx_ChannelMspDeInit(&haudio_in_dfsdm_rightchannel); 01478 01479 return AUDIO_OK; 01480 } 01481 01482 /** 01483 * @brief Initializes the DFSDM channel MSP. 01484 * @param hdfsdm_channel : DFSDM channel handle. 01485 * @retval None 01486 */ 01487 static void DFSDMx_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) 01488 { 01489 GPIO_InitTypeDef GPIO_InitStruct; 01490 01491 /* Enable DFSDM clock */ 01492 AUDIO_DFSDMx_CLK_ENABLE(); 01493 01494 /* Enable GPIO clock */ 01495 AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE(); 01496 01497 /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/ 01498 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN | AUDIO_DFSDMx_DMIC_DATIN_PIN; 01499 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; 01500 GPIO_InitStruct.Pull = GPIO_NOPULL; 01501 GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; 01502 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_DMIC_DATIN_AF; 01503 HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct); 01504 } 01505 01506 /** 01507 * @brief DeInitializes the DFSDM channel MSP. 01508 * @param hdfsdm_channel : DFSDM channel handle. 01509 * @retval None 01510 */ 01511 static void DFSDMx_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel) 01512 { 01513 GPIO_InitTypeDef GPIO_InitStruct; 01514 01515 /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/ 01516 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN | AUDIO_DFSDMx_DMIC_DATIN_PIN; 01517 HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, GPIO_InitStruct.Pin); 01518 } 01519 01520 /** 01521 * @brief Initializes the DFSDM filter MSP. 01522 * @param hdfsdm_filter : DFSDM filter handle. 01523 * @retval None 01524 */ 01525 static void DFSDMx_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01526 { 01527 DMA_HandleTypeDef *hdma_dfsdmReg; 01528 01529 /* Enable DFSDM clock */ 01530 AUDIO_DFSDMx_CLK_ENABLE(); 01531 01532 /* Enable the DMA clock */ 01533 AUDIO_DFSDMx_DMAx_CLK_ENABLE(); 01534 01535 if(hdfsdm_filter->Instance == AUDIO_DFSDMx_LEFT_FILTER) 01536 { 01537 hdma_dfsdmReg = &hdma_dfsdm_left; 01538 } 01539 else /* AUDIO_DFSDMx_RIGHT_FILTER */ 01540 { 01541 hdma_dfsdmReg = &hdma_dfsdm_right; 01542 } 01543 01544 /* Configure the hdma_dfsdmReg handle parameters */ 01545 hdma_dfsdmReg->Init.Request = DMA_REQUEST_0; 01546 hdma_dfsdmReg->Init.Direction = DMA_PERIPH_TO_MEMORY; 01547 hdma_dfsdmReg->Init.PeriphInc = DMA_PINC_DISABLE; 01548 hdma_dfsdmReg->Init.MemInc = DMA_MINC_ENABLE; 01549 hdma_dfsdmReg->Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE; 01550 hdma_dfsdmReg->Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE; 01551 hdma_dfsdmReg->Init.Mode = DMA_CIRCULAR; 01552 hdma_dfsdmReg->Init.Priority = DMA_PRIORITY_HIGH; 01553 01554 if(hdfsdm_filter->Instance == AUDIO_DFSDMx_LEFT_FILTER) 01555 { 01556 hdma_dfsdmReg->Instance = AUDIO_DFSDMx_DMAx_LEFT_CHANNEL; 01557 } 01558 else /* AUDIO_DFSDMx_RIGHT_FILTER */ 01559 { 01560 hdma_dfsdmReg->Instance = AUDIO_DFSDMx_DMAx_RIGHT_CHANNEL; 01561 } 01562 01563 /* Associate the DMA handle */ 01564 __HAL_LINKDMA(hdfsdm_filter, hdmaReg, *hdma_dfsdmReg); 01565 01566 /* Reset DMA handle state */ 01567 __HAL_DMA_RESET_HANDLE_STATE(hdma_dfsdmReg); 01568 01569 /* Configure the DMA Channel */ 01570 HAL_DMA_Init(hdma_dfsdmReg); 01571 01572 /* DMA IRQ Channel configuration */ 01573 if(hdfsdm_filter->Instance == AUDIO_DFSDMx_LEFT_FILTER) 01574 { 01575 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 01576 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ); 01577 } 01578 else /* AUDIO_DFSDMx_RIGHT_FILTER */ 01579 { 01580 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_RIGHT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); 01581 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_RIGHT_IRQ); 01582 } 01583 } 01584 01585 /** 01586 * @brief DeInitializes the DFSDM filter MSP. 01587 * @param hdfsdm_filter : DFSDM filter handle. 01588 * @retval None 01589 */ 01590 static void DFSDMx_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter) 01591 { 01592 DMA_HandleTypeDef *hdma_dfsdmReg; 01593 01594 if(hdfsdm_filter->Instance == AUDIO_DFSDMx_LEFT_FILTER) 01595 { 01596 hdma_dfsdmReg = &hdma_dfsdm_left; 01597 } 01598 else /* AUDIO_DFSDMx_RIGHT_FILTER */ 01599 { 01600 hdma_dfsdmReg = &hdma_dfsdm_right; 01601 } 01602 01603 /* Configure the DMA Channel */ 01604 HAL_DMA_DeInit(hdma_dfsdmReg); 01605 } 01606 01607 /** 01608 * @} 01609 */ 01610 01611 /** 01612 * @} 01613 */ 01614 01615 /** 01616 * @} 01617 */ 01618 01619 /** 01620 * @} 01621 */ 01622 01623 /** 01624 * @} 01625 */ 01626 01627 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
Generated on Sun Jun 21 2015 23:46:41 for STM32L476G_EVAL BSP User Manual by
