AudioRecord

Dependencies:   STM32L4xx_HAL_Driver CMSIS_DSP_401

Committer:
EricLew
Date:
Thu Nov 26 22:32:56 2015 +0000
Revision:
3:ec7e3c37fe80
Parent:
0:d4e5ad7ad71c
FFT is currently not working and commented out

Who changed what in which revision?

UserRevisionLine numberNew contents of line
EricLew 0:d4e5ad7ad71c 1 /**
EricLew 0:d4e5ad7ad71c 2 ******************************************************************************
EricLew 0:d4e5ad7ad71c 3 * @file stm32l476g_discovery_audio.c
EricLew 0:d4e5ad7ad71c 4 * @author MCD Application Team
EricLew 0:d4e5ad7ad71c 5 * @version V1.0.1
EricLew 0:d4e5ad7ad71c 6 * @date 16-September-2015
EricLew 0:d4e5ad7ad71c 7 * @brief This file provides a set of functions needed to manage the
EricLew 0:d4e5ad7ad71c 8 * Audio driver for the STM32L476G-Discovery board.
EricLew 0:d4e5ad7ad71c 9 ******************************************************************************
EricLew 0:d4e5ad7ad71c 10 * @attention
EricLew 0:d4e5ad7ad71c 11 *
EricLew 0:d4e5ad7ad71c 12 * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
EricLew 0:d4e5ad7ad71c 13 *
EricLew 0:d4e5ad7ad71c 14 * Redistribution and use in source and binary forms, with or without modification,
EricLew 0:d4e5ad7ad71c 15 * are permitted provided that the following conditions are met:
EricLew 0:d4e5ad7ad71c 16 * 1. Redistributions of source code must retain the above copyright notice,
EricLew 0:d4e5ad7ad71c 17 * this list of conditions and the following disclaimer.
EricLew 0:d4e5ad7ad71c 18 * 2. Redistributions in binary form must reproduce the above copyright notice,
EricLew 0:d4e5ad7ad71c 19 * this list of conditions and the following disclaimer in the documentation
EricLew 0:d4e5ad7ad71c 20 * and/or other materials provided with the distribution.
EricLew 0:d4e5ad7ad71c 21 * 3. Neither the name of STMicroelectronics nor the names of its contributors
EricLew 0:d4e5ad7ad71c 22 * may be used to endorse or promote products derived from this software
EricLew 0:d4e5ad7ad71c 23 * without specific prior written permission.
EricLew 0:d4e5ad7ad71c 24 *
EricLew 0:d4e5ad7ad71c 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
EricLew 0:d4e5ad7ad71c 26 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
EricLew 0:d4e5ad7ad71c 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
EricLew 0:d4e5ad7ad71c 28 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
EricLew 0:d4e5ad7ad71c 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
EricLew 0:d4e5ad7ad71c 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
EricLew 0:d4e5ad7ad71c 31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
EricLew 0:d4e5ad7ad71c 32 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
EricLew 0:d4e5ad7ad71c 33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
EricLew 0:d4e5ad7ad71c 34 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
EricLew 0:d4e5ad7ad71c 35 *
EricLew 0:d4e5ad7ad71c 36 ******************************************************************************
EricLew 0:d4e5ad7ad71c 37 */
EricLew 0:d4e5ad7ad71c 38
EricLew 0:d4e5ad7ad71c 39 /*==============================================================================
EricLew 0:d4e5ad7ad71c 40 User NOTES
EricLew 0:d4e5ad7ad71c 41
EricLew 0:d4e5ad7ad71c 42 1. How To use this driver:
EricLew 0:d4e5ad7ad71c 43 --------------------------
EricLew 0:d4e5ad7ad71c 44 + This driver supports STM32L4xx devices on STM32L476G-Discovery (MB1184) Discovery boards.
EricLew 0:d4e5ad7ad71c 45 a) to play an audio file (all functions names start by BSP_AUDIO_OUT_xxx)
EricLew 0:d4e5ad7ad71c 46 b) to record an audio file through MP34DT01TR, ST MEMS (all functions names start by BSP_AUDIO_IN_xxx)
EricLew 0:d4e5ad7ad71c 47
EricLew 0:d4e5ad7ad71c 48 a) PLAY A FILE:
EricLew 0:d4e5ad7ad71c 49 ==============
EricLew 0:d4e5ad7ad71c 50 + Call the function BSP_AUDIO_OUT_Init(
EricLew 0:d4e5ad7ad71c 51 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER,
EricLew 0:d4e5ad7ad71c 52 OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH)
EricLew 0:d4e5ad7ad71c 53 Volume : Initial volume to be set (0 is min (mute), 100 is max (100%)
EricLew 0:d4e5ad7ad71c 54 AudioFreq : Audio frequency in Hz (8000, 16000, 22500, 32000...)
EricLew 0:d4e5ad7ad71c 55 this parameter is relative to the audio file/stream type.
EricLew 0:d4e5ad7ad71c 56 )
EricLew 0:d4e5ad7ad71c 57 This function configures all the hardware required for the audio application (codec, I2C, SAI,
EricLew 0:d4e5ad7ad71c 58 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
EricLew 0:d4e5ad7ad71c 59 If the returned value is different from AUDIO_OK or the function is stuck then the communication with
EricLew 0:d4e5ad7ad71c 60 the audio codec has failed.
EricLew 0:d4e5ad7ad71c 61 - OUTPUT_DEVICE_SPEAKER : only speaker will be set as output for the audio stream.
EricLew 0:d4e5ad7ad71c 62 - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
EricLew 0:d4e5ad7ad71c 63 - OUTPUT_DEVICE_BOTH : both Speaker and Headphone are used as outputs for the audio stream
EricLew 0:d4e5ad7ad71c 64 at the same time.
EricLew 0:d4e5ad7ad71c 65
EricLew 0:d4e5ad7ad71c 66 + Call the function BSP_AUDIO_OUT_RegisterCallbacks to register user callbacks
EricLew 0:d4e5ad7ad71c 67 required to manage audio data streaming towards the audio codec (ErrorCallback(),
EricLew 0:d4e5ad7ad71c 68 HalfTransfer_CallBack() and TransferComplete_CallBack()).
EricLew 0:d4e5ad7ad71c 69
EricLew 0:d4e5ad7ad71c 70 + Call the function BSP_AUDIO_OUT_Play() to start audio playback (for the first time).
EricLew 0:d4e5ad7ad71c 71 + Call the function BSP_AUDIO_OUT_Pause() to pause audio playabck
EricLew 0:d4e5ad7ad71c 72 + Call the function BSP_AUDIO_OUT_Resume() to resume audio playback.
EricLew 0:d4e5ad7ad71c 73 Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
EricLew 0:d4e5ad7ad71c 74 for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
EricLew 0:d4e5ad7ad71c 75 Note. This function should be called only when the audio file is played or paused (not stopped).
EricLew 0:d4e5ad7ad71c 76 + Call the function BSP_AUDIO_OUT_Stop() to stop audio playback.
EricLew 0:d4e5ad7ad71c 77 + To modify the volume level, the sampling frequency, the device output mode,
EricLew 0:d4e5ad7ad71c 78 the mute status or the audio configuration or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(),
EricLew 0:d4e5ad7ad71c 79 AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetOutputMode(), BSP_AUDIO_OUT_SetMute()and
EricLew 0:d4e5ad7ad71c 80 BSP_AUDIO_OUT_ChangeAudioConfig().
EricLew 0:d4e5ad7ad71c 81
EricLew 0:d4e5ad7ad71c 82 Driver architecture:
EricLew 0:d4e5ad7ad71c 83 --------------------
EricLew 0:d4e5ad7ad71c 84 + This driver provides the audio layer high level API: it consists in functions
EricLew 0:d4e5ad7ad71c 85 exported in the stm32l476g_discovery_audio.h file (e.g. BSP_AUDIO_OUT_Init(),
EricLew 0:d4e5ad7ad71c 86 BSP_AUDIO_OUT_Play(), ...).
EricLew 0:d4e5ad7ad71c 87 + This driver also includes the Media Access Layer (MAL): it consists in
EricLew 0:d4e5ad7ad71c 88 functions allowing to access setup the audio devices. These functions
EricLew 0:d4e5ad7ad71c 89 are included as local functions into the stm32l476g_discovery_audio.c file
EricLew 0:d4e5ad7ad71c 90 (e.g. AUDIO_SAIx_Init()).
EricLew 0:d4e5ad7ad71c 91
EricLew 0:d4e5ad7ad71c 92 Known Limitations:
EricLew 0:d4e5ad7ad71c 93 ------------------
EricLew 0:d4e5ad7ad71c 94 1- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some
EricLew 0:d4e5ad7ad71c 95 user interrupt routines (in this case, interrupts could be disabled just before the start of
EricLew 0:d4e5ad7ad71c 96 communication then re-enabled when it is over). Note that this communication is only done at
EricLew 0:d4e5ad7ad71c 97 the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is
EricLew 0:d4e5ad7ad71c 98 performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()).
EricLew 0:d4e5ad7ad71c 99 When the audio data is played, no communication is required with the audio codec.
EricLew 0:d4e5ad7ad71c 100 2- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size,
EricLew 0:d4e5ad7ad71c 101 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
EricLew 0:d4e5ad7ad71c 102 3- Supports only 16-bits audio data size.
EricLew 0:d4e5ad7ad71c 103
EricLew 0:d4e5ad7ad71c 104 b) RECORD A FILE:
EricLew 0:d4e5ad7ad71c 105 ================
EricLew 0:d4e5ad7ad71c 106 + Call the function BSP_AUDIO_IN_Init(
EricLew 0:d4e5ad7ad71c 107 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
EricLew 0:d4e5ad7ad71c 108 )
EricLew 0:d4e5ad7ad71c 109 This function configures all the hardware required for the audio application (DFSDM,
EricLew 0:d4e5ad7ad71c 110 GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if the
EricLew 0:d4e5ad7ad71c 111 configuration completes successfully.
EricLew 0:d4e5ad7ad71c 112
EricLew 0:d4e5ad7ad71c 113 + Call the function BSP_AUDIO_IN_RegisterCallbacks to register user callbacks
EricLew 0:d4e5ad7ad71c 114 used to stream audio data toward the record buffer (ErrorCallback(),
EricLew 0:d4e5ad7ad71c 115 HalfTransfer_CallBack() and TransferComplete_CallBack()).
EricLew 0:d4e5ad7ad71c 116
EricLew 0:d4e5ad7ad71c 117 + Call the function BSP_AUDIO_IN_Record(
EricLew 0:d4e5ad7ad71c 118 pbuf Main buffer pointer for the recorded data storing
EricLew 0:d4e5ad7ad71c 119 size Current size of the recorded buffer
EricLew 0:d4e5ad7ad71c 120 )
EricLew 0:d4e5ad7ad71c 121 to start recording from the microphone.
EricLew 0:d4e5ad7ad71c 122
EricLew 0:d4e5ad7ad71c 123 + Call the function AUDIO_IN_STOP() to stop recording
EricLew 0:d4e5ad7ad71c 124 ==============================================================================*/
EricLew 0:d4e5ad7ad71c 125
EricLew 0:d4e5ad7ad71c 126 /* Includes ------------------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 127 #include <string.h>
EricLew 0:d4e5ad7ad71c 128 #include "stm32l476g_discovery_audio.h"
EricLew 0:d4e5ad7ad71c 129
EricLew 0:d4e5ad7ad71c 130 /** @addtogroup BSP
EricLew 0:d4e5ad7ad71c 131 * @{
EricLew 0:d4e5ad7ad71c 132 */
EricLew 0:d4e5ad7ad71c 133
EricLew 0:d4e5ad7ad71c 134 /** @addtogroup STM32L476G_DISCOVERY
EricLew 0:d4e5ad7ad71c 135 * @{
EricLew 0:d4e5ad7ad71c 136 */
EricLew 0:d4e5ad7ad71c 137
EricLew 0:d4e5ad7ad71c 138 /** @defgroup STM32L476G_DISCOVERY_AUDIO STM32L476G-DISCOVERY AUDIO
EricLew 0:d4e5ad7ad71c 139 * @brief This file includes the low layer driver for cs43l22 Audio Codec
EricLew 0:d4e5ad7ad71c 140 * available on STM32L476G-Discovery board(MB1184).
EricLew 0:d4e5ad7ad71c 141 * @{
EricLew 0:d4e5ad7ad71c 142 */
EricLew 0:d4e5ad7ad71c 143
EricLew 0:d4e5ad7ad71c 144 /* Private typedef -----------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 145 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Types Private Types
EricLew 0:d4e5ad7ad71c 146 * @{
EricLew 0:d4e5ad7ad71c 147 */
EricLew 0:d4e5ad7ad71c 148 typedef struct
EricLew 0:d4e5ad7ad71c 149 {
EricLew 0:d4e5ad7ad71c 150
EricLew 0:d4e5ad7ad71c 151 Audio_CallbackTypeDef CbError; /* pointer to the callback function invoked when ... */
EricLew 0:d4e5ad7ad71c 152 Audio_CallbackTypeDef CbHalfTransfer; /* pointer to the callback function invoked when ... */
EricLew 0:d4e5ad7ad71c 153 Audio_CallbackTypeDef CbTransferComplete; /* pointer to the callback function invoked when ... */
EricLew 0:d4e5ad7ad71c 154 } AUDIO_OUT_TypeDef;
EricLew 0:d4e5ad7ad71c 155
EricLew 0:d4e5ad7ad71c 156 typedef struct
EricLew 0:d4e5ad7ad71c 157 {
EricLew 0:d4e5ad7ad71c 158 DFSDM_Channel_HandleTypeDef hDfsdmLeftChannel; /* DFSDM channel handle used for left channel */
EricLew 0:d4e5ad7ad71c 159 DMA_HandleTypeDef hDmaDfsdmLeft; /* DMA handle used for DFSDM regular conversions on left channel */
EricLew 0:d4e5ad7ad71c 160 int32_t * LeftRecBuff; /* Buffers for left samples */
EricLew 0:d4e5ad7ad71c 161 uint32_t Frequency; /* Record Frequency */
EricLew 0:d4e5ad7ad71c 162 uint32_t BitResolution; /* Record bit resolution */
EricLew 0:d4e5ad7ad71c 163 uint32_t ChannelNbr; /* Record Channel Number */
EricLew 0:d4e5ad7ad71c 164 uint16_t * pRecBuf; /* Pointer to record user buffer */
EricLew 0:d4e5ad7ad71c 165 uint32_t RecSize; /* Size to record in mono, double size to record in stereo */
EricLew 0:d4e5ad7ad71c 166 Audio_CallbackTypeDef CbError; /* pointer to the callback function invoked when a DMA transfer fails */
EricLew 0:d4e5ad7ad71c 167 Audio_CallbackTypeDef CbHalfTransfer; /* pointer to the callback function invoked when half of the DMA transfer is completed */
EricLew 0:d4e5ad7ad71c 168 Audio_CallbackTypeDef CbTransferComplete; /* pointer to the callback function invoked when the DMA transfer is completed */
EricLew 0:d4e5ad7ad71c 169 } AUDIO_IN_TypeDef;
EricLew 0:d4e5ad7ad71c 170
EricLew 0:d4e5ad7ad71c 171 /**
EricLew 0:d4e5ad7ad71c 172 * @}
EricLew 0:d4e5ad7ad71c 173 */
EricLew 0:d4e5ad7ad71c 174
EricLew 0:d4e5ad7ad71c 175 /* Private defines ------------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 176 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Constants Private Constants
EricLew 0:d4e5ad7ad71c 177 * @{
EricLew 0:d4e5ad7ad71c 178 */
EricLew 0:d4e5ad7ad71c 179 /**
EricLew 0:d4e5ad7ad71c 180 * @}
EricLew 0:d4e5ad7ad71c 181 */
EricLew 0:d4e5ad7ad71c 182
EricLew 0:d4e5ad7ad71c 183 /* Private macros ------------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 184 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Macros Private Macros
EricLew 0:d4e5ad7ad71c 185 * @{
EricLew 0:d4e5ad7ad71c 186 */
EricLew 0:d4e5ad7ad71c 187 /*### PLAY ###*/
EricLew 0:d4e5ad7ad71c 188 /* SCK(kHz) = SAI_CK_x/(SAIClockDivider*2*256) */
EricLew 0:d4e5ad7ad71c 189 #define SAIClockDivider(__FREQUENCY__) \
EricLew 0:d4e5ad7ad71c 190 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 12 \
EricLew 0:d4e5ad7ad71c 191 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 2 \
EricLew 0:d4e5ad7ad71c 192 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 6 \
EricLew 0:d4e5ad7ad71c 193 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 1 \
EricLew 0:d4e5ad7ad71c 194 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \
EricLew 0:d4e5ad7ad71c 195 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 0 \
EricLew 0:d4e5ad7ad71c 196 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 2 : 1 \
EricLew 0:d4e5ad7ad71c 197
EricLew 0:d4e5ad7ad71c 198 /*### RECORD ###*/
EricLew 0:d4e5ad7ad71c 199 #define DFSDMOverSampling(__FREQUENCY__) \
EricLew 0:d4e5ad7ad71c 200 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 256 \
EricLew 0:d4e5ad7ad71c 201 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 256 \
EricLew 0:d4e5ad7ad71c 202 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 128 \
EricLew 0:d4e5ad7ad71c 203 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 128 \
EricLew 0:d4e5ad7ad71c 204 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 64 \
EricLew 0:d4e5ad7ad71c 205 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 64 \
EricLew 0:d4e5ad7ad71c 206 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 16 \
EricLew 0:d4e5ad7ad71c 207
EricLew 0:d4e5ad7ad71c 208 #define DFSDMClockDivider(__FREQUENCY__) \
EricLew 0:d4e5ad7ad71c 209 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 24 \
EricLew 0:d4e5ad7ad71c 210 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 4 \
EricLew 0:d4e5ad7ad71c 211 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 24 \
EricLew 0:d4e5ad7ad71c 212 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 4 \
EricLew 0:d4e5ad7ad71c 213 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 24 \
EricLew 0:d4e5ad7ad71c 214 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 4 \
EricLew 0:d4e5ad7ad71c 215 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 32 : 32 \
EricLew 0:d4e5ad7ad71c 216
EricLew 0:d4e5ad7ad71c 217 #define DFSDMFilterOrder(__FREQUENCY__) \
EricLew 0:d4e5ad7ad71c 218 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? DFSDM_FILTER_SINC3_ORDER \
EricLew 0:d4e5ad7ad71c 219 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? DFSDM_FILTER_SINC3_ORDER \
EricLew 0:d4e5ad7ad71c 220 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? DFSDM_FILTER_SINC3_ORDER \
EricLew 0:d4e5ad7ad71c 221 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? DFSDM_FILTER_SINC3_ORDER \
EricLew 0:d4e5ad7ad71c 222 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? DFSDM_FILTER_SINC4_ORDER \
EricLew 0:d4e5ad7ad71c 223 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? DFSDM_FILTER_SINC4_ORDER \
EricLew 0:d4e5ad7ad71c 224 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? DFSDM_FILTER_SINC4_ORDER : DFSDM_FILTER_SINC5_ORDER \
EricLew 0:d4e5ad7ad71c 225
EricLew 0:d4e5ad7ad71c 226 #define DFSDMRightBitShift(__FREQUENCY__) \
EricLew 0:d4e5ad7ad71c 227 (__FREQUENCY__ == AUDIO_FREQUENCY_8K) ? 2 \
EricLew 0:d4e5ad7ad71c 228 : (__FREQUENCY__ == AUDIO_FREQUENCY_11K) ? 3 \
EricLew 0:d4e5ad7ad71c 229 : (__FREQUENCY__ == AUDIO_FREQUENCY_16K) ? 3 \
EricLew 0:d4e5ad7ad71c 230 : (__FREQUENCY__ == AUDIO_FREQUENCY_22K) ? 0 \
EricLew 0:d4e5ad7ad71c 231 : (__FREQUENCY__ == AUDIO_FREQUENCY_32K) ? 3 \
EricLew 0:d4e5ad7ad71c 232 : (__FREQUENCY__ == AUDIO_FREQUENCY_44K) ? 3 \
EricLew 0:d4e5ad7ad71c 233 : (__FREQUENCY__ == AUDIO_FREQUENCY_48K) ? 7 : 0 \
EricLew 0:d4e5ad7ad71c 234
EricLew 0:d4e5ad7ad71c 235 /* Saturate the record PCM sample */
EricLew 0:d4e5ad7ad71c 236 #define SaturaLH(N, L, H) (((N)<(L))?(L):(((N)>(H))?(H):(N)))
EricLew 0:d4e5ad7ad71c 237
EricLew 0:d4e5ad7ad71c 238 /**
EricLew 0:d4e5ad7ad71c 239 * @}
EricLew 0:d4e5ad7ad71c 240 */
EricLew 0:d4e5ad7ad71c 241
EricLew 0:d4e5ad7ad71c 242 /* Private variables ---------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 243 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Variables Private Variables
EricLew 0:d4e5ad7ad71c 244 * @{
EricLew 0:d4e5ad7ad71c 245 */
EricLew 0:d4e5ad7ad71c 246 /* Audio output context information */
EricLew 0:d4e5ad7ad71c 247 static AUDIO_OUT_TypeDef hAudioOut;
EricLew 0:d4e5ad7ad71c 248
EricLew 0:d4e5ad7ad71c 249 /* Audio input context information */
EricLew 0:d4e5ad7ad71c 250 static AUDIO_IN_TypeDef hAudioIn;
EricLew 0:d4e5ad7ad71c 251
EricLew 0:d4e5ad7ad71c 252 /* SAI DMA handle */
EricLew 0:d4e5ad7ad71c 253 static DMA_HandleTypeDef hDmaSai;
EricLew 0:d4e5ad7ad71c 254 /**
EricLew 0:d4e5ad7ad71c 255 * @}
EricLew 0:d4e5ad7ad71c 256 */
EricLew 0:d4e5ad7ad71c 257
EricLew 0:d4e5ad7ad71c 258 /* Exported variables ---------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 259 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Exported_Variables Exported Variables
EricLew 0:d4e5ad7ad71c 260 * @{
EricLew 0:d4e5ad7ad71c 261 */
EricLew 0:d4e5ad7ad71c 262 /* SAIx handle */
EricLew 0:d4e5ad7ad71c 263 SAI_HandleTypeDef BSP_AUDIO_hSai;
EricLew 0:d4e5ad7ad71c 264
EricLew 0:d4e5ad7ad71c 265 /* DFSDM filter handle */
EricLew 0:d4e5ad7ad71c 266 DFSDM_Filter_HandleTypeDef BSP_AUDIO_hDfsdmLeftFilter;
EricLew 0:d4e5ad7ad71c 267 /**
EricLew 0:d4e5ad7ad71c 268 * @}
EricLew 0:d4e5ad7ad71c 269 */
EricLew 0:d4e5ad7ad71c 270
EricLew 0:d4e5ad7ad71c 271 /* Private function prototypes -----------------------------------------------*/
EricLew 0:d4e5ad7ad71c 272 /** @defgroup STM32L476G_DISCOVERY_AUDIO_Private_Functions Private Functions
EricLew 0:d4e5ad7ad71c 273 * @{
EricLew 0:d4e5ad7ad71c 274 */
EricLew 0:d4e5ad7ad71c 275 static void AUDIO_CODEC_Reset(void);
EricLew 0:d4e5ad7ad71c 276 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq);
EricLew 0:d4e5ad7ad71c 277 static uint8_t AUDIO_SAIx_DeInit(void);
EricLew 0:d4e5ad7ad71c 278 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq);
EricLew 0:d4e5ad7ad71c 279 static uint8_t AUDIO_DFSDMx_DeInit(void);
EricLew 0:d4e5ad7ad71c 280 static uint8_t AUDIO_SAIPLLConfig(uint32_t AudioFreq);
EricLew 0:d4e5ad7ad71c 281 /**
EricLew 0:d4e5ad7ad71c 282 * @}
EricLew 0:d4e5ad7ad71c 283 */
EricLew 0:d4e5ad7ad71c 284
EricLew 0:d4e5ad7ad71c 285 /* Exported functions --------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 286 /** @addtogroup STM32L476G_DISCOVERY_AUDIO_Exported_Functions
EricLew 0:d4e5ad7ad71c 287 * @{
EricLew 0:d4e5ad7ad71c 288 */
EricLew 0:d4e5ad7ad71c 289
EricLew 0:d4e5ad7ad71c 290 /**
EricLew 0:d4e5ad7ad71c 291 * @brief Configures the audio codec related peripherals.
EricLew 0:d4e5ad7ad71c 292 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
EricLew 0:d4e5ad7ad71c 293 * or OUTPUT_DEVICE_BOTH.
EricLew 0:d4e5ad7ad71c 294 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max))
EricLew 0:d4e5ad7ad71c 295 * @param AudioFreq: Audio frequency used to play the audio stream.ion.
EricLew 0:d4e5ad7ad71c 296 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 297 * @note The SAI PLL input clock must be configure in the user application.
EricLew 0:d4e5ad7ad71c 298 * The SAI PLL configuration done within this function assumes that
EricLew 0:d4e5ad7ad71c 299 * the SAI PLL input clock runs at 8 MHz.
EricLew 0:d4e5ad7ad71c 300 */
EricLew 0:d4e5ad7ad71c 301
EricLew 0:d4e5ad7ad71c 302 /**
EricLew 0:d4e5ad7ad71c 303 * @brief Tx Transfer completed callbacks.
EricLew 0:d4e5ad7ad71c 304 * @param hsai: SAI handle
EricLew 0:d4e5ad7ad71c 305 * @retval None
EricLew 0:d4e5ad7ad71c 306 */
EricLew 0:d4e5ad7ad71c 307 void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
EricLew 0:d4e5ad7ad71c 308 {
EricLew 0:d4e5ad7ad71c 309 /* Invoke the registered 'TransferComplete' function (if any) */
EricLew 0:d4e5ad7ad71c 310 if (hAudioOut.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
EricLew 0:d4e5ad7ad71c 311 {
EricLew 0:d4e5ad7ad71c 312 hAudioOut.CbTransferComplete();
EricLew 0:d4e5ad7ad71c 313 }
EricLew 0:d4e5ad7ad71c 314 }
EricLew 0:d4e5ad7ad71c 315
EricLew 0:d4e5ad7ad71c 316 /**
EricLew 0:d4e5ad7ad71c 317 * @brief Tx Half Transfer completed callbacks.
EricLew 0:d4e5ad7ad71c 318 * @param hsai: SAI handle
EricLew 0:d4e5ad7ad71c 319 * @retval None
EricLew 0:d4e5ad7ad71c 320 */
EricLew 0:d4e5ad7ad71c 321 void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
EricLew 0:d4e5ad7ad71c 322 {
EricLew 0:d4e5ad7ad71c 323 /* Invoke the registered 'HalfTransfer' callback function (if any) */
EricLew 0:d4e5ad7ad71c 324 if (hAudioOut.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
EricLew 0:d4e5ad7ad71c 325 {
EricLew 0:d4e5ad7ad71c 326 hAudioOut.CbHalfTransfer();
EricLew 0:d4e5ad7ad71c 327 }
EricLew 0:d4e5ad7ad71c 328 }
EricLew 0:d4e5ad7ad71c 329
EricLew 0:d4e5ad7ad71c 330 /**
EricLew 0:d4e5ad7ad71c 331 * @brief SAI error callbacks.
EricLew 0:d4e5ad7ad71c 332 * @param hsai: SAI handle
EricLew 0:d4e5ad7ad71c 333 * @retval None
EricLew 0:d4e5ad7ad71c 334 */
EricLew 0:d4e5ad7ad71c 335 void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
EricLew 0:d4e5ad7ad71c 336 {
EricLew 0:d4e5ad7ad71c 337 /* Invoke the registered 'ErrorCallback' callback function (if any) */
EricLew 0:d4e5ad7ad71c 338 if (hAudioOut.CbError != (Audio_CallbackTypeDef)NULL)
EricLew 0:d4e5ad7ad71c 339 {
EricLew 0:d4e5ad7ad71c 340 hAudioOut.CbError();
EricLew 0:d4e5ad7ad71c 341 }
EricLew 0:d4e5ad7ad71c 342 }
EricLew 0:d4e5ad7ad71c 343
EricLew 0:d4e5ad7ad71c 344 /**
EricLew 0:d4e5ad7ad71c 345 * @}
EricLew 0:d4e5ad7ad71c 346 */
EricLew 0:d4e5ad7ad71c 347
EricLew 0:d4e5ad7ad71c 348 /** @addtogroup STM32L476G_EVAL_AUDIO_Exported_Functions
EricLew 0:d4e5ad7ad71c 349 * @{
EricLew 0:d4e5ad7ad71c 350 */
EricLew 0:d4e5ad7ad71c 351
EricLew 0:d4e5ad7ad71c 352 /**
EricLew 0:d4e5ad7ad71c 353 * @brief Initializes micropone related peripherals.
EricLew 0:d4e5ad7ad71c 354 * @note This function assumes that the SAI input clock (through PLL_M)
EricLew 0:d4e5ad7ad71c 355 * is already configured and ready to be used.
EricLew 0:d4e5ad7ad71c 356 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral.
EricLew 0:d4e5ad7ad71c 357 * @param BitRes: Audio frequency to be configured for the SAI peripheral.
EricLew 0:d4e5ad7ad71c 358 * @param ChnlNbr: Audio frequency to be configured for the SAI peripheral.
EricLew 0:d4e5ad7ad71c 359 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 360 */
EricLew 0:d4e5ad7ad71c 361 uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
EricLew 0:d4e5ad7ad71c 362 {
EricLew 0:d4e5ad7ad71c 363 /* Update the audio input context */
EricLew 0:d4e5ad7ad71c 364 hAudioIn.Frequency = AudioFreq;
EricLew 0:d4e5ad7ad71c 365 hAudioIn.BitResolution = BitRes;
EricLew 0:d4e5ad7ad71c 366 hAudioIn.ChannelNbr = ChnlNbr;
EricLew 0:d4e5ad7ad71c 367 hAudioIn.CbError = (Audio_CallbackTypeDef)NULL;
EricLew 0:d4e5ad7ad71c 368 hAudioIn.CbHalfTransfer = (Audio_CallbackTypeDef)NULL;
EricLew 0:d4e5ad7ad71c 369 hAudioIn.CbTransferComplete = (Audio_CallbackTypeDef)NULL;
EricLew 0:d4e5ad7ad71c 370
EricLew 0:d4e5ad7ad71c 371 /* Configure the SAI PLL according to the requested audio frequency */
EricLew 0:d4e5ad7ad71c 372 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 373 {
EricLew 0:d4e5ad7ad71c 374 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 375 }
EricLew 0:d4e5ad7ad71c 376
EricLew 0:d4e5ad7ad71c 377 /* Initializes the Digital Filter for Sigma-Delta Modulators interface */
EricLew 0:d4e5ad7ad71c 378 if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 379 {
EricLew 0:d4e5ad7ad71c 380 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 381 }
EricLew 0:d4e5ad7ad71c 382
EricLew 0:d4e5ad7ad71c 383 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 384 }
EricLew 0:d4e5ad7ad71c 385
EricLew 0:d4e5ad7ad71c 386 /**
EricLew 0:d4e5ad7ad71c 387 * @brief De-Initializes microphone related peripherals.
EricLew 0:d4e5ad7ad71c 388 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 389
EricLew 0:d4e5ad7ad71c 390 */
EricLew 0:d4e5ad7ad71c 391 uint8_t BSP_AUDIO_IN_DeInit(void)
EricLew 0:d4e5ad7ad71c 392 {
EricLew 0:d4e5ad7ad71c 393 /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */
EricLew 0:d4e5ad7ad71c 394 if (AUDIO_DFSDMx_DeInit() != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 395 {
EricLew 0:d4e5ad7ad71c 396 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 397 }
EricLew 0:d4e5ad7ad71c 398
EricLew 0:d4e5ad7ad71c 399 /* Reset the audio input context */
EricLew 0:d4e5ad7ad71c 400 memset(&hAudioIn, 0, sizeof(hAudioIn));
EricLew 0:d4e5ad7ad71c 401
EricLew 0:d4e5ad7ad71c 402 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 403 }
EricLew 0:d4e5ad7ad71c 404
EricLew 0:d4e5ad7ad71c 405 /**
EricLew 0:d4e5ad7ad71c 406 * @brief Starts audio recording.
EricLew 0:d4e5ad7ad71c 407 * @param pbuf: Main buffer pointer for the recorded data storing
EricLew 0:d4e5ad7ad71c 408 * @param size: Current size of the recorded buffer
EricLew 0:d4e5ad7ad71c 409 * @note The Right channel is start at first with synchro on start of Left channel
EricLew 0:d4e5ad7ad71c 410 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 411 */
EricLew 0:d4e5ad7ad71c 412 uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
EricLew 0:d4e5ad7ad71c 413 {
EricLew 0:d4e5ad7ad71c 414 hAudioIn.pRecBuf = pbuf;
EricLew 0:d4e5ad7ad71c 415 hAudioIn.RecSize = size;
EricLew 0:d4e5ad7ad71c 416
EricLew 0:d4e5ad7ad71c 417 /* Allocate hAudioIn.LeftRecBuff buffer */
EricLew 0:d4e5ad7ad71c 418 #if defined(BSP_AUDIO_USE_RTOS)
EricLew 0:d4e5ad7ad71c 419 hAudioIn.LeftRecBuff = (int32_t *)k_malloc(size * sizeof(int32_t));
EricLew 0:d4e5ad7ad71c 420 #else
EricLew 0:d4e5ad7ad71c 421 hAudioIn.LeftRecBuff = (int32_t *)malloc(size * sizeof(int32_t));
EricLew 0:d4e5ad7ad71c 422 #endif
EricLew 0:d4e5ad7ad71c 423 if(hAudioIn.LeftRecBuff == NULL)
EricLew 0:d4e5ad7ad71c 424 {
EricLew 0:d4e5ad7ad71c 425 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 426 }
EricLew 0:d4e5ad7ad71c 427
EricLew 0:d4e5ad7ad71c 428 /* Call the Media layer start function for left channel */
EricLew 0:d4e5ad7ad71c 429 if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter,
EricLew 0:d4e5ad7ad71c 430 (int32_t*)hAudioIn.LeftRecBuff,
EricLew 0:d4e5ad7ad71c 431 (hAudioIn.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR)) != HAL_OK)
EricLew 0:d4e5ad7ad71c 432 {
EricLew 0:d4e5ad7ad71c 433 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 434 }
EricLew 0:d4e5ad7ad71c 435
EricLew 0:d4e5ad7ad71c 436 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 437 }
EricLew 0:d4e5ad7ad71c 438
EricLew 0:d4e5ad7ad71c 439 /**
EricLew 0:d4e5ad7ad71c 440 * @brief Updates the audio frequency.
EricLew 0:d4e5ad7ad71c 441 * @param AudioFreq: Audio frequency used to record the audio stream.
EricLew 0:d4e5ad7ad71c 442 * @note This API should be called after the BSP_AUDIO_IN_Init() to adjust the
EricLew 0:d4e5ad7ad71c 443 * audio frequency.
EricLew 0:d4e5ad7ad71c 444 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 445 */
EricLew 0:d4e5ad7ad71c 446 uint8_t BSP_AUDIO_IN_SetFrequency(uint32_t AudioFreq)
EricLew 0:d4e5ad7ad71c 447 {
EricLew 0:d4e5ad7ad71c 448 /* Configure the SAI PLL according to the requested audio frequency */
EricLew 0:d4e5ad7ad71c 449 if (AUDIO_SAIPLLConfig(AudioFreq) != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 450 {
EricLew 0:d4e5ad7ad71c 451 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 452 }
EricLew 0:d4e5ad7ad71c 453
EricLew 0:d4e5ad7ad71c 454 /* De-initializes the Digital Filter for Sigma-Delta Modulators interface */
EricLew 0:d4e5ad7ad71c 455 if(AUDIO_DFSDMx_DeInit() != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 456 {
EricLew 0:d4e5ad7ad71c 457 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 458 }
EricLew 0:d4e5ad7ad71c 459
EricLew 0:d4e5ad7ad71c 460 /* Initializes the Digital Filter for Sigma-Delta Modulators interface */
EricLew 0:d4e5ad7ad71c 461 if(AUDIO_DFSDMx_Init(AudioFreq) != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 462 {
EricLew 0:d4e5ad7ad71c 463 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 464 }
EricLew 0:d4e5ad7ad71c 465
EricLew 0:d4e5ad7ad71c 466 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 467 }
EricLew 0:d4e5ad7ad71c 468
EricLew 0:d4e5ad7ad71c 469 /**
EricLew 0:d4e5ad7ad71c 470 * @brief Regular conversion complete callback.
EricLew 0:d4e5ad7ad71c 471 * @note In interrupt mode, user has to read conversion value in this function
EricLew 0:d4e5ad7ad71c 472 using HAL_DFSDM_FilterGetRegularValue.
EricLew 0:d4e5ad7ad71c 473 * @param hdfsdm_filter : DFSDM filter handle.
EricLew 0:d4e5ad7ad71c 474 * @retval None
EricLew 0:d4e5ad7ad71c 475 */
EricLew 0:d4e5ad7ad71c 476 void HAL_DFSDM_FilterRegConvCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
EricLew 0:d4e5ad7ad71c 477 {
EricLew 0:d4e5ad7ad71c 478 uint32_t index;
EricLew 0:d4e5ad7ad71c 479 uint32_t recbufsize = (hAudioIn.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR);
EricLew 0:d4e5ad7ad71c 480
EricLew 0:d4e5ad7ad71c 481 for(index = (recbufsize/2); index < recbufsize; index++)
EricLew 0:d4e5ad7ad71c 482 {
EricLew 0:d4e5ad7ad71c 483 hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32760, 32760));
EricLew 0:d4e5ad7ad71c 484 }
EricLew 0:d4e5ad7ad71c 485
EricLew 0:d4e5ad7ad71c 486 /* Invoke the registered 'TransferComplete' function (if any) */
EricLew 0:d4e5ad7ad71c 487 if (hAudioIn.CbTransferComplete != (Audio_CallbackTypeDef)NULL)
EricLew 0:d4e5ad7ad71c 488 {
EricLew 0:d4e5ad7ad71c 489 hAudioIn.CbTransferComplete();
EricLew 0:d4e5ad7ad71c 490 }
EricLew 0:d4e5ad7ad71c 491 }
EricLew 0:d4e5ad7ad71c 492
EricLew 0:d4e5ad7ad71c 493 /**
EricLew 0:d4e5ad7ad71c 494 * @brief Half regular conversion complete callback.
EricLew 0:d4e5ad7ad71c 495 * @param hdfsdm_filter : DFSDM filter handle.
EricLew 0:d4e5ad7ad71c 496 * @retval None
EricLew 0:d4e5ad7ad71c 497 */
EricLew 0:d4e5ad7ad71c 498 void HAL_DFSDM_FilterRegConvHalfCpltCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
EricLew 0:d4e5ad7ad71c 499 {
EricLew 0:d4e5ad7ad71c 500 uint32_t index;
EricLew 0:d4e5ad7ad71c 501 uint32_t recbufsize = (hAudioIn.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR);
EricLew 0:d4e5ad7ad71c 502
EricLew 0:d4e5ad7ad71c 503
EricLew 0:d4e5ad7ad71c 504 for(index = 0; index < (recbufsize/2); index++)
EricLew 0:d4e5ad7ad71c 505 {
EricLew 0:d4e5ad7ad71c 506 hAudioIn.pRecBuf[index] = (uint16_t)(SaturaLH((hAudioIn.LeftRecBuff[index] >> 8), -32760, 32760));
EricLew 0:d4e5ad7ad71c 507 }
EricLew 0:d4e5ad7ad71c 508
EricLew 0:d4e5ad7ad71c 509 /* Invoke the registered 'HalfTransfer' callback function (if any) */
EricLew 0:d4e5ad7ad71c 510 if (hAudioIn.CbHalfTransfer != (Audio_CallbackTypeDef)NULL)
EricLew 0:d4e5ad7ad71c 511 {
EricLew 0:d4e5ad7ad71c 512 hAudioIn.CbHalfTransfer();
EricLew 0:d4e5ad7ad71c 513 }
EricLew 0:d4e5ad7ad71c 514 }
EricLew 0:d4e5ad7ad71c 515
EricLew 0:d4e5ad7ad71c 516 /**
EricLew 0:d4e5ad7ad71c 517 * @brief Error callback.
EricLew 0:d4e5ad7ad71c 518 * @param hdfsdm_filter : DFSDM filter handle.
EricLew 0:d4e5ad7ad71c 519 * @retval None
EricLew 0:d4e5ad7ad71c 520 */
EricLew 0:d4e5ad7ad71c 521 void HAL_DFSDM_FilterErrorCallback(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
EricLew 0:d4e5ad7ad71c 522 {
EricLew 0:d4e5ad7ad71c 523 /* Invoke the registered 'ErrorCallback' callback function (if any) */
EricLew 0:d4e5ad7ad71c 524 if (hAudioIn.CbError != (Audio_CallbackTypeDef)NULL)
EricLew 0:d4e5ad7ad71c 525 {
EricLew 0:d4e5ad7ad71c 526 hAudioIn.CbError();
EricLew 0:d4e5ad7ad71c 527 }
EricLew 0:d4e5ad7ad71c 528 }
EricLew 0:d4e5ad7ad71c 529
EricLew 0:d4e5ad7ad71c 530 /**
EricLew 0:d4e5ad7ad71c 531 * @brief Stops audio recording.
EricLew 0:d4e5ad7ad71c 532 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 533 */
EricLew 0:d4e5ad7ad71c 534 uint8_t BSP_AUDIO_IN_Stop(void)
EricLew 0:d4e5ad7ad71c 535 {
EricLew 0:d4e5ad7ad71c 536 /* Call the Media layer stop function for left channel */
EricLew 0:d4e5ad7ad71c 537 if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK )
EricLew 0:d4e5ad7ad71c 538 {
EricLew 0:d4e5ad7ad71c 539 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 540 }
EricLew 0:d4e5ad7ad71c 541
EricLew 0:d4e5ad7ad71c 542 /* Free hAudioIn.LeftRecBuff buffer */
EricLew 0:d4e5ad7ad71c 543 #if defined(BSP_AUDIO_USE_RTOS)
EricLew 0:d4e5ad7ad71c 544 k_free((void *)hAudioIn.LeftRecBuff);
EricLew 0:d4e5ad7ad71c 545 #else
EricLew 0:d4e5ad7ad71c 546 free((void *)hAudioIn.LeftRecBuff);
EricLew 0:d4e5ad7ad71c 547 #endif
EricLew 0:d4e5ad7ad71c 548
EricLew 0:d4e5ad7ad71c 549 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 550 }
EricLew 0:d4e5ad7ad71c 551
EricLew 0:d4e5ad7ad71c 552 /**
EricLew 0:d4e5ad7ad71c 553 * @brief Pauses the audio file stream.
EricLew 0:d4e5ad7ad71c 554 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 555 */
EricLew 0:d4e5ad7ad71c 556 uint8_t BSP_AUDIO_IN_Pause(void)
EricLew 0:d4e5ad7ad71c 557 {
EricLew 0:d4e5ad7ad71c 558 /* Call the Media layer stop function */
EricLew 0:d4e5ad7ad71c 559 if(HAL_DFSDM_FilterRegularStop_DMA(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
EricLew 0:d4e5ad7ad71c 560 {
EricLew 0:d4e5ad7ad71c 561 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 562 }
EricLew 0:d4e5ad7ad71c 563
EricLew 0:d4e5ad7ad71c 564 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 565 }
EricLew 0:d4e5ad7ad71c 566
EricLew 0:d4e5ad7ad71c 567 /**
EricLew 0:d4e5ad7ad71c 568 * @brief Resumes the audio file stream.
EricLew 0:d4e5ad7ad71c 569 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 570 */
EricLew 0:d4e5ad7ad71c 571 uint8_t BSP_AUDIO_IN_Resume(void)
EricLew 0:d4e5ad7ad71c 572 {
EricLew 0:d4e5ad7ad71c 573 /* Call the Media layer start function for left channel */
EricLew 0:d4e5ad7ad71c 574 if(HAL_DFSDM_FilterRegularStart_DMA(&BSP_AUDIO_hDfsdmLeftFilter,
EricLew 0:d4e5ad7ad71c 575 (int32_t*)hAudioIn.LeftRecBuff,
EricLew 0:d4e5ad7ad71c 576 (hAudioIn.RecSize/DEFAULT_AUDIO_IN_CHANNEL_NBR)) != HAL_OK)
EricLew 0:d4e5ad7ad71c 577 {
EricLew 0:d4e5ad7ad71c 578 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 579 }
EricLew 0:d4e5ad7ad71c 580
EricLew 0:d4e5ad7ad71c 581 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 582 }
EricLew 0:d4e5ad7ad71c 583
EricLew 0:d4e5ad7ad71c 584 /**
EricLew 0:d4e5ad7ad71c 585 * @brief register user callback functions
EricLew 0:d4e5ad7ad71c 586 * @param ErrorCallback: pointer to the error callback function
EricLew 0:d4e5ad7ad71c 587 * @param HalfTransferCallback: pointer to the half transfer callback function
EricLew 0:d4e5ad7ad71c 588 * @param TransferCompleteCallback: pointer to the transfer complete callback function
EricLew 0:d4e5ad7ad71c 589 * @retval None
EricLew 0:d4e5ad7ad71c 590 */
EricLew 0:d4e5ad7ad71c 591 void BSP_AUDIO_IN_RegisterCallbacks(Audio_CallbackTypeDef ErrorCallback,
EricLew 0:d4e5ad7ad71c 592 Audio_CallbackTypeDef HalfTransferCallback,
EricLew 0:d4e5ad7ad71c 593 Audio_CallbackTypeDef TransferCompleteCallback)
EricLew 0:d4e5ad7ad71c 594 {
EricLew 0:d4e5ad7ad71c 595 hAudioIn.CbError = ErrorCallback;
EricLew 0:d4e5ad7ad71c 596 hAudioIn.CbHalfTransfer = HalfTransferCallback;
EricLew 0:d4e5ad7ad71c 597 hAudioIn.CbTransferComplete = TransferCompleteCallback;
EricLew 0:d4e5ad7ad71c 598 }
EricLew 0:d4e5ad7ad71c 599 /**
EricLew 0:d4e5ad7ad71c 600 * @}
EricLew 0:d4e5ad7ad71c 601 */
EricLew 0:d4e5ad7ad71c 602
EricLew 0:d4e5ad7ad71c 603 /* private functions --------------------------------------------------------*/
EricLew 0:d4e5ad7ad71c 604 /** @addtogroup STM32L476G_DISCOVERY_AUDIO_Private_Functions
EricLew 0:d4e5ad7ad71c 605 * @{
EricLew 0:d4e5ad7ad71c 606 */
EricLew 0:d4e5ad7ad71c 607 /**
EricLew 0:d4e5ad7ad71c 608 * @brief Initializes the Audio Codec audio interface (SAI).
EricLew 0:d4e5ad7ad71c 609 * @param AudioFreq: Audio frequency to be configured for the SAI peripheral.
EricLew 0:d4e5ad7ad71c 610 * @note The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123
EricLew 0:d4e5ad7ad71c 611 * and user can update this configuration using
EricLew 0:d4e5ad7ad71c 612 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 613 */
EricLew 0:d4e5ad7ad71c 614 static uint8_t AUDIO_SAIx_Init(uint32_t AudioFreq)
EricLew 0:d4e5ad7ad71c 615 {
EricLew 0:d4e5ad7ad71c 616 /* Disable SAI peripheral to allow access to SAI internal registers */
EricLew 0:d4e5ad7ad71c 617 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai);
EricLew 0:d4e5ad7ad71c 618
EricLew 0:d4e5ad7ad71c 619 /* Initialize the BSP_AUDIO_hSai Instance parameter */
EricLew 0:d4e5ad7ad71c 620 BSP_AUDIO_hSai.Instance = AUDIO_SAIx;
EricLew 0:d4e5ad7ad71c 621
EricLew 0:d4e5ad7ad71c 622 /* Configure SAI_Block_x
EricLew 0:d4e5ad7ad71c 623 LSBFirst: Disabled
EricLew 0:d4e5ad7ad71c 624 DataSize: 16 */
EricLew 0:d4e5ad7ad71c 625 BSP_AUDIO_hSai.Init.AudioMode = SAI_MODEMASTER_TX;
EricLew 0:d4e5ad7ad71c 626 BSP_AUDIO_hSai.Init.Synchro = SAI_ASYNCHRONOUS;
EricLew 0:d4e5ad7ad71c 627 BSP_AUDIO_hSai.Init.SynchroExt = SAI_SYNCEXT_DISABLE;
EricLew 0:d4e5ad7ad71c 628 BSP_AUDIO_hSai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE;
EricLew 0:d4e5ad7ad71c 629 BSP_AUDIO_hSai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLE;
EricLew 0:d4e5ad7ad71c 630 BSP_AUDIO_hSai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
EricLew 0:d4e5ad7ad71c 631 BSP_AUDIO_hSai.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_MCKDIV;
EricLew 0:d4e5ad7ad71c 632 BSP_AUDIO_hSai.Init.Mckdiv = SAIClockDivider(AudioFreq);
EricLew 0:d4e5ad7ad71c 633 BSP_AUDIO_hSai.Init.MonoStereoMode = SAI_STEREOMODE;
EricLew 0:d4e5ad7ad71c 634 BSP_AUDIO_hSai.Init.CompandingMode = SAI_NOCOMPANDING;
EricLew 0:d4e5ad7ad71c 635 BSP_AUDIO_hSai.Init.TriState = SAI_OUTPUT_NOTRELEASED;
EricLew 0:d4e5ad7ad71c 636 BSP_AUDIO_hSai.Init.Protocol = SAI_FREE_PROTOCOL;
EricLew 0:d4e5ad7ad71c 637 BSP_AUDIO_hSai.Init.DataSize = SAI_DATASIZE_16;
EricLew 0:d4e5ad7ad71c 638 BSP_AUDIO_hSai.Init.FirstBit = SAI_FIRSTBIT_MSB;
EricLew 0:d4e5ad7ad71c 639 BSP_AUDIO_hSai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
EricLew 0:d4e5ad7ad71c 640
EricLew 0:d4e5ad7ad71c 641 /* Configure SAI_Block_x Frame
EricLew 0:d4e5ad7ad71c 642 Frame Length: 32
EricLew 0:d4e5ad7ad71c 643 Frame active Length: 16
EricLew 0:d4e5ad7ad71c 644 FS Definition: Start frame + Channel Side identification
EricLew 0:d4e5ad7ad71c 645 FS Polarity: FS active Low
EricLew 0:d4e5ad7ad71c 646 FS Offset: FS asserted one bit before the first bit of slot 0 */
EricLew 0:d4e5ad7ad71c 647 BSP_AUDIO_hSai.FrameInit.FrameLength = 32;
EricLew 0:d4e5ad7ad71c 648 BSP_AUDIO_hSai.FrameInit.ActiveFrameLength = 16;
EricLew 0:d4e5ad7ad71c 649 BSP_AUDIO_hSai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
EricLew 0:d4e5ad7ad71c 650 BSP_AUDIO_hSai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
EricLew 0:d4e5ad7ad71c 651 BSP_AUDIO_hSai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
EricLew 0:d4e5ad7ad71c 652
EricLew 0:d4e5ad7ad71c 653 /* Configure SAI Block_x Slot
EricLew 0:d4e5ad7ad71c 654 Slot First Bit Offset: 0
EricLew 0:d4e5ad7ad71c 655 Slot Size : 16
EricLew 0:d4e5ad7ad71c 656 Slot Number: 2
EricLew 0:d4e5ad7ad71c 657 Slot Active: Slots 0 and 1 actives */
EricLew 0:d4e5ad7ad71c 658 BSP_AUDIO_hSai.SlotInit.FirstBitOffset = 0;
EricLew 0:d4e5ad7ad71c 659 BSP_AUDIO_hSai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
EricLew 0:d4e5ad7ad71c 660 BSP_AUDIO_hSai.SlotInit.SlotNumber = 2;
EricLew 0:d4e5ad7ad71c 661 BSP_AUDIO_hSai.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1;
EricLew 0:d4e5ad7ad71c 662
EricLew 0:d4e5ad7ad71c 663 /* Initializes the SAI peripheral*/
EricLew 0:d4e5ad7ad71c 664 if (HAL_SAI_Init(&BSP_AUDIO_hSai) != HAL_OK)
EricLew 0:d4e5ad7ad71c 665 {
EricLew 0:d4e5ad7ad71c 666 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 667 }
EricLew 0:d4e5ad7ad71c 668
EricLew 0:d4e5ad7ad71c 669 /* Enable SAI peripheral to generate MCLK */
EricLew 0:d4e5ad7ad71c 670 __HAL_SAI_ENABLE(&BSP_AUDIO_hSai);
EricLew 0:d4e5ad7ad71c 671
EricLew 0:d4e5ad7ad71c 672 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 673
EricLew 0:d4e5ad7ad71c 674 }
EricLew 0:d4e5ad7ad71c 675
EricLew 0:d4e5ad7ad71c 676 /**
EricLew 0:d4e5ad7ad71c 677 * @brief De-initializes the Audio Codec audio interface (SAI).
EricLew 0:d4e5ad7ad71c 678 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 679 */
EricLew 0:d4e5ad7ad71c 680 static uint8_t AUDIO_SAIx_DeInit(void)
EricLew 0:d4e5ad7ad71c 681 {
EricLew 0:d4e5ad7ad71c 682 /* Disable the SAI audio block */
EricLew 0:d4e5ad7ad71c 683 __HAL_SAI_DISABLE(&BSP_AUDIO_hSai);
EricLew 0:d4e5ad7ad71c 684
EricLew 0:d4e5ad7ad71c 685 /* De-initializes the SAI peripheral */
EricLew 0:d4e5ad7ad71c 686 if (HAL_SAI_DeInit(&BSP_AUDIO_hSai) != HAL_OK)
EricLew 0:d4e5ad7ad71c 687 {
EricLew 0:d4e5ad7ad71c 688 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 689 }
EricLew 0:d4e5ad7ad71c 690
EricLew 0:d4e5ad7ad71c 691 /* Disable SAIx PLL */
EricLew 0:d4e5ad7ad71c 692 if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 693 {
EricLew 0:d4e5ad7ad71c 694 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 695 }
EricLew 0:d4e5ad7ad71c 696
EricLew 0:d4e5ad7ad71c 697 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 698 }
EricLew 0:d4e5ad7ad71c 699
EricLew 0:d4e5ad7ad71c 700 /**
EricLew 0:d4e5ad7ad71c 701 * @brief SAI MSP Init
EricLew 0:d4e5ad7ad71c 702 * @param hsai : pointer to a SAI_HandleTypeDef structure
EricLew 0:d4e5ad7ad71c 703 * @retval None
EricLew 0:d4e5ad7ad71c 704 */
EricLew 0:d4e5ad7ad71c 705 void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai)
EricLew 0:d4e5ad7ad71c 706 {
EricLew 0:d4e5ad7ad71c 707 GPIO_InitTypeDef GPIO_InitStruct;
EricLew 0:d4e5ad7ad71c 708
EricLew 0:d4e5ad7ad71c 709 /* Enable SAI clock */
EricLew 0:d4e5ad7ad71c 710 AUDIO_SAIx_CLK_ENABLE();
EricLew 0:d4e5ad7ad71c 711
EricLew 0:d4e5ad7ad71c 712 /* Enable GPIO clock */
EricLew 0:d4e5ad7ad71c 713 AUDIO_SAIx_MCK_SCK_SD_FS_ENABLE();
EricLew 0:d4e5ad7ad71c 714
EricLew 0:d4e5ad7ad71c 715 /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
EricLew 0:d4e5ad7ad71c 716 GPIO_InitStruct.Pin = AUDIO_SAIx_FS_PIN | AUDIO_SAIx_SCK_PIN | AUDIO_SAIx_SD_PIN | AUDIO_SAIx_MCK_PIN;
EricLew 0:d4e5ad7ad71c 717 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
EricLew 0:d4e5ad7ad71c 718 GPIO_InitStruct.Pull = GPIO_NOPULL;
EricLew 0:d4e5ad7ad71c 719 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
EricLew 0:d4e5ad7ad71c 720 GPIO_InitStruct.Alternate = AUDIO_SAIx_MCK_SCK_SD_FS_AF;
EricLew 0:d4e5ad7ad71c 721 HAL_GPIO_Init(AUDIO_SAIx_MCK_SCK_SD_FS_GPIO_PORT, &GPIO_InitStruct);
EricLew 0:d4e5ad7ad71c 722
EricLew 0:d4e5ad7ad71c 723 /* Enable the DMA clock */
EricLew 0:d4e5ad7ad71c 724 AUDIO_SAIx_DMAx_CLK_ENABLE();
EricLew 0:d4e5ad7ad71c 725
EricLew 0:d4e5ad7ad71c 726 if(hsai->Instance == AUDIO_SAIx)
EricLew 0:d4e5ad7ad71c 727 {
EricLew 0:d4e5ad7ad71c 728 /* Configure the hDmaSai handle parameters */
EricLew 0:d4e5ad7ad71c 729 hDmaSai.Init.Request = DMA_REQUEST_1;
EricLew 0:d4e5ad7ad71c 730 hDmaSai.Init.Direction = DMA_MEMORY_TO_PERIPH;
EricLew 0:d4e5ad7ad71c 731 hDmaSai.Init.PeriphInc = DMA_PINC_DISABLE;
EricLew 0:d4e5ad7ad71c 732 hDmaSai.Init.MemInc = DMA_MINC_ENABLE;
EricLew 0:d4e5ad7ad71c 733 hDmaSai.Init.PeriphDataAlignment = AUDIO_SAIx_DMAx_PERIPH_DATA_SIZE;
EricLew 0:d4e5ad7ad71c 734 hDmaSai.Init.MemDataAlignment = AUDIO_SAIx_DMAx_MEM_DATA_SIZE;
EricLew 0:d4e5ad7ad71c 735 hDmaSai.Init.Mode = DMA_NORMAL;
EricLew 0:d4e5ad7ad71c 736 hDmaSai.Init.Priority = DMA_PRIORITY_HIGH;
EricLew 0:d4e5ad7ad71c 737
EricLew 0:d4e5ad7ad71c 738 hDmaSai.Instance = AUDIO_SAIx_DMAx_CHANNEL;
EricLew 0:d4e5ad7ad71c 739
EricLew 0:d4e5ad7ad71c 740 /* Associate the DMA handle */
EricLew 0:d4e5ad7ad71c 741 __HAL_LINKDMA(hsai, hdmatx, hDmaSai);
EricLew 0:d4e5ad7ad71c 742
EricLew 0:d4e5ad7ad71c 743 /* Deinitialize the Stream for new transfer */
EricLew 0:d4e5ad7ad71c 744 HAL_DMA_DeInit(&hDmaSai);
EricLew 0:d4e5ad7ad71c 745
EricLew 0:d4e5ad7ad71c 746 /* Configure the DMA Stream */
EricLew 0:d4e5ad7ad71c 747 HAL_DMA_Init(&hDmaSai);
EricLew 0:d4e5ad7ad71c 748 }
EricLew 0:d4e5ad7ad71c 749
EricLew 0:d4e5ad7ad71c 750 /* SAI DMA IRQ Channel configuration */
EricLew 0:d4e5ad7ad71c 751 HAL_NVIC_SetPriority(AUDIO_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
EricLew 0:d4e5ad7ad71c 752 HAL_NVIC_EnableIRQ(AUDIO_SAIx_DMAx_IRQ);
EricLew 0:d4e5ad7ad71c 753 }
EricLew 0:d4e5ad7ad71c 754
EricLew 0:d4e5ad7ad71c 755 /**
EricLew 0:d4e5ad7ad71c 756 * @brief SAI MSP De-init
EricLew 0:d4e5ad7ad71c 757 * @param hsai : pointer to a SAI_HandleTypeDef structure
EricLew 0:d4e5ad7ad71c 758 * @retval None
EricLew 0:d4e5ad7ad71c 759 */
EricLew 0:d4e5ad7ad71c 760 void HAL_SAI_MspDeInit(SAI_HandleTypeDef *hsai)
EricLew 0:d4e5ad7ad71c 761 {
EricLew 0:d4e5ad7ad71c 762 /* Disable SAI DMA Channel IRQ */
EricLew 0:d4e5ad7ad71c 763 HAL_NVIC_DisableIRQ(AUDIO_SAIx_DMAx_IRQ);
EricLew 0:d4e5ad7ad71c 764
EricLew 0:d4e5ad7ad71c 765 /* Reset the DMA Stream configuration*/
EricLew 0:d4e5ad7ad71c 766 HAL_DMA_DeInit(&hDmaSai);
EricLew 0:d4e5ad7ad71c 767
EricLew 0:d4e5ad7ad71c 768 /* Disable the DMA clock */
EricLew 0:d4e5ad7ad71c 769 AUDIO_SAIx_DMAx_CLK_DISABLE();
EricLew 0:d4e5ad7ad71c 770
EricLew 0:d4e5ad7ad71c 771 /* De-initialize FS, SCK, MCK and SD pins*/
EricLew 0:d4e5ad7ad71c 772 HAL_GPIO_DeInit(AUDIO_SAIx_MCK_SCK_SD_FS_GPIO_PORT,
EricLew 0:d4e5ad7ad71c 773 AUDIO_SAIx_FS_PIN | AUDIO_SAIx_SCK_PIN | AUDIO_SAIx_SD_PIN | AUDIO_SAIx_MCK_PIN);
EricLew 0:d4e5ad7ad71c 774
EricLew 0:d4e5ad7ad71c 775 /* Disable GPIO clock */
EricLew 0:d4e5ad7ad71c 776 AUDIO_SAIx_MCK_SCK_SD_FS_DISABLE();
EricLew 0:d4e5ad7ad71c 777
EricLew 0:d4e5ad7ad71c 778 /* Disable SAI clock */
EricLew 0:d4e5ad7ad71c 779 AUDIO_SAIx_CLK_DISABLE();
EricLew 0:d4e5ad7ad71c 780 }
EricLew 0:d4e5ad7ad71c 781
EricLew 0:d4e5ad7ad71c 782 /**
EricLew 0:d4e5ad7ad71c 783 * @brief Resets the audio codec. It restores the default configuration of the
EricLew 0:d4e5ad7ad71c 784 * codec (this function shall be called before initializing the codec).
EricLew 0:d4e5ad7ad71c 785 * @retval None
EricLew 0:d4e5ad7ad71c 786 */
EricLew 0:d4e5ad7ad71c 787
EricLew 0:d4e5ad7ad71c 788
EricLew 0:d4e5ad7ad71c 789 /**
EricLew 0:d4e5ad7ad71c 790 * @}
EricLew 0:d4e5ad7ad71c 791 */
EricLew 0:d4e5ad7ad71c 792
EricLew 0:d4e5ad7ad71c 793 /** @addtogroup STM32L476G_DISCOVERY_AUDIO_Private_Functions
EricLew 0:d4e5ad7ad71c 794 * @{
EricLew 0:d4e5ad7ad71c 795 */
EricLew 0:d4e5ad7ad71c 796
EricLew 0:d4e5ad7ad71c 797 /**
EricLew 0:d4e5ad7ad71c 798 * @brief Initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
EricLew 0:d4e5ad7ad71c 799 * @param AudioFreq: Audio frequency to be used to set correctly the DFSDM peripheral.
EricLew 0:d4e5ad7ad71c 800 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 801 */
EricLew 0:d4e5ad7ad71c 802 static uint8_t AUDIO_DFSDMx_Init(uint32_t AudioFreq)
EricLew 0:d4e5ad7ad71c 803 {
EricLew 0:d4e5ad7ad71c 804 /*####CHANNEL 2####*/
EricLew 0:d4e5ad7ad71c 805 hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Activation = ENABLE;
EricLew 0:d4e5ad7ad71c 806 hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Selection = DFSDM_CHANNEL_OUTPUT_CLOCK_AUDIO;
EricLew 0:d4e5ad7ad71c 807 /* Set the DFSDM clock OUT audio frequency configuration */
EricLew 0:d4e5ad7ad71c 808 hAudioIn.hDfsdmLeftChannel.Init.OutputClock.Divider = DFSDMClockDivider(AudioFreq);
EricLew 0:d4e5ad7ad71c 809 hAudioIn.hDfsdmLeftChannel.Init.Input.Multiplexer = DFSDM_CHANNEL_EXTERNAL_INPUTS;
EricLew 0:d4e5ad7ad71c 810 hAudioIn.hDfsdmLeftChannel.Init.Input.DataPacking = DFSDM_CHANNEL_STANDARD_MODE;
EricLew 0:d4e5ad7ad71c 811 hAudioIn.hDfsdmLeftChannel.Init.Input.Pins = DFSDM_CHANNEL_SAME_CHANNEL_PINS;
EricLew 0:d4e5ad7ad71c 812 /* Request to sample stable data for LEFT micro on Rising edge */
EricLew 0:d4e5ad7ad71c 813 hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.Type = DFSDM_CHANNEL_SPI_RISING;
EricLew 0:d4e5ad7ad71c 814 hAudioIn.hDfsdmLeftChannel.Init.SerialInterface.SpiClock = DFSDM_CHANNEL_SPI_CLOCK_INTERNAL;
EricLew 0:d4e5ad7ad71c 815 hAudioIn.hDfsdmLeftChannel.Init.Awd.FilterOrder = DFSDM_CHANNEL_SINC1_ORDER;
EricLew 0:d4e5ad7ad71c 816 hAudioIn.hDfsdmLeftChannel.Init.Awd.Oversampling = 10;
EricLew 0:d4e5ad7ad71c 817 hAudioIn.hDfsdmLeftChannel.Init.Offset = 0;
EricLew 0:d4e5ad7ad71c 818 hAudioIn.hDfsdmLeftChannel.Init.RightBitShift = DFSDMRightBitShift(AudioFreq);
EricLew 0:d4e5ad7ad71c 819
EricLew 0:d4e5ad7ad71c 820 hAudioIn.hDfsdmLeftChannel.Instance = DFSDM_Channel2;
EricLew 0:d4e5ad7ad71c 821
EricLew 0:d4e5ad7ad71c 822 /* Init the DFSDM Channel */
EricLew 0:d4e5ad7ad71c 823 if (HAL_DFSDM_ChannelInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK)
EricLew 0:d4e5ad7ad71c 824 {
EricLew 0:d4e5ad7ad71c 825 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 826 }
EricLew 0:d4e5ad7ad71c 827
EricLew 0:d4e5ad7ad71c 828 /*####FILTER 0####*/
EricLew 0:d4e5ad7ad71c 829 BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.Trigger = DFSDM_FILTER_SW_TRIGGER;
EricLew 0:d4e5ad7ad71c 830 BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.FastMode = ENABLE;
EricLew 0:d4e5ad7ad71c 831 BSP_AUDIO_hDfsdmLeftFilter.Init.RegularParam.DmaMode = ENABLE;
EricLew 0:d4e5ad7ad71c 832 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.Trigger = DFSDM_FILTER_SW_TRIGGER;
EricLew 0:d4e5ad7ad71c 833 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ScanMode = DISABLE;
EricLew 0:d4e5ad7ad71c 834 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.DmaMode = DISABLE;
EricLew 0:d4e5ad7ad71c 835 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTrigger = DFSDM_FILTER_EXT_TRIG_TIM8_TRGO;
EricLew 0:d4e5ad7ad71c 836 BSP_AUDIO_hDfsdmLeftFilter.Init.InjectedParam.ExtTriggerEdge = DFSDM_FILTER_EXT_TRIG_BOTH_EDGES;
EricLew 0:d4e5ad7ad71c 837 BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.SincOrder = DFSDMFilterOrder(AudioFreq);
EricLew 0:d4e5ad7ad71c 838 /* Set the DFSDM Filters Oversampling to have correct sample rate */
EricLew 0:d4e5ad7ad71c 839 BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.Oversampling = DFSDMOverSampling(AudioFreq);
EricLew 0:d4e5ad7ad71c 840 BSP_AUDIO_hDfsdmLeftFilter.Init.FilterParam.IntOversampling = 1;
EricLew 0:d4e5ad7ad71c 841
EricLew 0:d4e5ad7ad71c 842 BSP_AUDIO_hDfsdmLeftFilter.Instance = AUDIO_DFSDMx_LEFT_FILTER;
EricLew 0:d4e5ad7ad71c 843
EricLew 0:d4e5ad7ad71c 844 /* Init the DFSDM Filter */
EricLew 0:d4e5ad7ad71c 845 if (HAL_DFSDM_FilterInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
EricLew 0:d4e5ad7ad71c 846 {
EricLew 0:d4e5ad7ad71c 847 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 848 }
EricLew 0:d4e5ad7ad71c 849
EricLew 0:d4e5ad7ad71c 850 /* Configure regular channel */
EricLew 0:d4e5ad7ad71c 851 if (HAL_DFSDM_FilterConfigRegChannel(&BSP_AUDIO_hDfsdmLeftFilter,
EricLew 0:d4e5ad7ad71c 852 DFSDM_CHANNEL_2,
EricLew 0:d4e5ad7ad71c 853 DFSDM_CONTINUOUS_CONV_ON) != HAL_OK)
EricLew 0:d4e5ad7ad71c 854 {
EricLew 0:d4e5ad7ad71c 855 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 856 }
EricLew 0:d4e5ad7ad71c 857
EricLew 0:d4e5ad7ad71c 858 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 859 }
EricLew 0:d4e5ad7ad71c 860
EricLew 0:d4e5ad7ad71c 861 /**
EricLew 0:d4e5ad7ad71c 862 * @brief De-initializes the Digital Filter for Sigma-Delta Modulators interface (DFSDM).
EricLew 0:d4e5ad7ad71c 863 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 864 */
EricLew 0:d4e5ad7ad71c 865 static uint8_t AUDIO_DFSDMx_DeInit(void)
EricLew 0:d4e5ad7ad71c 866 {
EricLew 0:d4e5ad7ad71c 867 /* De-initializes the DFSDM filters to allow access to DFSDM internal registers */
EricLew 0:d4e5ad7ad71c 868 if (HAL_DFSDM_FilterDeInit(&BSP_AUDIO_hDfsdmLeftFilter) != HAL_OK)
EricLew 0:d4e5ad7ad71c 869 {
EricLew 0:d4e5ad7ad71c 870 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 871 }
EricLew 0:d4e5ad7ad71c 872
EricLew 0:d4e5ad7ad71c 873 /* De-initializes the DFSDM channels to allow access to DFSDM internal registers */
EricLew 0:d4e5ad7ad71c 874 if (HAL_DFSDM_ChannelDeInit(&hAudioIn.hDfsdmLeftChannel) != HAL_OK)
EricLew 0:d4e5ad7ad71c 875 {
EricLew 0:d4e5ad7ad71c 876 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 877 }
EricLew 0:d4e5ad7ad71c 878
EricLew 0:d4e5ad7ad71c 879 /* Disable DFSDM clock */
EricLew 0:d4e5ad7ad71c 880 AUDIO_DFSDMx_CLK_DISABLE();
EricLew 0:d4e5ad7ad71c 881
EricLew 0:d4e5ad7ad71c 882 /* Disable SAIx PLL */
EricLew 0:d4e5ad7ad71c 883 if (AUDIO_SAIx_PLL_DISABLE() != AUDIO_OK)
EricLew 0:d4e5ad7ad71c 884 {
EricLew 0:d4e5ad7ad71c 885 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 886 }
EricLew 0:d4e5ad7ad71c 887
EricLew 0:d4e5ad7ad71c 888 /* DFSDM reset */
EricLew 0:d4e5ad7ad71c 889 __HAL_RCC_DFSDM_FORCE_RESET();
EricLew 0:d4e5ad7ad71c 890 __HAL_RCC_DFSDM_RELEASE_RESET();
EricLew 0:d4e5ad7ad71c 891
EricLew 0:d4e5ad7ad71c 892 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 893 }
EricLew 0:d4e5ad7ad71c 894
EricLew 0:d4e5ad7ad71c 895 /**
EricLew 0:d4e5ad7ad71c 896 * @brief Initializes the DFSDM channel MSP.
EricLew 0:d4e5ad7ad71c 897 * @param hdfsdm_channel : DFSDM channel handle.
EricLew 0:d4e5ad7ad71c 898 * @retval None
EricLew 0:d4e5ad7ad71c 899 */
EricLew 0:d4e5ad7ad71c 900 void HAL_DFSDM_ChannelMspInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
EricLew 0:d4e5ad7ad71c 901 {
EricLew 0:d4e5ad7ad71c 902 GPIO_InitTypeDef GPIO_InitStruct;
EricLew 0:d4e5ad7ad71c 903
EricLew 0:d4e5ad7ad71c 904 /* Enable DFSDM clock */
EricLew 0:d4e5ad7ad71c 905 AUDIO_DFSDMx_CLK_ENABLE();
EricLew 0:d4e5ad7ad71c 906
EricLew 0:d4e5ad7ad71c 907 /* Enable GPIO clock */
EricLew 0:d4e5ad7ad71c 908 AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE();
EricLew 0:d4e5ad7ad71c 909
EricLew 0:d4e5ad7ad71c 910 /* DFSDM pins configuration: DFSDM_CKOUT, DMIC_DATIN pins ------------------*/
EricLew 0:d4e5ad7ad71c 911 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN | AUDIO_DFSDMx_DMIC_DATIN_PIN;
EricLew 0:d4e5ad7ad71c 912 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
EricLew 0:d4e5ad7ad71c 913 GPIO_InitStruct.Pull = GPIO_NOPULL;
EricLew 0:d4e5ad7ad71c 914 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
EricLew 0:d4e5ad7ad71c 915 GPIO_InitStruct.Alternate = AUDIO_DFSDMx_CKOUT_DMIC_DATIN_AF;
EricLew 0:d4e5ad7ad71c 916 HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct);
EricLew 0:d4e5ad7ad71c 917 }
EricLew 0:d4e5ad7ad71c 918
EricLew 0:d4e5ad7ad71c 919 /**
EricLew 0:d4e5ad7ad71c 920 * @brief De-initializes the DFSDM channel MSP.
EricLew 0:d4e5ad7ad71c 921 * @param hdfsdm_channel : DFSDM channel handle.
EricLew 0:d4e5ad7ad71c 922 * @retval None
EricLew 0:d4e5ad7ad71c 923 */
EricLew 0:d4e5ad7ad71c 924 void HAL_DFSDM_ChannelMspDeInit(DFSDM_Channel_HandleTypeDef *hdfsdm_channel)
EricLew 0:d4e5ad7ad71c 925 {
EricLew 0:d4e5ad7ad71c 926 GPIO_InitTypeDef GPIO_InitStruct;
EricLew 0:d4e5ad7ad71c 927
EricLew 0:d4e5ad7ad71c 928 /* Enable GPIO clock */
EricLew 0:d4e5ad7ad71c 929 AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_CLK_ENABLE();
EricLew 0:d4e5ad7ad71c 930
EricLew 0:d4e5ad7ad71c 931 /* DFSDM pins configuration: DFSDM_CKOUT */
EricLew 0:d4e5ad7ad71c 932 GPIO_InitStruct.Pin = AUDIO_DFSDMx_CKOUT_PIN;
EricLew 0:d4e5ad7ad71c 933 GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
EricLew 0:d4e5ad7ad71c 934 GPIO_InitStruct.Pull = GPIO_NOPULL;
EricLew 0:d4e5ad7ad71c 935 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
EricLew 0:d4e5ad7ad71c 936 HAL_GPIO_Init(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, &GPIO_InitStruct);
EricLew 0:d4e5ad7ad71c 937 HAL_GPIO_WritePin(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, AUDIO_DFSDMx_CKOUT_PIN, GPIO_PIN_RESET);
EricLew 0:d4e5ad7ad71c 938
EricLew 0:d4e5ad7ad71c 939
EricLew 0:d4e5ad7ad71c 940 /* De-initialize DMIC_DATIN pin */
EricLew 0:d4e5ad7ad71c 941 HAL_GPIO_DeInit(AUDIO_DFSDMx_CKOUT_DMIC_DATIN_GPIO_PORT, AUDIO_DFSDMx_DMIC_DATIN_PIN);
EricLew 0:d4e5ad7ad71c 942 }
EricLew 0:d4e5ad7ad71c 943
EricLew 0:d4e5ad7ad71c 944 /**
EricLew 0:d4e5ad7ad71c 945 * @brief Initializes the DFSDM filter MSP.
EricLew 0:d4e5ad7ad71c 946 * @param hdfsdm_filter : DFSDM filter handle.
EricLew 0:d4e5ad7ad71c 947 * @retval None
EricLew 0:d4e5ad7ad71c 948 */
EricLew 0:d4e5ad7ad71c 949 void HAL_DFSDM_FilterMspInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
EricLew 0:d4e5ad7ad71c 950 {
EricLew 0:d4e5ad7ad71c 951 /* Enable DFSDM clock */
EricLew 0:d4e5ad7ad71c 952 AUDIO_DFSDMx_CLK_ENABLE();
EricLew 0:d4e5ad7ad71c 953
EricLew 0:d4e5ad7ad71c 954 /* Enable the DMA clock */
EricLew 0:d4e5ad7ad71c 955 AUDIO_DFSDMx_DMAx_CLK_ENABLE();
EricLew 0:d4e5ad7ad71c 956
EricLew 0:d4e5ad7ad71c 957 /* Configure the hAudioIn.hDmaDfsdmLeft handle parameters */
EricLew 0:d4e5ad7ad71c 958 hAudioIn.hDmaDfsdmLeft.Init.Request = DMA_REQUEST_0;
EricLew 0:d4e5ad7ad71c 959 hAudioIn.hDmaDfsdmLeft.Init.Direction = DMA_PERIPH_TO_MEMORY;
EricLew 0:d4e5ad7ad71c 960 hAudioIn.hDmaDfsdmLeft.Init.PeriphInc = DMA_PINC_DISABLE;
EricLew 0:d4e5ad7ad71c 961 hAudioIn.hDmaDfsdmLeft.Init.MemInc = DMA_MINC_ENABLE;
EricLew 0:d4e5ad7ad71c 962 hAudioIn.hDmaDfsdmLeft.Init.PeriphDataAlignment = AUDIO_DFSDMx_DMAx_PERIPH_DATA_SIZE;
EricLew 0:d4e5ad7ad71c 963 hAudioIn.hDmaDfsdmLeft.Init.MemDataAlignment = AUDIO_DFSDMx_DMAx_MEM_DATA_SIZE;
EricLew 0:d4e5ad7ad71c 964 hAudioIn.hDmaDfsdmLeft.Init.Mode = DMA_CIRCULAR;
EricLew 0:d4e5ad7ad71c 965 hAudioIn.hDmaDfsdmLeft.Init.Priority = DMA_PRIORITY_HIGH;
EricLew 0:d4e5ad7ad71c 966
EricLew 0:d4e5ad7ad71c 967 hAudioIn.hDmaDfsdmLeft.Instance = AUDIO_DFSDMx_DMAx_LEFT_CHANNEL;
EricLew 0:d4e5ad7ad71c 968
EricLew 0:d4e5ad7ad71c 969 /* Associate the DMA handle */
EricLew 0:d4e5ad7ad71c 970 __HAL_LINKDMA(hdfsdm_filter, hdmaReg, hAudioIn.hDmaDfsdmLeft);
EricLew 0:d4e5ad7ad71c 971
EricLew 0:d4e5ad7ad71c 972 /* Reset DMA handle state */
EricLew 0:d4e5ad7ad71c 973 __HAL_DMA_RESET_HANDLE_STATE(&hAudioIn.hDmaDfsdmLeft);
EricLew 0:d4e5ad7ad71c 974
EricLew 0:d4e5ad7ad71c 975 /* Configure the DMA Channel */
EricLew 0:d4e5ad7ad71c 976 HAL_DMA_Init(&hAudioIn.hDmaDfsdmLeft);
EricLew 0:d4e5ad7ad71c 977
EricLew 0:d4e5ad7ad71c 978 /* DMA IRQ Channel configuration */
EricLew 0:d4e5ad7ad71c 979 HAL_NVIC_SetPriority(AUDIO_DFSDMx_DMAx_LEFT_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
EricLew 0:d4e5ad7ad71c 980 HAL_NVIC_EnableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ);
EricLew 0:d4e5ad7ad71c 981 }
EricLew 0:d4e5ad7ad71c 982
EricLew 0:d4e5ad7ad71c 983 /**
EricLew 0:d4e5ad7ad71c 984 * @brief De-initializes the DFSDM filter MSP.
EricLew 0:d4e5ad7ad71c 985 * @param hdfsdm_filter : DFSDM filter handle.
EricLew 0:d4e5ad7ad71c 986 * @retval None
EricLew 0:d4e5ad7ad71c 987 */
EricLew 0:d4e5ad7ad71c 988 void HAL_DFSDM_FilterMspDeInit(DFSDM_Filter_HandleTypeDef *hdfsdm_filter)
EricLew 0:d4e5ad7ad71c 989 {
EricLew 0:d4e5ad7ad71c 990 /* Disable DMA Channel IRQ */
EricLew 0:d4e5ad7ad71c 991 HAL_NVIC_DisableIRQ(AUDIO_DFSDMx_DMAx_LEFT_IRQ);
EricLew 0:d4e5ad7ad71c 992
EricLew 0:d4e5ad7ad71c 993 /* De-initialize the DMA Channel */
EricLew 0:d4e5ad7ad71c 994 HAL_DMA_DeInit(&hAudioIn.hDmaDfsdmLeft);
EricLew 0:d4e5ad7ad71c 995
EricLew 0:d4e5ad7ad71c 996 /* Disable the DMA clock */
EricLew 0:d4e5ad7ad71c 997 AUDIO_DFSDMx_DMAx_CLK_DISABLE();
EricLew 0:d4e5ad7ad71c 998 }
EricLew 0:d4e5ad7ad71c 999
EricLew 0:d4e5ad7ad71c 1000 /**
EricLew 0:d4e5ad7ad71c 1001 * @brief Configures the SAI PLL clock according to the required audio frequency.
EricLew 0:d4e5ad7ad71c 1002 * @param Frequency: Audio frequency.
EricLew 0:d4e5ad7ad71c 1003 * @retval BSP AUDIO status
EricLew 0:d4e5ad7ad71c 1004 * @note The SAI PLL input clock must be configured in the user application.
EricLew 0:d4e5ad7ad71c 1005 * The SAI PLL configuration done within this function assumes that
EricLew 0:d4e5ad7ad71c 1006 * the SAI PLL input clock runs at 8 MHz.
EricLew 0:d4e5ad7ad71c 1007 */
EricLew 0:d4e5ad7ad71c 1008 static uint8_t AUDIO_SAIPLLConfig(uint32_t Frequency)
EricLew 0:d4e5ad7ad71c 1009 {
EricLew 0:d4e5ad7ad71c 1010 RCC_PeriphCLKInitTypeDef RCC_ExCLKInitStruct;
EricLew 0:d4e5ad7ad71c 1011
EricLew 0:d4e5ad7ad71c 1012 /* Retreive actual RCC configuration */
EricLew 0:d4e5ad7ad71c 1013 HAL_RCCEx_GetPeriphCLKConfig(&RCC_ExCLKInitStruct);
EricLew 0:d4e5ad7ad71c 1014
EricLew 0:d4e5ad7ad71c 1015 if ( (Frequency == AUDIO_FREQUENCY_11K)
EricLew 0:d4e5ad7ad71c 1016 || (Frequency == AUDIO_FREQUENCY_22K)
EricLew 0:d4e5ad7ad71c 1017 || (Frequency == AUDIO_FREQUENCY_44K) )
EricLew 0:d4e5ad7ad71c 1018 {
EricLew 0:d4e5ad7ad71c 1019 /* Configure PLLSAI prescalers */
EricLew 0:d4e5ad7ad71c 1020 /* SAI clock config
EricLew 0:d4e5ad7ad71c 1021 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 24 = VCO_192M
EricLew 0:d4e5ad7ad71c 1022 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 192/17 = 11.294 Mhz */
EricLew 0:d4e5ad7ad71c 1023 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
EricLew 0:d4e5ad7ad71c 1024 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 24;
EricLew 0:d4e5ad7ad71c 1025 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 17;
EricLew 0:d4e5ad7ad71c 1026 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
EricLew 0:d4e5ad7ad71c 1027 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
EricLew 0:d4e5ad7ad71c 1028 }
EricLew 0:d4e5ad7ad71c 1029 else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K, AUDIO_FREQUENCY_96K */
EricLew 0:d4e5ad7ad71c 1030 {
EricLew 0:d4e5ad7ad71c 1031 /* SAI clock config
EricLew 0:d4e5ad7ad71c 1032 PLLSAI1_VCO= 8 Mhz * PLLSAI1N = 8 * 43 = VCO_344M
EricLew 0:d4e5ad7ad71c 1033 SAI_CK_x = PLLSAI1_VCO/PLLSAI1P = 344/7 = 49.142 Mhz */
EricLew 0:d4e5ad7ad71c 1034 RCC_ExCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_SAI1;
EricLew 0:d4e5ad7ad71c 1035 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1N = 43;
EricLew 0:d4e5ad7ad71c 1036 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1P = 7;
EricLew 0:d4e5ad7ad71c 1037 RCC_ExCLKInitStruct.PLLSAI1.PLLSAI1ClockOut = RCC_PLLSAI1_SAI1CLK;
EricLew 0:d4e5ad7ad71c 1038 RCC_ExCLKInitStruct.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI1;
EricLew 0:d4e5ad7ad71c 1039 }
EricLew 0:d4e5ad7ad71c 1040
EricLew 0:d4e5ad7ad71c 1041 if (HAL_RCCEx_PeriphCLKConfig(&RCC_ExCLKInitStruct) != HAL_OK)
EricLew 0:d4e5ad7ad71c 1042 {
EricLew 0:d4e5ad7ad71c 1043 return AUDIO_ERROR;
EricLew 0:d4e5ad7ad71c 1044 }
EricLew 0:d4e5ad7ad71c 1045
EricLew 0:d4e5ad7ad71c 1046 return AUDIO_OK;
EricLew 0:d4e5ad7ad71c 1047 }
EricLew 0:d4e5ad7ad71c 1048
EricLew 0:d4e5ad7ad71c 1049 /**
EricLew 0:d4e5ad7ad71c 1050 * @}
EricLew 0:d4e5ad7ad71c 1051 */
EricLew 0:d4e5ad7ad71c 1052
EricLew 0:d4e5ad7ad71c 1053 /**
EricLew 0:d4e5ad7ad71c 1054 * @}
EricLew 0:d4e5ad7ad71c 1055 */
EricLew 0:d4e5ad7ad71c 1056
EricLew 0:d4e5ad7ad71c 1057 /**
EricLew 0:d4e5ad7ad71c 1058 * @}
EricLew 0:d4e5ad7ad71c 1059 */
EricLew 0:d4e5ad7ad71c 1060
EricLew 0:d4e5ad7ad71c 1061 /**
EricLew 0:d4e5ad7ad71c 1062 * @}
EricLew 0:d4e5ad7ad71c 1063 */
EricLew 0:d4e5ad7ad71c 1064
EricLew 0:d4e5ad7ad71c 1065 /**
EricLew 0:d4e5ad7ad71c 1066 * @}
EricLew 0:d4e5ad7ad71c 1067 */
EricLew 0:d4e5ad7ad71c 1068
EricLew 0:d4e5ad7ad71c 1069 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
EricLew 0:d4e5ad7ad71c 1070