--- /dev/null
+<!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> </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 Drivers 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: "Times New Roman";">
+ </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 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 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 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> </o:p></p>
+</div>
+
+</body></html>
\ No newline at end of file
--- /dev/null
+/**
+ ******************************************************************************
+ * @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>© 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****/
--- /dev/null
+/**
+ ******************************************************************************
+ * @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>© 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****/
--- /dev/null
+/**
+ ******************************************************************************
+ * @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>© 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****/
--- /dev/null
+/**
+ ******************************************************************************
+ * @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>© 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****/
--- /dev/null
+/**
+ ******************************************************************************
+ * @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>© 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****/
--- /dev/null
+/**
+ ******************************************************************************
+ * @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>© 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****/