Added STM32F4-Discovery utilities
authorjnosky <codegrinder69@hotmail.com>
Sat, 12 Nov 2011 21:17:03 +0000 (16:17 -0500)
committerjnosky <codegrinder69@hotmail.com>
Sat, 12 Nov 2011 21:17:03 +0000 (16:17 -0500)
example/stm32f4/Utilities/STM32F4-Discovery/Release_Notes.html [new file with mode: 0644]
example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery.c [new file with mode: 0644]
example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery.h [new file with mode: 0644]
example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_audio_codec.c [new file with mode: 0644]
example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_audio_codec.h [new file with mode: 0644]
example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_lis302dl.c [new file with mode: 0644]
example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_lis302dl.h [new file with mode: 0644]

diff --git a/example/stm32f4/Utilities/STM32F4-Discovery/Release_Notes.html b/example/stm32f4/Utilities/STM32F4-Discovery/Release_Notes.html
new file mode 100644 (file)
index 0000000..7b270b4
--- /dev/null
@@ -0,0 +1,151 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40"><head>
+
+
+
+
+
+
+  
+  <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
+
+  
+  <link rel="File-List" href="Library_files/filelist.xml">
+
+  
+  <link rel="Edit-Time-Data" href="Library_files/editdata.mso"><!--[if !mso]> <style> v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]--><title>Release Notes for STM32F4-Discovery Board Drivers</title><!--[if gte mso 9]><xml> <o:DocumentProperties> <o:Author>STMicroelectronics</o:Author> <o:LastAuthor>STMicroelectronics</o:LastAuthor> <o:Revision>37</o:Revision> <o:TotalTime>136</o:TotalTime> <o:Created>2009-02-27T19:26:00Z</o:Created> <o:LastSaved>2009-03-01T17:56:00Z</o:LastSaved> <o:Pages>1</o:Pages> <o:Words>522</o:Words> <o:Characters>2977</o:Characters> <o:Company>STMicroelectronics</o:Company> <o:Lines>24</o:Lines> <o:Paragraphs>6</o:Paragraphs> <o:CharactersWithSpaces>3493</o:CharactersWithSpaces> <o:Version>11.6568</o:Version> </o:DocumentProperties> </xml><![endif]--><!--[if gte mso 9]><xml> <w:WordDocument> <w:Zoom>110</w:Zoom> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]-->
+
+
+  
+
+  
+
+  
+  <style>
+<!--
+/* Style Definitions */
+p.MsoNormal, li.MsoNormal, div.MsoNormal
+{mso-style-parent:"";
+margin:0in;
+margin-bottom:.0001pt;
+mso-pagination:widow-orphan;
+font-size:12.0pt;
+font-family:"Times New Roman";
+mso-fareast-font-family:"Times New Roman";}
+h2
+{mso-style-next:Normal;
+margin-top:12.0pt;
+margin-right:0in;
+margin-bottom:3.0pt;
+margin-left:0in;
+mso-pagination:widow-orphan;
+page-break-after:avoid;
+mso-outline-level:2;
+font-size:14.0pt;
+font-family:Arial;
+font-weight:bold;
+font-style:italic;}
+a:link, span.MsoHyperlink
+{color:blue;
+text-decoration:underline;
+text-underline:single;}
+a:visited, span.MsoHyperlinkFollowed
+{color:blue;
+text-decoration:underline;
+text-underline:single;}
+p
+{mso-margin-top-alt:auto;
+margin-right:0in;
+mso-margin-bottom-alt:auto;
+margin-left:0in;
+mso-pagination:widow-orphan;
+font-size:12.0pt;
+font-family:"Times New Roman";
+mso-fareast-font-family:"Times New Roman";}
+@page Section1
+{size:8.5in 11.0in;
+margin:1.0in 1.25in 1.0in 1.25in;
+mso-header-margin:.5in;
+mso-footer-margin:.5in;
+mso-paper-source:0;}
+div.Section1
+{page:Section1;}
+-->
+  </style><!--[if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:"Table Normal"; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0in 5.4pt 0in 5.4pt; mso-para-margin:0in; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]--><!--[if gte mso 9]><xml> <o:shapedefaults v:ext="edit" spidmax="5122"/> </xml><![endif]--><!--[if gte mso 9]><xml> <o:shapelayout v:ext="edit"> <o:idmap v:ext="edit" data="1"/> </o:shapelayout></xml><![endif]-->
+  <meta content="MCD Application Team" name="author"></head>
+<body link="blue" vlink="blue">
+<div class="Section1">
+<p class="MsoNormal"><span style="font-family: Arial;"><o:p><br>
+</o:p></span></p>
+<div align="center">
+<table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" cellspacing="0" width="900">
+  <tbody>
+    <tr>
+      <td style="padding: 0cm;" valign="top">
+      <table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" cellspacing="0" width="900">
+        <tbody>
+          <tr>
+            <td style="vertical-align: top;">
+            <p class="MsoNormal"><span style="font-size: 8pt; font-family: Arial; color: blue;"><a href="../../Release_Notes.html">Back to Release page</a><o:p></o:p></span></p>
+            </td>
+          </tr>
+          <tr style="">
+            <td style="padding: 1.5pt;">
+            <h1 style="margin-bottom: 18pt; text-align: center;" align="center"><span style="font-size: 20pt; font-family: Verdana; color: rgb(51, 102, 255);">Release
+Notes for STM32F4-Discovery Board Drivers</span><span style="font-size: 20pt; font-family: Verdana;"><o:p></o:p></span></h1>
+            <p class="MsoNormal" style="text-align: center;" align="center"><span style="font-size: 10pt; font-family: Arial; color: black;">Copyright
+2011 STMicroelectronics</span><span style="color: black;"><u1:p></u1:p><o:p></o:p></span></p>
+            <p class="MsoNormal" style="text-align: center;" align="center"><span style="font-size: 10pt; font-family: Arial; color: black;"><img alt="" id="_x0000_i1025" src="../../_htmresc/logo.bmp" style="border: 0px solid ; width: 86px; height: 65px;"></span><span style="font-size: 10pt;"><o:p></o:p></span></p>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+      <p class="MsoNormal"><span style="font-family: Arial; display: none;"><o:p>&nbsp;</o:p></span></p>
+      <table class="MsoNormalTable" style="width: 675pt;" border="0" cellpadding="0" width="900">
+        <tbody>
+          <tr style="">
+            <td style="padding: 0cm;" valign="top">
+            <h2 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"><span style="font-size: 12pt; color: white;">Contents<o:p></o:p></span></h2>
+            <ol style="margin-top: 0cm;" start="1" type="1">
+              <li class="MsoNormal" style="color: black; margin-top: 4.5pt; margin-bottom: 4.5pt;"><span style="font-size: 10pt; font-family: Verdana;"><a href="#History">STM32F4-Discovery Board&nbsp;Drivers&nbsp;update History</a><o:p></o:p></span></li>
+              <li class="MsoNormal" style="color: black; margin-top: 4.5pt; margin-bottom: 4.5pt;"><span style="font-size: 10pt; font-family: Verdana;"><a href="#License">License</a><o:p></o:p></span></li>
+            </ol>
+            <span style="font-family: &quot;Times New Roman&quot;;">
+            </span>
+            <h2 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"><a name="History"></a><span style="font-size: 12pt; color: white;">STM32F4-Discovery Board Drivers&nbsp;update History</span></h2><div style="margin-left: 40px;"><span style="font-size: 10pt; font-family: Verdana;">For more information on the STM32F4-Discovery board&nbsp;visit <a href="http://www.st.com/stm32f4-discovery" target="_blank">www.st.com/stm32f4-discovery</a>.</span></div><h3 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial; margin-right: 500pt; width: 186px;"><span style="font-size: 10pt; font-family: Arial; color: white;">V1.0.0 / 19-September-2011</span></h3>
+            <p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt;"><b style=""><u><span style="font-size: 10pt; font-family: Verdana; color: black;">Main
+Changes<o:p></o:p></span></u></b></p>
+
+            <ul style="margin-top: 0cm;" type="square"><li class="MsoNormal"><span style="font-size: 10pt; font-family: Verdana;">First official version of the<span style="font-weight: bold; font-style: italic;"> STM32F4-Discovery Board&nbsp;Drivers</span></span></li></ul><span style="font-size: 10pt; font-family: Verdana;"><span style="font-weight: bold; font-style: italic;"></span></span><br><span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"><span style="font-style: italic; font-weight: bold;"></span></span><span style="font-size: 10pt; font-family: Verdana;"></span><h2 style="background: rgb(51, 102, 255) none repeat scroll 0% 50%; -moz-background-clip: initial; -moz-background-origin: initial; -moz-background-inline-policy: initial;"><a name="License"></a><span style="font-size: 12pt; color: white;">License<o:p></o:p></span></h2>
+            <p class="MsoNormal" style="margin: 4.5pt 0cm;"><span style="font-size: 10pt; font-family: Verdana; color: black;">The
+enclosed firmware and all the related documentation are not covered by
+a License Agreement, if you need such License you can contact your
+local STMicroelectronics office.<u1:p></u1:p><o:p></o:p></span></p>
+
+            <b><span style="font-size: 10pt; font-family: Verdana; color: black;">THE
+PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO
+SAVE TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR
+ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY
+CLAIMS ARISING FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY
+CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH
+THEIR PRODUCTS.</span></b>
+            
+            <div class="MsoNormal" style="text-align: center;" align="center"><span style="color: black;">
+            <hr align="center" size="2" width="100%"></span></div>
+            <p class="MsoNormal" style="margin: 4.5pt 0cm 4.5pt 18pt; text-align: center;" align="center"><span style="font-size: 10pt; font-family: Verdana; color: black;">For
+complete documentation on </span><span style="font-size: 10pt; font-family: Verdana;">STMicroelectronics<span style="color: black;"> Microcontrollers visit </span><a target="_blank" href="http://www.st.com/internet/mcu/family/141.jsp"><u><span style="color: blue;">www.st.com</span></u></a></span><span style="font-size: 10pt; font-family: Verdana;"><u><span style="color: blue;"><a href="http://www.st.com/stm32l" target="_blank"></a></span></u></span><span style="color: black;"><o:p></o:p></span></p>
+            </td>
+          </tr>
+        </tbody>
+      </table>
+      <p class="MsoNormal"><span style="font-size: 10pt;"><o:p></o:p></span></p>
+      </td>
+    </tr>
+  </tbody>
+</table>
+</div>
+<p class="MsoNormal"><o:p>&nbsp;</o:p></p>
+</div>
+
+</body></html>
\ No newline at end of file
diff --git a/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery.c b/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery.c
new file mode 100644 (file)
index 0000000..ff0d697
--- /dev/null
@@ -0,0 +1,257 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4_discovery.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    19-September-2011
+  * @brief   This file provides set of firmware functions to manage Leds and
+  *          push-button available on STM32F4-Discovery Kit from STMicroelectronics.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************
+  */ 
+  
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4_discovery.h"
+
+//ADDED BY ME!!!!!!!!!!!!!!!!!!!!
+#include "stm32f4xx_conf.h"
+
+
+/** @addtogroup Utilities
+  * @{
+  */ 
+
+/** @addtogroup STM32F4_DISCOVERY
+  * @{
+  */   
+    
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL 
+  * @brief This file provides set of firmware functions to manage Leds and push-button
+  *        available on STM32F4-Discovery Kit from STMicroelectronics.
+  * @{
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_TypesDefinitions
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_Defines
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_Macros
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_Variables
+  * @{
+  */ 
+GPIO_TypeDef* GPIO_PORT[LEDn] = {LED4_GPIO_PORT, LED3_GPIO_PORT, LED5_GPIO_PORT,
+                                 LED6_GPIO_PORT};
+const uint16_t GPIO_PIN[LEDn] = {LED4_PIN, LED3_PIN, LED5_PIN,
+                                 LED6_PIN};
+const uint32_t GPIO_CLK[LEDn] = {LED4_GPIO_CLK, LED3_GPIO_CLK, LED5_GPIO_CLK,
+                                 LED6_GPIO_CLK};
+
+GPIO_TypeDef* BUTTON_PORT[BUTTONn] = {USER_BUTTON_GPIO_PORT }; 
+
+const uint16_t BUTTON_PIN[BUTTONn] = {USER_BUTTON_PIN }; 
+
+const uint32_t BUTTON_CLK[BUTTONn] = {USER_BUTTON_GPIO_CLK };
+
+const uint16_t BUTTON_EXTI_LINE[BUTTONn] = {USER_BUTTON_EXTI_LINE };
+
+const uint8_t BUTTON_PORT_SOURCE[BUTTONn] = {USER_BUTTON_EXTI_PORT_SOURCE};
+                                                                
+const uint8_t BUTTON_PIN_SOURCE[BUTTONn] = {USER_BUTTON_EXTI_PIN_SOURCE }; 
+const uint8_t BUTTON_IRQn[BUTTONn] = {USER_BUTTON_EXTI_IRQn };
+
+NVIC_InitTypeDef   NVIC_InitStructure;
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_FunctionPrototypes
+  * @{
+  */ 
+
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Private_Functions
+  * @{
+  */ 
+
+/**
+  * @brief  Configures LED GPIO.
+  * @param  Led: Specifies the Led to be configured. 
+  *   This parameter can be one of following parameters:
+  *     @arg LED4
+  *     @arg LED3
+  *     @arg LED5
+  *     @arg LED6
+  * @retval None
+  */
+void STM_EVAL_LEDInit(Led_TypeDef Led)
+{
+  GPIO_InitTypeDef  GPIO_InitStructure;
+  
+  /* Enable the GPIO_LED Clock */
+  RCC_AHB1PeriphClockCmd(GPIO_CLK[Led], ENABLE);
+
+  /* Configure the GPIO_LED pin */
+  GPIO_InitStructure.GPIO_Pin = GPIO_PIN[Led];
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(GPIO_PORT[Led], &GPIO_InitStructure);
+}
+
+/**
+  * @brief  Turns selected LED On.
+  * @param  Led: Specifies the Led to be set on. 
+  *   This parameter can be one of following parameters:
+  *     @arg LED4
+  *     @arg LED3
+  *     @arg LED5
+  *     @arg LED6  
+  * @retval None
+  */
+void STM_EVAL_LEDOn(Led_TypeDef Led)
+{
+  GPIO_PORT[Led]->BSRRL = GPIO_PIN[Led];
+}
+
+/**
+  * @brief  Turns selected LED Off.
+  * @param  Led: Specifies the Led to be set off. 
+  *   This parameter can be one of following parameters:
+  *     @arg LED4
+  *     @arg LED3
+  *     @arg LED5
+  *     @arg LED6 
+  * @retval None
+  */
+void STM_EVAL_LEDOff(Led_TypeDef Led)
+{
+  GPIO_PORT[Led]->BSRRH = GPIO_PIN[Led];  
+}
+
+/**
+  * @brief  Toggles the selected LED.
+  * @param  Led: Specifies the Led to be toggled. 
+  *   This parameter can be one of following parameters:
+  *     @arg LED4
+  *     @arg LED3
+  *     @arg LED5
+  *     @arg LED6  
+  * @retval None
+  */
+void STM_EVAL_LEDToggle(Led_TypeDef Led)
+{
+  GPIO_PORT[Led]->ODR ^= GPIO_PIN[Led];
+}
+
+/**
+  * @brief  Configures Button GPIO and EXTI Line.
+  * @param  Button: Specifies the Button to be configured.
+  *   This parameter should be: BUTTON_USER
+  * @param  Button_Mode: Specifies Button mode.
+  *   This parameter can be one of following parameters:   
+  *     @arg BUTTON_MODE_GPIO: Button will be used as simple IO 
+  *     @arg BUTTON_MODE_EXTI: Button will be connected to EXTI line with interrupt
+  *                            generation capability  
+  * @retval None
+  */
+void STM_EVAL_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode)
+{
+  GPIO_InitTypeDef GPIO_InitStructure;
+  EXTI_InitTypeDef EXTI_InitStructure;
+  NVIC_InitTypeDef NVIC_InitStructure;
+
+  /* Enable the BUTTON Clock */
+  RCC_AHB1PeriphClockCmd(BUTTON_CLK[Button], ENABLE);
+  RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
+
+  /* Configure Button pin as input */
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_InitStructure.GPIO_Pin = BUTTON_PIN[Button];
+  GPIO_Init(BUTTON_PORT[Button], &GPIO_InitStructure);
+
+  if (Button_Mode == BUTTON_MODE_EXTI)
+  {
+    /* Connect Button EXTI Line to Button GPIO Pin */
+    SYSCFG_EXTILineConfig(BUTTON_PORT_SOURCE[Button], BUTTON_PIN_SOURCE[Button]);
+
+    /* Configure Button EXTI line */
+    EXTI_InitStructure.EXTI_Line = BUTTON_EXTI_LINE[Button];
+    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
+    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  
+    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
+    EXTI_Init(&EXTI_InitStructure);
+
+    /* Enable and set Button EXTI Interrupt to the lowest priority */
+    NVIC_InitStructure.NVIC_IRQChannel = BUTTON_IRQn[Button];
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+
+    NVIC_Init(&NVIC_InitStructure); 
+  }
+}
+
+/**
+  * @brief  Returns the selected Button state.
+  * @param  Button: Specifies the Button to be checked.
+  *   This parameter should be: BUTTON_USER  
+  * @retval The Button GPIO pin value.
+  */
+uint32_t STM_EVAL_PBGetState(Button_TypeDef Button)
+{
+  return GPIO_ReadInputDataBit(BUTTON_PORT[Button], BUTTON_PIN[Button]);
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */   
+
+/**
+  * @}
+  */ 
+    
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
diff --git a/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery.h b/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery.h
new file mode 100644 (file)
index 0000000..c6fec42
--- /dev/null
@@ -0,0 +1,158 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4_discovery.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    19-September-2011
+  * @brief   This file contains definitions for STM32F4-Discovery Kit's Leds and 
+  *          push-button hardware resources.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************  
+  */ 
+  
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4_DISCOVERY_H
+#define __STM32F4_DISCOVERY_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+                                              
+/* Includes ------------------------------------------------------------------*/
+ #include "stm32f4xx.h"
+   
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32F4_DISCOVERY
+  * @{
+  */
+      
+/** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL
+  * @{
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Types
+  * @{
+  */
+typedef enum 
+{
+  LED4 = 0,
+  LED3 = 1,
+  LED5 = 2,
+  LED6 = 3
+} Led_TypeDef;
+
+typedef enum 
+{  
+  BUTTON_USER = 0,
+} Button_TypeDef;
+
+typedef enum 
+{  
+  BUTTON_MODE_GPIO = 0,
+  BUTTON_MODE_EXTI = 1
+} ButtonMode_TypeDef;     
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Constants
+  * @{
+  */ 
+
+/** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL_LED
+  * @{
+  */
+#define LEDn                             4
+
+#define LED4_PIN                         GPIO_Pin_12
+#define LED4_GPIO_PORT                   GPIOD
+#define LED4_GPIO_CLK                    RCC_AHB1Periph_GPIOD  
+  
+#define LED3_PIN                         GPIO_Pin_13
+#define LED3_GPIO_PORT                   GPIOD
+#define LED3_GPIO_CLK                    RCC_AHB1Periph_GPIOD  
+  
+#define LED5_PIN                         GPIO_Pin_14
+#define LED5_GPIO_PORT                   GPIOD
+#define LED5_GPIO_CLK                    RCC_AHB1Periph_GPIOD  
+  
+#define LED6_PIN                         GPIO_Pin_15
+#define LED6_GPIO_PORT                   GPIOD
+#define LED6_GPIO_CLK                    RCC_AHB1Periph_GPIOD
+/**
+  * @}
+  */ 
+  
+/** @addtogroup STM32F4_DISCOVERY_LOW_LEVEL_BUTTON
+  * @{
+  */  
+#define BUTTONn                          1  
+
+/**
+ * @brief Wakeup push-button
+ */
+#define USER_BUTTON_PIN                GPIO_Pin_0
+#define USER_BUTTON_GPIO_PORT          GPIOA
+#define USER_BUTTON_GPIO_CLK           RCC_AHB1Periph_GPIOA
+#define USER_BUTTON_EXTI_LINE          EXTI_Line0
+#define USER_BUTTON_EXTI_PORT_SOURCE   EXTI_PortSourceGPIOA
+#define USER_BUTTON_EXTI_PIN_SOURCE    EXTI_PinSource0
+#define USER_BUTTON_EXTI_IRQn          EXTI0_IRQn 
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Macros
+  * @{
+  */  
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32F4_DISCOVERY_LOW_LEVEL_Exported_Functions
+  * @{
+  */
+void STM_EVAL_LEDInit(Led_TypeDef Led);
+void STM_EVAL_LEDOn(Led_TypeDef Led);
+void STM_EVAL_LEDOff(Led_TypeDef Led);
+void STM_EVAL_LEDToggle(Led_TypeDef Led);
+void STM_EVAL_PBInit(Button_TypeDef Button, ButtonMode_TypeDef Button_Mode);
+uint32_t STM_EVAL_PBGetState(Button_TypeDef Button);
+/**
+  * @}
+  */
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4_DISCOVERY_H */
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
diff --git a/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_audio_codec.c b/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_audio_codec.c
new file mode 100644 (file)
index 0000000..0445aa5
--- /dev/null
@@ -0,0 +1,1651 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4_discovery_audio_codec.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    19-September-2011
+  * @brief   This file includes the low layer driver for CS43L22 Audio Codec
+  *          available on STM32F4-Discovery Kit.  
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************  
+  */
+
+/*==============================================================================================================================
+                                             User NOTES
+1. How To use this driver:
+--------------------------
+   - This driver supports STM32F4xx devices on STM32F4-Discovery Kit.
+
+   - Configure the options in file stm32f4_discovery_audio_codec.h in the section CONFIGURATION.
+      Refer to the sections 2 and 3 to have more details on the possible configurations.
+
+   - Call the function EVAL_AUDIO_Init(
+                                    OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 
+                                                 OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_AUTO or 
+                                                 OUTPUT_DEVICE_BOTH)
+                                    Volume: initial volume to be set (0 is min (mute), 100 is max (100%)
+                                    AudioFreq: Audio frequency in Hz (8000, 16000, 22500, 32000 ...)
+                                    this parameter is relative to the audio file/stream type.
+                                   )
+      This function configures all the hardware required for the audio application (codec, I2C, I2S, 
+      GPIOs, DMA and interrupt if needed). This function returns 0 if configuration is OK.
+      if the returned value is different from 0 or the function is stuck then the communication with
+      the codec (try to un-plug the power or reset device in this case).
+      + OUTPUT_DEVICE_SPEAKER: only speaker will be set as output for the audio stream.
+      + OUTPUT_DEVICE_HEADPHONE: only headphones will be set as output for the audio stream.
+      + OUTPUT_DEVICE_AUTO: Selection of output device is made through external switch (implemented 
+         into the audio jack on the evaluation board). When the Headphone is connected it is used
+         as output. When the headphone is disconnected from the audio jack, the output is
+         automatically switched to Speaker.
+      + OUTPUT_DEVICE_BOTH: both Speaker and Headphone are used as outputs for the audio stream
+         at the same time.
+
+   - Call the function EVAL_AUDIO_Play(
+                                  pBuffer: pointer to the audio data file address
+                                  Size: size of the buffer to be sent in Bytes
+                                 )
+      to start playing (for the first time) from the audio file/stream.
+
+   - Call the function EVAL_AUDIO_PauseResume(
+                                         Cmd: AUDIO_PAUSE (or 0) to pause playing or AUDIO_RESUME (or 
+                                               any value different from 0) to resume playing.
+                                         )
+       Note. After calling EVAL_AUDIO_PauseResume() function for pause, only EVAL_AUDIO_PauseResume() should be called
+          for resume (it is not allowed to call EVAL_AUDIO_Play() in this case).
+       Note. This function should be called only when the audio file is played or paused (not stopped).
+
+   - For each mode, you may need to implement the relative callback functions into your code.
+      The Callback functions are named EVAL_AUDIO_XXX_CallBack() and only their prototypes are declared in 
+      the stm32f4_discovery_audio_codec.h file. (refer to the example for more details on the callbacks implementations)
+
+   - To Stop playing, to modify the volume level or to mute, use the functions
+       EVAL_AUDIO_Stop(), EVAL_AUDIO_VolumeCtl() and EVAL_AUDIO_Mute().
+
+   - The driver API and the callback functions are at the end of the stm32f4_discovery_audio_codec.h file.
+
+ Driver architecture:
+ --------------------
+ This driver is composed of three main layers:
+   o High Audio Layer: consists of the function API exported in the stm32f4_discovery_audio_codec.h file
+     (EVAL_AUDIO_Init(), EVAL_AUDIO_Play() ...)
+   o Codec Control layer: consists of the functions API controlling the audio codec (CS43L22) and 
+     included as local functions in file stm32f4_discovery_audio_codec.c (Codec_Init(), Codec_Play() ...)
+   o Media Access Layer (MAL): which consists of functions allowing to access the media containing/
+     providing the audio file/stream. These functions are also included as local functions into
+     the stm32f4_discovery_audio_codec.c file (Audio_MAL_Init(), Audio_MAL_Play() ...)
+  Each set of functions (layer) may be implemented independently of the others and customized when 
+  needed.    
+
+2. Modes description:
+---------------------
+     + AUDIO_MAL_MODE_NORMAL : is suitable when the audio file is in a memory location.
+     + AUDIO_MAL_MODE_CIRCULAR: is suitable when the audio data are read either from a 
+        memory location or from a device at real time (double buffer could be used).
+
+3. DMA interrupts description:
+------------------------------
+     + EVAL_AUDIO_IT_TC_ENABLE: Enable this define to use the DMA end of transfer interrupt.
+        then, a callback should be implemented by user to perform specific actions
+        when the DMA has finished the transfer.
+     + EVAL_AUDIO_IT_HT_ENABLE: Enable this define to use the DMA end of half transfer interrupt.
+        then, a callback should be implemented by user to perform specific actions
+        when the DMA has reached the half of the buffer transfer (generally, it is useful 
+        to load the first half of buffer while DMA is loading from the second half).
+     + EVAL_AUDIO_IT_ER_ENABLE: Enable this define to manage the cases of error on DMA transfer.
+
+4. Known Limitations:
+---------------------
+   1- When using the Speaker, if the audio file quality is not high enough, the speaker output
+      may produce high and uncomfortable noise level. To avoid this issue, to use speaker
+      output properly, try to increase audio file sampling rate (typically higher than 48KHz).
+      This operation will lead to larger file size.
+   2- Communication with the audio codec (through I2C) may be corrupted if it is interrupted by some
+      user interrupt routines (in this case, interrupts could be disabled just before the start of 
+      communication then re-enabled when it is over). Note that this communication is only done at
+      the configuration phase (EVAL_AUDIO_Init() or EVAL_AUDIO_Stop()) and when Volume control modification is 
+      performed (EVAL_AUDIO_VolumeCtl() or EVAL_AUDIO_Mute()). When the audio data is played, no communication is 
+      required with the audio codec.
+  3- Parsing of audio file is not implemented (in order to determine audio file properties: Mono/Stereo, Data size, 
+     File size, Audio Frequency, Audio Data header size ...). The configuration is fixed for the given audio file.
+  4- Mono audio streaming is not supported (in order to play mono audio streams, each data should be sent twice 
+     on the I2S or should be duplicated on the source buffer. Or convert the stream in stereo before playing).
+  5- Supports only 16-bit audio data size.
+===============================================================================================================================*/
+
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4_discovery_audio_codec.h"
+//ADDED BY ME!!!!!!!!!!!!!!!!!!!!
+#include "stm32f4xx_conf.h"
+
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32F4_DISCOVERY
+  * @{
+  */
+
+/** @addtogroup STM32F4_DISCOVERY_AUDIO_CODEC
+  * @brief       This file includes the low layer driver for CS43L22 Audio Codec
+  *              available on STM32F4-Discovery Kit.
+  * @{
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Types
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Defines
+  * @{
+  */ 
+
+/* Mask for the bit EN of the I2S CFGR register */
+#define I2S_ENABLE_MASK                 0x0400
+
+/* Delay for the Codec to be correctly reset */
+#define CODEC_RESET_DELAY               0x4FFF
+
+/* Codec audio Standards */
+#ifdef I2S_STANDARD_PHILLIPS
+ #define  CODEC_STANDARD                0x04
+ #define I2S_STANDARD                   I2S_Standard_Phillips         
+#elif defined(I2S_STANDARD_MSB)
+ #define  CODEC_STANDARD                0x00
+ #define I2S_STANDARD                   I2S_Standard_MSB    
+#elif defined(I2S_STANDARD_LSB)
+ #define  CODEC_STANDARD                0x08
+ #define I2S_STANDARD                   I2S_Standard_LSB    
+#else 
+ #error "Error: No audio communication standard selected !"
+#endif /* I2S_STANDARD */
+
+/* The 7 bits Codec address (sent through I2C interface) */
+#define CODEC_ADDRESS                   0x94  /* b00100111 */
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Macros
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Variables
+  * @{
+  */
+/* This structure is declared global because it is handled by two different functions */
+static DMA_InitTypeDef DMA_InitStructure; 
+DMA_InitTypeDef AUDIO_MAL_DMA_InitStructure;
+
+uint32_t AudioTotalSize = 0xFFFF; /* This variable holds the total size of the audio file */
+uint32_t AudioRemSize   = 0xFFFF; /* This variable holds the remaining data in audio file */
+uint16_t *CurrentPos;             /* This variable holds the current position of audio pointer */
+
+__IO uint32_t  CODECTimeout = CODEC_LONG_TIMEOUT;   
+__IO uint8_t OutputDev = 0;
+
+
+__IO uint32_t CurrAudioInterface = AUDIO_INTERFACE_I2S; //AUDIO_INTERFACE_DAC
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Function_Prototypes
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Private_Functions
+  * @{
+  */ 
+static void Audio_MAL_IRQHandler(void);
+/*-----------------------------------
+                           Audio Codec functions 
+                                    ------------------------------------------*/
+/* High Layer codec functions */
+static uint32_t Codec_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq);
+static uint32_t Codec_DeInit(void);
+static uint32_t Codec_Play(void);
+static uint32_t Codec_PauseResume(uint32_t Cmd);
+static uint32_t Codec_Stop(uint32_t Cmd);
+static uint32_t Codec_VolumeCtrl(uint8_t Volume);
+static uint32_t Codec_Mute(uint32_t Cmd);
+/* Low layer codec functions */
+static void     Codec_CtrlInterface_Init(void);
+static void     Codec_CtrlInterface_DeInit(void);
+static void     Codec_AudioInterface_Init(uint32_t AudioFreq);
+static void     Codec_AudioInterface_DeInit(void);
+static void     Codec_Reset(void);
+static uint32_t Codec_WriteRegister(uint8_t RegisterAddr, uint8_t RegisterValue);
+static uint32_t Codec_ReadRegister(uint8_t RegisterAddr);
+static void     Codec_GPIO_Init(void);
+static void     Codec_GPIO_DeInit(void);
+static void     Delay(__IO uint32_t nCount);
+/*----------------------------------------------------------------------------*/
+
+/*-----------------------------------
+                   MAL (Media Access Layer) functions 
+                                    ------------------------------------------*/
+/* Peripherals configuration functions */
+static void     Audio_MAL_Init(void);
+static void     Audio_MAL_DeInit(void);
+static void     Audio_MAL_Play(uint32_t Addr, uint32_t Size);
+static void     Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr);
+static void     Audio_MAL_Stop(void);
+/*----------------------------------------------------------------------------*/
+
+ /* DMA Stream definitions */
+ uint32_t AUDIO_MAL_DMA_CLOCK    = AUDIO_I2S_DMA_CLOCK;
+ DMA_Stream_TypeDef * AUDIO_MAL_DMA_STREAM   = AUDIO_I2S_DMA_STREAM ;       
+ uint32_t AUDIO_MAL_DMA_DREG     = AUDIO_I2S_DMA_DREG;
+ uint32_t AUDIO_MAL_DMA_CHANNEL  = AUDIO_I2S_DMA_CHANNEL;
+ uint32_t AUDIO_MAL_DMA_IRQ      = AUDIO_I2S_DMA_IRQ  ;
+ uint32_t AUDIO_MAL_DMA_FLAG_TC  = AUDIO_I2S_DMA_FLAG_TC;
+ uint32_t AUDIO_MAL_DMA_FLAG_HT  = AUDIO_I2S_DMA_FLAG_HT;
+ uint32_t AUDIO_MAL_DMA_FLAG_FE  = AUDIO_I2S_DMA_FLAG_FE;
+ uint32_t AUDIO_MAL_DMA_FLAG_TE  = AUDIO_I2S_DMA_FLAG_TE;
+ uint32_t AUDIO_MAL_DMA_FLAG_DME = AUDIO_I2S_DMA_FLAG_DME;
+
+/**
+  * @brief  Set the current audio interface (I2S or DAC).
+  * @param  Interface: AUDIO_INTERFACE_I2S or AUDIO_INTERFACE_DAC
+  * @retval None
+  */
+void EVAL_AUDIO_SetAudioInterface(uint32_t Interface)
+{    
+  CurrAudioInterface = Interface;
+  
+  if (CurrAudioInterface == AUDIO_INTERFACE_I2S)
+  {
+    /* DMA Stream definitions */
+    AUDIO_MAL_DMA_CLOCK    = AUDIO_I2S_DMA_CLOCK;
+    AUDIO_MAL_DMA_STREAM   = AUDIO_I2S_DMA_STREAM;        
+    AUDIO_MAL_DMA_DREG     = AUDIO_I2S_DMA_DREG;
+    AUDIO_MAL_DMA_CHANNEL  = AUDIO_I2S_DMA_CHANNEL;
+    AUDIO_MAL_DMA_IRQ      = AUDIO_I2S_DMA_IRQ  ;
+    AUDIO_MAL_DMA_FLAG_TC  = AUDIO_I2S_DMA_FLAG_TC;
+    AUDIO_MAL_DMA_FLAG_HT  = AUDIO_I2S_DMA_FLAG_HT;
+    AUDIO_MAL_DMA_FLAG_FE  = AUDIO_I2S_DMA_FLAG_FE;
+    AUDIO_MAL_DMA_FLAG_TE  = AUDIO_I2S_DMA_FLAG_TE;
+    AUDIO_MAL_DMA_FLAG_DME = AUDIO_I2S_DMA_FLAG_DME;
+  }
+  else if (Interface == AUDIO_INTERFACE_DAC)
+  {
+    /* DMA Stream definitions */
+    AUDIO_MAL_DMA_CLOCK    = AUDIO_DAC_DMA_CLOCK;
+    AUDIO_MAL_DMA_STREAM   = AUDIO_DAC_DMA_STREAM;        
+    AUDIO_MAL_DMA_DREG     = AUDIO_DAC_DMA_DREG;
+    AUDIO_MAL_DMA_CHANNEL  = AUDIO_DAC_DMA_CHANNEL;
+    AUDIO_MAL_DMA_IRQ      = AUDIO_DAC_DMA_IRQ  ;
+    AUDIO_MAL_DMA_FLAG_TC  = AUDIO_DAC_DMA_FLAG_TC;
+    AUDIO_MAL_DMA_FLAG_HT  = AUDIO_DAC_DMA_FLAG_HT;
+    AUDIO_MAL_DMA_FLAG_FE  = AUDIO_DAC_DMA_FLAG_FE;
+    AUDIO_MAL_DMA_FLAG_TE  = AUDIO_DAC_DMA_FLAG_TE;
+    AUDIO_MAL_DMA_FLAG_DME = AUDIO_DAC_DMA_FLAG_DME;    
+  }
+}
+
+/**
+  * @brief  Configure the audio peripherals.
+  * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
+  *                       OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO .
+  * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
+  * @param  AudioFreq: Audio frequency used to play the audio stream.
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t EVAL_AUDIO_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
+{    
+  /* Perform low layer Codec initialization */
+  if (Codec_Init(OutputDevice, VOLUME_CONVERT(Volume), AudioFreq) != 0)
+  {
+    return 1;                
+  }
+  else
+  {    
+    /* I2S data transfer preparation:
+    Prepare the Media to be used for the audio transfer from memory to I2S peripheral */
+    Audio_MAL_Init();
+    
+    /* Return 0 when all operations are OK */
+    return 0;
+  }
+}
+
+/**
+  * @brief  Deinitializes all the resources used by the codec (those initialized
+  *         by EVAL_AUDIO_Init() function). 
+  * @param  None
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t EVAL_AUDIO_DeInit(void)
+{ 
+  /* DeInitialize the Media layer */
+  Audio_MAL_DeInit();
+  
+  /* DeInitialize Codec */  
+  Codec_DeInit();  
+  
+  return 0;
+}
+
+/**
+  * @brief  Starts playing audio stream from a data buffer for a determined size. 
+  * @param  pBuffer: Pointer to the buffer 
+  * @param  Size: Number of audio data BYTES.
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t EVAL_AUDIO_Play(uint16_t* pBuffer, uint32_t Size)
+{
+  /* Set the total number of data to be played (count in half-word) */
+  AudioTotalSize = Size/2;
+
+  /* Call the audio Codec Play function */
+  Codec_Play();
+  
+  /* Update the Media layer and enable it for play */  
+  Audio_MAL_Play((uint32_t)pBuffer, (uint32_t)(DMA_MAX(AudioTotalSize / 2)));
+  
+  /* Update the remaining number of data to be played */
+  AudioRemSize = (Size/2) - DMA_MAX(AudioTotalSize);
+  
+  /* Update the current audio pointer position */
+  CurrentPos = pBuffer + DMA_MAX(AudioTotalSize);
+  
+  return 0;
+}
+
+/**
+  * @brief  This function Pauses or Resumes the audio file stream. In case
+  *         of using DMA, the DMA Pause feature is used. In all cases the I2S 
+  *         peripheral is disabled. 
+  * 
+  * @WARNING When calling EVAL_AUDIO_PauseResume() function for pause, only
+  *          this function should be called for resume (use of EVAL_AUDIO_Play() 
+  *          function for resume could lead to unexpected behavior).
+  * 
+  * @param  Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different
+  *         from 0) to resume. 
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t EVAL_AUDIO_PauseResume(uint32_t Cmd)
+{    
+  /* Call the Audio Codec Pause/Resume function */
+  if (Codec_PauseResume(Cmd) != 0)
+  {
+    return 1;
+  }
+  else
+  {
+    /* Call the Media layer pause/resume function */
+    Audio_MAL_PauseResume(Cmd, 0);
+    
+    /* Return 0 if all operations are OK */
+    return 0;
+  }
+}
+
+/**
+  * @brief  Stops audio playing and Power down the Audio Codec. 
+  * @param  Option: could be one of the following parameters 
+  *           - CODEC_PDWN_SW: for software power off (by writing registers). 
+  *                            Then no need to reconfigure the Codec after power on.
+  *           - CODEC_PDWN_HW: completely shut down the codec (physically). 
+  *                            Then need to reconfigure the Codec after power on.  
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t EVAL_AUDIO_Stop(uint32_t Option)
+{
+  /* Call Audio Codec Stop function */
+  if (Codec_Stop(Option) != 0)
+  {
+    return 1;
+  }
+  else
+  {
+    /* Call Media layer Stop function */
+    Audio_MAL_Stop();
+    
+    /* Update the remaining data number */
+    AudioRemSize = AudioTotalSize;    
+    
+    /* Return 0 when all operations are correctly done */
+    return 0;
+  }
+}
+
+/**
+  * @brief  Controls the current audio volume level. 
+  * @param  Volume: Volume level to be set in percentage from 0% to 100% (0 for 
+  *         Mute and 100 for Max volume level).
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t EVAL_AUDIO_VolumeCtl(uint8_t Volume)
+{
+  /* Call the codec volume control function with converted volume value */
+  return (Codec_VolumeCtrl(VOLUME_CONVERT(Volume)));
+}
+
+/**
+  * @brief  Enables or disables the MUTE mode by software 
+  * @param  Command: could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
+  *         unmute the codec and restore previous volume level.
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t EVAL_AUDIO_Mute(uint32_t Cmd)
+{ 
+  /* Call the Codec Mute function */
+  return (Codec_Mute(Cmd));
+}
+
+/**
+  * @brief  This function handles main Media layer interrupt. 
+  * @param  None
+  * @retval 0 if correct communication, else wrong communication
+  */
+static void Audio_MAL_IRQHandler(void)
+{    
+#ifndef AUDIO_MAL_MODE_NORMAL
+  uint16_t *pAddr = (uint16_t *)CurrentPos;
+  uint32_t Size = AudioRemSize;
+#endif /* AUDIO_MAL_MODE_NORMAL */
+  
+#ifdef AUDIO_MAL_DMA_IT_TC_EN
+  /* Transfer complete interrupt */
+  if (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC) != RESET)
+  {         
+ #ifdef AUDIO_MAL_MODE_NORMAL
+    /* Check if the end of file has been reached */
+    if (AudioRemSize > 0)
+    {      
+      /* Wait the DMA Stream to be effectively disabled */
+      while (DMA_GetCmdStatus(AUDIO_MAL_DMA_STREAM) != DISABLE)
+      {}
+      
+      /* Clear the Interrupt flag */
+      DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC);  
+      
+      /* Re-Configure the buffer address and size */
+      DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) CurrentPos;
+      DMA_InitStructure.DMA_BufferSize = (uint32_t) (DMA_MAX(AudioRemSize));
+      
+      /* Configure the DMA Stream with the new parameters */
+      DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
+      
+      /* Enable the I2S DMA Stream*/
+      DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);    
+      
+      /* Update the current pointer position */
+      CurrentPos += DMA_MAX(AudioRemSize);        
+      
+      /* Update the remaining number of data to be played */
+      AudioRemSize -= DMA_MAX(AudioRemSize);    
+    }
+    else
+    {
+      /* Disable the I2S DMA Stream*/
+      DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);   
+      
+      /* Clear the Interrupt flag */
+      DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC);       
+      
+      /* Manage the remaining file size and new address offset: This function 
+      should be coded by user (its prototype is already declared in stm32f4_discovery_audio_codec.h) */  
+      EVAL_AUDIO_TransferComplete_CallBack((uint32_t)CurrentPos, 0);       
+    }
+    
+ #elif defined(AUDIO_MAL_MODE_CIRCULAR)
+    /* Manage the remaining file size and new address offset: This function 
+       should be coded by user (its prototype is already declared in stm32f4_discovery_audio_codec.h) */  
+    EVAL_AUDIO_TransferComplete_CallBack(pAddr, Size);    
+    
+    /* Clear the Interrupt flag */
+    DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC);
+ #endif /* AUDIO_MAL_MODE_NORMAL */  
+  }
+#endif /* AUDIO_MAL_DMA_IT_TC_EN */
+
+#ifdef AUDIO_MAL_DMA_IT_HT_EN  
+  /* Half Transfer complete interrupt */
+  if (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_HT) != RESET)
+  {
+    /* Manage the remaining file size and new address offset: This function 
+       should be coded by user (its prototype is already declared in stm32f4_discovery_audio_codec.h) */  
+    EVAL_AUDIO_HalfTransfer_CallBack((uint32_t)pAddr, Size);    
+   
+    /* Clear the Interrupt flag */
+    DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_HT);    
+  }
+#endif /* AUDIO_MAL_DMA_IT_HT_EN */
+  
+#ifdef AUDIO_MAL_DMA_IT_TE_EN  
+  /* FIFO Error interrupt */
+  if ((DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TE) != RESET) || \
+     (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_FE) != RESET) || \
+     (DMA_GetFlagStatus(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_DME) != RESET))
+    
+  {
+    /* Manage the error generated on DMA FIFO: This function 
+       should be coded by user (its prototype is already declared in stm32f4_discovery_audio_codec.h) */  
+    EVAL_AUDIO_Error_CallBack((uint32_t*)&pAddr);    
+    
+    /* Clear the Interrupt flag */
+    DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TE | AUDIO_MAL_DMA_FLAG_FE | \
+                                        AUDIO_MAL_DMA_FLAG_DME);
+  }  
+#endif /* AUDIO_MAL_DMA_IT_TE_EN */
+}
+
+/**
+  * @brief  This function handles main I2S interrupt. 
+  * @param  None
+  * @retval 0 if correct communication, else wrong communication
+  */
+void Audio_MAL_I2S_IRQHandler(void)
+{ 
+  Audio_MAL_IRQHandler();
+}
+
+/**
+  * @brief  This function handles main DAC interrupt. 
+  * @param  None
+  * @retval 0 if correct communication, else wrong communication
+  */
+void Audio_MAL_DAC_IRQHandler(void)
+{ 
+  Audio_MAL_IRQHandler();
+}
+
+/**
+  * @brief  I2S interrupt management
+  * @param  None
+  * @retval None
+  */
+void Audio_I2S_IRQHandler(void)
+{
+  /* Check on the I2S TXE flag */  
+  if (SPI_I2S_GetFlagStatus(SPI3, SPI_I2S_FLAG_TXE) != RESET)
+  { 
+    if (CurrAudioInterface == AUDIO_INTERFACE_DAC)
+    {
+      /* Wirte data to the DAC interface */
+      DAC_SetChannel1Data(DAC_Align_12b_L, EVAL_AUDIO_GetSampleCallBack()); 
+    }
+    
+    /* Send dummy data on I2S to avoid the underrun condition */
+    SPI_I2S_SendData(CODEC_I2S, EVAL_AUDIO_GetSampleCallBack()); 
+  }
+}
+/*========================
+
+                CS43L22 Audio Codec Control Functions
+                                                ==============================*/
+/**
+  * @brief  Initializes the audio codec and all related interfaces (control 
+  *         interface: I2C and audio interface: I2S)
+  * @param  OutputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
+  *                       OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO .
+  * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
+  * @param  AudioFreq: Audio frequency used to play the audio stream.
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t Codec_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
+{
+  uint32_t counter = 0; 
+
+  /* Configure the Codec related IOs */
+  Codec_GPIO_Init();   
+  
+  /* Reset the Codec Registers */
+  Codec_Reset();
+
+  /* Initialize the Control interface of the Audio Codec */
+  Codec_CtrlInterface_Init();     
+  
+  /* Keep Codec powered OFF */
+  counter += Codec_WriteRegister(0x02, 0x01);  
+      
+  counter += Codec_WriteRegister(0x04, 0xAF); /* SPK always OFF & HP always ON */
+  OutputDev = 0xAF;
+  
+  /* Clock configuration: Auto detection */  
+  counter += Codec_WriteRegister(0x05, 0x81);
+  
+  /* Set the Slave Mode and the audio Standard */  
+  counter += Codec_WriteRegister(0x06, CODEC_STANDARD);
+      
+  /* Set the Master volume */
+  Codec_VolumeCtrl(Volume);
+  
+  if (CurrAudioInterface == AUDIO_INTERFACE_DAC)
+  {
+    /* Enable the PassThrough on AIN1A and AIN1B */
+    counter += Codec_WriteRegister(0x08, 0x01);
+    counter += Codec_WriteRegister(0x09, 0x01);
+    
+    /* Route the analog input to the HP line */
+    counter += Codec_WriteRegister(0x0E, 0xC0);
+    
+    /* Set the Passthough volume */
+    counter += Codec_WriteRegister(0x14, 0x00);
+    counter += Codec_WriteRegister(0x15, 0x00);
+  }
+
+  /* Power on the Codec */
+  counter += Codec_WriteRegister(0x02, 0x9E);  
+  
+  /* Additional configuration for the CODEC. These configurations are done to reduce
+      the time needed for the Codec to power off. If these configurations are removed, 
+      then a long delay should be added between powering off the Codec and switching 
+      off the I2S peripheral MCLK clock (which is the operating clock for Codec).
+      If this delay is not inserted, then the codec will not shut down properly and
+      it results in high noise after shut down. */
+  
+  /* Disable the analog soft ramp */
+  counter += Codec_WriteRegister(0x0A, 0x00);
+  if (CurrAudioInterface != AUDIO_INTERFACE_DAC)
+  {  
+    /* Disable the digital soft ramp */
+    counter += Codec_WriteRegister(0x0E, 0x04);
+  }
+  /* Disable the limiter attack level */
+  counter += Codec_WriteRegister(0x27, 0x00);
+  /* Adjust Bass and Treble levels */
+  counter += Codec_WriteRegister(0x1F, 0x0F);
+  /* Adjust PCM volume level */
+  counter += Codec_WriteRegister(0x1A, 0x0A);
+  counter += Codec_WriteRegister(0x1B, 0x0A);
+
+  /* Configure the I2S peripheral */
+  Codec_AudioInterface_Init(AudioFreq);  
+  
+  /* Return communication control value */
+  return counter;  
+}
+
+/**
+  * @brief  Restore the audio codec state to default state and free all used 
+  *         resources.
+  * @param  None
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t Codec_DeInit(void)
+{
+  uint32_t counter = 0; 
+
+  /* Reset the Codec Registers */
+  Codec_Reset();  
+  
+  /* Keep Codec powered OFF */
+  counter += Codec_WriteRegister(0x02, 0x01);    
+  
+  /* Deinitialize all use GPIOs */
+  Codec_GPIO_DeInit();
+
+  /* Disable the Codec control interface */
+  Codec_CtrlInterface_DeInit();
+  
+  /* Deinitialize the Codec audio interface (I2S) */
+  Codec_AudioInterface_DeInit(); 
+  
+  /* Return communication control value */
+  return counter;  
+}
+
+/**
+  * @brief  Start the audio Codec play feature.
+  * @note   For this codec no Play options are required.
+  * @param  None
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t Codec_Play(void)
+{
+  /* 
+     No actions required on Codec level for play command
+     */  
+
+  /* Return communication control value */
+  return 0;  
+}
+
+/**
+  * @brief  Pauses and resumes playing on the audio codec.
+  * @param  Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different
+  *         from 0) to resume. 
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t Codec_PauseResume(uint32_t Cmd)
+{
+  uint32_t counter = 0;   
+  
+  /* Pause the audio file playing */
+  if (Cmd == AUDIO_PAUSE)
+  { 
+    /* Mute the output first */
+    counter += Codec_Mute(AUDIO_MUTE_ON);
+
+    /* Put the Codec in Power save mode */    
+    counter += Codec_WriteRegister(0x02, 0x01);    
+  }
+  else /* AUDIO_RESUME */
+  {
+    /* Unmute the output first */
+    counter += Codec_Mute(AUDIO_MUTE_OFF);
+    
+    counter += Codec_WriteRegister(0x04, OutputDev);
+    
+    /* Exit the Power save mode */
+    counter += Codec_WriteRegister(0x02, 0x9E); 
+  }
+
+  return counter;
+}
+
+/**
+  * @brief  Stops audio Codec playing. It powers down the codec.
+  * @param  CodecPdwnMode: selects the  power down mode.
+  *          - CODEC_PDWN_SW: only mutes the audio codec. When resuming from this 
+  *                           mode the codec keeps the previous initialization
+  *                           (no need to re-Initialize the codec registers).
+  *          - CODEC_PDWN_HW: Physically power down the codec. When resuming from this
+  *                           mode, the codec is set to default configuration 
+  *                           (user should re-Initialize the codec in order to 
+  *                            play again the audio stream).
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t Codec_Stop(uint32_t CodecPdwnMode)
+{
+  uint32_t counter = 0;   
+
+  /* Mute the output first */
+  Codec_Mute(AUDIO_MUTE_ON);
+  
+  if (CodecPdwnMode == CODEC_PDWN_SW)
+  {    
+    /* Power down the DAC and the speaker (PMDAC and PMSPK bits)*/
+    counter += Codec_WriteRegister(0x02, 0x9F);
+  }
+  else /* CODEC_PDWN_HW */
+  { 
+    /* Power down the DAC components */
+    counter += Codec_WriteRegister(0x02, 0x9F);
+    
+    /* Wait at least 100us */
+    Delay(0xFFF);
+    
+    /* Reset The pin */
+    GPIO_WriteBit(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, Bit_RESET);
+  }
+  
+  return counter;    
+}
+
+/**
+  * @brief  Sets higher or lower the codec volume level.
+  * @param  Volume: a byte value from 0 to 255 (refer to codec registers 
+  *         description for more details).
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t Codec_VolumeCtrl(uint8_t Volume)
+{
+  uint32_t counter = 0;
+  
+  if (Volume > 0xE6)
+  {
+    /* Set the Master volume */
+    counter += Codec_WriteRegister(0x20, Volume - 0xE7); 
+    counter += Codec_WriteRegister(0x21, Volume - 0xE7);     
+  }
+  else
+  {
+    /* Set the Master volume */
+    counter += Codec_WriteRegister(0x20, Volume + 0x19); 
+    counter += Codec_WriteRegister(0x21, Volume + 0x19); 
+  }
+
+  return counter;  
+}
+
+/**
+  * @brief  Enables or disables the mute feature on the audio codec.
+  * @param  Cmd: AUDIO_MUTE_ON to enable the mute or AUDIO_MUTE_OFF to disable the
+  *             mute mode.
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t Codec_Mute(uint32_t Cmd)
+{
+  uint32_t counter = 0;  
+  
+  /* Set the Mute mode */
+  if (Cmd == AUDIO_MUTE_ON)
+  {
+    counter += Codec_WriteRegister(0x04, 0xFF);
+  }
+  else /* AUDIO_MUTE_OFF Disable the Mute */
+  {
+    counter += Codec_WriteRegister(0x04, OutputDev);
+  }
+  
+  return counter; 
+}
+
+/**
+  * @brief  Resets the audio codec. It restores the default configuration of the 
+  *         codec (this function shall be called before initializing the codec).
+  * @note   This function calls an external driver function: The IO Expander driver.
+  * @param  None
+  * @retval None
+  */
+static void Codec_Reset(void)
+{
+  /* Power Down the codec */
+  GPIO_WriteBit(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, Bit_RESET);
+
+  /* wait for a delay to insure registers erasing */
+  Delay(CODEC_RESET_DELAY); 
+  
+  /* Power on the codec */
+  GPIO_WriteBit(AUDIO_RESET_GPIO, AUDIO_RESET_PIN, Bit_SET);
+}
+
+/**
+  * @brief  Writes a Byte to a given register into the audio codec through the 
+            control interface (I2C)
+  * @param  RegisterAddr: The address (location) of the register to be written.
+  * @param  RegisterValue: the Byte value to be written into destination register.
+  * @retval 0 if correct communication, else wrong communication
+  */
+static uint32_t Codec_WriteRegister(uint8_t RegisterAddr, uint8_t RegisterValue)
+{
+  uint32_t result = 0;
+
+  /*!< While the bus is busy */
+  CODECTimeout = CODEC_LONG_TIMEOUT;
+  while(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BUSY))
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }
+  
+  /* Start the config sequence */
+  I2C_GenerateSTART(CODEC_I2C, ENABLE);
+
+  /* Test on EV5 and clear it */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_MODE_SELECT))
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }
+  
+  /* Transmit the slave address and enable writing operation */
+  I2C_Send7bitAddress(CODEC_I2C, CODEC_ADDRESS, I2C_Direction_Transmitter);
+
+  /* Test on EV6 and clear it */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }
+
+  /* Transmit the first address for write operation */
+  I2C_SendData(CODEC_I2C, RegisterAddr);
+
+  /* Test on EV8 and clear it */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_BYTE_TRANSMITTING))
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }
+  
+  /* Prepare the register value to be sent */
+  I2C_SendData(CODEC_I2C, RegisterValue);
+  
+  /*!< Wait till all data have been physically transferred on the bus */
+  CODECTimeout = CODEC_LONG_TIMEOUT;
+  while(!I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BTF))
+  {
+    if((CODECTimeout--) == 0) Codec_TIMEOUT_UserCallback();
+  }
+  
+  /* End the configuration sequence */
+  I2C_GenerateSTOP(CODEC_I2C, ENABLE);  
+  
+#ifdef VERIFY_WRITTENDATA
+  /* Verify that the data has been correctly written */  
+  result = (Codec_ReadRegister(RegisterAddr) == RegisterValue)? 0:1;
+#endif /* VERIFY_WRITTENDATA */
+
+  /* Return the verifying value: 0 (Passed) or 1 (Failed) */
+  return result;  
+}
+
+/**
+  * @brief  Reads and returns the value of an audio codec register through the
+  *         control interface (I2C).
+  * @param  RegisterAddr: Address of the register to be read.
+  * @retval Value of the register to be read or dummy value if the communication
+  *         fails.
+  */
+static uint32_t Codec_ReadRegister(uint8_t RegisterAddr)
+{
+  uint32_t result = 0;
+
+  /*!< While the bus is busy */
+  CODECTimeout = CODEC_LONG_TIMEOUT;
+  while(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BUSY))
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }
+  
+  /* Start the config sequence */
+  I2C_GenerateSTART(CODEC_I2C, ENABLE);
+
+  /* Test on EV5 and clear it */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_MODE_SELECT))
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }
+  
+  /* Transmit the slave address and enable writing operation */
+  I2C_Send7bitAddress(CODEC_I2C, CODEC_ADDRESS, I2C_Direction_Transmitter);
+
+  /* Test on EV6 and clear it */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while (!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }
+
+  /* Transmit the register address to be read */
+  I2C_SendData(CODEC_I2C, RegisterAddr);
+
+  /* Test on EV8 and clear it */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while (I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_BTF) == RESET)
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }
+  
+  /*!< Send START condition a second time */  
+  I2C_GenerateSTART(CODEC_I2C, ENABLE);
+  
+  /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while(!I2C_CheckEvent(CODEC_I2C, I2C_EVENT_MASTER_MODE_SELECT))
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  } 
+  
+  /*!< Send Codec address for read */
+  I2C_Send7bitAddress(CODEC_I2C, CODEC_ADDRESS, I2C_Direction_Receiver);  
+  
+  /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_ADDR) == RESET)
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }     
+  
+  /*!< Disable Acknowledgment */
+  I2C_AcknowledgeConfig(CODEC_I2C, DISABLE);   
+  
+  /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */
+  (void)CODEC_I2C->SR2;
+  
+  /*!< Send STOP Condition */
+  I2C_GenerateSTOP(CODEC_I2C, ENABLE);
+  
+  /* Wait for the byte to be received */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while(I2C_GetFlagStatus(CODEC_I2C, I2C_FLAG_RXNE) == RESET)
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }
+  
+  /*!< Read the byte received from the Codec */
+  result = I2C_ReceiveData(CODEC_I2C);
+  
+  /* Wait to make sure that STOP flag has been cleared */
+  CODECTimeout = CODEC_FLAG_TIMEOUT;
+  while(CODEC_I2C->CR1 & I2C_CR1_STOP)
+  {
+    if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback();
+  }  
+  
+  /*!< Re-Enable Acknowledgment to be ready for another reception */
+  I2C_AcknowledgeConfig(CODEC_I2C, ENABLE);  
+  
+  /* Clear AF flag for next communication */
+  I2C_ClearFlag(CODEC_I2C, I2C_FLAG_AF); 
+  
+  /* Return the byte read from Codec */
+  return result;
+}
+
+/**
+  * @brief  Initializes the Audio Codec control interface (I2C).
+  * @param  None
+  * @retval None
+  */
+static void Codec_CtrlInterface_Init(void)
+{
+  I2C_InitTypeDef I2C_InitStructure;
+  
+  /* Enable the CODEC_I2C peripheral clock */
+  RCC_APB1PeriphClockCmd(CODEC_I2C_CLK, ENABLE);
+  
+  /* CODEC_I2C peripheral configuration */
+  I2C_DeInit(CODEC_I2C);
+  I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
+  I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
+  I2C_InitStructure.I2C_OwnAddress1 = 0x33;
+  I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
+  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
+  I2C_InitStructure.I2C_ClockSpeed = I2C_SPEED;
+  /* Enable the I2C peripheral */
+  I2C_Cmd(CODEC_I2C, ENABLE);  
+  I2C_Init(CODEC_I2C, &I2C_InitStructure);
+}
+
+/**
+  * @brief  Restore the Audio Codec control interface to its default state.
+  *         This function doesn't de-initialize the I2C because the I2C peripheral
+  *         may be used by other modules.
+  * @param  None
+  * @retval None
+  */
+static void Codec_CtrlInterface_DeInit(void)
+{
+  /* Disable the I2C peripheral */ /* This step is not done here because 
+     the I2C interface can be used by other modules */
+  /* I2C_DeInit(CODEC_I2C); */
+}
+
+/**
+  * @brief  Initializes the Audio Codec audio interface (I2S)
+  * @note   This function assumes that the I2S input clock (through PLL_R in 
+  *         Devices RevA/Z and through dedicated PLLI2S_R in Devices RevB/Y)
+  *         is already configured and ready to be used.    
+  * @param  AudioFreq: Audio frequency to be configured for the I2S peripheral. 
+  * @retval None
+  */
+static void Codec_AudioInterface_Init(uint32_t AudioFreq)
+{
+  I2S_InitTypeDef I2S_InitStructure;
+  DAC_InitTypeDef  DAC_InitStructure;
+
+  /* Enable the CODEC_I2S peripheral clock */
+  RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, ENABLE);
+  
+  /* CODEC_I2S peripheral configuration */
+  SPI_I2S_DeInit(CODEC_I2S);
+  I2S_InitStructure.I2S_AudioFreq = AudioFreq;
+  I2S_InitStructure.I2S_Standard = I2S_STANDARD;
+  I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
+  I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
+#ifdef DAC_USE_I2S_DMA
+  if (CurrAudioInterface == AUDIO_INTERFACE_DAC)
+  {  
+    I2S_InitStructure.I2S_Mode = I2S_Mode_MasterRx;
+  }
+  else
+  {
+#else
+   I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
+#endif
+#ifdef DAC_USE_I2S_DMA
+  }
+#endif /* DAC_USE_I2S_DMA */
+#ifdef CODEC_MCLK_ENABLED
+  I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
+#elif defined(CODEC_MCLK_DISABLED)
+  I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Disable;
+#else
+#error "No selection for the MCLK output has been defined !"
+#endif /* CODEC_MCLK_ENABLED */
+  
+  /* Initialize the I2S peripheral with the structure above */
+  I2S_Init(CODEC_I2S, &I2S_InitStructure);
+
+
+  /* Configure the DAC interface */
+  if (CurrAudioInterface == AUDIO_INTERFACE_DAC)
+  {    
+    /* DAC Periph clock enable */
+    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
+    
+    /* DAC channel1 Configuration */
+    DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
+    DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
+    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+    DAC_Init(AUDIO_DAC_CHANNEL, &DAC_InitStructure);
+    
+    /* Enable DAC Channel1 */
+    DAC_Cmd(AUDIO_DAC_CHANNEL, ENABLE);  
+  }
+  
+  /* The I2S peripheral will be enabled only in the EVAL_AUDIO_Play() function 
+       or by user functions if DMA mode not enabled */  
+}
+
+/**
+  * @brief  Restores the Audio Codec audio interface to its default state.
+  * @param  None
+  * @retval None
+  */
+static void Codec_AudioInterface_DeInit(void)
+{
+  /* Disable the CODEC_I2S peripheral (in case it hasn't already been disabled) */
+  I2S_Cmd(CODEC_I2S, DISABLE);
+  
+  /* Deinitialize the CODEC_I2S peripheral */
+  SPI_I2S_DeInit(CODEC_I2S);
+  
+  /* Disable the CODEC_I2S peripheral clock */
+  RCC_APB1PeriphClockCmd(CODEC_I2S_CLK, DISABLE); 
+}
+
+/**
+  * @brief Initializes IOs used by the Audio Codec (on the control and audio 
+  *        interfaces).
+  * @param  None
+  * @retval None
+  */
+static void Codec_GPIO_Init(void)
+{
+  GPIO_InitTypeDef GPIO_InitStructure;
+  
+  /* Enable Reset GPIO Clock */
+  RCC_AHB1PeriphClockCmd(AUDIO_RESET_GPIO_CLK,ENABLE);
+  
+  /* Audio reset pin configuration -------------------------------------------------*/
+  GPIO_InitStructure.GPIO_Pin = AUDIO_RESET_PIN; 
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
+  GPIO_Init(AUDIO_RESET_GPIO, &GPIO_InitStructure);    
+  
+  /* Enable I2S and I2C GPIO clocks */
+  RCC_AHB1PeriphClockCmd(CODEC_I2C_GPIO_CLOCK | CODEC_I2S_GPIO_CLOCK, ENABLE);
+
+  /* CODEC_I2C SCL and SDA pins configuration -------------------------------------*/
+  GPIO_InitStructure.GPIO_Pin = CODEC_I2C_SCL_PIN | CODEC_I2C_SDA_PIN; 
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
+  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
+  GPIO_Init(CODEC_I2C_GPIO, &GPIO_InitStructure);     
+  /* Connect pins to I2C peripheral */
+  GPIO_PinAFConfig(CODEC_I2C_GPIO, CODEC_I2S_SCL_PINSRC, CODEC_I2C_GPIO_AF);  
+  GPIO_PinAFConfig(CODEC_I2C_GPIO, CODEC_I2S_SDA_PINSRC, CODEC_I2C_GPIO_AF);  
+
+  /* CODEC_I2S pins configuration: WS, SCK and SD pins -----------------------------*/
+  GPIO_InitStructure.GPIO_Pin = CODEC_I2S_SCK_PIN | CODEC_I2S_SD_PIN; 
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_Init(CODEC_I2S_GPIO, &GPIO_InitStructure);
+  
+  /* Connect pins to I2S peripheral  */
+  GPIO_PinAFConfig(CODEC_I2S_WS_GPIO, CODEC_I2S_WS_PINSRC, CODEC_I2S_GPIO_AF);  
+  GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SCK_PINSRC, CODEC_I2S_GPIO_AF);
+
+  if (CurrAudioInterface != AUDIO_INTERFACE_DAC) 
+  {
+    GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN ;
+    GPIO_Init(CODEC_I2S_WS_GPIO, &GPIO_InitStructure); 
+    GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SD_PINSRC, CODEC_I2S_GPIO_AF);
+  }
+  else
+  {
+    /* GPIOA clock enable (to be used with DAC) */
+    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
+   
+    /* DAC channel 1 & 2 (DAC_OUT1 = PA.4) configuration */
+    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
+    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
+    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+    GPIO_Init(GPIOA, &GPIO_InitStructure);
+  }
+
+#ifdef CODEC_MCLK_ENABLED
+  /* CODEC_I2S pins configuration: MCK pin */
+  GPIO_InitStructure.GPIO_Pin = CODEC_I2S_MCK_PIN; 
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_Init(CODEC_I2S_MCK_GPIO, &GPIO_InitStructure);   
+  /* Connect pins to I2S peripheral  */
+  GPIO_PinAFConfig(CODEC_I2S_MCK_GPIO, CODEC_I2S_MCK_PINSRC, CODEC_I2S_GPIO_AF); 
+#endif /* CODEC_MCLK_ENABLED */ 
+}
+
+/**
+  * @brief  Restores the IOs used by the Audio Codec interface to their default state.
+  * @param  None
+  * @retval None
+  */
+static void Codec_GPIO_DeInit(void)
+{
+  GPIO_InitTypeDef GPIO_InitStructure;
+  
+  /* Deinitialize all the GPIOs used by the driver */
+  GPIO_InitStructure.GPIO_Pin =  CODEC_I2S_SCK_PIN | CODEC_I2S_SD_PIN;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
+  GPIO_Init(CODEC_I2S_GPIO, &GPIO_InitStructure);  
+  
+  GPIO_InitStructure.GPIO_Pin = CODEC_I2S_WS_PIN ;
+  GPIO_Init(CODEC_I2S_WS_GPIO, &GPIO_InitStructure); 
+     
+  /* Disconnect pins from I2S peripheral  */
+  GPIO_PinAFConfig(CODEC_I2S_WS_GPIO, CODEC_I2S_WS_PINSRC, 0x00);  
+  GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SCK_PINSRC, 0x00);
+  GPIO_PinAFConfig(CODEC_I2S_GPIO, CODEC_I2S_SD_PINSRC, 0x00);  
+  
+#ifdef CODEC_MCLK_ENABLED
+  /* CODEC_I2S pins deinitialization: MCK pin */
+  GPIO_InitStructure.GPIO_Pin = CODEC_I2S_MCK_PIN; 
+  GPIO_Init(CODEC_I2S_MCK_GPIO, &GPIO_InitStructure);   
+  /* Disconnect pins from I2S peripheral  */
+  GPIO_PinAFConfig(CODEC_I2S_MCK_GPIO, CODEC_I2S_MCK_PINSRC, CODEC_I2S_GPIO_AF); 
+#endif /* CODEC_MCLK_ENABLED */    
+}
+
+/**
+  * @brief  Inserts a delay time (not accurate timing).
+  * @param  nCount: specifies the delay time length.
+  * @retval None
+  */
+static void Delay( __IO uint32_t nCount)
+{
+  for (; nCount != 0; nCount--);
+}
+
+#ifdef USE_DEFAULT_TIMEOUT_CALLBACK
+/**
+  * @brief  Basic management of the timeout situation.
+  * @param  None
+  * @retval None
+  */
+uint32_t Codec_TIMEOUT_UserCallback(void)
+{
+  /* Block communication and all processes */
+  while (1)
+  {   
+  }
+}
+#endif /* USE_DEFAULT_TIMEOUT_CALLBACK */
+/*========================
+
+                Audio MAL Interface Control Functions
+
+                                                ==============================*/
+
+/**
+  * @brief  Initializes and prepares the Media to perform audio data transfer 
+  *         from Media to the I2S peripheral.
+  * @param  None
+  * @retval None
+  */
+static void Audio_MAL_Init(void)  
+{ 
+  
+#ifdef I2S_INTERRUPT  
+  NVIC_InitTypeDef   NVIC_InitStructure;
+
+  NVIC_InitStructure.NVIC_IRQChannel = SPI3_IRQn;
+  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
+  NVIC_InitStructure.NVIC_IRQChannelSubPriority =0;
+  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+  NVIC_Init(&NVIC_InitStructure);
+  
+  SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, ENABLE);
+
+  I2S_Cmd(SPI3, ENABLE); 
+#else  
+#if defined(AUDIO_MAL_DMA_IT_TC_EN) || defined(AUDIO_MAL_DMA_IT_HT_EN) || defined(AUDIO_MAL_DMA_IT_TE_EN)
+  NVIC_InitTypeDef NVIC_InitStructure;
+#endif
+
+  if (CurrAudioInterface == AUDIO_INTERFACE_I2S)
+  {
+    /* Enable the DMA clock */
+    RCC_AHB1PeriphClockCmd(AUDIO_MAL_DMA_CLOCK, ENABLE); 
+    
+    /* Configure the DMA Stream */
+    DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
+    DMA_DeInit(AUDIO_MAL_DMA_STREAM);
+    /* Set the parameters to be configured */
+    DMA_InitStructure.DMA_Channel = AUDIO_MAL_DMA_CHANNEL;  
+    DMA_InitStructure.DMA_PeripheralBaseAddr = AUDIO_MAL_DMA_DREG;
+    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;      /* This field will be configured in play function */
+    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
+    DMA_InitStructure.DMA_BufferSize = (uint32_t)0xFFFE;      /* This field will be configured in play function */
+    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+    DMA_InitStructure.DMA_PeripheralDataSize = AUDIO_MAL_DMA_PERIPH_DATA_SIZE;
+    DMA_InitStructure.DMA_MemoryDataSize = AUDIO_MAL_DMA_MEM_DATA_SIZE; 
+#ifdef AUDIO_MAL_MODE_NORMAL
+    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
+#elif defined(AUDIO_MAL_MODE_CIRCULAR)
+    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
+#else
+#error "AUDIO_MAL_MODE_NORMAL or AUDIO_MAL_MODE_CIRCULAR should be selected !!"
+#endif /* AUDIO_MAL_MODE_NORMAL */  
+    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
+    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;         
+    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
+    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  
+    DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);  
+    
+    /* Enable the selected DMA interrupts (selected in "stm32f4_discovery_eval_audio_codec.h" defines) */
+#ifdef AUDIO_MAL_DMA_IT_TC_EN
+    DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TC, ENABLE);
+#endif /* AUDIO_MAL_DMA_IT_TC_EN */
+#ifdef AUDIO_MAL_DMA_IT_HT_EN
+    DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_HT, ENABLE);
+#endif /* AUDIO_MAL_DMA_IT_HT_EN */
+#ifdef AUDIO_MAL_DMA_IT_TE_EN
+    DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TE | DMA_IT_FE | DMA_IT_DME, ENABLE);
+#endif /* AUDIO_MAL_DMA_IT_TE_EN */
+    
+#if defined(AUDIO_MAL_DMA_IT_TC_EN) || defined(AUDIO_MAL_DMA_IT_HT_EN) || defined(AUDIO_MAL_DMA_IT_TE_EN)
+    /* I2S DMA IRQ Channel configuration */
+    NVIC_InitStructure.NVIC_IRQChannel = AUDIO_MAL_DMA_IRQ;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = EVAL_AUDIO_IRQ_PREPRIO;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = EVAL_AUDIO_IRQ_SUBRIO;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+    NVIC_Init(&NVIC_InitStructure);
+#endif     
+  }
+
+#ifdef DAC_USE_I2S_DMA
+  else
+  {
+    /* Enable the DMA clock */
+    RCC_AHB1PeriphClockCmd(AUDIO_MAL_DMA_CLOCK, ENABLE); 
+    
+    /* Configure the DMA Stream */
+    DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
+    DMA_DeInit(AUDIO_MAL_DMA_STREAM);
+    /* Set the parameters to be configured */
+    DMA_InitStructure.DMA_Channel = AUDIO_MAL_DMA_CHANNEL;  
+    DMA_InitStructure.DMA_PeripheralBaseAddr = AUDIO_MAL_DMA_DREG;
+    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0;      /* This field will be configured in play function */
+    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
+    DMA_InitStructure.DMA_BufferSize = (uint32_t)0xFFFE;      /* This field will be configured in play function */
+    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
+    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
+    DMA_InitStructure.DMA_PeripheralDataSize = AUDIO_MAL_DMA_PERIPH_DATA_SIZE;
+    DMA_InitStructure.DMA_MemoryDataSize = AUDIO_MAL_DMA_MEM_DATA_SIZE; 
+#ifdef AUDIO_MAL_MODE_NORMAL
+    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
+#elif defined(AUDIO_MAL_MODE_CIRCULAR)
+    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
+#else
+#error "AUDIO_MAL_MODE_NORMAL or AUDIO_MAL_MODE_CIRCULAR should be selected !!"
+#endif /* AUDIO_MAL_MODE_NORMAL */  
+    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
+    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;         
+    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
+    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
+    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;  
+    DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);  
+    
+    /* Enable the selected DMA interrupts (selected in "stm32f4_discovery_eval_audio_codec.h" defines) */
+#ifdef AUDIO_MAL_DMA_IT_TC_EN
+    DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TC, ENABLE);
+#endif /* AUDIO_MAL_DMA_IT_TC_EN */
+#ifdef AUDIO_MAL_DMA_IT_HT_EN
+    DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_HT, ENABLE);
+#endif /* AUDIO_MAL_DMA_IT_HT_EN */
+#ifdef AUDIO_MAL_DMA_IT_TE_EN
+    DMA_ITConfig(AUDIO_MAL_DMA_STREAM, DMA_IT_TE | DMA_IT_FE | DMA_IT_DME, ENABLE);
+#endif /* AUDIO_MAL_DMA_IT_TE_EN */
+    
+#if defined(AUDIO_MAL_DMA_IT_TC_EN) || defined(AUDIO_MAL_DMA_IT_HT_EN) || defined(AUDIO_MAL_DMA_IT_TE_EN)
+    /* I2S DMA IRQ Channel configuration */
+    NVIC_InitStructure.NVIC_IRQChannel = AUDIO_MAL_DMA_IRQ;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = EVAL_AUDIO_IRQ_PREPRIO;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = EVAL_AUDIO_IRQ_SUBRIO;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+    NVIC_Init(&NVIC_InitStructure);
+#endif 
+  }
+#endif /* DAC_USE_I2S_DMA */
+  
+  if (CurrAudioInterface == AUDIO_INTERFACE_I2S)
+  {
+    /* Enable the I2S DMA request */
+    SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, ENABLE);  
+  }
+  else
+  {
+    /* Configure the STM32 DAC to geenrate audio analog signal */
+    DAC_Config();
+    
+#ifndef DAC_USE_I2S_DMA
+    /* Enable the I2S interrupt used to write into the DAC register */
+    SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, ENABLE);
+    
+    /* I2S DMA IRQ Channel configuration */
+    NVIC_InitStructure.NVIC_IRQChannel = CODEC_I2S_IRQ;
+    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = EVAL_AUDIO_IRQ_PREPRIO;
+    NVIC_InitStructure.NVIC_IRQChannelSubPriority = EVAL_AUDIO_IRQ_SUBRIO;
+    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+    NVIC_Init(&NVIC_InitStructure); 
+#else
+    /* Enable the I2S DMA request */
+    SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Rx, ENABLE);   
+#endif /* DAC_USE_I2S_DMA */
+  }
+#endif
+}
+
+/**
+  * @brief  Restore default state of the used Media.
+  * @param  None
+  * @retval None
+  */
+static void Audio_MAL_DeInit(void)  
+{   
+#if defined(AUDIO_MAL_DMA_IT_TC_EN) || defined(AUDIO_MAL_DMA_IT_HT_EN) || defined(AUDIO_MAL_DMA_IT_TE_EN)
+  NVIC_InitTypeDef NVIC_InitStructure;  
+  
+  /* Deinitialize the NVIC interrupt for the I2S DMA Stream */
+  NVIC_InitStructure.NVIC_IRQChannel = AUDIO_MAL_DMA_IRQ;
+  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = EVAL_AUDIO_IRQ_PREPRIO;
+  NVIC_InitStructure.NVIC_IRQChannelSubPriority = EVAL_AUDIO_IRQ_SUBRIO;
+  NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE;
+  NVIC_Init(&NVIC_InitStructure);  
+#endif 
+  
+  /* Disable the DMA stream before the deinit */
+  DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
+  
+  /* Dinitialize the DMA Stream */
+  DMA_DeInit(AUDIO_MAL_DMA_STREAM);
+  
+  /* 
+     The DMA clock is not disabled, since it can be used by other streams 
+                                                                          */ 
+}
+
+/**
+  * @brief  Starts playing audio stream from the audio Media.
+  * @param  None
+  * @retval None
+  */
+static void Audio_MAL_Play(uint32_t Addr, uint32_t Size)
+{         
+  if (CurrAudioInterface == AUDIO_INTERFACE_I2S)
+  {
+    /* Configure the buffer address and size */
+    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr;
+    DMA_InitStructure.DMA_BufferSize = (uint32_t)Size;
+    
+    /* Configure the DMA Stream with the new parameters */
+    DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
+    
+    /* Enable the I2S DMA Stream*/
+    DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);   
+  }
+#ifndef DAC_USE_I2S_DMA
+  else
+  {
+    /* Configure the buffer address and size */
+    DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)Addr;
+    DMA_InitStructure.DMA_BufferSize = (uint32_t)Size;
+    
+    /* Configure the DMA Stream with the new parameters */
+    DMA_Init(AUDIO_MAL_DMA_STREAM, &DMA_InitStructure);
+    
+    /* Enable the I2S DMA Stream*/
+    DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);
+  }
+#endif /* DAC_USE_I2S_DMA */
+  
+  /* If the I2S peripheral is still not enabled, enable it */
+  if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0)
+  {
+    I2S_Cmd(CODEC_I2S, ENABLE);
+  }
+}
+
+/**
+  * @brief  Pauses or Resumes the audio stream playing from the Media.
+  * @param  Cmd: AUDIO_PAUSE (or 0) to pause, AUDIO_RESUME (or any value different
+  *              from 0) to resume. 
+  * @param  Addr: Address from/at which the audio stream should resume/pause.
+  * @retval None
+  */
+static void Audio_MAL_PauseResume(uint32_t Cmd, uint32_t Addr)
+{
+  /* Pause the audio file playing */
+  if (Cmd == AUDIO_PAUSE)
+  {   
+    /* Disable the I2S DMA request */
+    SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, DISABLE);
+
+    /* Pause the I2S DMA Stream 
+        Note. For the STM32F4xx devices, the DMA implements a pause feature, 
+              by disabling the stream, all configuration is preserved and data 
+              transfer is paused till the next enable of the stream.
+              This feature is not available on STM32F4xx devices. */
+    DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
+  }
+  else /* AUDIO_RESUME */
+  {
+    /* Enable the I2S DMA request */
+    SPI_I2S_DMACmd(CODEC_I2S, SPI_I2S_DMAReq_Tx, ENABLE);
+  
+    /* Resume the I2S DMA Stream 
+        Note. For the STM32F4xx devices, the DMA implements a pause feature, 
+              by disabling the stream, all configuration is preserved and data 
+              transfer is paused till the next enable of the stream.
+              This feature is not available on STM32F4xx devices. */
+    DMA_Cmd(AUDIO_MAL_DMA_STREAM, ENABLE);
+    
+    /* If the I2S peripheral is still not enabled, enable it */
+    if ((CODEC_I2S->I2SCFGR & I2S_ENABLE_MASK) == 0)
+    {
+      I2S_Cmd(CODEC_I2S, ENABLE);
+    }    
+  } 
+}
+
+/**
+  * @brief  Stops audio stream playing on the used Media.
+  * @param  None
+  * @retval None
+  */
+static void Audio_MAL_Stop(void)
+{   
+  /* Stop the Transfer on the I2S side: Stop and disable the DMA stream */
+  DMA_Cmd(AUDIO_MAL_DMA_STREAM, DISABLE);
+
+  /* Clear all the DMA flags for the next transfer */
+  DMA_ClearFlag(AUDIO_MAL_DMA_STREAM, AUDIO_MAL_DMA_FLAG_TC |AUDIO_MAL_DMA_FLAG_HT | \
+                                  AUDIO_MAL_DMA_FLAG_FE | AUDIO_MAL_DMA_FLAG_TE);
+  
+  /*  
+           The I2S DMA requests are not disabled here.
+                                                            */
+  
+  /* In all modes, disable the I2S peripheral */
+  I2S_Cmd(CODEC_I2S, DISABLE);
+}
+
+/**
+  * @brief  DAC  Channel1 Configuration
+  * @param  None
+  * @retval None
+  */
+void DAC_Config(void)
+{
+  DAC_InitTypeDef  DAC_InitStructure;
+  GPIO_InitTypeDef GPIO_InitStructure;
+
+  /* DMA1 clock and GPIOA clock enable (to be used with DAC) */
+  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1 | RCC_AHB1Periph_GPIOA, ENABLE);
+
+  /* DAC Periph clock enable */
+  RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
+
+  /* DAC channel 1 & 2 (DAC_OUT1 = PA.4) configuration */
+  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
+  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
+  GPIO_Init(GPIOA, &GPIO_InitStructure);
+
+  /* DAC channel1 Configuration */
+  DAC_InitStructure.DAC_Trigger = DAC_Trigger_None;
+  DAC_InitStructure.DAC_WaveGeneration = DAC_WaveGeneration_None;
+  DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
+  DAC_Init(AUDIO_DAC_CHANNEL, &DAC_InitStructure);
+
+  /* Enable DAC Channel1 */
+  DAC_Cmd(AUDIO_DAC_CHANNEL, ENABLE);
+}
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
diff --git a/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_audio_codec.h b/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_audio_codec.h
new file mode 100644 (file)
index 0000000..33ba0e7
--- /dev/null
@@ -0,0 +1,304 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4_discovery_audio_codec.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    19-September-2011
+  * @brief   This file contains all the functions prototypes for the 
+  *          stm32f4_discovery_audio_codec.c driver.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************  
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4_DISCOVERY_AUDIOCODEC_H
+#define __STM32F4_DISCOVERY_AUDIOCODEC_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4xx.h"
+#include "stm32f4xx_gpio.h"
+
+/** @addtogroup Utilities
+  * @{
+  */
+
+
+/** @addtogroup STM32F4_DISCOVERY
+  * @{
+  */
+    
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC 
+  * @{
+  */    
+
+
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Exported_Types
+  * @{
+  */
+
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Exported_Constants
+  * @{
+  */ 
+
+/*------------------------------------
+             CONFIGURATION: Audio Codec Driver Configuration parameters
+                                      ----------------------------------------*/
+#define I2S_INTERRUPT
+/* Audio Transfer mode (DMA, Interrupt or Polling) */
+#define AUDIO_MAL_MODE_NORMAL         /* Uncomment this line to enable the audio 
+                                         Transfer using DMA */
+/* #define AUDIO_MAL_MODE_CIRCULAR */ /* Uncomment this line to enable the audio 
+                                         Transfer using DMA */
+
+/* For the DMA modes select the interrupt that will be used */
+#define AUDIO_MAL_DMA_IT_TC_EN        /* Uncomment this line to enable DMA Transfer Complete interrupt */
+/* #define AUDIO_MAL_DMA_IT_HT_EN */  /* Uncomment this line to enable DMA Half Transfer Complete interrupt */
+/* #define AUDIO_MAL_DMA_IT_TE_EN */  /* Uncomment this line to enable DMA Transfer Error interrupt */
+
+/* Select the interrupt preemption priority and subpriority for the DMA interrupt */
+#define EVAL_AUDIO_IRQ_PREPRIO           0   /* Select the preemption priority level(0 is the highest) */
+#define EVAL_AUDIO_IRQ_SUBRIO            0   /* Select the sub-priority level (0 is the highest) */
+
+/* Uncomment the following line to use the default Codec_TIMEOUT_UserCallback() 
+   function implemented in stm32f4_discovery_audio_codec.c file.
+   Codec_TIMEOUT_UserCallback() function is called whenever a timeout condition 
+   occurs during communication (waiting on an event that doesn't occur, bus 
+   errors, busy devices ...). */   
+/* #define USE_DEFAULT_TIMEOUT_CALLBACK */
+
+/* Enable this define to use the I2S DMA for writing into DAC register */
+//#define DAC_USE_I2S_DMA
+/*----------------------------------------------------------------------------*/
+
+/*------------------------------------
+                    OPTIONAL Configuration defines parameters
+                                      ----------------------------------------*/
+/* I2C clock speed configuration (in Hz) 
+  WARNING: 
+   Make sure that this define is not already declared in other files (ie. 
+  stm322xg_eval.h file). It can be used in parallel by other modules. */
+#ifndef I2C_SPEED
+ #define I2C_SPEED                        100000
+#endif /* I2C_SPEED */
+
+/* Uncomment defines below to select standard for audio communication between 
+  Codec and I2S peripheral */
+#define I2S_STANDARD_PHILLIPS
+/* #define I2S_STANDARD_MSB */
+/* #define I2S_STANDARD_LSB */
+
+/* Uncomment the defines below to select if the Master clock mode should be 
+  enabled or not */
+#define CODEC_MCLK_ENABLED
+/* #deine CODEC_MCLK_DISABLED */
+
+/* Uncomment this line to enable verifying data sent to codec after each write 
+  operation */
+#define VERIFY_WRITTENDATA 
+/*----------------------------------------------------------------------------*/
+
+/*-----------------------------------
+                    Hardware Configuration defines parameters
+                                     -----------------------------------------*/
+/* Audio Reset Pin definition */
+#define AUDIO_RESET_GPIO_CLK           RCC_AHB1Periph_GPIOD  
+#define AUDIO_RESET_PIN                GPIO_Pin_4    
+#define AUDIO_RESET_GPIO               GPIOD 
+                 
+/* I2S peripheral configuration defines */
+#define CODEC_I2S                      SPI3
+#define CODEC_I2S_CLK                  RCC_APB1Periph_SPI3
+#define CODEC_I2S_ADDRESS              0x40003C0C
+#define CODEC_I2S_GPIO_AF              GPIO_AF_SPI3
+#define CODEC_I2S_IRQ                  SPI3_IRQn
+#define CODEC_I2S_GPIO_CLOCK           (RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOA)
+#define CODEC_I2S_WS_PIN               GPIO_Pin_4
+#define CODEC_I2S_SCK_PIN              GPIO_Pin_10
+#define CODEC_I2S_SD_PIN               GPIO_Pin_12
+#define CODEC_I2S_MCK_PIN              GPIO_Pin_7
+#define CODEC_I2S_WS_PINSRC            GPIO_PinSource4
+#define CODEC_I2S_SCK_PINSRC           GPIO_PinSource10
+#define CODEC_I2S_SD_PINSRC            GPIO_PinSource12
+#define CODEC_I2S_MCK_PINSRC           GPIO_PinSource7
+#define CODEC_I2S_GPIO                 GPIOC
+#define CODEC_I2S_WS_GPIO              GPIOA
+#define CODEC_I2S_MCK_GPIO             GPIOC
+#define Audio_I2S_IRQHandler           SPI3_IRQHandler
+
+
+ #define AUDIO_MAL_DMA_PERIPH_DATA_SIZE DMA_PeripheralDataSize_HalfWord
+ #define AUDIO_MAL_DMA_MEM_DATA_SIZE    DMA_MemoryDataSize_HalfWord
+ #define DMA_MAX_SZE                    0xFFFF
+
+
+ #define DAC_DHR12L1_ADDRESS            0x4000740C
+ #define DAC_DHR12R1_ADDRESS            0x40007408
+ #define DAC_DHR8R1_ADDRESS             0x40007410
+ #define AUDIO_DAC_CHANNEL              DAC_Channel_1
+
+ /* I2S DMA Stream definitions */
+ #define AUDIO_I2S_DMA_CLOCK            RCC_AHB1Periph_DMA1
+ #define AUDIO_I2S_DMA_STREAM           DMA1_Stream7
+ #define AUDIO_I2S_DMA_DREG             CODEC_I2S_ADDRESS
+ #define AUDIO_I2S_DMA_CHANNEL          DMA_Channel_0
+ #define AUDIO_I2S_DMA_IRQ              DMA1_Stream7_IRQn
+ #define AUDIO_I2S_DMA_FLAG_TC          DMA_FLAG_TCIF7
+ #define AUDIO_I2S_DMA_FLAG_HT          DMA_FLAG_HTIF7
+ #define AUDIO_I2S_DMA_FLAG_FE          DMA_FLAG_FEIF7
+ #define AUDIO_I2S_DMA_FLAG_TE          DMA_FLAG_TEIF7
+ #define AUDIO_I2S_DMA_FLAG_DME         DMA_FLAG_DMEIF7
+
+ #define Audio_MAL_I2S_IRQHandler       DMA1_Stream7_IRQHandler
+
+
+ /* DAC DMA Stream definitions */
+ #define AUDIO_DAC_DMA_CLOCK            RCC_AHB1Periph_DMA1
+ #define AUDIO_DAC_DMA_STREAM           DMA1_Stream0
+ #define AUDIO_DAC_DMA_DREG             DAC_DHR12L1_ADDRESS
+ #define AUDIO_DAC_DMA_CHANNEL          DMA_Channel_0
+ #define AUDIO_DAC_DMA_IRQ              DMA1_Stream0_IRQn
+ #define AUDIO_DAC_DMA_FLAG_TC          DMA_FLAG_TCIF0
+ #define AUDIO_DAC_DMA_FLAG_HT          DMA_FLAG_HTIF0
+ #define AUDIO_DAC_DMA_FLAG_FE          DMA_FLAG_FEIF0
+ #define AUDIO_DAC_DMA_FLAG_TE          DMA_FLAG_TEIF0
+ #define AUDIO_DAC_DMA_FLAG_DME         DMA_FLAG_DMEIF0
+
+ #define Audio_MAL_DAC_IRQHandler       DMA1_Stream0_IRQHandler
+
+
+/* I2C peripheral configuration defines (control interface of the audio codec) */
+#define CODEC_I2C                      I2C1
+#define CODEC_I2C_CLK                  RCC_APB1Periph_I2C1
+#define CODEC_I2C_GPIO_CLOCK           RCC_AHB1Periph_GPIOB
+#define CODEC_I2C_GPIO_AF              GPIO_AF_I2C1
+#define CODEC_I2C_GPIO                 GPIOB
+#define CODEC_I2C_SCL_PIN              GPIO_Pin_6
+#define CODEC_I2C_SDA_PIN              GPIO_Pin_9
+#define CODEC_I2S_SCL_PINSRC           GPIO_PinSource6
+#define CODEC_I2S_SDA_PINSRC           GPIO_PinSource9
+
+/* Maximum Timeout values for flags and events waiting loops. These timeouts are
+   not based on accurate values, they just guarantee that the application will 
+   not remain stuck if the I2C communication is corrupted.
+   You may modify these timeout values depending on CPU frequency and application
+   conditions (interrupts routines ...). */   
+#define CODEC_FLAG_TIMEOUT             ((uint32_t)0x1000)
+#define CODEC_LONG_TIMEOUT             ((uint32_t)(300 * CODEC_FLAG_TIMEOUT))
+/*----------------------------------------------------------------------------*/
+
+/*-----------------------------------
+                        Audio Codec User defines
+                                     -----------------------------------------*/
+/* Audio interface : I2S or DAC */
+#define AUDIO_INTERFACE_I2S           1
+#define AUDIO_INTERFACE_DAC           2
+
+/* Codec output DEVICE */
+#define OUTPUT_DEVICE_SPEAKER         1
+#define OUTPUT_DEVICE_HEADPHONE       2
+#define OUTPUT_DEVICE_BOTH            3
+#define OUTPUT_DEVICE_AUTO            4
+
+/* Volume Levels values */
+#define DEFAULT_VOLMIN                0x00
+#define DEFAULT_VOLMAX                0xFF
+#define DEFAULT_VOLSTEP               0x04
+
+#define AUDIO_PAUSE                   0
+#define AUDIO_RESUME                  1
+
+/* Codec POWER DOWN modes */
+#define CODEC_PDWN_HW                 1
+#define CODEC_PDWN_SW                 2
+
+/* MUTE commands */
+#define AUDIO_MUTE_ON                 1
+#define AUDIO_MUTE_OFF                0
+/*----------------------------------------------------------------------------*/
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Exported_Macros
+  * @{
+  */ 
+#define VOLUME_CONVERT(x)    ((Volume > 100)? 100:((uint8_t)((Volume * 255) / 100)))
+#define DMA_MAX(x)           (((x) <= DMA_MAX_SZE)? (x):DMA_MAX_SZE)
+
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_AUDIO_CODEC_Exported_Functions
+  * @{
+  */ 
+void EVAL_AUDIO_SetAudioInterface(uint32_t Interface);
+uint32_t EVAL_AUDIO_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq);
+uint32_t EVAL_AUDIO_DeInit(void);
+uint32_t EVAL_AUDIO_Play(uint16_t* pBuffer, uint32_t Size);
+uint32_t EVAL_AUDIO_PauseResume(uint32_t Cmd);
+uint32_t EVAL_AUDIO_Stop(uint32_t CodecPowerDown_Mode);
+uint32_t EVAL_AUDIO_VolumeCtl(uint8_t Volume);
+uint32_t EVAL_AUDIO_Mute(uint32_t Command);
+void DAC_Config(void);
+
+/* User Callbacks: user has to implement these functions in his code if
+  they are needed. -----------------------------------------------------------*/
+
+uint16_t EVAL_AUDIO_GetSampleCallBack(void);
+
+/* This function is called when the requested data has been completely transferred.
+   In Normal mode (when  the define AUDIO_MAL_MODE_NORMAL is enabled) this function
+   is called at the end of the whole audio file.
+   In circular mode (when  the define AUDIO_MAL_MODE_CIRCULAR is enabled) this 
+   function is called at the end of the current buffer transmission. */
+void EVAL_AUDIO_TransferComplete_CallBack(uint32_t pBuffer, uint32_t Size);
+
+/* This function is called when half of the requested buffer has been transferred 
+   This callback is useful in Circular mode only (when AUDIO_MAL_MODE_CIRCULAR 
+   define is enabled)*/
+void EVAL_AUDIO_HalfTransfer_CallBack(uint32_t pBuffer, uint32_t Size);
+
+/* This function is called when an Interrupt due to transfer error on or peripheral
+   error occurs. */
+void EVAL_AUDIO_Error_CallBack(void* pData);
+
+/* Codec_TIMEOUT_UserCallback() function is called whenever a timeout condition 
+   occurs during communication (waiting on an event that doesn't occur, bus 
+   errors, busy devices ...) on the Codec control interface (I2C).
+   You can use the default timeout callback implementation by uncommenting the 
+   define USE_DEFAULT_TIMEOUT_CALLBACK in stm32f4_discovery_audio_codec.h file.
+   Typically the user implementation of this callback should reset I2C peripheral
+   and re-initialize communication or in worst case reset all the application. */
+uint32_t Codec_TIMEOUT_UserCallback(void);
+
+#endif /* __STM32F4_DISCOVERY_AUDIOCODEC_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+   
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
diff --git a/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_lis302dl.c b/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_lis302dl.c
new file mode 100644 (file)
index 0000000..d354dc4
--- /dev/null
@@ -0,0 +1,504 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4_discovery_lis302dl.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    19-September-2011
+  * @brief   This file provides a set of functions needed to manage the LIS302DL
+  *          MEMS accelerometer available on STM32F4-Discovery Kit.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************  
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f4_discovery_lis302dl.h"
+//ADDED BY ME!!!!!!!!!!!!!!!!!!!!
+#include "stm32f4xx_conf.h"
+
+/** @addtogroup Utilities
+  * @{
+  */ 
+
+/** @addtogroup STM32F4_DISCOVERY
+  * @{
+  */ 
+
+/** @addtogroup STM32F4_DISCOVERY_LIS302DL
+  * @{
+  */
+
+
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_TypesDefinitions
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Defines
+  * @{
+  */
+__IO uint32_t  LIS302DLTimeout = LIS302DL_FLAG_TIMEOUT;   
+
+/* Read/Write command */
+#define READWRITE_CMD              ((uint8_t)0x80) 
+/* Multiple byte read/write command */ 
+#define MULTIPLEBYTE_CMD           ((uint8_t)0x40)
+/* Dummy Byte Send by the SPI Master device in order to generate the Clock to the Slave device */
+#define DUMMY_BYTE                 ((uint8_t)0x00)
+
+/**
+  * @}
+  */
+
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Macros
+  * @{
+  */
+
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Variables
+  * @{
+  */ 
+
+/**
+  * @}
+  */
+
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_FunctionPrototypes
+  * @{
+  */
+static uint8_t LIS302DL_SendByte(uint8_t byte);
+static void LIS302DL_LowLevel_Init(void);
+/**
+  * @}
+  */
+
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Private_Functions
+  * @{
+  */
+
+
+/**
+  * @brief  Set LIS302DL Initialization.
+  * @param  LIS302DL_Config_Struct: pointer to a LIS302DL_Config_TypeDef structure 
+  *         that contains the configuration setting for the LIS302DL.
+  * @retval None
+  */
+void LIS302DL_Init(LIS302DL_InitTypeDef *LIS302DL_InitStruct)
+{
+  uint8_t ctrl = 0x00;
+  
+  /* Configure the low level interface ---------------------------------------*/
+  LIS302DL_LowLevel_Init();
+  
+  /* Configure MEMS: data rate, power mode, full scale, self test and axes */
+  ctrl = (uint8_t) (LIS302DL_InitStruct->Output_DataRate | LIS302DL_InitStruct->Power_Mode | \
+                    LIS302DL_InitStruct->Full_Scale | LIS302DL_InitStruct->Self_Test | \
+                    LIS302DL_InitStruct->Axes_Enable);
+  
+  /* Write value to MEMS CTRL_REG1 regsister */
+  LIS302DL_Write(&ctrl, LIS302DL_CTRL_REG1_ADDR, 1);
+}
+
+/**
+  * @brief  Set LIS302DL Internal High Pass Filter configuration.
+  * @param  LIS302DL_Filter_ConfigTypeDef: pointer to a LIS302DL_FilterConfig_TypeDef 
+  *         structure that contains the configuration setting for the LIS302DL Filter.
+  * @retval None
+  */
+void LIS302DL_FilterConfig(LIS302DL_FilterConfigTypeDef *LIS302DL_FilterConfigStruct)
+{
+  uint8_t ctrl = 0x00;
+  
+  /* Read CTRL_REG2 register */
+  LIS302DL_Read(&ctrl, LIS302DL_CTRL_REG2_ADDR, 1);
+  
+  /* Clear high pass filter cut-off level, interrupt and data selection bits*/
+  ctrl &= (uint8_t)~(LIS302DL_FILTEREDDATASELECTION_OUTPUTREGISTER | \
+                     LIS302DL_HIGHPASSFILTER_LEVEL_3 | \
+                     LIS302DL_HIGHPASSFILTERINTERRUPT_1_2);
+  /* Configure MEMS high pass filter cut-off level, interrupt and data selection bits */                     
+  ctrl |= (uint8_t)(LIS302DL_FilterConfigStruct->HighPassFilter_Data_Selection | \
+                    LIS302DL_FilterConfigStruct->HighPassFilter_CutOff_Frequency | \
+                    LIS302DL_FilterConfigStruct->HighPassFilter_Interrupt);
+  
+  /* Write value to MEMS CTRL_REG2 register */
+  LIS302DL_Write(&ctrl, LIS302DL_CTRL_REG2_ADDR, 1);
+}
+
+/**
+  * @brief Set LIS302DL Interrupt configuration
+  * @param  LIS302DL_InterruptConfig_TypeDef: pointer to a LIS302DL_InterruptConfig_TypeDef 
+  *         structure that contains the configuration setting for the LIS302DL Interrupt.
+  * @retval None
+  */
+void LIS302DL_InterruptConfig(LIS302DL_InterruptConfigTypeDef *LIS302DL_IntConfigStruct)
+{
+  uint8_t ctrl = 0x00;
+  
+  /* Read CLICK_CFG register */
+  LIS302DL_Read(&ctrl, LIS302DL_CLICK_CFG_REG_ADDR, 1);
+  
+  /* Configure latch Interrupt request, click interrupts and double click interrupts */                   
+  ctrl = (uint8_t)(LIS302DL_IntConfigStruct->Latch_Request| \
+                   LIS302DL_IntConfigStruct->SingleClick_Axes | \
+                   LIS302DL_IntConfigStruct->DoubleClick_Axes);
+  
+  /* Write value to MEMS CLICK_CFG register */
+  LIS302DL_Write(&ctrl, LIS302DL_CLICK_CFG_REG_ADDR, 1);
+}
+
+/**
+  * @brief  Change the lowpower mode for LIS302DL
+  * @param  LowPowerMode: new state for the lowpower mode.
+  *   This parameter can be one of the following values:
+  *     @arg LIS302DL_LOWPOWERMODE_POWERDOWN: Power down mode
+  *     @arg LIS302DL_LOWPOWERMODE_ACTIVE: Active mode  
+  * @retval None
+  */
+void LIS302DL_LowpowerCmd(uint8_t LowPowerMode)
+{
+  uint8_t tmpreg;
+  
+  /* Read CTRL_REG1 register */
+  LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
+  
+  /* Set new low power mode configuration */
+  tmpreg &= (uint8_t)~LIS302DL_LOWPOWERMODE_ACTIVE;
+  tmpreg |= LowPowerMode;
+  
+  /* Write value to MEMS CTRL_REG1 regsister */
+  LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
+}
+
+/**
+  * @brief  Data Rate command 
+  * @param  DataRateValue: Data rate value
+  *   This parameter can be one of the following values:
+  *     @arg LIS302DL_DATARATE_100: 100 Hz output data rate 
+  *     @arg LIS302DL_DATARATE_400: 400 Hz output data rate    
+  * @retval None
+  */
+void LIS302DL_DataRateCmd(uint8_t DataRateValue)
+{
+  uint8_t tmpreg;
+  
+  /* Read CTRL_REG1 register */
+  LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
+  
+  /* Set new Data rate configuration */
+  tmpreg &= (uint8_t)~LIS302DL_DATARATE_400;
+  tmpreg |= DataRateValue;
+  
+  /* Write value to MEMS CTRL_REG1 regsister */
+  LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
+}
+
+/**
+  * @brief  Change the Full Scale of LIS302DL
+  * @param  FS_value: new full scale value. 
+  *   This parameter can be one of the following values:
+  *     @arg LIS302DL_FULLSCALE_2_3: +-2.3g
+  *     @arg LIS302DL_FULLSCALE_9_2: +-9.2g   
+  * @retval None
+  */
+void LIS302DL_FullScaleCmd(uint8_t FS_value)
+{
+  uint8_t tmpreg;
+  
+  /* Read CTRL_REG1 register */
+  LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
+  
+  /* Set new full scale configuration */
+  tmpreg &= (uint8_t)~LIS302DL_FULLSCALE_9_2;
+  tmpreg |= FS_value;
+  
+  /* Write value to MEMS CTRL_REG1 regsister */
+  LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG1_ADDR, 1);
+}
+
+/**
+  * @brief  Reboot memory content of LIS302DL
+  * @param  None
+  * @retval None
+  */
+void LIS302DL_RebootCmd(void)
+{
+  uint8_t tmpreg;
+  /* Read CTRL_REG2 register */
+  LIS302DL_Read(&tmpreg, LIS302DL_CTRL_REG2_ADDR, 1);
+  
+  /* Enable or Disable the reboot memory */
+  tmpreg |= LIS302DL_BOOT_REBOOTMEMORY;
+  
+  /* Write value to MEMS CTRL_REG2 regsister */
+  LIS302DL_Write(&tmpreg, LIS302DL_CTRL_REG2_ADDR, 1);
+}
+
+/**
+  * @brief  Writes one byte to the LIS302DL.
+  * @param  pBuffer : pointer to the buffer  containing the data to be written to the LIS302DL.
+  * @param  WriteAddr : LIS302DL's internal address to write to.
+  * @param  NumByteToWrite: Number of bytes to write.
+  * @retval None
+  */
+void LIS302DL_Write(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite)
+{
+  /* Configure the MS bit: 
+       - When 0, the address will remain unchanged in multiple read/write commands.
+       - When 1, the address will be auto incremented in multiple read/write commands.
+  */
+  if(NumByteToWrite > 0x01)
+  {
+    WriteAddr |= (uint8_t)MULTIPLEBYTE_CMD;
+  }
+  /* Set chip select Low at the start of the transmission */
+  LIS302DL_CS_LOW();
+  
+  /* Send the Address of the indexed register */
+  LIS302DL_SendByte(WriteAddr);
+  /* Send the data that will be written into the device (MSB First) */
+  while(NumByteToWrite >= 0x01)
+  {
+    LIS302DL_SendByte(*pBuffer);
+    NumByteToWrite--;
+    pBuffer++;
+  }
+  
+  /* Set chip select High at the end of the transmission */ 
+  LIS302DL_CS_HIGH();
+}
+
+/**
+  * @brief  Reads a block of data from the LIS302DL.
+  * @param  pBuffer : pointer to the buffer that receives the data read from the LIS302DL.
+  * @param  ReadAddr : LIS302DL's internal address to read from.
+  * @param  NumByteToRead : number of bytes to read from the LIS302DL.
+  * @retval None
+  */
+void LIS302DL_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead)
+{  
+  if(NumByteToRead > 0x01)
+  {
+    ReadAddr |= (uint8_t)(READWRITE_CMD | MULTIPLEBYTE_CMD);
+  }
+  else
+  {
+    ReadAddr |= (uint8_t)READWRITE_CMD;
+  }
+  /* Set chip select Low at the start of the transmission */
+  LIS302DL_CS_LOW();
+  
+  /* Send the Address of the indexed register */
+  LIS302DL_SendByte(ReadAddr);
+  
+  /* Receive the data that will be read from the device (MSB First) */
+  while(NumByteToRead > 0x00)
+  {
+    /* Send dummy byte (0x00) to generate the SPI clock to LIS302DL (Slave device) */
+    *pBuffer = LIS302DL_SendByte(DUMMY_BYTE);
+    NumByteToRead--;
+    pBuffer++;
+  }
+  
+  /* Set chip select High at the end of the transmission */ 
+  LIS302DL_CS_HIGH();
+}
+
+/**
+  * @brief  Read LIS302DL output register, and calculate the acceleration 
+  *         ACC[mg]=SENSITIVITY* (out_h*256+out_l)/16 (12 bit rappresentation)
+  * @param  s16 buffer to store data
+  * @retval None
+  */
+void LIS302DL_ReadACC(int32_t* out)
+{
+  uint8_t buffer[6];
+  uint8_t crtl, i = 0x00;
+   
+  LIS302DL_Read(&crtl, LIS302DL_CTRL_REG1_ADDR, 1);  
+  LIS302DL_Read(buffer, LIS302DL_OUT_X_ADDR, 6);
+  
+  switch(crtl & 0x20) 
+    {
+    /* FS bit = 0 ==> Sensitivity typical value = 18milligals/digit*/ 
+    case 0x00:
+      for(i=0; i<0x03; i++)
+      {
+        *out =(int32_t)(LIS302DL_SENSITIVITY_2_3G *  (int8_t)buffer[2*i]);
+        out++;
+      }
+      break;
+    /* FS bit = 1 ==> Sensitivity typical value = 72milligals/digit*/ 
+    case 0x20:
+      for(i=0; i<0x03; i++)
+      {
+        *out =(int32_t)(LIS302DL_SENSITIVITY_9_2G * (int8_t)buffer[2*i]);
+        out++;
+      }         
+      break;
+    default:
+      break;
+    }
+ }
+
+/**
+  * @brief  Initializes the low level interface used to drive the LIS302DL
+  * @param  None
+  * @retval None
+  */
+static void LIS302DL_LowLevel_Init(void)
+{
+  GPIO_InitTypeDef GPIO_InitStructure;
+  SPI_InitTypeDef  SPI_InitStructure;
+
+  /* Enable the SPI periph */
+  RCC_APB2PeriphClockCmd(LIS302DL_SPI_CLK, ENABLE);
+
+  /* Enable SCK, MOSI and MISO GPIO clocks */
+  RCC_AHB1PeriphClockCmd(LIS302DL_SPI_SCK_GPIO_CLK | LIS302DL_SPI_MISO_GPIO_CLK | LIS302DL_SPI_MOSI_GPIO_CLK, ENABLE);
+
+  /* Enable CS  GPIO clock */
+  RCC_AHB1PeriphClockCmd(LIS302DL_SPI_CS_GPIO_CLK, ENABLE);
+  
+  /* Enable INT1 GPIO clock */
+  RCC_AHB1PeriphClockCmd(LIS302DL_SPI_INT1_GPIO_CLK, ENABLE);
+  
+  /* Enable INT2 GPIO clock */
+  RCC_AHB1PeriphClockCmd(LIS302DL_SPI_INT2_GPIO_CLK, ENABLE);
+
+  GPIO_PinAFConfig(LIS302DL_SPI_SCK_GPIO_PORT, LIS302DL_SPI_SCK_SOURCE, LIS302DL_SPI_SCK_AF);
+  GPIO_PinAFConfig(LIS302DL_SPI_MISO_GPIO_PORT, LIS302DL_SPI_MISO_SOURCE, LIS302DL_SPI_MISO_AF);
+  GPIO_PinAFConfig(LIS302DL_SPI_MOSI_GPIO_PORT, LIS302DL_SPI_MOSI_SOURCE, LIS302DL_SPI_MOSI_AF);
+
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+
+  /* SPI SCK pin configuration */
+  GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_SCK_PIN;
+  GPIO_Init(LIS302DL_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
+
+  /* SPI  MOSI pin configuration */
+  GPIO_InitStructure.GPIO_Pin =  LIS302DL_SPI_MOSI_PIN;
+  GPIO_Init(LIS302DL_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
+
+  /* SPI MISO pin configuration */
+  GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_MISO_PIN;
+  GPIO_Init(LIS302DL_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
+
+  /* SPI configuration -------------------------------------------------------*/
+  SPI_I2S_DeInit(LIS302DL_SPI);
+  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
+  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
+  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
+  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
+  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
+  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
+  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
+  SPI_InitStructure.SPI_CRCPolynomial = 7;
+  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
+  SPI_Init(LIS302DL_SPI, &SPI_InitStructure);
+
+  /* Enable SPI1  */
+  SPI_Cmd(LIS302DL_SPI, ENABLE);
+
+  /* Configure GPIO PIN for Lis Chip select */
+  GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_CS_PIN;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_Init(LIS302DL_SPI_CS_GPIO_PORT, &GPIO_InitStructure);
+
+  /* Deselect : Chip Select high */
+  GPIO_SetBits(LIS302DL_SPI_CS_GPIO_PORT, LIS302DL_SPI_CS_PIN);
+  
+  /* Configure GPIO PINs to detect Interrupts */
+  GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_INT1_PIN;
+  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
+  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
+  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
+  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
+  GPIO_Init(LIS302DL_SPI_INT1_GPIO_PORT, &GPIO_InitStructure);
+  
+  GPIO_InitStructure.GPIO_Pin = LIS302DL_SPI_INT2_PIN;
+  GPIO_Init(LIS302DL_SPI_INT2_GPIO_PORT, &GPIO_InitStructure);
+}
+
+/**
+  * @brief  Sends a Byte through the SPI interface and return the Byte received 
+  *         from the SPI bus.
+  * @param  Byte : Byte send.
+  * @retval The received byte value
+  */
+static uint8_t LIS302DL_SendByte(uint8_t byte)
+{
+  /* Loop while DR register in not emplty */
+  LIS302DLTimeout = LIS302DL_FLAG_TIMEOUT;
+  while (SPI_I2S_GetFlagStatus(LIS302DL_SPI, SPI_I2S_FLAG_TXE) == RESET)
+  {
+    if((LIS302DLTimeout--) == 0) return LIS302DL_TIMEOUT_UserCallback();
+  }
+  
+  /* Send a Byte through the SPI peripheral */
+  SPI_I2S_SendData(LIS302DL_SPI, byte);
+  
+  /* Wait to receive a Byte */
+  LIS302DLTimeout = LIS302DL_FLAG_TIMEOUT;
+  while (SPI_I2S_GetFlagStatus(LIS302DL_SPI, SPI_I2S_FLAG_RXNE) == RESET)
+  {
+    if((LIS302DLTimeout--) == 0) return LIS302DL_TIMEOUT_UserCallback();
+  }
+  
+  /* Return the Byte read from the SPI bus */
+  return (uint8_t)SPI_I2S_ReceiveData(LIS302DL_SPI);
+}
+
+#ifdef USE_DEFAULT_TIMEOUT_CALLBACK
+/**
+  * @brief  Basic management of the timeout situation.
+  * @param  None.
+  * @retval None.
+  */
+uint32_t LIS302DL_TIMEOUT_UserCallback(void)
+{
+  /* Block communication and all processes */
+  while (1)
+  {   
+  }
+}
+#endif /* USE_DEFAULT_TIMEOUT_CALLBACK */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+  
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+  
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
diff --git a/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_lis302dl.h b/example/stm32f4/Utilities/STM32F4-Discovery/stm32f4_discovery_lis302dl.h
new file mode 100644 (file)
index 0000000..b99cb80
--- /dev/null
@@ -0,0 +1,772 @@
+/**
+  ******************************************************************************
+  * @file    stm32f4_discovery_lis302dl.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    19-September-2011
+  * @brief   This file contains all the functions prototypes for the stm32f4_discovery_lis302dl.c
+  *          firmware driver.
+  ******************************************************************************
+  * @attention
+  *
+  * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+  * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+  * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+  * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+  * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+  * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+  *
+  * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+  ******************************************************************************  
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32F4_DISCOVERY_LIS302DL_H
+#define __STM32F4_DISCOVERY_LIS302DL_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+ #include "stm32f4xx.h"
+
+/** @addtogroup Utilities
+  * @{
+  */
+  
+/** @addtogroup STM32F4_DISCOVERY
+  * @{
+  */ 
+
+/** @addtogroup STM32F4_DISCOVERY_LIS302DL
+  * @{
+  */
+  
+
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Exported_Types
+  * @{
+  */
+   
+/* LIS302DL struct */
+typedef struct
+{
+  uint8_t Power_Mode;                         /* Power-down/Active Mode */
+  uint8_t Output_DataRate;                    /* OUT data rate 100 Hz / 400 Hz */
+  uint8_t Axes_Enable;                        /* Axes enable */
+  uint8_t Full_Scale;                         /* Full scale */
+  uint8_t Self_Test;                          /* Self test */
+}LIS302DL_InitTypeDef;
+
+/* LIS302DL High Pass Filter struct */
+typedef struct
+{
+  uint8_t HighPassFilter_Data_Selection;      /* Internal filter bypassed or data from internal filter send to output register*/
+  uint8_t HighPassFilter_CutOff_Frequency;    /* High pass filter cut-off frequency */
+  uint8_t HighPassFilter_Interrupt;           /* High pass filter enabled for Freefall/WakeUp #1 or #2 */ 
+}LIS302DL_FilterConfigTypeDef;  
+
+/* LIS302DL Interrupt struct */
+typedef struct
+{
+  uint8_t Latch_Request;                      /* Latch interrupt request into CLICK_SRC register*/
+  uint8_t SingleClick_Axes;                   /* Single Click Axes Interrupts */
+  uint8_t DoubleClick_Axes;                   /* Double Click Axes Interrupts */ 
+}LIS302DL_InterruptConfigTypeDef;  
+
+/**
+  * @}
+  */
+  
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Exported_Constants
+  * @{
+  */
+
+/* Uncomment the following line to use the default LIS302DL_TIMEOUT_UserCallback() 
+   function implemented in stm32f4_discovery_lis302dl.c file.
+   LIS302DL_TIMEOUT_UserCallback() function is called whenever a timeout condition 
+   occure during communication (waiting transmit data register empty flag(TXE)
+   or waiting receive data register is not empty flag (RXNE)). */   
+/* #define USE_DEFAULT_TIMEOUT_CALLBACK */
+
+/* Maximum Timeout values for flags waiting loops. These timeouts are not based
+   on accurate values, they just guarantee that the application will not remain
+   stuck if the SPI communication is corrupted.
+   You may modify these timeout values depending on CPU frequency and application
+   conditions (interrupts routines ...). */   
+#define LIS302DL_FLAG_TIMEOUT         ((uint32_t)0x1000)
+
+/**
+  * @brief  LIS302DL SPI Interface pins
+  */
+#define LIS302DL_SPI                       SPI1
+#define LIS302DL_SPI_CLK                   RCC_APB2Periph_SPI1
+
+#define LIS302DL_SPI_SCK_PIN               GPIO_Pin_5                  /* PA.05 */
+#define LIS302DL_SPI_SCK_GPIO_PORT         GPIOA                       /* GPIOA */
+#define LIS302DL_SPI_SCK_GPIO_CLK          RCC_AHB1Periph_GPIOA
+#define LIS302DL_SPI_SCK_SOURCE            GPIO_PinSource5
+#define LIS302DL_SPI_SCK_AF                GPIO_AF_SPI1
+
+#define LIS302DL_SPI_MISO_PIN              GPIO_Pin_6                  /* PA.6 */
+#define LIS302DL_SPI_MISO_GPIO_PORT        GPIOA                       /* GPIOA */
+#define LIS302DL_SPI_MISO_GPIO_CLK         RCC_AHB1Periph_GPIOA
+#define LIS302DL_SPI_MISO_SOURCE           GPIO_PinSource6
+#define LIS302DL_SPI_MISO_AF               GPIO_AF_SPI1
+
+#define LIS302DL_SPI_MOSI_PIN              GPIO_Pin_7                  /* PA.7 */
+#define LIS302DL_SPI_MOSI_GPIO_PORT        GPIOA                       /* GPIOA */
+#define LIS302DL_SPI_MOSI_GPIO_CLK         RCC_AHB1Periph_GPIOA
+#define LIS302DL_SPI_MOSI_SOURCE           GPIO_PinSource7
+#define LIS302DL_SPI_MOSI_AF               GPIO_AF_SPI1
+
+#define LIS302DL_SPI_CS_PIN                GPIO_Pin_3                  /* PE.03 */
+#define LIS302DL_SPI_CS_GPIO_PORT          GPIOE                       /* GPIOE */
+#define LIS302DL_SPI_CS_GPIO_CLK           RCC_AHB1Periph_GPIOE
+
+#define LIS302DL_SPI_INT1_PIN              GPIO_Pin_0                  /* PE.00 */
+#define LIS302DL_SPI_INT1_GPIO_PORT        GPIOE                       /* GPIOE */
+#define LIS302DL_SPI_INT1_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define LIS302DL_SPI_INT1_EXTI_LINE        EXTI_Line0
+#define LIS302DL_SPI_INT1_EXTI_PORT_SOURCE EXTI_PortSourceGPIOE
+#define LIS302DL_SPI_INT1_EXTI_PIN_SOURCE  EXTI_PinSource0
+#define LIS302DL_SPI_INT1_EXTI_IRQn        EXTI0_IRQn 
+
+#define LIS302DL_SPI_INT2_PIN              GPIO_Pin_1                  /* PE.01 */
+#define LIS302DL_SPI_INT2_GPIO_PORT        GPIOE                       /* GPIOE */
+#define LIS302DL_SPI_INT2_GPIO_CLK         RCC_AHB1Periph_GPIOE
+#define LIS302DL_SPI_INT2_EXTI_LINE        EXTI_Line1
+#define LIS302DL_SPI_INT2_EXTI_PORT_SOURCE EXTI_PortSourceGPIOE
+#define LIS302DL_SPI_INT2_EXTI_PIN_SOURCE  EXTI_PinSource1
+#define LIS302DL_SPI_INT2_EXTI_IRQn        EXTI1_IRQn 
+
+
+/******************************************************************************/
+/*************************** START REGISTER MAPPING  **************************/
+/******************************************************************************/
+
+/*******************************************************************************
+*  WHO_AM_I Register: Device Identification Register
+*  Read only register
+*  Default value: 0x3B
+*******************************************************************************/
+#define LIS302DL_WHO_AM_I_ADDR                  0x0F
+
+/*******************************************************************************
+*  CTRL_REG1 Register: Control Register 1
+*  Read Write register
+*  Default value: 0x07
+*  7 DR: Data Rate selection.
+*        0 - 100 Hz output data rate
+*        1 - 400 Hz output data rate
+*  6 PD: Power Down control.
+*        0 - power down mode
+*        1 - active mode
+*  5 FS: Full Scale selection.
+*        0 - Typical measurement range 2.3
+*        1 - Typical measurement range 9.2
+*  4:3 STP-STM Self Test Enable:
+*              STP |  STM |   mode
+*            ----------------------------
+*               0  |  0   |   Normal mode
+*               0  |  1   |   Self Test M
+*               1  |  0   |   Self Test P
+*  2 Zen: Z axis enable.
+*         0 - Z axis disabled
+*         1- Z axis enabled
+*  1 Yen: Y axis enable.
+*         0 - Y axis disabled
+*         1- Y axis enabled
+*  0 Xen: X axis enable.
+*         0 - X axis disabled
+*         1- X axis enabled
+********************************************************************************/
+#define LIS302DL_CTRL_REG1_ADDR                 0x20
+
+/*******************************************************************************
+*  CTRL_REG2 Regsiter: Control Register 2
+*  Read Write register
+*  Default value: 0x00
+*  7 SIM: SPI Serial Interface Mode Selection. 
+*         0 - 4 wire interface
+*         1 - 3 wire interface
+*  6 BOOT: Reboot memory content
+*          0 - normal mode 
+*          1 - reboot memory content
+*  5 Reserved
+*  4 FDS: Filtered data selection.
+*         0 - internal filter bypassed
+*         1 - data from internal filter sent to output register
+*  3 HP FF_WU2: High pass filter enabled for FreeFall/WakeUp#2.
+*               0 - filter bypassed
+*               1 - filter enabled
+*  2 HP FF_WU1: High pass filter enabled for FreeFall/WakeUp#1.
+*               0 - filter bypassed
+*               1 - filter enabled
+*  1:0 HP coeff2-HP coeff1 High pass filter cut-off frequency (ft) configuration.
+*                 ft= ODR[hz]/6*HP coeff
+*            HP coeff2 | HP coeff1 |   HP coeff
+*            -------------------------------------------
+*                 0     |     0     |   8
+*                 0     |     1     |   16
+*                 1     |     0     |   32
+*                 1     |     1     |   64
+*            HP coeff |  ft[hz]   |  ft[hz]   |
+*                     |ODR 100Hz | ODR 400Hz  |
+*            --------------------------------------------
+*              00     |    2      |     8     |
+*              01     |    1      |     4     |
+*              10     |    0.5    |     2     |
+*              11     |    0.25   |     1     |
+*******************************************************************************/
+#define LIS302DL_CTRL_REG2_ADDR              0x21
+
+/*******************************************************************************
+*  CTRL_REG3 Register: Interrupt Control Register
+*  Read Write register
+*  Default value: 0x00
+*  7 IHL active: Interrupt active high/low.
+*                0 - active high
+*                1 - active low
+*  6 PP_OD: push-pull/open-drain.
+*           0 - push-pull
+*           1 - open-drain
+*  5:3 I2_CFG2 - I2_CFG0 Data signal on INT2 pad control bits
+*  2:0 I1_CFG2 - I1_CFG0 Data signal on INT1 pad control bits
+*        I1(2)_CFG2  |  I1(2)_CFG1  |  I1(2)_CFG0  | INT1(2) Pad
+*        ----------------------------------------------------------
+*              0     |      0       |       0      | GND
+*              0     |      0       |       1      | FreeFall/WakeUp#1
+*              0     |      1       |       0      | FreeFall/WakeUp#2
+*              0     |      1       |       1      | FreeFall/WakeUp#1 or FreeFall/WakeUp#2
+*              1     |      0       |       0      | Data ready
+*              1     |      1       |       1      | Click interrupt
+*******************************************************************************/
+#define LIS302DL_CTRL_REG3_ADDR              0x22
+
+/*******************************************************************************
+*  HP_FILTER_RESET Register: Dummy register. Reading at this address zeroes 
+*  instantaneously the content of the internal high pass filter. If the high pass
+*  filter is enabled all three axes are instantaneously set to 0g.
+*  This allows to overcome the settling time of the high pass filter.
+*  Read only register
+*  Default value: Dummy
+*******************************************************************************/
+#define LIS302DL_HP_FILTER_RESET_REG_ADDR     0x23
+
+/*******************************************************************************
+*  STATUS_REG Register: Status Register
+*  Default value: 0x00
+*  7 ZYXOR: X, Y and Z axis data overrun.
+*           0: no overrun has occurred
+*           1: new data has overwritten the previous one before it was read
+*  6 ZOR: Z axis data overrun.
+*         0: no overrun has occurred 
+*         1: new data for Z-axis has overwritten the previous one before it was read
+*  5 yOR: y axis data overrun.
+*         0: no overrun has occurred
+*         1: new data for y-axis has overwritten the previous one before it was read
+*  4 XOR: X axis data overrun.
+*         0: no overrun has occurred
+*         1: new data for X-axis has overwritten the previous one before it was read
+*  3 ZYXDA: X, Y and Z axis new data available
+*           0: a new set of data is not yet available
+*           1: a new set of data is available
+*  2 ZDA: Z axis new data available.
+*         0: a new set of data is not yet available
+*         1: a new data for Z axis is available
+*  1 YDA: Y axis new data available
+*         0: a new set of data is not yet available
+*         1: a new data for Y axis is available
+*  0 XDA: X axis new data available
+*         0: a new set of data is not yet available
+*         1: a new data for X axis is available
+*******************************************************************************/
+#define LIS302DL_STATUS_REG_ADDR             0x27
+
+/*******************************************************************************
+*  OUT_X Register: X-axis output Data
+*  Read only register
+*  Default value: output
+*  7:0 XD7-XD0: X-axis output Data
+*******************************************************************************/
+#define LIS302DL_OUT_X_ADDR                  0x29
+
+/*******************************************************************************
+*  OUT_Y Register: Y-axis output Data
+*  Read only register
+*  Default value: output
+*  7:0 YD7-YD0: Y-axis output Data
+*******************************************************************************/
+#define LIS302DL_OUT_Y_ADDR                  0x2B
+
+/*******************************************************************************
+*  OUT_Z Register: Z-axis output Data
+*  Read only register
+*  Default value: output
+*  7:0 ZD7-ZD0: Z-axis output Data
+*******************************************************************************/
+#define LIS302DL_OUT_Z_ADDR                  0x2D
+
+/*******************************************************************************
+*  FF_WW_CFG_1 Register: Configuration register for Interrupt 1 source.
+*  Read write register
+*  Default value: 0x00
+*  7 AOI: AND/OR combination of Interrupt events. 
+*         0: OR combination of interrupt events
+*         1: AND combination of interrupt events 
+*  6 LIR: Latch/not latch interrupt request
+*         0: interrupt request not latched
+*         1: interrupt request latched
+*  5 ZHIE: Enable interrupt generation on Z high event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value higher than preset threshold
+*  4 ZLIE: Enable interrupt generation on Z low event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value lower than preset threshold
+*  3 YHIE: Enable interrupt generation on Y high event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value higher than preset threshold
+*  2 YLIE: Enable interrupt generation on Y low event. 
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value lower than preset threshold
+*  1 XHIE: Enable interrupt generation on X high event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value higher than preset threshold
+*  0 XLIE: Enable interrupt generation on X low event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value lower than preset threshold
+*******************************************************************************/
+#define LIS302DL_FF_WU_CFG1_REG_ADDR         0x30
+
+/*******************************************************************************
+*  FF_WU_SRC_1 Register: Interrupt 1 source register.
+*  Reading at this address clears FF_WU_SRC_1 register and the FF, WU 1 interrupt
+*  and allow the refreshment of data in the FF_WU_SRC_1 register if the latched option
+*  was chosen.
+*  Read only register
+*  Default value: 0x00
+*  7 Reserved
+*  6 IA: Interrupt active.
+*        0: no interrupt has been generated
+*        1: one or more interrupts have been generated
+*  5 ZH: Z high. 
+*        0: no interrupt
+*        1: ZH event has occurred 
+*  4 ZL: Z low.
+*        0: no interrupt
+*        1: ZL event has occurred
+*  3 YH: Y high.
+*        0: no interrupt
+*        1: YH event has occurred 
+*  2 YL: Y low.
+*        0: no interrupt
+*        1: YL event has occurred
+*  1 YH: X high.
+*        0: no interrupt
+*        1: XH event has occurred 
+*  0 YL: X low.
+*        0: no interrupt
+*        1: XL event has occurred
+*******************************************************************************/
+#define LIS302DL_FF_WU_SRC1_REG_ADDR           0x31
+
+/*******************************************************************************
+*  FF_WU_THS_1 Register: Threshold register
+*  Read Write register
+*  Default value: 0x00
+*  7 DCRM: Reset mode selection.
+*          0 - counter resetted
+*          1 - counter decremented
+*  6 THS6-THS0: Free-fall/wake-up threshold value.
+*******************************************************************************/
+#define LIS302DL_FF_WU_THS1_REG_ADDR          0x32
+
+/*******************************************************************************
+*  FF_WU_DURATION_1 Register: duration Register
+*  Read Write register
+*  Default value: 0x00
+*  7:0 D7-D0 Duration value. (Duration steps and maximum values depend on the ODR chosen)
+ ******************************************************************************/
+#define LIS302DL_FF_WU_DURATION1_REG_ADDR     0x33
+
+/*******************************************************************************
+*  FF_WW_CFG_2 Register: Configuration register for Interrupt 2 source.
+*  Read write register
+*  Default value: 0x00
+*  7 AOI: AND/OR combination of Interrupt events. 
+*         0: OR combination of interrupt events
+*         1: AND combination of interrupt events 
+*  6 LIR: Latch/not latch interrupt request
+*         0: interrupt request not latched
+*         1: interrupt request latched
+*  5 ZHIE: Enable interrupt generation on Z high event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value higher than preset threshold
+*  4 ZLIE: Enable interrupt generation on Z low event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value lower than preset threshold
+*  3 YHIE: Enable interrupt generation on Y high event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value higher than preset threshold
+*  2 YLIE: Enable interrupt generation on Y low event. 
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value lower than preset threshold
+*  1 XHIE: Enable interrupt generation on X high event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value higher than preset threshold
+*  0 XLIE: Enable interrupt generation on X low event.
+*          0: disable interrupt request
+*          1: enable interrupt request on measured accel. value lower than preset threshold
+*******************************************************************************/
+#define LIS302DL_FF_WU_CFG2_REG_ADDR         0x34
+
+/*******************************************************************************
+*  FF_WU_SRC_2 Register: Interrupt 2 source register.
+*  Reading at this address clears FF_WU_SRC_2 register and the FF, WU 2 interrupt
+*  and allow the refreshment of data in the FF_WU_SRC_2 register if the latched option
+*  was chosen.
+*  Read only register
+*  Default value: 0x00
+*  7 Reserved
+*  6 IA: Interrupt active.
+*        0: no interrupt has been generated
+*        1: one or more interrupts have been generated
+*  5 ZH: Z high. 
+*        0: no interrupt
+*        1: ZH event has occurred 
+*  4 ZL: Z low.
+*        0: no interrupt
+*        1: ZL event has occurred
+*  3 YH: Y high.
+*        0: no interrupt
+*        1: YH event has occurred 
+*  2 YL: Y low.
+*        0: no interrupt
+*        1: YL event has occurred
+*  1 YH: X high.
+*        0: no interrupt
+*        1: XH event has occurred 
+*  0 YL: X low.
+*        0: no interrupt
+*        1: XL event has occurred
+*******************************************************************************/
+#define LIS302DL_FF_WU_SRC2_REG_ADDR           0x35
+
+/*******************************************************************************
+*  FF_WU_THS_2 Register: Threshold register
+*  Read Write register
+*  Default value: 0x00
+*  7 DCRM: Reset mode selection.
+*          0 - counter resetted
+*          1 - counter decremented
+*  6 THS6-THS0: Free-fall/wake-up threshold value.
+*******************************************************************************/
+#define LIS302DL_FF_WU_THS2_REG_ADDR          0x36
+
+/*******************************************************************************
+*  FF_WU_DURATION_2 Register: duration Register
+*  Read Write register
+*  Default value: 0x00
+*  7:0 D7-D0 Duration value. (Duration steps and maximum values depend on the ODR chosen)
+ ******************************************************************************/
+#define LIS302DL_FF_WU_DURATION2_REG_ADDR     0x37
+
+/******************************************************************************
+*  CLICK_CFG Register: click Register
+*  Read Write register
+*  Default value: 0x00
+*  7 Reserved
+*  6 LIR: Latch Interrupt request.
+*         0: interrupt request not latched
+*         1: interrupt request latched
+*  5 Double_Z: Enable interrupt generation on double click event on Z axis.
+*              0: disable interrupt request
+*              1: enable interrupt request
+*  4 Single_Z: Enable interrupt generation on single click event on Z axis.
+*              0: disable interrupt request
+*              1: enable interrupt request
+*  3 Double_Y: Enable interrupt generation on double click event on Y axis.
+*              0: disable interrupt request
+*              1: enable interrupt request
+*  2 Single_Y: Enable interrupt generation on single click event on Y axis.
+*              0: disable interrupt request
+*              1: enable interrupt request
+*  1 Double_X: Enable interrupt generation on double click event on X axis.
+*              0: disable interrupt request
+*              1: enable interrupt request
+*  0 Single_y: Enable interrupt generation on single click event on X axis.
+*              0: disable interrupt request
+*              1: enable interrupt request
+ ******************************************************************************/
+#define LIS302DL_CLICK_CFG_REG_ADDR     0x38
+
+/******************************************************************************
+*  CLICK_SRC Register: click status Register
+*  Read only register
+*  Default value: 0x00
+*  7 Reserved
+*  6 IA: Interrupt active.
+*        0: no interrupt has been generated
+*        1: one or more interrupts have been generated
+*  5 Double_Z: Double click on Z axis event.
+*        0: no interrupt
+*        1: Double Z event has occurred 
+*  4 Single_Z: Z low.
+*        0: no interrupt
+*        1: Single Z event has occurred 
+*  3 Double_Y: Y high.
+*        0: no interrupt
+*        1: Double Y event has occurred 
+*  2 Single_Y: Y low.
+*        0: no interrupt
+*        1: Single Y event has occurred 
+*  1 Double_X: X high.
+*        0: no interrupt
+*        1: Double X event has occurred 
+*  0 Single_X: X low.
+*        0: no interrupt
+*        1: Single X event has occurred 
+*******************************************************************************/
+#define LIS302DL_CLICK_SRC_REG_ADDR        0x39
+
+/*******************************************************************************
+*  CLICK_THSY_X Register: Click threshold Y and X register
+*  Read Write register
+*  Default value: 0x00
+*  7:4 THSy3-THSy0: Click threshold on Y axis, step 0.5g
+*  3:0 THSx3-THSx0: Click threshold on X axis, step 0.5g
+*******************************************************************************/
+#define LIS302DL_CLICK_THSY_X_REG_ADDR        0x3B
+
+/*******************************************************************************
+*  CLICK_THSZ Register: Click threshold Z register
+*  Read Write register
+*  Default value: 0x00
+*  7:4 Reserved
+*  3:0 THSz3-THSz0: Click threshold on Z axis, step 0.5g
+*******************************************************************************/
+#define LIS302DL_CLICK_THSZ_REG_ADDR         0x3C
+
+/*******************************************************************************
+*  CLICK_TimeLimit Register: Time Limit register
+*  Read Write register
+*  Default value: 0x00
+*  7:0 Dur7-Dur0: Time Limit value, step 0.5g
+*******************************************************************************/
+#define LIS302DL_CLICK_TIMELIMIT_REG_ADDR        0x3D
+
+/*******************************************************************************
+*  CLICK_Latency Register: Latency register
+*  Read Write register
+*  Default value: 0x00
+*  7:0 Lat7-Lat0: Latency value, step 1msec
+*******************************************************************************/
+#define LIS302DL_CLICK_LATENCY_REG_ADDR        0x3E
+
+/*******************************************************************************
+*  CLICK_Window Register: Window register
+*  Read Write register
+*  Default value: 0x00
+*  7:0 Win7-Win0: Window value, step 1msec
+*******************************************************************************/
+#define LIS302DL_CLICK_WINDOW_REG_ADDR        0x3F
+
+/******************************************************************************/
+/**************************** END REGISTER MAPPING  ***************************/
+/******************************************************************************/
+
+#define LIS302DL_SENSITIVITY_2_3G                         18  /* 18 mg/digit*/
+#define LIS302DL_SENSITIVITY_9_2G                         72  /* 72 mg/digit*/
+
+/** @defgroup Data_Rate_selection                 
+  * @{
+  */
+#define LIS302DL_DATARATE_100                             ((uint8_t)0x00)
+#define LIS302DL_DATARATE_400                             ((uint8_t)0x80)
+/**
+  * @}
+  */
+  
+/** @defgroup Power_Mode_selection 
+  * @{
+  */
+#define LIS302DL_LOWPOWERMODE_POWERDOWN                   ((uint8_t)0x00)
+#define LIS302DL_LOWPOWERMODE_ACTIVE                      ((uint8_t)0x40)
+/**
+  * @}
+  */
+  
+/** @defgroup Full_Scale_selection 
+  * @{
+  */
+#define LIS302DL_FULLSCALE_2_3                            ((uint8_t)0x00)
+#define LIS302DL_FULLSCALE_9_2                            ((uint8_t)0x20)
+/**
+  * @}
+  */
+  
+/** @defgroup Self_Test_selection 
+  * @{
+  */
+#define LIS302DL_SELFTEST_NORMAL                          ((uint8_t)0x00)
+#define LIS302DL_SELFTEST_P                               ((uint8_t)0x10)
+#define LIS302DL_SELFTEST_M                               ((uint8_t)0x08)
+/**
+  * @}
+  */  
+
+/** @defgroup Direction_XYZ_selection 
+  * @{
+  */
+#define LIS302DL_X_ENABLE                                 ((uint8_t)0x01)
+#define LIS302DL_Y_ENABLE                                 ((uint8_t)0x02)
+#define LIS302DL_Z_ENABLE                                 ((uint8_t)0x04)
+#define LIS302DL_XYZ_ENABLE                               ((uint8_t)0x07)
+/**
+  * @}
+  */
+ /** @defgroup SPI_Serial_Interface_Mode_selection 
+  * @{
+  */
+#define LIS302DL_SERIALINTERFACE_4WIRE                    ((uint8_t)0x00)
+#define LIS302DL_SERIALINTERFACE_3WIRE                    ((uint8_t)0x80)
+/**
+  * @}
+  */ 
+
+ /** @defgroup Boot_Mode_selection 
+  * @{
+  */
+#define LIS302DL_BOOT_NORMALMODE                          ((uint8_t)0x00)
+#define LIS302DL_BOOT_REBOOTMEMORY                        ((uint8_t)0x40)
+/**
+  * @}
+  */   
+
+ /** @defgroup Filtered_Data_Selection_Mode_selection 
+  * @{
+  */
+#define LIS302DL_FILTEREDDATASELECTION_BYPASSED           ((uint8_t)0x00)
+#define LIS302DL_FILTEREDDATASELECTION_OUTPUTREGISTER     ((uint8_t)0x20)
+/**
+  * @}
+  */ 
+  
+ /** @defgroup High_Pass_Filter_Interrupt_selection 
+  * @{
+  */  
+#define LIS302DL_HIGHPASSFILTERINTERRUPT_OFF              ((uint8_t)0x00)
+#define LIS302DL_HIGHPASSFILTERINTERRUPT_1                ((uint8_t)0x04)
+#define LIS302DL_HIGHPASSFILTERINTERRUPT_2                ((uint8_t)0x08)
+#define LIS302DL_HIGHPASSFILTERINTERRUPT_1_2              ((uint8_t)0x0C)
+/**
+  * @}
+  */ 
+  
+ /** @defgroup High_Pass_Filter_selection 
+  * @{
+  */
+#define LIS302DL_HIGHPASSFILTER_LEVEL_0                   ((uint8_t)0x00)
+#define LIS302DL_HIGHPASSFILTER_LEVEL_1                   ((uint8_t)0x01)
+#define LIS302DL_HIGHPASSFILTER_LEVEL_2                   ((uint8_t)0x02)
+#define LIS302DL_HIGHPASSFILTER_LEVEL_3                   ((uint8_t)0x03)
+/**
+  * @}
+  */
+
+
+/** @defgroup latch_Interrupt_Request_selection 
+  * @{
+  */
+#define LIS302DL_INTERRUPTREQUEST_NOTLATCHED              ((uint8_t)0x00)
+#define LIS302DL_INTERRUPTREQUEST_LATCHED                 ((uint8_t)0x40)
+/**
+  * @}
+  */
+
+/** @defgroup Click_Interrupt_XYZ_selection 
+  * @{
+  */
+#define LIS302DL_CLICKINTERRUPT_XYZ_DISABLE               ((uint8_t)0x00)
+#define LIS302DL_CLICKINTERRUPT_X_ENABLE                  ((uint8_t)0x01)
+#define LIS302DL_CLICKINTERRUPT_Y_ENABLE                  ((uint8_t)0x04)
+#define LIS302DL_CLICKINTERRUPT_Z_ENABLE                  ((uint8_t)0x10)
+#define LIS302DL_CLICKINTERRUPT_XYZ_ENABLE                ((uint8_t)0x15)
+/**
+  * @}
+  */
+
+/** @defgroup Double_Click_Interrupt_XYZ_selection 
+  * @{
+  */
+#define LIS302DL_DOUBLECLICKINTERRUPT_XYZ_DISABLE         ((uint8_t)0x00)
+#define LIS302DL_DOUBLECLICKINTERRUPT_X_ENABLE            ((uint8_t)0x02)
+#define LIS302DL_DOUBLECLICKINTERRUPT_Y_ENABLE            ((uint8_t)0x08)
+#define LIS302DL_DOUBLECLICKINTERRUPT_Z_ENABLE            ((uint8_t)0x20)
+#define LIS302DL_DOUBLECLICKINTERRUPT_XYZ_ENABLE          ((uint8_t)0x2A)
+/**
+  * @}
+  */
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Exported_Macros
+  * @{
+  */
+#define LIS302DL_CS_LOW()       GPIO_ResetBits(LIS302DL_SPI_CS_GPIO_PORT, LIS302DL_SPI_CS_PIN)
+#define LIS302DL_CS_HIGH()      GPIO_SetBits(LIS302DL_SPI_CS_GPIO_PORT, LIS302DL_SPI_CS_PIN)
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32F4_DISCOVERY_LIS302DL_Exported_Functions
+  * @{
+  */ 
+void LIS302DL_Init(LIS302DL_InitTypeDef *LIS302DL_InitStruct);
+void LIS302DL_InterruptConfig(LIS302DL_InterruptConfigTypeDef *LIS302DL_InterruptConfigStruct);
+void LIS302DL_FilterConfig(LIS302DL_FilterConfigTypeDef *LIS302DL_FilterConfigStruct);
+void LIS302DL_LowpowerCmd(uint8_t LowPowerMode);
+void LIS302DL_FullScaleCmd(uint8_t FS_value);
+void LIS302DL_DataRateCmd(uint8_t DataRateValue);
+void LIS302DL_RebootCmd(void);
+void LIS302DL_ReadACC(int32_t* out);
+void LIS302DL_Write(uint8_t* pBuffer, uint8_t WriteAddr, uint16_t NumByteToWrite);
+void LIS302DL_Read(uint8_t* pBuffer, uint8_t ReadAddr, uint16_t NumByteToRead);
+
+/* USER Callbacks: This is function for which prototype only is declared in
+   MEMS accelerometre driver and that should be implemented into user applicaiton. */  
+/* LIS302DL_TIMEOUT_UserCallback() function is called whenever a timeout condition 
+   occure during communication (waiting transmit data register empty flag(TXE)
+   or waiting receive data register is not empty flag (RXNE)).
+   You can use the default timeout callback implementation by uncommenting the 
+   define USE_DEFAULT_TIMEOUT_CALLBACK in stm32f4_discovery_lis302dl.h file.
+   Typically the user implementation of this callback should reset MEMS peripheral
+   and re-initialize communication or in worst case reset all the application. */
+uint32_t LIS302DL_TIMEOUT_UserCallback(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32F4_DISCOVERY_LIS302DL_H */
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/