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