2 ******************************************************************************
3 * @file stm32f4_discovery_audio_codec.c
4 * @author MCD Application Team
6 * @date 19-September-2011
7 * @brief This file includes the low layer driver for CS43L22 Audio Codec
8 * available on STM32F4-Discovery Kit.
9 ******************************************************************************
12 * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
13 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
14 * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
15 * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
16 * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
17 * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
19 * <h2><center>© COPYRIGHT 2011 STMicroelectronics</center></h2>
20 ******************************************************************************
23 /*==============================================================================================================================
25 1. How To use this driver:
26 --------------------------
27 - This driver supports STM32F4xx devices on STM32F4-Discovery Kit.
29 - Configure the options in file stm32f4_discovery_audio_codec.h in the section CONFIGURATION.
30 Refer to the sections 2 and 3 to have more details on the possible configurations.
32 - Call the function EVAL_AUDIO_Init(
33 OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER,
34 OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_AUTO or
36 Volume: initial volume to be set (0 is min (mute), 100 is max (100%)
37 AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
38 this parameter is relative to the audio file/stream type.
40 This function configures all the hardware required for the audio application (codec, I2C, I2S,
41 GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK.
42 if the returned value is different from 0 or the function is stuck then the communication with
43 the codec (try to un-plug the power or reset device in this case).
44 + OUTPUT_DEVICE_SPEAKER: only speaker will be set as output for the audio stream.
45 + OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
46 + OUTPUT_DEVICE_AUTO: Selection of output device is made through external switch (implemented
47 into the audio jack on the evaluation board). When the Headphone is connected it is used
48 as output. When the headphone is disconnected from the audio jack, the output is
49 automatically switched to Speaker.
50 + OUTPUT_DEVICE_BOTH: both Speaker and Headphone are used as outputs for the audio stream
53 - Call the function EVAL_AUDIO_Play(
54 pBuffer: pointer to the audio data file address
55 Size: size of the buffer to be sent in Bytes
57 to start playing (for the first time) from the audio file/stream.
59 - Call the function EVAL_AUDIO_PauseResume(
60 Cmd: AUDIO_PAUSE (or 0) to pause playing or AUDIO_RESUME (or
61 any value different from 0) to resume playing.
63 Note. After calling EVAL_AUDIO_PauseResume() function for pause, only EVAL_AUDIO_PauseResume() should be called
64 for resume (it is not allowed to call EVAL_AUDIO_Play() in this case).
65 Note. This function should be called only when the audio file is played or paused (not stopped).
67 - For each mode, you may need to implement the relative callback functions into your code.
68 The Callback functions are named EVAL_AUDIO_XXX_CallBack() and only their prototypes are declared in
69 the stm32f4_discovery_audio_codec.h file. (refer to the example for more details on the callbacks implementations)
71 - To Stop playing, to modify the volume level or to mute, use the functions
72 EVAL_AUDIO_Stop(), EVAL_AUDIO_VolumeCtl() and EVAL_AUDIO_Mute().
74 - The driver API and the callback functions are at the end of the stm32f4_discovery_audio_codec.h file.
79 This driver is composed of three main layers:
80 o High Audio Layer: consists of the function API exported in the stm32f4_discovery_audio_codec.h file
81 (EVAL_AUDIO_Init(), EVAL_AUDIO_Play() ...)
82 o Codec Control layer: consists of the functions API controlling the audio codec (CS43L22) and
83 included as local functions in file stm32f4_discovery_audio_codec.c (Codec_Init(), Codec_Play() ...)
84 o Media Access Layer (MAL): which consists of functions allowing to access the media containing/
85 providing the audio file/stream. These functions are also included as local functions into
86 the stm32f4_discovery_audio_codec.c file (Audio_MAL_Init(), Audio_MAL_Play() ...)
87 Each set of functions (layer) may be implemented independently of the others and customized when
92 + AUDIO_MAL_MODE_NORMAL : is suitable when the audio file is in a memory location.
93 + AUDIO_MAL_MODE_CIRCULAR: is suitable when the audio data are read either from a
94 memory location or from a device at real time (double buffer could be used).
96 3. DMA interrupts description:
97 ------------------------------
98 + EVAL_AUDIO_IT_TC_ENABLE: Enable this define to use the DMA end of transfer interrupt.
99 then, a callback should be implemented by user to perform specific actions
100 when the DMA has finished the transfer.
101 + EVAL_AUDIO_IT_HT_ENABLE: Enable this define to use the DMA end of half transfer interrupt.
102 then, a callback should be implemented by user to perform specific actions
103 when the DMA has reached the half of the buffer transfer (generally, it is useful
104 to load the first half of buffer while DMA is loading from the second half).
105 + EVAL_AUDIO_IT_ER_ENABLE: Enable this define to manage the cases of error on DMA transfer.
107 4. Known Limitations:
108 ---------------------
109 1- When using the Speaker, if the audio file quality is not high enough, the speaker output
110 may produce high and uncomfortable noise level. To avoid this issue, to use speaker
111 output properly, try to increase audio file sampling rate (typically higher than 48KHz).
112 This operation will lead to larger file size.
113 2- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some
114 user interrupt routines (in this case, interrupts could be disabled just before the start of
115 communication then re-enabled when it is over). Note that this communication is only done at
116 the configuration phase (EVAL_AUDIO_Init() or EVAL_AUDIO_Stop()) and when Volume control modification is
117 performed (EVAL_AUDIO_VolumeCtl() or EVAL_AUDIO_Mute()). When the audio data is played, no communication is
118 required with the audio codec.
119 3- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size,
120 File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
121 4- Mono audio streaming is not supported (in order to play mono audio streams, each data should be sent twice
122 on the I2S or should be duplicated on the source buffer. Or convert the stream in stereo before playing).
123 5- Supports only 16-bit audio data size.
124 ===============================================================================================================================*/
127 /* Includes ------------------------------------------------------------------*/
128 #include "stm32f4_discovery_audio_codec.h"
129 //ADDED BY ME!!!!!!!!!!!!!!!!!!!!
130 #include "stm32f4xx_conf.h"
132 /** @addtogroup Utilities
136 /** @addtogroup STM32F4_DISCOVERY
140 /** @addtogroup STM32F4_DISCOVERY_AUDIO_CODEC
141 * @brief This file includes the low layer driver for CS43L22 Audio Codec
142 * available on STM32F4-Discovery Kit.
146 /** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Types
153 /** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Defines
157 /* Mask for the bit EN of the I2S CFGR register */
158 #define I2S_ENABLE_MASK 0x0400
160 /* Delay for the Codec to be correctly reset */
161 #define CODEC_RESET_DELAY 0x4FFF
163 /* Codec audio Standards */
164 #ifdef I2S_STANDARD_PHILLIPS
165 #define CODEC_STANDARD 0x04
166 #define I2S_STANDARD I2S_Standard_Phillips
167 #elif defined(I2S_STANDARD_MSB)
168 #define CODEC_STANDARD 0x00
169 #define I2S_STANDARD I2S_Standard_MSB
170 #elif defined(I2S_STANDARD_LSB)
171 #define CODEC_STANDARD 0x08
172 #define I2S_STANDARD I2S_Standard_LSB
174 #error "Error: No audio communication standard selected !"
175 #endif /* I2S_STANDARD */
177 /* The 7 bits Codec address (sent through I2C interface) */
178 #define CODEC_ADDRESS 0x94 /* b00100111 */
183 /** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Macros
190 /** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Variables
193 /* This structure is declared global because it is handled by two different functions */
194 static DMA_InitTypeDef DMA_InitStructure;
195 DMA_InitTypeDef AUDIO_MAL_DMA_InitStructure;
197 uint32_t AudioTotalSize = 0xFFFF; /* This variable holds the total size of the audio file */
198 uint32_t AudioRemSize = 0xFFFF; /* This variable holds the remaining data in audio file */
199 uint16_t *CurrentPos; /* This variable holds the current position of audio pointer */
201 __IO uint32_t CODECTimeout = CODEC_LONG_TIMEOUT;
202 __IO uint8_t OutputDev = 0;
205 __IO uint32_t CurrAudioInterface = AUDIO_INTERFACE_I2S; //AUDIO_INTERFACE_DAC
210 /** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Function_Prototypes
217 /** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Functions
220 static void Audio_MAL_IRQHandler(void);
221 /*-----------------------------------
222 Audio Codec functions
223 ------------------------------------------*/
224 /* High Layer codec functions */
225 static uint32_t Codec_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq);
226 static uint32_t Codec_DeInit(void);
227 static uint32_t Codec_Play(void);
228 static uint32_t Codec_PauseResume(uint32_t Cmd);
229 static uint32_t Codec_Stop(uint32_t Cmd);
230 static uint32_t Codec_VolumeCtrl(uint8_t Volume);
231 static uint32_t Codec_Mute(uint32_t Cmd);
232 /* Low layer codec functions */
233 static void Codec_CtrlInterface_Init(void);
234 static void Codec_CtrlInterface_DeInit(void);
235 static void Codec_AudioInterface_Init(uint32_t AudioFreq);
236 static void Codec_AudioInterface_DeInit(void);
237 static void Codec_Reset(void);
238 static uint32_t Codec_WriteRegister(uint8_t RegisterAddr, uint8_t RegisterValue);
239 static uint32_t Codec_ReadRegister(uint8_t RegisterAddr);
240 static void Codec_GPIO_Init(void);
241 static void Codec_GPIO_DeInit(void);
242 static void Delay(__IO uint32_t nCount);
243 /*----------------------------------------------------------------------------*/
245 /*-----------------------------------
246 MAL (Media Access Layer) functions
247 ------------------------------------------*/
248 /* Peripherals configuration functions */
249 static void Audio_MAL_Init(void);
250 static void Audio_MAL_DeInit(void);
251 static void Audio_MAL_Play(uint32_t Addr, uint32_t Size);
252 static void Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr);
253 static void Audio_MAL_Stop(void);
254 /*----------------------------------------------------------------------------*/
256 /* DMA Stream definitions */
257 uint32_t AUDIO_MAL_DMA_CLOCK = AUDIO_I2S_DMA_CLOCK;
258 DMA_Stream_TypeDef * AUDIO_MAL_DMA_STREAM = AUDIO_I2S_DMA_STREAM ;
259 uint32_t AUDIO_MAL_DMA_DREG = AUDIO_I2S_DMA_DREG;
260 uint32_t AUDIO_MAL_DMA_CHANNEL = AUDIO_I2S_DMA_CHANNEL;
261 uint32_t AUDIO_MAL_DMA_IRQ = AUDIO_I2S_DMA_IRQ ;
262 uint32_t AUDIO_MAL_DMA_FLAG_TC = AUDIO_I2S_DMA_FLAG_TC;
263 uint32_t AUDIO_MAL_DMA_FLAG_HT = AUDIO_I2S_DMA_FLAG_HT;
264 uint32_t AUDIO_MAL_DMA_FLAG_FE = AUDIO_I2S_DMA_FLAG_FE;
265 uint32_t AUDIO_MAL_DMA_FLAG_TE = AUDIO_I2S_DMA_FLAG_TE;
266 uint32_t AUDIO_MAL_DMA_FLAG_DME = AUDIO_I2S_DMA_FLAG_DME;
269 * @brief Set the current audio interface (I2S or DAC).
270 * @param Interface: AUDIO_INTERFACE_I2S or AUDIO_INTERFACE_DAC
273 void EVAL_AUDIO_SetAudioInterface(uint32_t Interface)
275 CurrAudioInterface = Interface;
277 if (CurrAudioInterface == AUDIO_INTERFACE_I2S)
279 /* DMA Stream definitions */
280 AUDIO_MAL_DMA_CLOCK = AUDIO_I2S_DMA_CLOCK;
281 AUDIO_MAL_DMA_STREAM = AUDIO_I2S_DMA_STREAM;
282 AUDIO_MAL_DMA_DREG = AUDIO_I2S_DMA_DREG;
283 AUDIO_MAL_DMA_CHANNEL = AUDIO_I2S_DMA_CHANNEL;
284 AUDIO_MAL_DMA_IRQ = AUDIO_I2S_DMA_IRQ ;
285 AUDIO_MAL_DMA_FLAG_TC = AUDIO_I2S_DMA_FLAG_TC;
286 AUDIO_MAL_DMA_FLAG_HT = AUDIO_I2S_DMA_FLAG_HT;
287 AUDIO_MAL_DMA_FLAG_FE = AUDIO_I2S_DMA_FLAG_FE;
288 AUDIO_MAL_DMA_FLAG_TE = AUDIO_I2S_DMA_FLAG_TE;
289 AUDIO_MAL_DMA_FLAG_DME = AUDIO_I2S_DMA_FLAG_DME;
291 else if (Interface == AUDIO_INTERFACE_DAC)
293 /* DMA Stream definitions */
294 AUDIO_MAL_DMA_CLOCK = AUDIO_DAC_DMA_CLOCK;
295 AUDIO_MAL_DMA_STREAM = AUDIO_DAC_DMA_STREAM;
296 AUDIO_MAL_DMA_DREG = AUDIO_DAC_DMA_DREG;
297 AUDIO_MAL_DMA_CHANNEL = AUDIO_DAC_DMA_CHANNEL;
298 AUDIO_MAL_DMA_IRQ = AUDIO_DAC_DMA_IRQ ;
299 AUDIO_MAL_DMA_FLAG_TC = AUDIO_DAC_DMA_FLAG_TC;
300 AUDIO_MAL_DMA_FLAG_HT = AUDIO_DAC_DMA_FLAG_HT;
301 AUDIO_MAL_DMA_FLAG_FE = AUDIO_DAC_DMA_FLAG_FE;
302 AUDIO_MAL_DMA_FLAG_TE = AUDIO_DAC_DMA_FLAG_TE;
303 AUDIO_MAL_DMA_FLAG_DME = AUDIO_DAC_DMA_FLAG_DME;
308 * @brief Configure the audio peripherals.
309 * @param OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
310 * OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO .
311 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max))
312 * @param AudioFreq: Audio frequency used to play the audio stream.
313 * @retval 0 if correct communication, else wrong communication
315 uint32_t EVAL_AUDIO_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
317 /* Perform low layer Codec initialization */
318 if (Codec_Init(OutputDevice, VOLUME_CONVERT(Volume), AudioFreq) != 0)
324 /* I2S data transfer preparation:
325 Prepare the Media to be used for the audio transfer from memory to I2S peripheral */
328 /* Return 0 when all operations are OK */
334 * @brief Deinitializes all the resources used by the codec (those initialized
335 * by EVAL_AUDIO_Init() function).
337 * @retval 0 if correct communication, else wrong communication
339 uint32_t EVAL_AUDIO_DeInit(void)
341 /* DeInitialize the Media layer */
344 /* DeInitialize Codec */
351 * @brief Starts playing audio stream from a data buffer for a determined size.
352 * @param pBuffer: Pointer to the buffer
353 * @param Size: Number of audio data BYTES.
354 * @retval 0 if correct communication, else wrong communication
356 uint32_t EVAL_AUDIO_Play(uint16_t* pBuffer, uint32_t Size)
358 /* Set the total number of data to be played (count in half-word) */
359 AudioTotalSize = Size/2;
361 /* Call the audio Codec Play function */
364 /* Update the Media layer and enable it for play */
365 Audio_MAL_Play((uint32_t)pBuffer, (uint32_t)(DMA_MAX(AudioTotalSize / 2)));
367 /* Update the remaining number of data to be played */
368 AudioRemSize = (Size/2) - DMA_MAX(AudioTotalSize);
370 /* Update the current audio pointer position */
371 CurrentPos = pBuffer + DMA_MAX(AudioTotalSize);
377 * @brief This function Pauses or Resumes the audio file stream. In case
378 * of using DMA, the DMA Pause feature is used. In all cases the I2S
379 * peripheral is disabled.
381 * @WARNING When calling EVAL_AUDIO_PauseResume() function for pause, only
382 * this function should be called for resume (use of EVAL_AUDIO_Play()
383 * function for resume could lead to unexpected behavior).
385 * @param Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different
387 * @retval 0 if correct communication, else wrong communication
389 uint32_t EVAL_AUDIO_PauseResume(uint32_t Cmd)
391 /* Call the Audio Codec Pause/Resume function */
392 if (Codec_PauseResume(Cmd) != 0)
398 /* Call the Media layer pause/resume function */
399 Audio_MAL_PauseResume(Cmd, 0);
401 /* Return 0 if all operations are OK */
407 * @brief Stops audio playing and Power down the Audio Codec.
408 * @param Option: could be one of the following parameters
409 * - CODEC_PDWN_SW: for software power off (by writing registers).
410 * Then no need to reconfigure the Codec after power on.
411 * - CODEC_PDWN_HW: completely shut down the codec (physically).
412 * Then need to reconfigure the Codec after power on.
413 * @retval 0 if correct communication, else wrong communication
415 uint32_t EVAL_AUDIO_Stop(uint32_t Option)
417 /* Call Audio Codec Stop function */
418 if (Codec_Stop(Option) != 0)
424 /* Call Media layer Stop function */
427 /* Update the remaining data number */
428 AudioRemSize = AudioTotalSize;
430 /* Return 0 when all operations are correctly done */
436 * @brief Controls the current audio volume level.
437 * @param Volume: Volume level to be set in percentage from 0% to 100% (0 for
438 * Mute and 100 for Max volume level).
439 * @retval 0 if correct communication, else wrong communication
441 uint32_t EVAL_AUDIO_VolumeCtl(uint8_t Volume)
443 /* Call the codec volume control function with converted volume value */
444 return (Codec_VolumeCtrl(VOLUME_CONVERT(Volume)));
448 * @brief Enables or disables the MUTE mode by software
449 * @param Command: could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to
450 * unmute the codec and restore previous volume level.
451 * @retval 0 if correct communication, else wrong communication
453 uint32_t EVAL_AUDIO_Mute(uint32_t Cmd)
455 /* Call the Codec Mute function */
456 return (Codec_Mute(Cmd));
460 * @brief This function handles main Media layer interrupt.
462 * @retval 0 if correct communication, else wrong communication
464 static void Audio_MAL_IRQHandler(void)
466 #ifndef AUDIO_MAL_MODE_NORMAL
467 uint16_t *pAddr = (uint16_t *)CurrentPos;
468 uint32_t Size = AudioRemSize;
469 #endif /* AUDIO_MAL_MODE_NORMAL */
471 #ifdef AUDIO_MAL_DMA_IT_TC_EN
472 /* Transfer complete interrupt */
473 if (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC) != RESET)
475 #ifdef AUDIO_MAL_MODE_NORMAL
476 /* Check if the end of file has been reached */
477 if (AudioRemSize > 0)
479 /* Wait the DMA Stream to be effectively disabled */
480 while (DMA_GetCmdStatus(AUDIO_MAL_DMA_STREAM) != DISABLE)
483 /* Clear the Interrupt flag */
484 DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC);
486 /* Re-Configure the buffer address and size */
487 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) CurrentPos;
488 DMA_InitStructure.DMA_BufferSize = (uint32_t) (DMA_MAX(AudioRemSize));
490 /* Configure the DMA Stream with the new parameters */
491 DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
493 /* Enable the I2S DMA Stream*/
494 DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);
496 /* Update the current pointer position */
497 CurrentPos += DMA_MAX(AudioRemSize);
499 /* Update the remaining number of data to be played */
500 AudioRemSize -= DMA_MAX(AudioRemSize);
504 /* Disable the I2S DMA Stream*/
505 DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
507 /* Clear the Interrupt flag */
508 DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC);
510 /* Manage the remaining file size and new address offset: This function
511 should be coded by user (its prototype is already declared in stm32f4_discovery_audio_codec.h) */
512 EVAL_AUDIO_TransferComplete_CallBack((uint32_t)CurrentPos, 0);
515 #elif defined(AUDIO_MAL_MODE_CIRCULAR)
516 /* Manage the remaining file size and new address offset: This function
517 should be coded by user (its prototype is already declared in stm32f4_discovery_audio_codec.h) */
518 EVAL_AUDIO_TransferComplete_CallBack(pAddr, Size);
520 /* Clear the Interrupt flag */
521 DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC);
522 #endif /* AUDIO_MAL_MODE_NORMAL */
524 #endif /* AUDIO_MAL_DMA_IT_TC_EN */
526 #ifdef AUDIO_MAL_DMA_IT_HT_EN
527 /* Half Transfer complete interrupt */
528 if (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_HT) != RESET)
530 /* Manage the remaining file size and new address offset: This function
531 should be coded by user (its prototype is already declared in stm32f4_discovery_audio_codec.h) */
532 EVAL_AUDIO_HalfTransfer_CallBack((uint32_t)pAddr, Size);
534 /* Clear the Interrupt flag */
535 DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_HT);
537 #endif /* AUDIO_MAL_DMA_IT_HT_EN */
539 #ifdef AUDIO_MAL_DMA_IT_TE_EN
540 /* FIFO Error interrupt */
541 if ((DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TE) != RESET) || \
542 (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_FE) != RESET) || \
543 (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_DME) != RESET))
546 /* Manage the error generated on DMA FIFO: This function
547 should be coded by user (its prototype is already declared in stm32f4_discovery_audio_codec.h) */
548 EVAL_AUDIO_Error_CallBack((uint32_t*)&pAddr);
550 /* Clear the Interrupt flag */
551 DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TE | AUDIO_MAL_DMA_FLAG_FE | \
552 AUDIO_MAL_DMA_FLAG_DME);
554 #endif /* AUDIO_MAL_DMA_IT_TE_EN */
558 * @brief This function handles main I2S interrupt.
560 * @retval 0 if correct communication, else wrong communication
562 void Audio_MAL_I2S_IRQHandler(void)
564 Audio_MAL_IRQHandler();
568 * @brief This function handles main DAC interrupt.
570 * @retval 0 if correct communication, else wrong communication
572 void Audio_MAL_DAC_IRQHandler(void)
574 Audio_MAL_IRQHandler();
578 * @brief I2S interrupt management
582 void Audio_I2S_IRQHandler(void)
584 /* Check on the I2S TXE flag */
585 if (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) != RESET)
587 if (CurrAudioInterface == AUDIO_INTERFACE_DAC)
589 /* Wirte data to the DAC interface */
590 DAC_SetChannel1Data(DAC_Align_12b_L, EVAL_AUDIO_GetSampleCallBack());
593 /* Send dummy data on I2S to avoid the underrun condition */
594 SPI_I2S_SendData(CODEC_I2S, EVAL_AUDIO_GetSampleCallBack());
597 /*========================
599 CS43L22 Audio Codec Control Functions
600 ==============================*/
602 * @brief Initializes the audio codec and all related interfaces (control
603 * interface: I2C and audio interface: I2S)
604 * @param OutputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
605 * OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO .
606 * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max))
607 * @param AudioFreq: Audio frequency used to play the audio stream.
608 * @retval 0 if correct communication, else wrong communication
610 static uint32_t Codec_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
612 uint32_t counter = 0;
614 /* Configure the Codec related IOs */
617 /* Reset the Codec Registers */
620 /* Initialize the Control interface of the Audio Codec */
621 Codec_CtrlInterface_Init();
623 /* Keep Codec powered OFF */
624 counter += Codec_WriteRegister(0x02, 0x01);
626 counter += Codec_WriteRegister(0x04, 0xAF); /* SPK always OFF & HP always ON */
629 /* Clock configuration: Auto detection */
630 counter += Codec_WriteRegister(0x05, 0x81);
632 /* Set the Slave Mode and the audio Standard */
633 counter += Codec_WriteRegister(0x06, CODEC_STANDARD);
635 /* Set the Master volume */
636 Codec_VolumeCtrl(Volume);
638 if (CurrAudioInterface == AUDIO_INTERFACE_DAC)
640 /* Enable the PassThrough on AIN1A and AIN1B */
641 counter += Codec_WriteRegister(0x08, 0x01);
642 counter += Codec_WriteRegister(0x09, 0x01);
644 /* Route the analog input to the HP line */
645 counter += Codec_WriteRegister(0x0E, 0xC0);
647 /* Set the Passthough volume */
648 counter += Codec_WriteRegister(0x14, 0x00);
649 counter += Codec_WriteRegister(0x15, 0x00);
652 /* Power on the Codec */
653 counter += Codec_WriteRegister(0x02, 0x9E);
655 /* Additional configuration for the CODEC. These configurations are done to reduce
656 the time needed for the Codec to power off. If these configurations are removed,
657 then a long delay should be added between powering off the Codec and switching
658 off the I2S peripheral MCLK clock (which is the operating clock for Codec).
659 If this delay is not inserted, then the codec will not shut down properly and
660 it results in high noise after shut down. */
662 /* Disable the analog soft ramp */
663 counter += Codec_WriteRegister(0x0A, 0x00);
664 if (CurrAudioInterface != AUDIO_INTERFACE_DAC)
666 /* Disable the digital soft ramp */
667 counter += Codec_WriteRegister(0x0E, 0x04);
669 /* Disable the limiter attack level */
670 counter += Codec_WriteRegister(0x27, 0x00);
671 /* Adjust Bass and Treble levels */
672 counter += Codec_WriteRegister(0x1F, 0x0F);
673 /* Adjust PCM volume level */
674 counter += Codec_WriteRegister(0x1A, 0x0A);
675 counter += Codec_WriteRegister(0x1B, 0x0A);
677 /* Configure the I2S peripheral */
678 Codec_AudioInterface_Init(AudioFreq);
680 /* Return communication control value */
685 * @brief Restore the audio codec state to default state and free all used
688 * @retval 0 if correct communication, else wrong communication
690 static uint32_t Codec_DeInit(void)
692 uint32_t counter = 0;
694 /* Reset the Codec Registers */
697 /* Keep Codec powered OFF */
698 counter += Codec_WriteRegister(0x02, 0x01);
700 /* Deinitialize all use GPIOs */
703 /* Disable the Codec control interface */
704 Codec_CtrlInterface_DeInit();
706 /* Deinitialize the Codec audio interface (I2S) */
707 Codec_AudioInterface_DeInit();
709 /* Return communication control value */
714 * @brief Start the audio Codec play feature.
715 * @note For this codec no Play options are required.
717 * @retval 0 if correct communication, else wrong communication
719 static uint32_t Codec_Play(void)
722 No actions required on Codec level for play command
725 /* Return communication control value */
730 * @brief Pauses and resumes playing on the audio codec.
731 * @param Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different
733 * @retval 0 if correct communication, else wrong communication
735 static uint32_t Codec_PauseResume(uint32_t Cmd)
737 uint32_t counter = 0;
739 /* Pause the audio file playing */
740 if (Cmd == AUDIO_PAUSE)
742 /* Mute the output first */
743 counter += Codec_Mute(AUDIO_MUTE_ON);
745 /* Put the Codec in Power save mode */
746 counter += Codec_WriteRegister(0x02, 0x01);
748 else /* AUDIO_RESUME */
750 /* Unmute the output first */
751 counter += Codec_Mute(AUDIO_MUTE_OFF);
753 counter += Codec_WriteRegister(0x04, OutputDev);
755 /* Exit the Power save mode */
756 counter += Codec_WriteRegister(0x02, 0x9E);
763 * @brief Stops audio Codec playing. It powers down the codec.
764 * @param CodecPdwnMode: selects the power down mode.
765 * - CODEC_PDWN_SW: only mutes the audio codec. When resuming from this
766 * mode the codec keeps the previous initialization
767 * (no need to re-Initialize the codec registers).
768 * - CODEC_PDWN_HW: Physically power down the codec. When resuming from this
769 * mode, the codec is set to default configuration
770 * (user should re-Initialize the codec in order to
771 * play again the audio stream).
772 * @retval 0 if correct communication, else wrong communication
774 static uint32_t Codec_Stop(uint32_t CodecPdwnMode)
776 uint32_t counter = 0;
778 /* Mute the output first */
779 Codec_Mute(AUDIO_MUTE_ON);
781 if (CodecPdwnMode == CODEC_PDWN_SW)
783 /* Power down the DAC and the speaker (PMDAC and PMSPK bits)*/
784 counter += Codec_WriteRegister(0x02, 0x9F);
786 else /* CODEC_PDWN_HW */
788 /* Power down the DAC components */
789 counter += Codec_WriteRegister(0x02, 0x9F);
791 /* Wait at least 100us */
795 GPIO_WriteBit(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, Bit_RESET);
802 * @brief Sets higher or lower the codec volume level.
803 * @param Volume: a byte value from 0 to 255 (refer to codec registers
804 * description for more details).
805 * @retval 0 if correct communication, else wrong communication
807 static uint32_t Codec_VolumeCtrl(uint8_t Volume)
809 uint32_t counter = 0;
813 /* Set the Master volume */
814 counter += Codec_WriteRegister(0x20, Volume - 0xE7);
815 counter += Codec_WriteRegister(0x21, Volume - 0xE7);
819 /* Set the Master volume */
820 counter += Codec_WriteRegister(0x20, Volume + 0x19);
821 counter += Codec_WriteRegister(0x21, Volume + 0x19);
828 * @brief Enables or disables the mute feature on the audio codec.
829 * @param Cmd: AUDIO_MUTE_ON to enable the mute or AUDIO_MUTE_OFF to disable the
831 * @retval 0 if correct communication, else wrong communication
833 static uint32_t Codec_Mute(uint32_t Cmd)
835 uint32_t counter = 0;
837 /* Set the Mute mode */
838 if (Cmd == AUDIO_MUTE_ON)
840 counter += Codec_WriteRegister(0x04, 0xFF);
842 else /* AUDIO_MUTE_OFF Disable the Mute */
844 counter += Codec_WriteRegister(0x04, OutputDev);
851 * @brief Resets the audio codec. It restores the default configuration of the
852 * codec (this function shall be called before initializing the codec).
853 * @note This function calls an external driver function: The IO Expander driver.
857 static void Codec_Reset(void)
859 /* Power Down the codec */
860 GPIO_WriteBit(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, Bit_RESET);
862 /* wait for a delay to insure registers erasing */
863 Delay(CODEC_RESET_DELAY);
865 /* Power on the codec */
866 GPIO_WriteBit(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, Bit_SET);
870 * @brief Writes a Byte to a given register into the audio codec through the
871 control interface (I2C)
872 * @param RegisterAddr: The address (location) of the register to be written.
873 * @param RegisterValue: the Byte value to be written into destination register.
874 * @retval 0 if correct communication, else wrong communication
876 static uint32_t Codec_WriteRegister(uint8_t RegisterAddr, uint8_t RegisterValue)
880 /*!< While the bus is busy */
881 CODECTimeout = CODEC_LONG_TIMEOUT;
882 while(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BUSY))
884 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
887 /* Start the config sequence */
888 I2C_GenerateSTART(CODEC_I2C, ENABLE);
890 /* Test on EV5 and clear it */
891 CODECTimeout = CODEC_FLAG_TIMEOUT;
892 while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_MODE_SELECT))
894 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
897 /* Transmit the slave address and enable writing operation */
898 I2C_Send7bitAddress(CODEC_I2C, CODEC_ADDRESS, I2C_Direction_Transmitter);
900 /* Test on EV6 and clear it */
901 CODECTimeout = CODEC_FLAG_TIMEOUT;
902 while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
904 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
907 /* Transmit the first address for write operation */
908 I2C_SendData(CODEC_I2C, RegisterAddr);
910 /* Test on EV8 and clear it */
911 CODECTimeout = CODEC_FLAG_TIMEOUT;
912 while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING))
914 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
917 /* Prepare the register value to be sent */
918 I2C_SendData(CODEC_I2C, RegisterValue);
920 /*!< Wait till all data have been physically transferred on the bus */
921 CODECTimeout = CODEC_LONG_TIMEOUT;
922 while(!I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BTF))
924 if((CODECTimeout--) == 0) Codec_TIMEOUT_UserCallback();
927 /* End the configuration sequence */
928 I2C_GenerateSTOP(CODEC_I2C, ENABLE);
930 #ifdef VERIFY_WRITTENDATA
931 /* Verify that the data has been correctly written */
932 result = (Codec_ReadRegister(RegisterAddr) == RegisterValue)? 0:1;
933 #endif /* VERIFY_WRITTENDATA */
935 /* Return the verifying value: 0 (Passed) or 1 (Failed) */
940 * @brief Reads and returns the value of an audio codec register through the
941 * control interface (I2C).
942 * @param RegisterAddr: Address of the register to be read.
943 * @retval Value of the register to be read or dummy value if the communication
946 static uint32_t Codec_ReadRegister(uint8_t RegisterAddr)
950 /*!< While the bus is busy */
951 CODECTimeout = CODEC_LONG_TIMEOUT;
952 while(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BUSY))
954 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
957 /* Start the config sequence */
958 I2C_GenerateSTART(CODEC_I2C, ENABLE);
960 /* Test on EV5 and clear it */
961 CODECTimeout = CODEC_FLAG_TIMEOUT;
962 while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_MODE_SELECT))
964 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
967 /* Transmit the slave address and enable writing operation */
968 I2C_Send7bitAddress(CODEC_I2C, CODEC_ADDRESS, I2C_Direction_Transmitter);
970 /* Test on EV6 and clear it */
971 CODECTimeout = CODEC_FLAG_TIMEOUT;
972 while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
974 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
977 /* Transmit the register address to be read */
978 I2C_SendData(CODEC_I2C, RegisterAddr);
980 /* Test on EV8 and clear it */
981 CODECTimeout = CODEC_FLAG_TIMEOUT;
982 while (I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BTF) == RESET)
984 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
987 /*!< Send START condition a second time */
988 I2C_GenerateSTART(CODEC_I2C, ENABLE);
990 /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
991 CODECTimeout = CODEC_FLAG_TIMEOUT;
992 while(!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_MODE_SELECT))
994 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
997 /*!< Send Codec address for read */
998 I2C_Send7bitAddress(CODEC_I2C, CODEC_ADDRESS, I2C_Direction_Receiver);
1000 /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
1001 CODECTimeout = CODEC_FLAG_TIMEOUT;
1002 while(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_ADDR) == RESET)
1004 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
1007 /*!< Disable Acknowledgment */
1008 I2C_AcknowledgeConfig(CODEC_I2C, DISABLE);
1010 /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
1011 (void)CODEC_I2C->SR2;
1013 /*!< Send STOP Condition */
1014 I2C_GenerateSTOP(CODEC_I2C, ENABLE);
1016 /* Wait for the byte to be received */
1017 CODECTimeout = CODEC_FLAG_TIMEOUT;
1018 while(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_RXNE) == RESET)
1020 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
1023 /*!< Read the byte received from the Codec */
1024 result = I2C_ReceiveData(CODEC_I2C);
1026 /* Wait to make sure that STOP flag has been cleared */
1027 CODECTimeout = CODEC_FLAG_TIMEOUT;
1028 while(CODEC_I2C->CR1 & I2C_CR1_STOP)
1030 if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
1033 /*!< Re-Enable Acknowledgment to be ready for another reception */
1034 I2C_AcknowledgeConfig(CODEC_I2C, ENABLE);
1036 /* Clear AF flag for next communication */
1037 I2C_ClearFlag(CODEC_I2C, I2C_FLAG_AF);
1039 /* Return the byte read from Codec */
1044 * @brief Initializes the Audio Codec control interface (I2C).
1048 static void Codec_CtrlInterface_Init(void)
1050 I2C_InitTypeDef I2C_InitStructure;
1052 /* Enable the CODEC_I2C peripheral clock */
1053 RCC_APB1PeriphClockCmd(CODEC_I2C_CLK, ENABLE);
1055 /* CODEC_I2C peripheral configuration */
1056 I2C_DeInit(CODEC_I2C);
1057 I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
1058 I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
1059 I2C_InitStructure.I2C_OwnAddress1 = 0x33;
1060 I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
1061 I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
1062 I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
1063 /* Enable the I2C peripheral */
1064 I2C_Cmd(CODEC_I2C, ENABLE);
1065 I2C_Init(CODEC_I2C, &I2C_InitStructure);
1069 * @brief Restore the Audio Codec control interface to its default state.
1070 * This function doesn't de-initialize the I2C because the I2C peripheral
1071 * may be used by other modules.
1075 static void Codec_CtrlInterface_DeInit(void)
1077 /* Disable the I2C peripheral */ /* This step is not done here because
1078 the I2C interface can be used by other modules */
1079 /* I2C_DeInit(CODEC_I2C); */
1083 * @brief Initializes the Audio Codec audio interface (I2S)
1084 * @note This function assumes that the I2S input clock (through PLL_R in
1085 * Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y)
1086 * is already configured and ready to be used.
1087 * @param AudioFreq: Audio frequency to be configured for the I2S peripheral.
1090 static void Codec_AudioInterface_Init(uint32_t AudioFreq)
1092 I2S_InitTypeDef I2S_InitStructure;
1093 DAC_InitTypeDef DAC_InitStructure;
1095 /* Enable the CODEC_I2S peripheral clock */
1096 RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE);
1098 /* CODEC_I2S peripheral configuration */
1099 SPI_I2S_DeInit(CODEC_I2S);
1100 I2S_InitStructure.I2S_AudioFreq = AudioFreq;
1101 I2S_InitStructure.I2S_Standard = I2S_STANDARD;
1102 I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
1103 I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
1104 #ifdef DAC_USE_I2S_DMA
1105 if (CurrAudioInterface == AUDIO_INTERFACE_DAC)
1107 I2S_InitStructure.I2S_Mode = I2S_Mode_MasterRx;
1112 I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
1114 #ifdef DAC_USE_I2S_DMA
1116 #endif /* DAC_USE_I2S_DMA */
1117 #ifdef CODEC_MCLK_ENABLED
1118 I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
1119 #elif defined(CODEC_MCLK_DISABLED)
1120 I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
1122 #error "No selection for the MCLK output has been defined !"
1123 #endif /* CODEC_MCLK_ENABLED */
1125 /* Initialize the I2S peripheral with the structure above */
1126 I2S_Init(CODEC_I2S, &I2S_InitStructure);
1129 /* Configure the DAC interface */
1130 if (CurrAudioInterface == AUDIO_INTERFACE_DAC)
1132 /* DAC Periph clock enable */
1133 RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
1135 /* DAC channel1 Configuration */
1136 DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
1137 DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
1138 DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
1139 DAC_Init(AUDIO_DAC_CHANNEL, &DAC_InitStructure);
1141 /* Enable DAC Channel1 */
1142 DAC_Cmd(AUDIO_DAC_CHANNEL, ENABLE);
1145 /* The I2S peripheral will be enabled only in the EVAL_AUDIO_Play() function
1146 or by user functions if DMA mode not enabled */
1150 * @brief Restores the Audio Codec audio interface to its default state.
1154 static void Codec_AudioInterface_DeInit(void)
1156 /* Disable the CODEC_I2S peripheral (in case it hasn't already been disabled) */
1157 I2S_Cmd(CODEC_I2S, DISABLE);
1159 /* Deinitialize the CODEC_I2S peripheral */
1160 SPI_I2S_DeInit(CODEC_I2S);
1162 /* Disable the CODEC_I2S peripheral clock */
1163 RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, DISABLE);
1167 * @brief Initializes IOs used by the Audio Codec (on the control and audio
1172 static void Codec_GPIO_Init(void)
1174 GPIO_InitTypeDef GPIO_InitStructure;
1176 /* Enable Reset GPIO Clock */
1177 RCC_AHB1PeriphClockCmd(AUDIO_RESET_GPIO_CLK,ENABLE);
1179 /* Audio reset pin configuration -------------------------------------------------*/
1180 GPIO_InitStructure.GPIO_Pin = AUDIO_RESET_PIN;
1181 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
1182 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
1183 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
1184 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
1185 GPIO_Init(AUDIO_RESET_GPIO, &GPIO_InitStructure);
1187 /* Enable I2S and I2C GPIO clocks */
1188 RCC_AHB1PeriphClockCmd(CODEC_I2C_GPIO_CLOCK | CODEC_I2S_GPIO_CLOCK, ENABLE);
1190 /* CODEC_I2C SCL and SDA pins configuration -------------------------------------*/
1191 GPIO_InitStructure.GPIO_Pin = CODEC_I2C_SCL_PIN | CODEC_I2C_SDA_PIN;
1192 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
1193 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
1194 GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
1195 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
1196 GPIO_Init(CODEC_I2C_GPIO, &GPIO_InitStructure);
1197 /* Connect pins to I2C peripheral */
1198 GPIO_PinAFConfig(CODEC_I2C_GPIO, CODEC_I2S_SCL_PINSRC, CODEC_I2C_GPIO_AF);
1199 GPIO_PinAFConfig(CODEC_I2C_GPIO, CODEC_I2S_SDA_PINSRC, CODEC_I2C_GPIO_AF);
1201 /* CODEC_I2S pins configuration: WS, SCK and SD pins -----------------------------*/
1202 GPIO_InitStructure.GPIO_Pin = CODEC_I2S_SCK_PIN | CODEC_I2S_SD_PIN;
1203 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
1204 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
1205 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
1206 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
1207 GPIO_Init(CODEC_I2S_GPIO, &GPIO_InitStructure);
1209 /* Connect pins to I2S peripheral */
1210 GPIO_PinAFConfig(CODEC_I2S_WS_GPIO, CODEC_I2S_WS_PINSRC, CODEC_I2S_GPIO_AF);
1211 GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SCK_PINSRC, CODEC_I2S_GPIO_AF);
1213 if (CurrAudioInterface != AUDIO_INTERFACE_DAC)
1215 GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN ;
1216 GPIO_Init(CODEC_I2S_WS_GPIO, &GPIO_InitStructure);
1217 GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SD_PINSRC, CODEC_I2S_GPIO_AF);
1221 /* GPIOA clock enable (to be used with DAC) */
1222 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
1224 /* DAC channel 1 & 2 (DAC_OUT1 = PA.4) configuration */
1225 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
1226 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
1227 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
1228 GPIO_Init(GPIOA, &GPIO_InitStructure);
1231 #ifdef CODEC_MCLK_ENABLED
1232 /* CODEC_I2S pins configuration: MCK pin */
1233 GPIO_InitStructure.GPIO_Pin = CODEC_I2S_MCK_PIN;
1234 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
1235 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
1236 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
1237 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
1238 GPIO_Init(CODEC_I2S_MCK_GPIO, &GPIO_InitStructure);
1239 /* Connect pins to I2S peripheral */
1240 GPIO_PinAFConfig(CODEC_I2S_MCK_GPIO, CODEC_I2S_MCK_PINSRC, CODEC_I2S_GPIO_AF);
1241 #endif /* CODEC_MCLK_ENABLED */
1245 * @brief Restores the IOs used by the Audio Codec interface to their default state.
1249 static void Codec_GPIO_DeInit(void)
1251 GPIO_InitTypeDef GPIO_InitStructure;
1253 /* Deinitialize all the GPIOs used by the driver */
1254 GPIO_InitStructure.GPIO_Pin = CODEC_I2S_SCK_PIN | CODEC_I2S_SD_PIN;
1255 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
1256 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
1257 GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
1258 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
1259 GPIO_Init(CODEC_I2S_GPIO, &GPIO_InitStructure);
1261 GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN ;
1262 GPIO_Init(CODEC_I2S_WS_GPIO, &GPIO_InitStructure);
1264 /* Disconnect pins from I2S peripheral */
1265 GPIO_PinAFConfig(CODEC_I2S_WS_GPIO, CODEC_I2S_WS_PINSRC, 0x00);
1266 GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SCK_PINSRC, 0x00);
1267 GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SD_PINSRC, 0x00);
1269 #ifdef CODEC_MCLK_ENABLED
1270 /* CODEC_I2S pins deinitialization: MCK pin */
1271 GPIO_InitStructure.GPIO_Pin = CODEC_I2S_MCK_PIN;
1272 GPIO_Init(CODEC_I2S_MCK_GPIO, &GPIO_InitStructure);
1273 /* Disconnect pins from I2S peripheral */
1274 GPIO_PinAFConfig(CODEC_I2S_MCK_GPIO, CODEC_I2S_MCK_PINSRC, CODEC_I2S_GPIO_AF);
1275 #endif /* CODEC_MCLK_ENABLED */
1279 * @brief Inserts a delay time (not accurate timing).
1280 * @param nCount: specifies the delay time length.
1283 static void Delay( __IO uint32_t nCount)
1285 for (; nCount != 0; nCount--);
1288 #ifdef USE_DEFAULT_TIMEOUT_CALLBACK
1290 * @brief Basic management of the timeout situation.
1294 uint32_t Codec_TIMEOUT_UserCallback(void)
1296 /* Block communication and all processes */
1301 #endif /* USE_DEFAULT_TIMEOUT_CALLBACK */
1302 /*========================
1304 Audio MAL Interface Control Functions
1306 ==============================*/
1309 * @brief Initializes and prepares the Media to perform audio data transfer
1310 * from Media to the I2S peripheral.
1314 static void Audio_MAL_Init(void)
1317 #ifdef I2S_INTERRUPT
1318 NVIC_InitTypeDef NVIC_InitStructure;
1320 NVIC_InitStructure.NVIC_IRQChannel = SPI3_IRQn;
1321 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
1322 NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;
1323 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
1324 NVIC_Init(&NVIC_InitStructure);
1326 SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, ENABLE);
1328 I2S_Cmd(SPI3, ENABLE);
1330 #if defined(AUDIO_MAL_DMA_IT_TC_EN) || defined(AUDIO_MAL_DMA_IT_HT_EN) || defined(AUDIO_MAL_DMA_IT_TE_EN)
1331 NVIC_InitTypeDef NVIC_InitStructure;
1334 if (CurrAudioInterface == AUDIO_INTERFACE_I2S)
1336 /* Enable the DMA clock */
1337 RCC_AHB1PeriphClockCmd(AUDIO_MAL_DMA_CLOCK, ENABLE);
1339 /* Configure the DMA Stream */
1340 DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
1341 DMA_DeInit(AUDIO_MAL_DMA_STREAM);
1342 /* Set the parameters to be configured */
1343 DMA_InitStructure.DMA_Channel = AUDIO_MAL_DMA_CHANNEL;
1344 DMA_InitStructure.DMA_PeripheralBaseAddr = AUDIO_MAL_DMA_DREG;
1345 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0; /* This field will be configured in play function */
1346 DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
1347 DMA_InitStructure.DMA_BufferSize = (uint32_t)0xFFFE; /* This field will be configured in play function */
1348 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
1349 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
1350 DMA_InitStructure.DMA_PeripheralDataSize = AUDIO_MAL_DMA_PERIPH_DATA_SIZE;
1351 DMA_InitStructure.DMA_MemoryDataSize = AUDIO_MAL_DMA_MEM_DATA_SIZE;
1352 #ifdef AUDIO_MAL_MODE_NORMAL
1353 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
1354 #elif defined(AUDIO_MAL_MODE_CIRCULAR)
1355 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
1357 #error "AUDIO_MAL_MODE_NORMAL or AUDIO_MAL_MODE_CIRCULAR should be selected !!"
1358 #endif /* AUDIO_MAL_MODE_NORMAL */
1359 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
1360 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
1361 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
1362 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
1363 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
1364 DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
1366 /* Enable the selected DMA interrupts (selected in "stm32f4_discovery_eval_audio_codec.h" defines) */
1367 #ifdef AUDIO_MAL_DMA_IT_TC_EN
1368 DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TC, ENABLE);
1369 #endif /* AUDIO_MAL_DMA_IT_TC_EN */
1370 #ifdef AUDIO_MAL_DMA_IT_HT_EN
1371 DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_HT, ENABLE);
1372 #endif /* AUDIO_MAL_DMA_IT_HT_EN */
1373 #ifdef AUDIO_MAL_DMA_IT_TE_EN
1374 DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TE | DMA_IT_FE | DMA_IT_DME, ENABLE);
1375 #endif /* AUDIO_MAL_DMA_IT_TE_EN */
1377 #if defined(AUDIO_MAL_DMA_IT_TC_EN) || defined(AUDIO_MAL_DMA_IT_HT_EN) || defined(AUDIO_MAL_DMA_IT_TE_EN)
1378 /* I2S DMA IRQ Channel configuration */
1379 NVIC_InitStructure.NVIC_IRQChannel = AUDIO_MAL_DMA_IRQ;
1380 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = EVAL_AUDIO_IRQ_PREPRIO;
1381 NVIC_InitStructure.NVIC_IRQChannelSubPriority = EVAL_AUDIO_IRQ_SUBRIO;
1382 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
1383 NVIC_Init(&NVIC_InitStructure);
1387 #ifdef DAC_USE_I2S_DMA
1390 /* Enable the DMA clock */
1391 RCC_AHB1PeriphClockCmd(AUDIO_MAL_DMA_CLOCK, ENABLE);
1393 /* Configure the DMA Stream */
1394 DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
1395 DMA_DeInit(AUDIO_MAL_DMA_STREAM);
1396 /* Set the parameters to be configured */
1397 DMA_InitStructure.DMA_Channel = AUDIO_MAL_DMA_CHANNEL;
1398 DMA_InitStructure.DMA_PeripheralBaseAddr = AUDIO_MAL_DMA_DREG;
1399 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0; /* This field will be configured in play function */
1400 DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
1401 DMA_InitStructure.DMA_BufferSize = (uint32_t)0xFFFE; /* This field will be configured in play function */
1402 DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
1403 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
1404 DMA_InitStructure.DMA_PeripheralDataSize = AUDIO_MAL_DMA_PERIPH_DATA_SIZE;
1405 DMA_InitStructure.DMA_MemoryDataSize = AUDIO_MAL_DMA_MEM_DATA_SIZE;
1406 #ifdef AUDIO_MAL_MODE_NORMAL
1407 DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
1408 #elif defined(AUDIO_MAL_MODE_CIRCULAR)
1409 DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
1411 #error "AUDIO_MAL_MODE_NORMAL or AUDIO_MAL_MODE_CIRCULAR should be selected !!"
1412 #endif /* AUDIO_MAL_MODE_NORMAL */
1413 DMA_InitStructure.DMA_Priority = DMA_Priority_High;
1414 DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
1415 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
1416 DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
1417 DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
1418 DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
1420 /* Enable the selected DMA interrupts (selected in "stm32f4_discovery_eval_audio_codec.h" defines) */
1421 #ifdef AUDIO_MAL_DMA_IT_TC_EN
1422 DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TC, ENABLE);
1423 #endif /* AUDIO_MAL_DMA_IT_TC_EN */
1424 #ifdef AUDIO_MAL_DMA_IT_HT_EN
1425 DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_HT, ENABLE);
1426 #endif /* AUDIO_MAL_DMA_IT_HT_EN */
1427 #ifdef AUDIO_MAL_DMA_IT_TE_EN
1428 DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TE | DMA_IT_FE | DMA_IT_DME, ENABLE);
1429 #endif /* AUDIO_MAL_DMA_IT_TE_EN */
1431 #if defined(AUDIO_MAL_DMA_IT_TC_EN) || defined(AUDIO_MAL_DMA_IT_HT_EN) || defined(AUDIO_MAL_DMA_IT_TE_EN)
1432 /* I2S DMA IRQ Channel configuration */
1433 NVIC_InitStructure.NVIC_IRQChannel = AUDIO_MAL_DMA_IRQ;
1434 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = EVAL_AUDIO_IRQ_PREPRIO;
1435 NVIC_InitStructure.NVIC_IRQChannelSubPriority = EVAL_AUDIO_IRQ_SUBRIO;
1436 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
1437 NVIC_Init(&NVIC_InitStructure);
1440 #endif /* DAC_USE_I2S_DMA */
1442 if (CurrAudioInterface == AUDIO_INTERFACE_I2S)
1444 /* Enable the I2S DMA request */
1445 SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, ENABLE);
1449 /* Configure the STM32 DAC to geenrate audio analog signal */
1452 #ifndef DAC_USE_I2S_DMA
1453 /* Enable the I2S interrupt used to write into the DAC register */
1454 SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, ENABLE);
1456 /* I2S DMA IRQ Channel configuration */
1457 NVIC_InitStructure.NVIC_IRQChannel = CODEC_I2S_IRQ;
1458 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = EVAL_AUDIO_IRQ_PREPRIO;
1459 NVIC_InitStructure.NVIC_IRQChannelSubPriority = EVAL_AUDIO_IRQ_SUBRIO;
1460 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
1461 NVIC_Init(&NVIC_InitStructure);
1463 /* Enable the I2S DMA request */
1464 SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Rx, ENABLE);
1465 #endif /* DAC_USE_I2S_DMA */
1471 * @brief Restore default state of the used Media.
1475 static void Audio_MAL_DeInit(void)
1477 #if defined(AUDIO_MAL_DMA_IT_TC_EN) || defined(AUDIO_MAL_DMA_IT_HT_EN) || defined(AUDIO_MAL_DMA_IT_TE_EN)
1478 NVIC_InitTypeDef NVIC_InitStructure;
1480 /* Deinitialize the NVIC interrupt for the I2S DMA Stream */
1481 NVIC_InitStructure.NVIC_IRQChannel = AUDIO_MAL_DMA_IRQ;
1482 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = EVAL_AUDIO_IRQ_PREPRIO;
1483 NVIC_InitStructure.NVIC_IRQChannelSubPriority = EVAL_AUDIO_IRQ_SUBRIO;
1484 NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
1485 NVIC_Init(&NVIC_InitStructure);
1488 /* Disable the DMA stream before the deinit */
1489 DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
1491 /* Dinitialize the DMA Stream */
1492 DMA_DeInit(AUDIO_MAL_DMA_STREAM);
1495 The DMA clock is not disabled, since it can be used by other streams
1500 * @brief Starts playing audio stream from the audio Media.
1504 static void Audio_MAL_Play(uint32_t Addr, uint32_t Size)
1506 if (CurrAudioInterface == AUDIO_INTERFACE_I2S)
1508 /* Configure the buffer address and size */
1509 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr;
1510 DMA_InitStructure.DMA_BufferSize = (uint32_t)Size;
1512 /* Configure the DMA Stream with the new parameters */
1513 DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
1515 /* Enable the I2S DMA Stream*/
1516 DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);
1518 #ifndef DAC_USE_I2S_DMA
1521 /* Configure the buffer address and size */
1522 DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr;
1523 DMA_InitStructure.DMA_BufferSize = (uint32_t)Size;
1525 /* Configure the DMA Stream with the new parameters */
1526 DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
1528 /* Enable the I2S DMA Stream*/
1529 DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);
1531 #endif /* DAC_USE_I2S_DMA */
1533 /* If the I2S peripheral is still not enabled, enable it */
1534 if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0)
1536 I2S_Cmd(CODEC_I2S, ENABLE);
1541 * @brief Pauses or Resumes the audio stream playing from the Media.
1542 * @param Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different
1543 * from 0) to resume.
1544 * @param Addr: Address from/at which the audio stream should resume/pause.
1547 static void Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr)
1549 /* Pause the audio file playing */
1550 if (Cmd == AUDIO_PAUSE)
1552 /* Disable the I2S DMA request */
1553 SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, DISABLE);
1555 /* Pause the I2S DMA Stream
1556 Note. For the STM32F4xx devices, the DMA implements a pause feature,
1557 by disabling the stream, all configuration is preserved and data
1558 transfer is paused till the next enable of the stream.
1559 This feature is not available on STM32F4xx devices. */
1560 DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
1562 else /* AUDIO_RESUME */
1564 /* Enable the I2S DMA request */
1565 SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, ENABLE);
1567 /* Resume the I2S DMA Stream
1568 Note. For the STM32F4xx devices, the DMA implements a pause feature,
1569 by disabling the stream, all configuration is preserved and data
1570 transfer is paused till the next enable of the stream.
1571 This feature is not available on STM32F4xx devices. */
1572 DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);
1574 /* If the I2S peripheral is still not enabled, enable it */
1575 if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0)
1577 I2S_Cmd(CODEC_I2S, ENABLE);
1583 * @brief Stops audio stream playing on the used Media.
1587 static void Audio_MAL_Stop(void)
1589 /* Stop the Transfer on the I2S side: Stop and disable the DMA stream */
1590 DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
1592 /* Clear all the DMA flags for the next transfer */
1593 DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC |AUDIO_MAL_DMA_FLAG_HT | \
1594 AUDIO_MAL_DMA_FLAG_FE | AUDIO_MAL_DMA_FLAG_TE);
1597 The I2S DMA requests are not disabled here.
1600 /* In all modes, disable the I2S peripheral */
1601 I2S_Cmd(CODEC_I2S, DISABLE);
1605 * @brief DAC Channel1 Configuration
1609 void DAC_Config(void)
1611 DAC_InitTypeDef DAC_InitStructure;
1612 GPIO_InitTypeDef GPIO_InitStructure;
1614 /* DMA1 clock and GPIOA clock enable (to be used with DAC) */
1615 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_GPIOA, ENABLE);
1617 /* DAC Periph clock enable */
1618 RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
1620 /* DAC channel 1 & 2 (DAC_OUT1 = PA.4) configuration */
1621 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
1622 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
1623 GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
1624 GPIO_Init(GPIOA, &GPIO_InitStructure);
1626 /* DAC channel1 Configuration */
1627 DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
1628 DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
1629 DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
1630 DAC_Init(AUDIO_DAC_CHANNEL, &DAC_InitStructure);
1632 /* Enable DAC Channel1 */
1633 DAC_Cmd(AUDIO_DAC_CHANNEL, ENABLE);
1651 /******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/