xref: /btstack/port/stm32-f4discovery-usb/bsp/stm32f4_discovery_audio.c (revision e0a94143c1f0305eb5125b599df7b54ca2d10b42)
1f763b8ceSMatthias Ringwald /**
2f763b8ceSMatthias Ringwald   ******************************************************************************
3f763b8ceSMatthias Ringwald   * @file    stm32f4_discovery_audio.c
4f763b8ceSMatthias Ringwald   * @author  MCD Application Team
5f763b8ceSMatthias Ringwald   * @version V2.1.2
6f763b8ceSMatthias Ringwald   * @date    27-January-2017
7f763b8ceSMatthias Ringwald   * @brief   This file provides the Audio driver for the STM32F4-Discovery
8f763b8ceSMatthias Ringwald   *          board.
9f763b8ceSMatthias Ringwald   ******************************************************************************
10f763b8ceSMatthias Ringwald   * @attention
11f763b8ceSMatthias Ringwald   *
12f763b8ceSMatthias Ringwald   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
13f763b8ceSMatthias Ringwald   *
14f763b8ceSMatthias Ringwald   * Redistribution and use in source and binary forms, with or without modification,
15f763b8ceSMatthias Ringwald   * are permitted provided that the following conditions are met:
16f763b8ceSMatthias Ringwald   *   1. Redistributions of source code must retain the above copyright notice,
17f763b8ceSMatthias Ringwald   *      this list of conditions and the following disclaimer.
18f763b8ceSMatthias Ringwald   *   2. Redistributions in binary form must reproduce the above copyright notice,
19f763b8ceSMatthias Ringwald   *      this list of conditions and the following disclaimer in the documentation
20f763b8ceSMatthias Ringwald   *      and/or other materials provided with the distribution.
21f763b8ceSMatthias Ringwald   *   3. Neither the name of STMicroelectronics nor the names of its contributors
22f763b8ceSMatthias Ringwald   *      may be used to endorse or promote products derived from this software
23f763b8ceSMatthias Ringwald   *      without specific prior written permission.
24f763b8ceSMatthias Ringwald   *
25f763b8ceSMatthias Ringwald   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26f763b8ceSMatthias Ringwald   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27f763b8ceSMatthias Ringwald   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28f763b8ceSMatthias Ringwald   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29f763b8ceSMatthias Ringwald   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30f763b8ceSMatthias Ringwald   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31f763b8ceSMatthias Ringwald   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32f763b8ceSMatthias Ringwald   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33f763b8ceSMatthias Ringwald   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34f763b8ceSMatthias Ringwald   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35f763b8ceSMatthias Ringwald   *
36f763b8ceSMatthias Ringwald   ******************************************************************************
37f763b8ceSMatthias Ringwald   */
38f763b8ceSMatthias Ringwald 
39f763b8ceSMatthias Ringwald /*==============================================================================
40f763b8ceSMatthias Ringwald                                              User NOTES
41f763b8ceSMatthias Ringwald 1. How To use this driver:
42f763b8ceSMatthias Ringwald --------------------------
43f763b8ceSMatthias Ringwald    - This driver supports STM32F4xx devices on STM32F4-Discovery Kit:
44f763b8ceSMatthias Ringwald         a) to play an audio file (all functions names start by BSP_AUDIO_OUT_xxx)
45f763b8ceSMatthias Ringwald         b) to record an audio file through MP45DT02, ST MEMS (all functions names start by AUDIO_IN_xxx)
46f763b8ceSMatthias Ringwald 
47f763b8ceSMatthias Ringwald a) PLAY A FILE:
48f763b8ceSMatthias Ringwald ==============
49f763b8ceSMatthias Ringwald    + Call the function BSP_AUDIO_OUT_Init(
50f763b8ceSMatthias Ringwald                                     OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER,
51f763b8ceSMatthias Ringwald                                                  OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_AUTO or
52f763b8ceSMatthias Ringwald                                                  OUTPUT_DEVICE_BOTH)
53f763b8ceSMatthias Ringwald                                     Volume: initial volume to be set (0 is min (mute), 100 is max (100%)
54f763b8ceSMatthias Ringwald                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
55f763b8ceSMatthias Ringwald                                     this parameter is relative to the audio file/stream type.
56f763b8ceSMatthias Ringwald                                    )
57f763b8ceSMatthias Ringwald       This function configures all the hardware required for the audio application (codec, I2C, I2S,
58f763b8ceSMatthias Ringwald       GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK.
59f763b8ceSMatthias Ringwald       If the returned value is different from 0 or the function is stuck then the communication with
60f763b8ceSMatthias Ringwald       the codec (try to un-plug the power or reset device in this case).
61f763b8ceSMatthias Ringwald       - OUTPUT_DEVICE_SPEAKER: only speaker will be set as output for the audio stream.
62f763b8ceSMatthias Ringwald       - OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
63f763b8ceSMatthias Ringwald       - OUTPUT_DEVICE_AUTO: Selection of output device is made through external switch (implemented
64f763b8ceSMatthias Ringwald          into the audio jack on the discovery board). When the Headphone is connected it is used
65f763b8ceSMatthias Ringwald          as output. When the headphone is disconnected from the audio jack, the output is
66f763b8ceSMatthias Ringwald          automatically switched to Speaker.
67f763b8ceSMatthias Ringwald       - OUTPUT_DEVICE_BOTH: both Speaker and Headphone are used as outputs for the audio stream
68f763b8ceSMatthias Ringwald          at the same time.
69f763b8ceSMatthias Ringwald    + Call the function BSP_AUDIO_OUT_Play(
70f763b8ceSMatthias Ringwald                                   pBuffer: pointer to the audio data file address
71f763b8ceSMatthias Ringwald                                   Size: size of the buffer to be sent in Bytes
72f763b8ceSMatthias Ringwald                                  )
73f763b8ceSMatthias Ringwald       to start playing (for the first time) from the audio file/stream.
74f763b8ceSMatthias Ringwald    + Call the function BSP_AUDIO_OUT_Pause() to pause playing
75f763b8ceSMatthias Ringwald    + Call the function BSP_AUDIO_OUT_Resume() to resume playing.
76f763b8ceSMatthias Ringwald        Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
77f763b8ceSMatthias Ringwald           for resume (it is not allowed to call BSP_AUDIO_OUT_Play() in this case).
78f763b8ceSMatthias Ringwald        Note. This function should be called only when the audio file is played or paused (not stopped).
79f763b8ceSMatthias Ringwald    + For each mode, you may need to implement the relative callback functions into your code.
80f763b8ceSMatthias Ringwald       The Callback functions are named BSP_AUDIO_OUT_XXXCallBack() and only their prototypes are declared in
81f763b8ceSMatthias Ringwald       the stm32f4_discovery_audio.h file. (refer to the example for more details on the callbacks implementations)
82f763b8ceSMatthias Ringwald    + To Stop playing, to modify the volume level, the frequency or to mute, use the functions
83f763b8ceSMatthias Ringwald        BSP_AUDIO_OUT_Stop(), BSP_AUDIO_OUT_SetVolume(), AUDIO_OUT_SetFrequency() BSP_AUDIO_OUT_SetOutputMode and BSP_AUDIO_OUT_SetMute().
84f763b8ceSMatthias Ringwald    + The driver API and the callback functions are at the end of the stm32f4_discovery_audio.h file.
85f763b8ceSMatthias Ringwald 
86f763b8ceSMatthias Ringwald Driver architecture:
87f763b8ceSMatthias Ringwald --------------------
88f763b8ceSMatthias Ringwald    + This driver provide the High Audio Layer: consists of the function API exported in the stm32f4_discovery_audio.h file
89f763b8ceSMatthias Ringwald        (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...)
90f763b8ceSMatthias Ringwald    + This driver provide also the Media Access Layer (MAL): which consists of functions allowing to access the media containing/
91f763b8ceSMatthias Ringwald        providing the audio file/stream. These functions are also included as local functions into
92f763b8ceSMatthias Ringwald        the stm32f4_discovery_audio.c file (I2S3_Init()...)
93f763b8ceSMatthias Ringwald 
94f763b8ceSMatthias Ringwald Known Limitations:
95f763b8ceSMatthias Ringwald -------------------
96f763b8ceSMatthias Ringwald    1- When using the Speaker, if the audio file quality is not high enough, the speaker output
97f763b8ceSMatthias Ringwald       may produce high and uncomfortable noise level. To avoid this issue, to use speaker
98f763b8ceSMatthias Ringwald       output properly, try to increase audio file sampling rate (typically higher than 48KHz).
99f763b8ceSMatthias Ringwald       This operation will lead to larger file size.
100f763b8ceSMatthias Ringwald    2- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some
101f763b8ceSMatthias Ringwald       user interrupt routines (in this case, interrupts could be disabled just before the start of
102f763b8ceSMatthias Ringwald       communication then re-enabled when it is over). Note that this communication is only done at
103f763b8ceSMatthias Ringwald       the configuration phase (BSP_AUDIO_OUT_Init() or BSP_AUDIO_OUT_Stop()) and when Volume control modification is
104f763b8ceSMatthias Ringwald       performed (BSP_AUDIO_OUT_SetVolume() or BSP_AUDIO_OUT_SetMute()or BSP_AUDIO_OUT_SetOutputMode()).
105f763b8ceSMatthias Ringwald       When the audio data is played, no communication is required with the audio codec.
106f763b8ceSMatthias Ringwald    3- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size,
107f763b8ceSMatthias Ringwald       File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
108f763b8ceSMatthias Ringwald    4- Supports only Stereo audio streaming. To play mono audio streams, each data should be sent twice
109f763b8ceSMatthias Ringwald       on the I2S or should be duplicated on the source buffer. Or convert the stream in stereo before playing.
110f763b8ceSMatthias Ringwald    5- Supports only 16-bits audio data size.
111f763b8ceSMatthias Ringwald 
112f763b8ceSMatthias Ringwald b) RECORD A FILE:
113f763b8ceSMatthias Ringwald ================
114f763b8ceSMatthias Ringwald    + Call the function BSP_AUDIO_IN_Init(
115f763b8ceSMatthias Ringwald                                     AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
116f763b8ceSMatthias Ringwald                                     )
117f763b8ceSMatthias Ringwald       This function configures all the hardware required for the audio application (I2S,
118f763b8ceSMatthias Ringwald       GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK.
119f763b8ceSMatthias Ringwald 
120f763b8ceSMatthias Ringwald    + Call the function BSP_AUDIO_IN_Record(
121f763b8ceSMatthias Ringwald                             pbuf Main buffer pointer for the recorded data storing
122f763b8ceSMatthias Ringwald                             size Current size of the recorded buffer
123f763b8ceSMatthias Ringwald                             )
124f763b8ceSMatthias Ringwald       to start recording from the microphone.
125f763b8ceSMatthias Ringwald 
126f763b8ceSMatthias Ringwald    + User needs to implement user callbacks to retrieve data saved in the record buffer
127f763b8ceSMatthias Ringwald       (AUDIO_IN_RxHalfCpltCallback/BSP_AUDIO_IN_ReceiveComplete_CallBack)
128f763b8ceSMatthias Ringwald 
129f763b8ceSMatthias Ringwald    + Call the function AUDIO_IN_STOP() to stop recording
130f763b8ceSMatthias Ringwald 
131f763b8ceSMatthias Ringwald ==============================================================================*/
132f763b8ceSMatthias Ringwald 
133f763b8ceSMatthias Ringwald /* Includes ------------------------------------------------------------------*/
134f763b8ceSMatthias Ringwald #include "stm32f4_discovery_audio.h"
135f763b8ceSMatthias Ringwald #include "pdm_filter.h"
136f763b8ceSMatthias Ringwald #include "btstack_config.h"
137f763b8ceSMatthias Ringwald 
138f763b8ceSMatthias Ringwald /** @addtogroup BSP
139f763b8ceSMatthias Ringwald   * @{
140f763b8ceSMatthias Ringwald   */
141f763b8ceSMatthias Ringwald 
142f763b8ceSMatthias Ringwald /** @addtogroup STM32F4_DISCOVERY
143f763b8ceSMatthias Ringwald   * @{
144f763b8ceSMatthias Ringwald   */
145f763b8ceSMatthias Ringwald 
146f763b8ceSMatthias Ringwald /** @defgroup STM32F4_DISCOVERY_AUDIO STM32F4 DISCOVERY AUDIO
147f763b8ceSMatthias Ringwald   * @brief This file includes the low layer audio driver available on STM32F4-Discovery
148f763b8ceSMatthias Ringwald   *        discovery board.
149f763b8ceSMatthias Ringwald   * @{
150f763b8ceSMatthias Ringwald   */
151f763b8ceSMatthias Ringwald 
152f763b8ceSMatthias Ringwald /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Types STM32F4 DISCOVERY AUDIO Private Types
153f763b8ceSMatthias Ringwald   * @{
154f763b8ceSMatthias Ringwald   */
155f763b8ceSMatthias Ringwald /**
156f763b8ceSMatthias Ringwald   * @}
157f763b8ceSMatthias Ringwald   */
158f763b8ceSMatthias Ringwald 
159f763b8ceSMatthias Ringwald /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Defines STM32F4 DISCOVERY AUDIO Private Defines
160f763b8ceSMatthias Ringwald   * @{
161f763b8ceSMatthias Ringwald   */
162*e0a94143SDirk Helbig static uint32_t bsp_audio_out_actual_frequency = 0;
163*e0a94143SDirk Helbig static uint32_t bsp_audio_out_frequency = 0;
164*e0a94143SDirk Helbig 
165*e0a94143SDirk Helbig typedef struct {
166*e0a94143SDirk Helbig     uint32_t freq;
167*e0a94143SDirk Helbig     uint32_t actual;
168*e0a94143SDirk Helbig     uint16_t r;
169*e0a94143SDirk Helbig     uint16_t n;
170*e0a94143SDirk Helbig } i2s_pll_entry_t;
171*e0a94143SDirk Helbig 
172*e0a94143SDirk Helbig // HSE_VALUE = 8000000
173*e0a94143SDirk Helbig // PLLM = 4
174*e0a94143SDirk Helbig // MCK on
175*e0a94143SDirk Helbig static const i2s_pll_entry_t i2s_pll_table[] = {
176*e0a94143SDirk Helbig     {  8000,  8000, 5, 128 }, /* i2sdiv:  12, odd: 1, rate error % (desired vs actual)%: 0.0000 */
177*e0a94143SDirk Helbig     { 11025, 11024, 2, 127 }, /* i2sdiv:  22, odd: 1, rate error % (desired vs actual)%: 0.0063 */
178*e0a94143SDirk Helbig     { 12000, 12000, 5, 192 }, /* i2sdiv:  12, odd: 1, rate error % (desired vs actual)%: 0.0000 */
179*e0a94143SDirk Helbig     { 16000, 16000, 4, 213 }, /* i2sdiv:  13, odd: 0, rate error % (desired vs actual)%: 0.0038 */
180*e0a94143SDirk Helbig     { 22050, 22048, 5, 127 }, /* i2sdiv:   4, odd: 1, rate error % (desired vs actual)%: 0.0063 */
181*e0a94143SDirk Helbig     { 24000, 24003, 3, 212 }, /* i2sdiv:  11, odd: 1, rate error % (desired vs actual)%: 0.0151 */
182*e0a94143SDirk Helbig     { 32000, 32001, 4, 213 }, /* i2sdiv:   6, odd: 1, rate error % (desired vs actual)%: 0.0038 */
183*e0a94143SDirk Helbig     { 44100, 44084, 2,  79 }, /* i2sdiv:   3, odd: 1, rate error % (desired vs actual)%: 0.0344 */
184*e0a94143SDirk Helbig     { 48000, 47991, 2,  86 }, /* i2sdiv:   3, odd: 1, rate error % (desired vs actual)%: 0.0186 */
185*e0a94143SDirk Helbig     { 96000, 95982, 2, 172 }, /* i2sdiv:   3, odd: 1, rate error % (desired vs actual)%: 0.0186 */
186*e0a94143SDirk Helbig };
187*e0a94143SDirk Helbig 
188*e0a94143SDirk Helbig #define BARRIER do { __asm__ volatile("" ::: "memory"); } while (0)
189*e0a94143SDirk Helbig #define BINARY(I) do {                                            \
190*e0a94143SDirk Helbig                 base = ((base)[I].freq <= frequency)?base+I:base; \
191*e0a94143SDirk Helbig                 BARRIER;                                          \
192*e0a94143SDirk Helbig         } while (0)
193*e0a94143SDirk Helbig 
194*e0a94143SDirk Helbig /** @brief  Searches I2S PLL parameter giving highest frequency accuracy possible
195*e0a94143SDirk Helbig   * @param  frequency: the frequency to seach PLL parameter for
196*e0a94143SDirk Helbig   * @retval The PLL config with helps setting specified frequency
197*e0a94143SDirk Helbig   * @note   This assembles a unrolled binary search for a fixed table size,
198*e0a94143SDirk Helbig   *         so changes to the table size need to be reflected here. Or should
199*e0a94143SDirk Helbig   *         be auto-generated
200*e0a94143SDirk Helbig   */
i2s_find_pll_params(uint32_t frequency)201*e0a94143SDirk Helbig static i2s_pll_entry_t const *i2s_find_pll_params( uint32_t frequency ) {
202*e0a94143SDirk Helbig     i2s_pll_entry_t const* base = i2s_pll_table;
203*e0a94143SDirk Helbig     BINARY(5);
204*e0a94143SDirk Helbig     BINARY(2);
205*e0a94143SDirk Helbig     BINARY(1);
206*e0a94143SDirk Helbig     BINARY(1);
207*e0a94143SDirk Helbig     return base;
208*e0a94143SDirk Helbig }
209f763b8ceSMatthias Ringwald /**
210f763b8ceSMatthias Ringwald   * @}
211f763b8ceSMatthias Ringwald   */
212f763b8ceSMatthias Ringwald 
213f763b8ceSMatthias Ringwald /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Macros STM32F4 DISCOVERY AUDIO Private Macros
214f763b8ceSMatthias Ringwald   * @{
215f763b8ceSMatthias Ringwald   */
216f763b8ceSMatthias Ringwald /**
217f763b8ceSMatthias Ringwald   * @}
218f763b8ceSMatthias Ringwald   */
219f763b8ceSMatthias Ringwald 
220f763b8ceSMatthias Ringwald /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Variables STM32F4 DISCOVERY AUDIO Private Variables
221f763b8ceSMatthias Ringwald   * @{
222f763b8ceSMatthias Ringwald   */
223f763b8ceSMatthias Ringwald /*##### PLAY #####*/
224f763b8ceSMatthias Ringwald static AUDIO_DrvTypeDef           *pAudioDrv;
225f763b8ceSMatthias Ringwald I2S_HandleTypeDef                 hAudioOutI2s;
226f763b8ceSMatthias Ringwald 
227f763b8ceSMatthias Ringwald /*### RECORDER ###*/
228f763b8ceSMatthias Ringwald I2S_HandleTypeDef                 hAudioInI2s;
229f763b8ceSMatthias Ringwald 
230f763b8ceSMatthias Ringwald static PDMFilter_InitStruct Filter[DEFAULT_AUDIO_IN_CHANNEL_NBR];
231f763b8ceSMatthias Ringwald __IO uint16_t AudioInVolume = DEFAULT_AUDIO_IN_VOLUME;
232f763b8ceSMatthias Ringwald /**
233f763b8ceSMatthias Ringwald   * @}
234f763b8ceSMatthias Ringwald   */
235f763b8ceSMatthias Ringwald 
236f763b8ceSMatthias Ringwald /** @defgroup STM32F4_DISCOVERY_AUDIO_Private_Function_Prototypes STM32F4 DISCOVERY AUDIO Private Function Prototypes
237f763b8ceSMatthias Ringwald   * @{
238f763b8ceSMatthias Ringwald   */
239f763b8ceSMatthias Ringwald static uint8_t I2S2_Init(uint32_t AudioFreq);
240f763b8ceSMatthias Ringwald static uint8_t I2S3_Init(uint32_t AudioFreq);
241f763b8ceSMatthias Ringwald static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr);
242f763b8ceSMatthias Ringwald 
243f763b8ceSMatthias Ringwald /**
244f763b8ceSMatthias Ringwald   * @}
245f763b8ceSMatthias Ringwald   */
246f763b8ceSMatthias Ringwald 
247f763b8ceSMatthias Ringwald /** @defgroup STM32F4_DISCOVERY_AUDIO_OUT_Private_Functions STM32F4 DISCOVERY AUDIO OUT Private Functions
248f763b8ceSMatthias Ringwald   * @{
249f763b8ceSMatthias Ringwald   */
250f763b8ceSMatthias Ringwald 
251f763b8ceSMatthias Ringwald /**
252f763b8ceSMatthias Ringwald   * @brief  Configures the audio peripherals.
253f763b8ceSMatthias Ringwald   * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
254f763b8ceSMatthias Ringwald   *                       OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO .
255f763b8ceSMatthias Ringwald   * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
256f763b8ceSMatthias Ringwald   * @param  AudioFreq: Audio frequency used to play the audio stream.
257f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
258f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_Init(uint16_t OutputDevice,uint8_t Volume,uint32_t AudioFreq)259f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
260f763b8ceSMatthias Ringwald {
261f763b8ceSMatthias Ringwald   uint8_t ret = AUDIO_OK;
262f763b8ceSMatthias Ringwald 
263f763b8ceSMatthias Ringwald   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
264f763b8ceSMatthias Ringwald   BSP_AUDIO_OUT_ClockConfig(&hAudioOutI2s, AudioFreq, NULL);
265f763b8ceSMatthias Ringwald 
266f763b8ceSMatthias Ringwald   /* I2S data transfer preparation:
267f763b8ceSMatthias Ringwald   Prepare the Media to be used for the audio transfer from memory to I2S peripheral */
268f763b8ceSMatthias Ringwald   hAudioOutI2s.Instance = I2S3;
269f763b8ceSMatthias Ringwald   if(HAL_I2S_GetState(&hAudioOutI2s) == HAL_I2S_STATE_RESET)
270f763b8ceSMatthias Ringwald   {
271f763b8ceSMatthias Ringwald     /* Init the I2S MSP: this __weak function can be redefined by the application*/
272f763b8ceSMatthias Ringwald     BSP_AUDIO_OUT_MspInit(&hAudioOutI2s, NULL);
273f763b8ceSMatthias Ringwald   }
274f763b8ceSMatthias Ringwald 
275f763b8ceSMatthias Ringwald   /* I2S data transfer preparation:
276f763b8ceSMatthias Ringwald   Prepare the Media to be used for the audio transfer from memory to I2S peripheral */
277f763b8ceSMatthias Ringwald   /* Configure the I2S peripheral */
278f763b8ceSMatthias Ringwald   if(I2S3_Init(AudioFreq) != AUDIO_OK)
279f763b8ceSMatthias Ringwald   {
280f763b8ceSMatthias Ringwald     ret = AUDIO_ERROR;
281f763b8ceSMatthias Ringwald   }
282f763b8ceSMatthias Ringwald 
283f763b8ceSMatthias Ringwald   if(ret == AUDIO_OK)
284f763b8ceSMatthias Ringwald   {
285f763b8ceSMatthias Ringwald     /* Retieve audio codec identifier */
286f763b8ceSMatthias Ringwald     if(((cs43l22_drv.ReadID(AUDIO_I2C_ADDRESS)) & CS43L22_ID_MASK) == CS43L22_ID)
287f763b8ceSMatthias Ringwald     {
288f763b8ceSMatthias Ringwald       /* Initialize the audio driver structure */
289f763b8ceSMatthias Ringwald       pAudioDrv = &cs43l22_drv;
290f763b8ceSMatthias Ringwald     }
291f763b8ceSMatthias Ringwald     else
292f763b8ceSMatthias Ringwald     {
293f763b8ceSMatthias Ringwald       ret = AUDIO_ERROR;
294f763b8ceSMatthias Ringwald     }
295f763b8ceSMatthias Ringwald   }
296f763b8ceSMatthias Ringwald 
297f763b8ceSMatthias Ringwald   if(ret == AUDIO_OK)
298f763b8ceSMatthias Ringwald   {
299f763b8ceSMatthias Ringwald     pAudioDrv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
300f763b8ceSMatthias Ringwald   }
301f763b8ceSMatthias Ringwald 
302f763b8ceSMatthias Ringwald   return ret;
303f763b8ceSMatthias Ringwald }
304f763b8ceSMatthias Ringwald 
305f763b8ceSMatthias Ringwald /**
306f763b8ceSMatthias Ringwald   * @brief  Starts playing audio stream from a data buffer for a determined size.
307f763b8ceSMatthias Ringwald   * @param  pBuffer: Pointer to the buffer
308f763b8ceSMatthias Ringwald   * @param  Size: Number of audio data BYTES.
309f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
310f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_Play(uint16_t * pBuffer,uint32_t Size)311f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
312f763b8ceSMatthias Ringwald {
313f763b8ceSMatthias Ringwald   /* Call the audio Codec Play function */
314f763b8ceSMatthias Ringwald   if(pAudioDrv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
315f763b8ceSMatthias Ringwald   {
316f763b8ceSMatthias Ringwald     return AUDIO_ERROR;
317f763b8ceSMatthias Ringwald   }
318f763b8ceSMatthias Ringwald   else
319f763b8ceSMatthias Ringwald   {
320*e0a94143SDirk Helbig     bsp_audio_out_frequency = bsp_audio_out_actual_frequency;
321f763b8ceSMatthias Ringwald     /* Update the Media layer and enable it for play */
322f763b8ceSMatthias Ringwald     HAL_I2S_Transmit_DMA(&hAudioOutI2s, pBuffer, DMA_MAX(Size/AUDIODATA_SIZE));
323f763b8ceSMatthias Ringwald 
324f763b8ceSMatthias Ringwald     /* Return AUDIO_OK when all operations are correctly done */
325f763b8ceSMatthias Ringwald     return AUDIO_OK;
326f763b8ceSMatthias Ringwald   }
327f763b8ceSMatthias Ringwald }
328f763b8ceSMatthias Ringwald 
329f763b8ceSMatthias Ringwald /**
330f763b8ceSMatthias Ringwald   * @brief  Sends n-Bytes on the I2S interface.
331f763b8ceSMatthias Ringwald   * @param  pData: Pointer to data address
332f763b8ceSMatthias Ringwald   * @param  Size: Number of data to be written
333f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_ChangeBuffer(uint16_t * pData,uint16_t Size)334f763b8ceSMatthias Ringwald void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
335f763b8ceSMatthias Ringwald {
336f763b8ceSMatthias Ringwald   HAL_I2S_Transmit_DMA(&hAudioOutI2s, pData, Size);
337f763b8ceSMatthias Ringwald }
338f763b8ceSMatthias Ringwald 
339f763b8ceSMatthias Ringwald /**
340f763b8ceSMatthias Ringwald   * @brief   Pauses the audio file stream. In case of using DMA, the DMA Pause
341f763b8ceSMatthias Ringwald   *          feature is used.
342f763b8ceSMatthias Ringwald   * WARNING: When calling BSP_AUDIO_OUT_Pause() function for pause, only the
343f763b8ceSMatthias Ringwald   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play()
344f763b8ceSMatthias Ringwald   *          function for resume could lead to unexpected behavior).
345f763b8ceSMatthias Ringwald   * @retval  AUDIO_OK if correct communication, else wrong communication
346f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_Pause(void)347f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_OUT_Pause(void)
348f763b8ceSMatthias Ringwald {
349f763b8ceSMatthias Ringwald   /* Call the Audio Codec Pause/Resume function */
350f763b8ceSMatthias Ringwald   if(pAudioDrv->Pause(AUDIO_I2C_ADDRESS) != 0)
351f763b8ceSMatthias Ringwald   {
352f763b8ceSMatthias Ringwald     return AUDIO_ERROR;
353f763b8ceSMatthias Ringwald   }
354f763b8ceSMatthias Ringwald   else
355f763b8ceSMatthias Ringwald   {
356f763b8ceSMatthias Ringwald     /* Call the Media layer pause function */
357f763b8ceSMatthias Ringwald     HAL_I2S_DMAPause(&hAudioOutI2s);
358f763b8ceSMatthias Ringwald 
359f763b8ceSMatthias Ringwald     /* Return AUDIO_OK when all operations are correctly done */
360f763b8ceSMatthias Ringwald     return AUDIO_OK;
361f763b8ceSMatthias Ringwald   }
362f763b8ceSMatthias Ringwald }
363f763b8ceSMatthias Ringwald 
364f763b8ceSMatthias Ringwald /**
365f763b8ceSMatthias Ringwald   * @brief   Resumes the audio file streaming.
366f763b8ceSMatthias Ringwald   * WARNING: When calling BSP_AUDIO_OUT_Pause() function for pause, only
367f763b8ceSMatthias Ringwald   *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play()
368f763b8ceSMatthias Ringwald   *          function for resume could lead to unexpected behavior).
369f763b8ceSMatthias Ringwald   * @retval  AUDIO_OK if correct communication, else wrong communication
370f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_Resume(void)371f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_OUT_Resume(void)
372f763b8ceSMatthias Ringwald {
373f763b8ceSMatthias Ringwald   /* Call the Audio Codec Pause/Resume function */
374f763b8ceSMatthias Ringwald   if(pAudioDrv->Resume(AUDIO_I2C_ADDRESS) != 0)
375f763b8ceSMatthias Ringwald   {
376f763b8ceSMatthias Ringwald     return AUDIO_ERROR;
377f763b8ceSMatthias Ringwald   }
378f763b8ceSMatthias Ringwald   else
379f763b8ceSMatthias Ringwald   {
380f763b8ceSMatthias Ringwald     /* Call the Media layer resume function */
381f763b8ceSMatthias Ringwald     HAL_I2S_DMAResume(&hAudioOutI2s);
382f763b8ceSMatthias Ringwald 
383f763b8ceSMatthias Ringwald     /* Return AUDIO_OK when all operations are correctly done */
384f763b8ceSMatthias Ringwald     return AUDIO_OK;
385f763b8ceSMatthias Ringwald   }
386f763b8ceSMatthias Ringwald }
387f763b8ceSMatthias Ringwald 
388f763b8ceSMatthias Ringwald /**
389f763b8ceSMatthias Ringwald   * @brief  Stops audio playing and Power down the Audio Codec.
390f763b8ceSMatthias Ringwald   * @param  Option: could be one of the following parameters
391f763b8ceSMatthias Ringwald   *           - CODEC_PDWN_HW: completely shut down the codec (physically).
392f763b8ceSMatthias Ringwald   *                            Then need to reconfigure the Codec after power on.
393f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
394f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_Stop(uint32_t Option)395f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
396f763b8ceSMatthias Ringwald {
397f763b8ceSMatthias Ringwald   /* Call DMA Stop to disable DMA stream before stopping codec */
398f763b8ceSMatthias Ringwald   HAL_I2S_DMAStop(&hAudioOutI2s);
399f763b8ceSMatthias Ringwald 
400*e0a94143SDirk Helbig   bsp_audio_out_frequency = 0;
401f763b8ceSMatthias Ringwald   /* Call Audio Codec Stop function */
402f763b8ceSMatthias Ringwald   if(pAudioDrv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
403f763b8ceSMatthias Ringwald   {
404f763b8ceSMatthias Ringwald     return AUDIO_ERROR;
405f763b8ceSMatthias Ringwald   }
406f763b8ceSMatthias Ringwald   else
407f763b8ceSMatthias Ringwald   {
408f763b8ceSMatthias Ringwald     if(Option == CODEC_PDWN_HW)
409f763b8ceSMatthias Ringwald     {
410f763b8ceSMatthias Ringwald       /* Wait at least 1ms */
411f763b8ceSMatthias Ringwald       HAL_Delay(1);
412f763b8ceSMatthias Ringwald 
413f763b8ceSMatthias Ringwald       /* Reset the pin */
414f763b8ceSMatthias Ringwald       HAL_GPIO_WritePin(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, GPIO_PIN_RESET);
415f763b8ceSMatthias Ringwald     }
416f763b8ceSMatthias Ringwald 
417f763b8ceSMatthias Ringwald     /* Return AUDIO_OK when all operations are correctly done */
418f763b8ceSMatthias Ringwald     return AUDIO_OK;
419f763b8ceSMatthias Ringwald   }
420f763b8ceSMatthias Ringwald }
421f763b8ceSMatthias Ringwald 
422f763b8ceSMatthias Ringwald /**
423f763b8ceSMatthias Ringwald   * @brief  Controls the current audio volume level.
424f763b8ceSMatthias Ringwald   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for
425f763b8ceSMatthias Ringwald   *         Mute and 100 for Max volume level).
426f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
427f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_SetVolume(uint8_t Volume)428f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
429f763b8ceSMatthias Ringwald {
430f763b8ceSMatthias Ringwald   /* Call the codec volume control function with converted volume value */
431f763b8ceSMatthias Ringwald   if(pAudioDrv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
432f763b8ceSMatthias Ringwald   {
433f763b8ceSMatthias Ringwald     return AUDIO_ERROR;
434f763b8ceSMatthias Ringwald   }
435f763b8ceSMatthias Ringwald   else
436f763b8ceSMatthias Ringwald   {
437f763b8ceSMatthias Ringwald     /* Return AUDIO_OK when all operations are correctly done */
438f763b8ceSMatthias Ringwald     return AUDIO_OK;
439f763b8ceSMatthias Ringwald   }
440f763b8ceSMatthias Ringwald }
441f763b8ceSMatthias Ringwald 
442f763b8ceSMatthias Ringwald /**
443f763b8ceSMatthias Ringwald   * @brief  Enables or disables the MUTE mode by software
444f763b8ceSMatthias Ringwald   * @param  Cmd: could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to
445f763b8ceSMatthias Ringwald   *         unmute the codec and restore previous volume level.
446f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
447f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_SetMute(uint32_t Cmd)448f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
449f763b8ceSMatthias Ringwald {
450f763b8ceSMatthias Ringwald   /* Call the Codec Mute function */
451f763b8ceSMatthias Ringwald   if(pAudioDrv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
452f763b8ceSMatthias Ringwald   {
453f763b8ceSMatthias Ringwald     return AUDIO_ERROR;
454f763b8ceSMatthias Ringwald   }
455f763b8ceSMatthias Ringwald   else
456f763b8ceSMatthias Ringwald   {
457f763b8ceSMatthias Ringwald     /* Return AUDIO_OK when all operations are correctly done */
458f763b8ceSMatthias Ringwald     return AUDIO_OK;
459f763b8ceSMatthias Ringwald   }
460f763b8ceSMatthias Ringwald }
461f763b8ceSMatthias Ringwald 
462f763b8ceSMatthias Ringwald /**
463f763b8ceSMatthias Ringwald   * @brief  Switch dynamically (while audio file is played) the output target
464f763b8ceSMatthias Ringwald   *         (speaker or headphone).
465f763b8ceSMatthias Ringwald   * @note   This function modifies a global variable of the audio codec driver: OutputDev.
466f763b8ceSMatthias Ringwald   * @param  Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER,
467f763b8ceSMatthias Ringwald   *         OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO
468f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
469f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)470f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
471f763b8ceSMatthias Ringwald {
472f763b8ceSMatthias Ringwald   /* Call the Codec output Device function */
473f763b8ceSMatthias Ringwald   if(pAudioDrv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
474f763b8ceSMatthias Ringwald   {
475f763b8ceSMatthias Ringwald     return AUDIO_ERROR;
476f763b8ceSMatthias Ringwald   }
477f763b8ceSMatthias Ringwald   else
478f763b8ceSMatthias Ringwald   {
479f763b8ceSMatthias Ringwald     /* Return AUDIO_OK when all operations are correctly done */
480f763b8ceSMatthias Ringwald     return AUDIO_OK;
481f763b8ceSMatthias Ringwald   }
482f763b8ceSMatthias Ringwald }
483f763b8ceSMatthias Ringwald 
484f763b8ceSMatthias Ringwald /**
485f763b8ceSMatthias Ringwald   * @brief  Update the audio frequency.
486f763b8ceSMatthias Ringwald   * @param  AudioFreq: Audio frequency used to play the audio stream.
487f763b8ceSMatthias Ringwald   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
488f763b8ceSMatthias Ringwald   *         audio frequency.
489f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)490f763b8ceSMatthias Ringwald void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
491f763b8ceSMatthias Ringwald {
492f763b8ceSMatthias Ringwald   /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */
493f763b8ceSMatthias Ringwald   BSP_AUDIO_OUT_ClockConfig(&hAudioOutI2s, AudioFreq, NULL);
494f763b8ceSMatthias Ringwald 
495f763b8ceSMatthias Ringwald   /* Update the I2S audio frequency configuration */
496f763b8ceSMatthias Ringwald   I2S3_Init(AudioFreq);
497f763b8ceSMatthias Ringwald }
498f763b8ceSMatthias Ringwald 
499f763b8ceSMatthias Ringwald /**
500f763b8ceSMatthias Ringwald   * @brief  Tx Transfer completed callbacks.
501f763b8ceSMatthias Ringwald   * @param  hi2s: I2S handle
502f763b8ceSMatthias Ringwald   */
HAL_I2S_TxCpltCallback(I2S_HandleTypeDef * hi2s)503f763b8ceSMatthias Ringwald void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
504f763b8ceSMatthias Ringwald {
505f763b8ceSMatthias Ringwald   if(hi2s->Instance == I2S3)
506f763b8ceSMatthias Ringwald   {
507f763b8ceSMatthias Ringwald     /* Call the user function which will manage directly transfer complete */
508f763b8ceSMatthias Ringwald     BSP_AUDIO_OUT_TransferComplete_CallBack();
509f763b8ceSMatthias Ringwald   }
510f763b8ceSMatthias Ringwald }
511f763b8ceSMatthias Ringwald 
512f763b8ceSMatthias Ringwald /**
513f763b8ceSMatthias Ringwald   * @brief  Tx Half Transfer completed callbacks.
514f763b8ceSMatthias Ringwald   * @param  hi2s: I2S handle
515f763b8ceSMatthias Ringwald   */
HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef * hi2s)516f763b8ceSMatthias Ringwald void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
517f763b8ceSMatthias Ringwald {
518f763b8ceSMatthias Ringwald   if(hi2s->Instance == I2S3)
519f763b8ceSMatthias Ringwald   {
520f763b8ceSMatthias Ringwald     /* Manage the remaining file size and new address offset: This function should
521f763b8ceSMatthias Ringwald        be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */
522f763b8ceSMatthias Ringwald     BSP_AUDIO_OUT_HalfTransfer_CallBack();
523f763b8ceSMatthias Ringwald   }
524f763b8ceSMatthias Ringwald }
525f763b8ceSMatthias Ringwald 
526f763b8ceSMatthias Ringwald /**
527f763b8ceSMatthias Ringwald   * @brief  Clock Config.
528f763b8ceSMatthias Ringwald   * @param  hi2s: might be required to set audio peripheral predivider if any.
529f763b8ceSMatthias Ringwald   * @param  AudioFreq: Audio frequency used to play the audio stream.
530f763b8ceSMatthias Ringwald   * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
531f763b8ceSMatthias Ringwald   *         Being __weak it can be overwritten by the application
532f763b8ceSMatthias Ringwald   * @param  Params : pointer on additional configuration parameters, can be NULL.
533f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_ClockConfig(I2S_HandleTypeDef * hi2s,uint32_t AudioFreq,void * Params)534f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_OUT_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params)
535f763b8ceSMatthias Ringwald {
536f763b8ceSMatthias Ringwald   RCC_PeriphCLKInitTypeDef rccclkinit;
537f763b8ceSMatthias Ringwald 
538*e0a94143SDirk Helbig   i2s_pll_entry_t const *pll_params = i2s_find_pll_params( AudioFreq );
539*e0a94143SDirk Helbig 
540*e0a94143SDirk Helbig   bsp_audio_out_actual_frequency = pll_params->actual;
541f763b8ceSMatthias Ringwald   /* Enable PLLI2S clock */
542f763b8ceSMatthias Ringwald   HAL_RCCEx_GetPeriphCLKConfig(&rccclkinit);
543*e0a94143SDirk Helbig   /* PLLI2S_VCO Input = HSE_VALUE/PLL_M */
544f763b8ceSMatthias Ringwald 
545f763b8ceSMatthias Ringwald   /* I2S clock config
546f763b8ceSMatthias Ringwald   PLLI2S_VCO = f(VCO clock) = f(PLLI2S clock input) � (PLLI2SN/PLLM)
547f763b8ceSMatthias Ringwald   I2SCLK = f(PLLI2S clock output) = f(VCO clock) / PLLI2SR */
548f763b8ceSMatthias Ringwald   rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
549*e0a94143SDirk Helbig   rccclkinit.PLLI2S.PLLI2SN = pll_params->n;
550*e0a94143SDirk Helbig   rccclkinit.PLLI2S.PLLI2SR = pll_params->r;
551f763b8ceSMatthias Ringwald   HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
552f763b8ceSMatthias Ringwald }
553f763b8ceSMatthias Ringwald 
554f763b8ceSMatthias Ringwald /**
555f763b8ceSMatthias Ringwald   * @brief  AUDIO OUT I2S MSP Init.
556f763b8ceSMatthias Ringwald   * @param  hi2s: might be required to set audio peripheral predivider if any.
557f763b8ceSMatthias Ringwald   * @param  Params : pointer on additional configuration parameters, can be NULL.
558f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_MspInit(I2S_HandleTypeDef * hi2s,void * Params)559f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_OUT_MspInit(I2S_HandleTypeDef *hi2s, void *Params)
560f763b8ceSMatthias Ringwald {
561f763b8ceSMatthias Ringwald   static DMA_HandleTypeDef hdma_i2sTx;
562f763b8ceSMatthias Ringwald   GPIO_InitTypeDef  GPIO_InitStruct;
563f763b8ceSMatthias Ringwald 
564f763b8ceSMatthias Ringwald   /* Enable I2S3 clock */
565f763b8ceSMatthias Ringwald   I2S3_CLK_ENABLE();
566f763b8ceSMatthias Ringwald 
567f763b8ceSMatthias Ringwald   /*** Configure the GPIOs ***/
568f763b8ceSMatthias Ringwald   /* Enable I2S GPIO clocks */
569f763b8ceSMatthias Ringwald   I2S3_SCK_SD_CLK_ENABLE();
570f763b8ceSMatthias Ringwald   I2S3_WS_CLK_ENABLE();
571f763b8ceSMatthias Ringwald 
572f763b8ceSMatthias Ringwald   /* I2S3 pins configuration: WS, SCK and SD pins ----------------------------*/
573f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pin         = I2S3_SCK_PIN | I2S3_SD_PIN;
574f763b8ceSMatthias Ringwald   GPIO_InitStruct.Mode        = GPIO_MODE_AF_PP;
575f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pull        = GPIO_NOPULL;
576f763b8ceSMatthias Ringwald   GPIO_InitStruct.Speed       = GPIO_SPEED_FAST;
577f763b8ceSMatthias Ringwald   GPIO_InitStruct.Alternate   = I2S3_SCK_SD_WS_AF;
578f763b8ceSMatthias Ringwald   HAL_GPIO_Init(I2S3_SCK_SD_GPIO_PORT, &GPIO_InitStruct);
579f763b8ceSMatthias Ringwald 
580f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pin         = I2S3_WS_PIN ;
581f763b8ceSMatthias Ringwald   HAL_GPIO_Init(I2S3_WS_GPIO_PORT, &GPIO_InitStruct);
582f763b8ceSMatthias Ringwald 
583f763b8ceSMatthias Ringwald   /* I2S3 pins configuration: MCK pin */
584f763b8ceSMatthias Ringwald   I2S3_MCK_CLK_ENABLE();
585f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pin         = I2S3_MCK_PIN;
586f763b8ceSMatthias Ringwald   HAL_GPIO_Init(I2S3_MCK_GPIO_PORT, &GPIO_InitStruct);
587f763b8ceSMatthias Ringwald 
588f763b8ceSMatthias Ringwald   /* Enable the I2S DMA clock */
589f763b8ceSMatthias Ringwald   I2S3_DMAx_CLK_ENABLE();
590f763b8ceSMatthias Ringwald 
591f763b8ceSMatthias Ringwald   if(hi2s->Instance == I2S3)
592f763b8ceSMatthias Ringwald   {
593f763b8ceSMatthias Ringwald     /* Configure the hdma_i2sTx handle parameters */
594f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.Channel             = I2S3_DMAx_CHANNEL;
595f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
596f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.PeriphInc           = DMA_PINC_DISABLE;
597f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.MemInc              = DMA_MINC_ENABLE;
598f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.PeriphDataAlignment = I2S3_DMAx_PERIPH_DATA_SIZE;
599f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.MemDataAlignment    = I2S3_DMAx_MEM_DATA_SIZE;
600f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.Mode                = DMA_NORMAL;
601f763b8ceSMatthias Ringwald 
602f763b8ceSMatthias Ringwald     // BK: use circular DMA for hal_audio.h
603f763b8ceSMatthias Ringwald #ifdef HAVE_HAL_AUDIO
604f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.Mode                = DMA_CIRCULAR;
605f763b8ceSMatthias Ringwald #endif
606f763b8ceSMatthias Ringwald     // BK: use circular DMA (end)
607f763b8ceSMatthias Ringwald 
608f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.Priority            = DMA_PRIORITY_HIGH;
609f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
610f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
611f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.MemBurst            = DMA_MBURST_SINGLE;
612f763b8ceSMatthias Ringwald     hdma_i2sTx.Init.PeriphBurst         = DMA_PBURST_SINGLE;
613f763b8ceSMatthias Ringwald 
614f763b8ceSMatthias Ringwald     hdma_i2sTx.Instance                 = I2S3_DMAx_STREAM;
615f763b8ceSMatthias Ringwald 
616f763b8ceSMatthias Ringwald     /* Associate the DMA handle */
617f763b8ceSMatthias Ringwald     __HAL_LINKDMA(hi2s, hdmatx, hdma_i2sTx);
618f763b8ceSMatthias Ringwald 
619f763b8ceSMatthias Ringwald     /* Deinitialize the Stream for new transfer */
620f763b8ceSMatthias Ringwald     HAL_DMA_DeInit(&hdma_i2sTx);
621f763b8ceSMatthias Ringwald 
622f763b8ceSMatthias Ringwald     /* Configure the DMA Stream */
623f763b8ceSMatthias Ringwald     HAL_DMA_Init(&hdma_i2sTx);
624f763b8ceSMatthias Ringwald   }
625f763b8ceSMatthias Ringwald 
626f763b8ceSMatthias Ringwald   /* I2S DMA IRQ Channel configuration */
627f763b8ceSMatthias Ringwald   HAL_NVIC_SetPriority(I2S3_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
628f763b8ceSMatthias Ringwald   HAL_NVIC_EnableIRQ(I2S3_DMAx_IRQ);
629f763b8ceSMatthias Ringwald }
630f763b8ceSMatthias Ringwald 
631f763b8ceSMatthias Ringwald /**
632f763b8ceSMatthias Ringwald   * @brief  De-Initializes BSP_AUDIO_OUT MSP.
633f763b8ceSMatthias Ringwald   * @param  hi2s: might be required to set audio peripheral predivider if any.
634f763b8ceSMatthias Ringwald   * @param  Params : pointer on additional configuration parameters, can be NULL.
635f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_MspDeInit(I2S_HandleTypeDef * hi2s,void * Params)636f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_OUT_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params)
637f763b8ceSMatthias Ringwald {
638f763b8ceSMatthias Ringwald   GPIO_InitTypeDef  GPIO_InitStruct;
639f763b8ceSMatthias Ringwald 
640f763b8ceSMatthias Ringwald   /* I2S DMA IRQ Channel deactivation */
641f763b8ceSMatthias Ringwald   HAL_NVIC_DisableIRQ(I2S3_DMAx_IRQ);
642f763b8ceSMatthias Ringwald 
643f763b8ceSMatthias Ringwald   if(hi2s->Instance == I2S3)
644f763b8ceSMatthias Ringwald   {
645f763b8ceSMatthias Ringwald     /* Deinitialize the Stream for new transfer */
646f763b8ceSMatthias Ringwald     HAL_DMA_DeInit(hi2s->hdmatx);
647f763b8ceSMatthias Ringwald   }
648f763b8ceSMatthias Ringwald 
649f763b8ceSMatthias Ringwald  /* Disable I2S block */
650f763b8ceSMatthias Ringwald   __HAL_I2S_DISABLE(hi2s);
651f763b8ceSMatthias Ringwald 
652f763b8ceSMatthias Ringwald   /* CODEC_I2S pins configuration: SCK and SD pins */
653f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pin = I2S3_SCK_PIN | I2S3_SD_PIN;
654f763b8ceSMatthias Ringwald   HAL_GPIO_DeInit(I2S3_SCK_SD_GPIO_PORT, GPIO_InitStruct.Pin);
655f763b8ceSMatthias Ringwald 
656f763b8ceSMatthias Ringwald   /* CODEC_I2S pins configuration: WS pin */
657f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pin = I2S3_WS_PIN;
658f763b8ceSMatthias Ringwald   HAL_GPIO_DeInit(I2S3_WS_GPIO_PORT, GPIO_InitStruct.Pin);
659f763b8ceSMatthias Ringwald 
660f763b8ceSMatthias Ringwald   /* CODEC_I2S pins configuration: MCK pin */
661f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pin = I2S3_MCK_PIN;
662f763b8ceSMatthias Ringwald   HAL_GPIO_DeInit(I2S3_MCK_GPIO_PORT, GPIO_InitStruct.Pin);
663f763b8ceSMatthias Ringwald 
664f763b8ceSMatthias Ringwald   /* Disable I2S clock */
665f763b8ceSMatthias Ringwald   I2S3_CLK_DISABLE();
666f763b8ceSMatthias Ringwald 
667f763b8ceSMatthias Ringwald   /* GPIO pins clock and DMA clock can be shut down in the applic
668f763b8ceSMatthias Ringwald      by surcgarging this __weak function */
669f763b8ceSMatthias Ringwald }
670f763b8ceSMatthias Ringwald 
671f763b8ceSMatthias Ringwald /**
672f763b8ceSMatthias Ringwald   * @brief  Manages the DMA full Transfer complete event.
673f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_TransferComplete_CallBack(void)674f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
675f763b8ceSMatthias Ringwald {
676f763b8ceSMatthias Ringwald }
677f763b8ceSMatthias Ringwald 
678f763b8ceSMatthias Ringwald /**
679f763b8ceSMatthias Ringwald   * @brief  Manages the DMA Half Transfer complete event.
680f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_HalfTransfer_CallBack(void)681f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
682f763b8ceSMatthias Ringwald {
683f763b8ceSMatthias Ringwald }
684f763b8ceSMatthias Ringwald 
685f763b8ceSMatthias Ringwald /**
686f763b8ceSMatthias Ringwald   * @brief  Manages the DMA FIFO error event.
687f763b8ceSMatthias Ringwald   */
BSP_AUDIO_OUT_Error_CallBack(void)688f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_OUT_Error_CallBack(void)
689f763b8ceSMatthias Ringwald {
690f763b8ceSMatthias Ringwald }
691f763b8ceSMatthias Ringwald 
692f763b8ceSMatthias Ringwald /*******************************************************************************
693f763b8ceSMatthias Ringwald                             Static Functions
694f763b8ceSMatthias Ringwald *******************************************************************************/
695f763b8ceSMatthias Ringwald 
696f763b8ceSMatthias Ringwald /**
697f763b8ceSMatthias Ringwald   * @brief  Initializes the Audio Codec audio interface (I2S).
698f763b8ceSMatthias Ringwald   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral.
699f763b8ceSMatthias Ringwald   */
I2S3_Init(uint32_t AudioFreq)700f763b8ceSMatthias Ringwald static uint8_t I2S3_Init(uint32_t AudioFreq)
701f763b8ceSMatthias Ringwald {
702f763b8ceSMatthias Ringwald   /* Initialize the hAudioOutI2s Instance parameter */
703f763b8ceSMatthias Ringwald   hAudioOutI2s.Instance         = I2S3;
704f763b8ceSMatthias Ringwald 
705f763b8ceSMatthias Ringwald  /* Disable I2S block */
706f763b8ceSMatthias Ringwald   __HAL_I2S_DISABLE(&hAudioOutI2s);
707f763b8ceSMatthias Ringwald 
708f763b8ceSMatthias Ringwald   /* I2S3 peripheral configuration */
709f763b8ceSMatthias Ringwald   hAudioOutI2s.Init.AudioFreq   = AudioFreq;
710f763b8ceSMatthias Ringwald   hAudioOutI2s.Init.ClockSource = I2S_CLOCK_PLL;
711f763b8ceSMatthias Ringwald   hAudioOutI2s.Init.CPOL        = I2S_CPOL_LOW;
712f763b8ceSMatthias Ringwald   hAudioOutI2s.Init.DataFormat  = I2S_DATAFORMAT_16B;
713f763b8ceSMatthias Ringwald   hAudioOutI2s.Init.MCLKOutput  = I2S_MCLKOUTPUT_ENABLE;
714f763b8ceSMatthias Ringwald   hAudioOutI2s.Init.Mode        = I2S_MODE_MASTER_TX;
715f763b8ceSMatthias Ringwald   hAudioOutI2s.Init.Standard    = I2S_STANDARD;
716f763b8ceSMatthias Ringwald   /* Initialize the I2S peripheral with the structure above */
717f763b8ceSMatthias Ringwald   if(HAL_I2S_Init(&hAudioOutI2s) != HAL_OK)
718f763b8ceSMatthias Ringwald   {
719f763b8ceSMatthias Ringwald     return AUDIO_ERROR;
720f763b8ceSMatthias Ringwald   }
721f763b8ceSMatthias Ringwald   else
722f763b8ceSMatthias Ringwald   {
723f763b8ceSMatthias Ringwald     return AUDIO_OK;
724f763b8ceSMatthias Ringwald   }
725f763b8ceSMatthias Ringwald }
726f763b8ceSMatthias Ringwald 
727f763b8ceSMatthias Ringwald /**
728f763b8ceSMatthias Ringwald   * @}
729f763b8ceSMatthias Ringwald   */
730f763b8ceSMatthias Ringwald 
731f763b8ceSMatthias Ringwald /** @defgroup STM32F4_DISCOVERY_AUDIO_IN_Private_Functions STM32F4 DISCOVERY AUDIO IN Private Functions
732f763b8ceSMatthias Ringwald   * @{
733f763b8ceSMatthias Ringwald   */
734f763b8ceSMatthias Ringwald 
735f763b8ceSMatthias Ringwald /**
736f763b8ceSMatthias Ringwald   * @brief  Initializes wave recording.
737f763b8ceSMatthias Ringwald   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral.
738f763b8ceSMatthias Ringwald   * @param  BitRes: Audio frequency to be configured for the I2S peripheral.
739f763b8ceSMatthias Ringwald   * @param  ChnlNbr: Audio frequency to be configured for the I2S peripheral.
740f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
741f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_Init(uint32_t AudioFreq,uint32_t BitRes,uint32_t ChnlNbr)742f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_IN_Init(uint32_t AudioFreq, uint32_t BitRes, uint32_t ChnlNbr)
743f763b8ceSMatthias Ringwald {
744f763b8ceSMatthias Ringwald 
745f763b8ceSMatthias Ringwald #if 0
746f763b8ceSMatthias Ringwald   // BK: only do PLL clock configuration in sink
747f763b8ceSMatthias Ringwald   /* Configure PLL clock */
748f763b8ceSMatthias Ringwald   BSP_AUDIO_IN_ClockConfig(&hAudioInI2s, AudioFreq, NULL);
749f763b8ceSMatthias Ringwald #endif
750f763b8ceSMatthias Ringwald 
751f763b8ceSMatthias Ringwald   /* Configure the PDM library */
752f763b8ceSMatthias Ringwald   PDMDecoder_Init(AudioFreq, ChnlNbr);
753f763b8ceSMatthias Ringwald 
754f763b8ceSMatthias Ringwald   /* Configure the I2S peripheral */
755f763b8ceSMatthias Ringwald   hAudioInI2s.Instance = I2S2;
756f763b8ceSMatthias Ringwald   if(HAL_I2S_GetState(&hAudioInI2s) == HAL_I2S_STATE_RESET)
757f763b8ceSMatthias Ringwald   {
758f763b8ceSMatthias Ringwald     /* Initialize the I2S Msp: this __weak function can be rewritten by the application */
759f763b8ceSMatthias Ringwald     BSP_AUDIO_IN_MspInit(&hAudioInI2s, NULL);
760f763b8ceSMatthias Ringwald   }
761f763b8ceSMatthias Ringwald 
762f763b8ceSMatthias Ringwald   /* Configure the I2S2 */
763f763b8ceSMatthias Ringwald   I2S2_Init(AudioFreq);
764f763b8ceSMatthias Ringwald 
765f763b8ceSMatthias Ringwald   /* Return AUDIO_OK when all operations are correctly done */
766f763b8ceSMatthias Ringwald   return AUDIO_OK;
767f763b8ceSMatthias Ringwald }
768f763b8ceSMatthias Ringwald 
769f763b8ceSMatthias Ringwald /**
770f763b8ceSMatthias Ringwald   * @brief  Starts audio recording.
771f763b8ceSMatthias Ringwald   * @param  pbuf: Main buffer pointer for the recorded data storing
772f763b8ceSMatthias Ringwald   * @param  size: Current size of the recorded buffer
773f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
774f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_Record(uint16_t * pbuf,uint32_t size)775f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
776f763b8ceSMatthias Ringwald {
777f763b8ceSMatthias Ringwald   uint32_t ret = AUDIO_ERROR;
778f763b8ceSMatthias Ringwald 
779f763b8ceSMatthias Ringwald   /* Start the process receive DMA */
780f763b8ceSMatthias Ringwald   HAL_I2S_Receive_DMA(&hAudioInI2s, pbuf, size);
781f763b8ceSMatthias Ringwald 
782f763b8ceSMatthias Ringwald   /* Return AUDIO_OK when all operations are correctly done */
783f763b8ceSMatthias Ringwald   ret = AUDIO_OK;
784f763b8ceSMatthias Ringwald 
785f763b8ceSMatthias Ringwald   return ret;
786f763b8ceSMatthias Ringwald }
787f763b8ceSMatthias Ringwald 
788f763b8ceSMatthias Ringwald /**
789f763b8ceSMatthias Ringwald   * @brief  Stops audio recording.
790f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
791f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_Stop(void)792f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_IN_Stop(void)
793f763b8ceSMatthias Ringwald {
794f763b8ceSMatthias Ringwald   uint32_t ret = AUDIO_ERROR;
795f763b8ceSMatthias Ringwald 
796f763b8ceSMatthias Ringwald   /* Call the Media layer pause function */
797f763b8ceSMatthias Ringwald   HAL_I2S_DMAStop(&hAudioInI2s);
798f763b8ceSMatthias Ringwald 
799f763b8ceSMatthias Ringwald   /* Return AUDIO_OK when all operations are correctly done */
800f763b8ceSMatthias Ringwald   ret = AUDIO_OK;
801f763b8ceSMatthias Ringwald 
802f763b8ceSMatthias Ringwald   return ret;
803f763b8ceSMatthias Ringwald }
804f763b8ceSMatthias Ringwald 
805f763b8ceSMatthias Ringwald /**
806f763b8ceSMatthias Ringwald   * @brief  Pauses the audio file stream.
807f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
808f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_Pause(void)809f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_IN_Pause(void)
810f763b8ceSMatthias Ringwald {
811f763b8ceSMatthias Ringwald   /* Call the Media layer pause function */
812f763b8ceSMatthias Ringwald   HAL_I2S_DMAPause(&hAudioInI2s);
813f763b8ceSMatthias Ringwald 
814f763b8ceSMatthias Ringwald   /* Return AUDIO_OK when all operations are correctly done */
815f763b8ceSMatthias Ringwald   return AUDIO_OK;
816f763b8ceSMatthias Ringwald }
817f763b8ceSMatthias Ringwald 
818f763b8ceSMatthias Ringwald /**
819f763b8ceSMatthias Ringwald   * @brief  Resumes the audio file stream.
820f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
821f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_Resume(void)822f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_IN_Resume(void)
823f763b8ceSMatthias Ringwald {
824f763b8ceSMatthias Ringwald   /* Call the Media layer pause/resume function */
825f763b8ceSMatthias Ringwald   HAL_I2S_DMAResume(&hAudioInI2s);
826f763b8ceSMatthias Ringwald 
827f763b8ceSMatthias Ringwald   /* Return AUDIO_OK when all operations are correctly done */
828f763b8ceSMatthias Ringwald   return AUDIO_OK;
829f763b8ceSMatthias Ringwald }
830f763b8ceSMatthias Ringwald 
831f763b8ceSMatthias Ringwald /**
832f763b8ceSMatthias Ringwald   * @brief  Controls the audio in volume level.
833f763b8ceSMatthias Ringwald   * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for
834f763b8ceSMatthias Ringwald   *         Mute and 100 for Max volume level).
835f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
836f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_SetVolume(uint8_t Volume)837f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
838f763b8ceSMatthias Ringwald {
839f763b8ceSMatthias Ringwald   /* Set the Global variable AudioInVolume */
840f763b8ceSMatthias Ringwald   AudioInVolume = Volume;
841f763b8ceSMatthias Ringwald 
842f763b8ceSMatthias Ringwald   /* Return AUDIO_OK when all operations are correctly done */
843f763b8ceSMatthias Ringwald   return AUDIO_OK;
844f763b8ceSMatthias Ringwald }
845f763b8ceSMatthias Ringwald 
846f763b8ceSMatthias Ringwald /**
847f763b8ceSMatthias Ringwald   * @brief  Converts audio format from PDM to PCM.
848f763b8ceSMatthias Ringwald   * @param  PDMBuf: Pointer to data PDM buffer
849f763b8ceSMatthias Ringwald   * @param  PCMBuf: Pointer to data PCM buffer
850f763b8ceSMatthias Ringwald   * @retval AUDIO_OK if correct communication, else wrong communication
851f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_PDMToPCM(uint16_t * PDMBuf,uint16_t * PCMBuf)852f763b8ceSMatthias Ringwald uint8_t BSP_AUDIO_IN_PDMToPCM(uint16_t *PDMBuf, uint16_t *PCMBuf)
853f763b8ceSMatthias Ringwald {
854f763b8ceSMatthias Ringwald   uint16_t AppPDM[INTERNAL_BUFF_SIZE/2];
855f763b8ceSMatthias Ringwald   uint32_t index = 0;
856f763b8ceSMatthias Ringwald 
857f763b8ceSMatthias Ringwald   /* PDM Demux */
858f763b8ceSMatthias Ringwald   for(index = 0; index<INTERNAL_BUFF_SIZE/2; index++)
859f763b8ceSMatthias Ringwald   {
860f763b8ceSMatthias Ringwald     AppPDM[index] = HTONS(PDMBuf[index]);
861f763b8ceSMatthias Ringwald   }
862f763b8ceSMatthias Ringwald 
863f763b8ceSMatthias Ringwald   for(index = 0; index < DEFAULT_AUDIO_IN_CHANNEL_NBR; index++)
864f763b8ceSMatthias Ringwald   {
865f763b8ceSMatthias Ringwald     /* PDM to PCM filter */
866f763b8ceSMatthias Ringwald     PDM_Filter_64_LSB((uint8_t*)&AppPDM[index], (uint16_t*)&(PCMBuf[index]), AudioInVolume , (PDMFilter_InitStruct *)&Filter[index]);
867f763b8ceSMatthias Ringwald   }
868f763b8ceSMatthias Ringwald #if 0
869f763b8ceSMatthias Ringwald   // BK - generate mono output
870f763b8ceSMatthias Ringwald 
871f763b8ceSMatthias Ringwald   /* Duplicate samples since a single microphone in mounted on STM32F4-Discovery */
872f763b8ceSMatthias Ringwald   for(index = 0; index < PCM_OUT_SIZE; index++)
873f763b8ceSMatthias Ringwald   {
874f763b8ceSMatthias Ringwald     PCMBuf[(index<<1)+1] = PCMBuf[index<<1];
875f763b8ceSMatthias Ringwald   }
876f763b8ceSMatthias Ringwald #endif
877f763b8ceSMatthias Ringwald 
878f763b8ceSMatthias Ringwald   /* Return AUDIO_OK when all operations are correctly done */
879f763b8ceSMatthias Ringwald   return AUDIO_OK;
880f763b8ceSMatthias Ringwald }
881f763b8ceSMatthias Ringwald 
882f763b8ceSMatthias Ringwald /**
883f763b8ceSMatthias Ringwald   * @brief  Rx Transfer completed callbacks
884f763b8ceSMatthias Ringwald   * @param  hi2s: I2S handle
885f763b8ceSMatthias Ringwald   */
HAL_I2S_RxCpltCallback(I2S_HandleTypeDef * hi2s)886f763b8ceSMatthias Ringwald void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
887f763b8ceSMatthias Ringwald {
888f763b8ceSMatthias Ringwald   /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
889f763b8ceSMatthias Ringwald   BSP_AUDIO_IN_TransferComplete_CallBack();
890f763b8ceSMatthias Ringwald }
891f763b8ceSMatthias Ringwald 
892f763b8ceSMatthias Ringwald /**
893f763b8ceSMatthias Ringwald   * @brief  Rx Half Transfer completed callbacks.
894f763b8ceSMatthias Ringwald   * @param  hi2s: I2S handle
895f763b8ceSMatthias Ringwald   */
HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef * hi2s)896f763b8ceSMatthias Ringwald void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
897f763b8ceSMatthias Ringwald {
898f763b8ceSMatthias Ringwald   /* Manage the remaining file size and new address offset: This function
899f763b8ceSMatthias Ringwald      should be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */
900f763b8ceSMatthias Ringwald   BSP_AUDIO_IN_HalfTransfer_CallBack();
901f763b8ceSMatthias Ringwald }
902f763b8ceSMatthias Ringwald 
903f763b8ceSMatthias Ringwald /**
904*e0a94143SDirk Helbig   * @brief  Retrive the audio frequency.
905*e0a94143SDirk Helbig   * @retval AudioFreq: Audio frequency used to play the audio stream.
906*e0a94143SDirk Helbig   * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
907*e0a94143SDirk Helbig   *         audio frequency.
908*e0a94143SDirk Helbig   */
BSP_AUDIO_OUT_GetFrequency(uint32_t AudioFreq)909*e0a94143SDirk Helbig uint32_t BSP_AUDIO_OUT_GetFrequency(uint32_t AudioFreq)
910*e0a94143SDirk Helbig {
911*e0a94143SDirk Helbig   return bsp_audio_out_frequency;
912*e0a94143SDirk Helbig }
913*e0a94143SDirk Helbig 
914*e0a94143SDirk Helbig /**
915f763b8ceSMatthias Ringwald   * @brief  Audio In Clock Config.
916f763b8ceSMatthias Ringwald   * @param  hi2s: I2S handle
917f763b8ceSMatthias Ringwald   * @param  AudioFreq: Audio frequency used to record the audio stream.
918f763b8ceSMatthias Ringwald   * @param  Params : pointer on additional configuration parameters, can be NULL.
919f763b8ceSMatthias Ringwald   * @note   This API is called by BSP_AUDIO_IN_Init()
920f763b8ceSMatthias Ringwald   *         Being __weak it can be overwritten by the application
921f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_ClockConfig(I2S_HandleTypeDef * hi2s,uint32_t AudioFreq,void * Params)922f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_IN_ClockConfig(I2S_HandleTypeDef *hi2s, uint32_t AudioFreq, void *Params)
923f763b8ceSMatthias Ringwald {
924f763b8ceSMatthias Ringwald   RCC_PeriphCLKInitTypeDef rccclkinit;
925f763b8ceSMatthias Ringwald 
926f763b8ceSMatthias Ringwald   /*Enable PLLI2S clock*/
927f763b8ceSMatthias Ringwald   HAL_RCCEx_GetPeriphCLKConfig(&rccclkinit);
928*e0a94143SDirk Helbig   i2s_pll_entry_t const *pll_params = i2s_find_pll_params( AudioFreq );
929*e0a94143SDirk Helbig 
930f763b8ceSMatthias Ringwald   rccclkinit.PeriphClockSelection = RCC_PERIPHCLK_I2S;
931*e0a94143SDirk Helbig   rccclkinit.PLLI2S.PLLI2SN = pll_params->n;
932*e0a94143SDirk Helbig   rccclkinit.PLLI2S.PLLI2SR = pll_params->r;
933f763b8ceSMatthias Ringwald   HAL_RCCEx_PeriphCLKConfig(&rccclkinit);
934f763b8ceSMatthias Ringwald }
935f763b8ceSMatthias Ringwald 
936f763b8ceSMatthias Ringwald /**
937f763b8ceSMatthias Ringwald   * @brief  BSP AUDIO IN MSP Init.
938f763b8ceSMatthias Ringwald   * @param  hi2s: I2S handle
939f763b8ceSMatthias Ringwald   * @param  Params : pointer on additional configuration parameters, can be NULL.
940f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_MspInit(I2S_HandleTypeDef * hi2s,void * Params)941f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_IN_MspInit(I2S_HandleTypeDef *hi2s, void *Params)
942f763b8ceSMatthias Ringwald {
943f763b8ceSMatthias Ringwald   static DMA_HandleTypeDef hdma_i2sRx;
944f763b8ceSMatthias Ringwald   GPIO_InitTypeDef  GPIO_InitStruct;
945f763b8ceSMatthias Ringwald 
946f763b8ceSMatthias Ringwald   /* Enable the I2S2 peripheral clock */
947f763b8ceSMatthias Ringwald   I2S2_CLK_ENABLE();
948f763b8ceSMatthias Ringwald 
949f763b8ceSMatthias Ringwald   /* Enable I2S GPIO clocks */
950f763b8ceSMatthias Ringwald   I2S2_SCK_GPIO_CLK_ENABLE();
951f763b8ceSMatthias Ringwald   I2S2_MOSI_GPIO_CLK_ENABLE();
952f763b8ceSMatthias Ringwald 
953f763b8ceSMatthias Ringwald   /* I2S2 pins configuration: SCK and MOSI pins ------------------------------*/
954f763b8ceSMatthias Ringwald   GPIO_InitStruct.Mode      = GPIO_MODE_AF_PP;
955f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pull      = GPIO_NOPULL;
956f763b8ceSMatthias Ringwald   GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;
957f763b8ceSMatthias Ringwald 
958f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pin       = I2S2_SCK_PIN;
959f763b8ceSMatthias Ringwald   GPIO_InitStruct.Alternate = I2S2_SCK_AF;
960f763b8ceSMatthias Ringwald   HAL_GPIO_Init(I2S2_SCK_GPIO_PORT, &GPIO_InitStruct);
961f763b8ceSMatthias Ringwald 
962f763b8ceSMatthias Ringwald   GPIO_InitStruct.Pin       = I2S2_MOSI_PIN ;
963f763b8ceSMatthias Ringwald   GPIO_InitStruct.Alternate = I2S2_MOSI_AF;
964f763b8ceSMatthias Ringwald   HAL_GPIO_Init(I2S2_MOSI_GPIO_PORT, &GPIO_InitStruct);
965f763b8ceSMatthias Ringwald 
966f763b8ceSMatthias Ringwald   /* Enable the DMA clock */
967f763b8ceSMatthias Ringwald   I2S2_DMAx_CLK_ENABLE();
968f763b8ceSMatthias Ringwald 
969f763b8ceSMatthias Ringwald   if(hi2s->Instance == I2S2)
970f763b8ceSMatthias Ringwald   {
971f763b8ceSMatthias Ringwald     /* Configure the hdma_i2sRx handle parameters */
972f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.Channel             = I2S2_DMAx_CHANNEL;
973f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
974f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.PeriphInc           = DMA_PINC_DISABLE;
975f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.MemInc              = DMA_MINC_ENABLE;
976f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.PeriphDataAlignment = I2S2_DMAx_PERIPH_DATA_SIZE;
977f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.MemDataAlignment    = I2S2_DMAx_MEM_DATA_SIZE;
978f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.Mode                = DMA_CIRCULAR;
979f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.Priority            = DMA_PRIORITY_HIGH;
980f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
981f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
982f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.MemBurst            = DMA_MBURST_SINGLE;
983f763b8ceSMatthias Ringwald     hdma_i2sRx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
984f763b8ceSMatthias Ringwald 
985f763b8ceSMatthias Ringwald     hdma_i2sRx.Instance = I2S2_DMAx_STREAM;
986f763b8ceSMatthias Ringwald 
987f763b8ceSMatthias Ringwald     /* Associate the DMA handle */
988f763b8ceSMatthias Ringwald     __HAL_LINKDMA(hi2s, hdmarx, hdma_i2sRx);
989f763b8ceSMatthias Ringwald 
990f763b8ceSMatthias Ringwald     /* Deinitialize the Stream for new transfer */
991f763b8ceSMatthias Ringwald     HAL_DMA_DeInit(&hdma_i2sRx);
992f763b8ceSMatthias Ringwald 
993f763b8ceSMatthias Ringwald     /* Configure the DMA Stream */
994f763b8ceSMatthias Ringwald     HAL_DMA_Init(&hdma_i2sRx);
995f763b8ceSMatthias Ringwald   }
996f763b8ceSMatthias Ringwald 
997f763b8ceSMatthias Ringwald   /* I2S DMA IRQ Channel configuration */
998f763b8ceSMatthias Ringwald   HAL_NVIC_SetPriority(I2S2_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
999f763b8ceSMatthias Ringwald   HAL_NVIC_EnableIRQ(I2S2_DMAx_IRQ);
1000f763b8ceSMatthias Ringwald }
1001f763b8ceSMatthias Ringwald 
1002f763b8ceSMatthias Ringwald /**
1003f763b8ceSMatthias Ringwald   * @brief  DeInitializes BSP_AUDIO_IN MSP.
1004f763b8ceSMatthias Ringwald   * @param  hi2s: I2S handle
1005f763b8ceSMatthias Ringwald   * @param  Params : pointer on additional configuration parameters, can be NULL.
1006f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_MspDeInit(I2S_HandleTypeDef * hi2s,void * Params)1007f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_IN_MspDeInit(I2S_HandleTypeDef *hi2s, void *Params)
1008f763b8ceSMatthias Ringwald {
1009f763b8ceSMatthias Ringwald   GPIO_InitTypeDef  gpio_init_structure;
1010f763b8ceSMatthias Ringwald 
1011f763b8ceSMatthias Ringwald   /* I2S DMA IRQ Channel deactivation */
1012f763b8ceSMatthias Ringwald   HAL_NVIC_DisableIRQ(I2S2_DMAx_IRQ);
1013f763b8ceSMatthias Ringwald 
1014f763b8ceSMatthias Ringwald   if(hi2s->Instance == I2S2)
1015f763b8ceSMatthias Ringwald   {
1016f763b8ceSMatthias Ringwald     /* Deinitialize the Stream for new transfer */
1017f763b8ceSMatthias Ringwald     HAL_DMA_DeInit(hi2s->hdmarx);
1018f763b8ceSMatthias Ringwald   }
1019f763b8ceSMatthias Ringwald 
1020f763b8ceSMatthias Ringwald  /* Disable I2S block */
1021f763b8ceSMatthias Ringwald   __HAL_I2S_DISABLE(hi2s);
1022f763b8ceSMatthias Ringwald 
1023f763b8ceSMatthias Ringwald   /* Disable pins: SCK and SD pins */
1024f763b8ceSMatthias Ringwald   gpio_init_structure.Pin = I2S2_SCK_PIN;
1025f763b8ceSMatthias Ringwald   HAL_GPIO_DeInit(I2S2_SCK_GPIO_PORT, gpio_init_structure.Pin);
1026f763b8ceSMatthias Ringwald   gpio_init_structure.Pin = I2S2_MOSI_PIN;
1027f763b8ceSMatthias Ringwald   HAL_GPIO_DeInit(I2S2_MOSI_GPIO_PORT, gpio_init_structure.Pin);
1028f763b8ceSMatthias Ringwald 
1029f763b8ceSMatthias Ringwald   /* Disable I2S clock */
1030f763b8ceSMatthias Ringwald   I2S2_CLK_DISABLE();
1031f763b8ceSMatthias Ringwald 
1032f763b8ceSMatthias Ringwald   /* GPIO pins clock and DMA clock can be shut down in the applic
1033f763b8ceSMatthias Ringwald      by surcgarging this __weak function */
1034f763b8ceSMatthias Ringwald }
1035f763b8ceSMatthias Ringwald 
1036f763b8ceSMatthias Ringwald /**
1037f763b8ceSMatthias Ringwald   * @brief  User callback when record buffer is filled.
1038f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_TransferComplete_CallBack(void)1039f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
1040f763b8ceSMatthias Ringwald {
1041f763b8ceSMatthias Ringwald   /* This function should be implemented by the user application.
1042f763b8ceSMatthias Ringwald      It is called into this driver when the current buffer is filled
1043f763b8ceSMatthias Ringwald      to prepare the next buffer pointer and its size. */
1044f763b8ceSMatthias Ringwald }
1045f763b8ceSMatthias Ringwald 
1046f763b8ceSMatthias Ringwald /**
1047f763b8ceSMatthias Ringwald   * @brief  Manages the DMA Half Transfer complete event.
1048f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_HalfTransfer_CallBack(void)1049f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
1050f763b8ceSMatthias Ringwald {
1051f763b8ceSMatthias Ringwald   /* This function should be implemented by the user application.
1052f763b8ceSMatthias Ringwald      It is called into this driver when the current buffer is filled
1053f763b8ceSMatthias Ringwald      to prepare the next buffer pointer and its size. */
1054f763b8ceSMatthias Ringwald }
1055f763b8ceSMatthias Ringwald 
1056f763b8ceSMatthias Ringwald /**
1057f763b8ceSMatthias Ringwald   * @brief  Audio IN Error callback function.
1058f763b8ceSMatthias Ringwald   */
BSP_AUDIO_IN_Error_Callback(void)1059f763b8ceSMatthias Ringwald __weak void BSP_AUDIO_IN_Error_Callback(void)
1060f763b8ceSMatthias Ringwald {
1061f763b8ceSMatthias Ringwald   /* This function is called when an Interrupt due to transfer error on or peripheral
1062f763b8ceSMatthias Ringwald      error occurs. */
1063f763b8ceSMatthias Ringwald }
1064f763b8ceSMatthias Ringwald 
1065f763b8ceSMatthias Ringwald /*******************************************************************************
1066f763b8ceSMatthias Ringwald                             Static Functions
1067f763b8ceSMatthias Ringwald *******************************************************************************/
1068f763b8ceSMatthias Ringwald 
1069f763b8ceSMatthias Ringwald /**
1070f763b8ceSMatthias Ringwald   * @brief  Initialize the PDM library.
1071f763b8ceSMatthias Ringwald   * @param  AudioFreq: Audio sampling frequency
1072f763b8ceSMatthias Ringwald   * @param  ChnlNbr: Number of audio channels (1: mono; 2: stereo)
1073f763b8ceSMatthias Ringwald   */
PDMDecoder_Init(uint32_t AudioFreq,uint32_t ChnlNbr)1074f763b8ceSMatthias Ringwald static void PDMDecoder_Init(uint32_t AudioFreq, uint32_t ChnlNbr)
1075f763b8ceSMatthias Ringwald {
1076f763b8ceSMatthias Ringwald #if 1
1077f763b8ceSMatthias Ringwald   uint32_t i = 0;
1078f763b8ceSMatthias Ringwald 
1079f763b8ceSMatthias Ringwald   /* Enable CRC peripheral to unlock the PDM library */
1080f763b8ceSMatthias Ringwald   __CRC_CLK_ENABLE();
1081f763b8ceSMatthias Ringwald 
1082f763b8ceSMatthias Ringwald   for(i = 0; i < ChnlNbr; i++)
1083f763b8ceSMatthias Ringwald   {
1084f763b8ceSMatthias Ringwald     /* Filter LP and HP Init */
1085f763b8ceSMatthias Ringwald     Filter[i].LP_HZ = AudioFreq / 2;
1086f763b8ceSMatthias Ringwald     Filter[i].HP_HZ = 10;
1087f763b8ceSMatthias Ringwald     Filter[i].Fs = AudioFreq;
1088f763b8ceSMatthias Ringwald     /* On STM32F4-Discovery a single microphone is mounted, samples are duplicated
1089f763b8ceSMatthias Ringwald        to make stereo audio streams */
1090f763b8ceSMatthias Ringwald     // BK - generate mono output
1091f763b8ceSMatthias Ringwald     // Filter[i].Out_MicChannels = 2;
1092f763b8ceSMatthias Ringwald     Filter[i].Out_MicChannels = 1;
1093f763b8ceSMatthias Ringwald     Filter[i].In_MicChannels = ChnlNbr;
1094f763b8ceSMatthias Ringwald     PDM_Filter_Init((PDMFilter_InitStruct *)&Filter[i]);
1095f763b8ceSMatthias Ringwald   }
1096f763b8ceSMatthias Ringwald #endif
1097f763b8ceSMatthias Ringwald }
1098f763b8ceSMatthias Ringwald 
1099f763b8ceSMatthias Ringwald /**
1100f763b8ceSMatthias Ringwald   * @brief  Initializes the Audio Codec audio interface (I2S)
1101f763b8ceSMatthias Ringwald   * @note   This function assumes that the I2S input clock (through PLL_R in
1102f763b8ceSMatthias Ringwald   *         Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y)
1103f763b8ceSMatthias Ringwald   *         is already configured and ready to be used.
1104f763b8ceSMatthias Ringwald   * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral.
1105f763b8ceSMatthias Ringwald   */
I2S2_Init(uint32_t AudioFreq)1106f763b8ceSMatthias Ringwald static uint8_t I2S2_Init(uint32_t AudioFreq)
1107f763b8ceSMatthias Ringwald {
1108f763b8ceSMatthias Ringwald   /* Initialize the hAudioInI2s Instance parameter */
1109f763b8ceSMatthias Ringwald   hAudioInI2s.Instance          = I2S2;
1110f763b8ceSMatthias Ringwald 
1111f763b8ceSMatthias Ringwald   /* Disable I2S block */
1112f763b8ceSMatthias Ringwald   __HAL_I2S_DISABLE(&hAudioInI2s);
1113f763b8ceSMatthias Ringwald 
1114f763b8ceSMatthias Ringwald   /* I2S2 peripheral configuration */
1115f763b8ceSMatthias Ringwald   hAudioInI2s.Init.AudioFreq    = 2 * AudioFreq;
1116f763b8ceSMatthias Ringwald   hAudioInI2s.Init.ClockSource  = I2S_CLOCK_PLL;
1117f763b8ceSMatthias Ringwald   hAudioInI2s.Init.CPOL         = I2S_CPOL_HIGH;
1118f763b8ceSMatthias Ringwald   hAudioInI2s.Init.DataFormat   = I2S_DATAFORMAT_16B;
1119f763b8ceSMatthias Ringwald   hAudioInI2s.Init.MCLKOutput   = I2S_MCLKOUTPUT_DISABLE;
1120f763b8ceSMatthias Ringwald   hAudioInI2s.Init.Mode         = I2S_MODE_MASTER_RX;
1121f763b8ceSMatthias Ringwald   hAudioInI2s.Init.Standard     = I2S_STANDARD_LSB;
1122f763b8ceSMatthias Ringwald 
1123f763b8ceSMatthias Ringwald   /* Initialize the I2S peripheral with the structure above */
1124f763b8ceSMatthias Ringwald   if(HAL_I2S_Init(&hAudioInI2s) != HAL_OK)
1125f763b8ceSMatthias Ringwald   {
1126f763b8ceSMatthias Ringwald     return AUDIO_ERROR;
1127f763b8ceSMatthias Ringwald   }
1128f763b8ceSMatthias Ringwald   else
1129f763b8ceSMatthias Ringwald   {
1130f763b8ceSMatthias Ringwald     return AUDIO_OK;
1131f763b8ceSMatthias Ringwald   }
1132f763b8ceSMatthias Ringwald }
1133f763b8ceSMatthias Ringwald 
1134f763b8ceSMatthias Ringwald /**
1135f763b8ceSMatthias Ringwald   * @}
1136f763b8ceSMatthias Ringwald   */
1137f763b8ceSMatthias Ringwald 
1138f763b8ceSMatthias Ringwald /** @defgroup STM32F4_DISCOVERY_AUDIO_IN_OUT_Private_Functions STM32F4 DISCOVERY AUDIO IN OUT Private Functions
1139f763b8ceSMatthias Ringwald   * @{
1140f763b8ceSMatthias Ringwald   */
1141f763b8ceSMatthias Ringwald 
1142f763b8ceSMatthias Ringwald /**
1143f763b8ceSMatthias Ringwald   * @brief  I2S error callbacks.
1144f763b8ceSMatthias Ringwald   * @param  hi2s: I2S handle
1145f763b8ceSMatthias Ringwald   */
HAL_I2S_ErrorCallback(I2S_HandleTypeDef * hi2s)1146f763b8ceSMatthias Ringwald void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
1147f763b8ceSMatthias Ringwald {
1148f763b8ceSMatthias Ringwald   /* Manage the error generated on DMA FIFO: This function
1149f763b8ceSMatthias Ringwald      should be coded by user (its prototype is already declared in stm32f4_discovery_audio.h) */
1150f763b8ceSMatthias Ringwald   if(hi2s->Instance == I2S3)
1151f763b8ceSMatthias Ringwald   {
1152f763b8ceSMatthias Ringwald     BSP_AUDIO_OUT_Error_CallBack();
1153f763b8ceSMatthias Ringwald   }
1154f763b8ceSMatthias Ringwald   if(hi2s->Instance == I2S2)
1155f763b8ceSMatthias Ringwald   {
1156f763b8ceSMatthias Ringwald     BSP_AUDIO_IN_Error_Callback();
1157f763b8ceSMatthias Ringwald   }
1158f763b8ceSMatthias Ringwald  }
1159f763b8ceSMatthias Ringwald 
1160f763b8ceSMatthias Ringwald /**
1161f763b8ceSMatthias Ringwald   * @}
1162f763b8ceSMatthias Ringwald   */
1163f763b8ceSMatthias Ringwald 
1164f763b8ceSMatthias Ringwald /**
1165f763b8ceSMatthias Ringwald   * @}
1166f763b8ceSMatthias Ringwald   */
1167f763b8ceSMatthias Ringwald 
1168f763b8ceSMatthias Ringwald /**
1169f763b8ceSMatthias Ringwald   * @}
1170f763b8ceSMatthias Ringwald   */
1171f763b8ceSMatthias Ringwald 
1172f763b8ceSMatthias Ringwald /**
1173f763b8ceSMatthias Ringwald   * @}
1174f763b8ceSMatthias Ringwald   */
1175f763b8ceSMatthias Ringwald 
1176f763b8ceSMatthias Ringwald /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
1177