STM32746G-Discovery board drivers V1.0.0

Dependents:   F746_SD_GraphicEqualizer_ren0620

Fork of BSP_DISCO_F746NG by ST

Files at this revision

API Documentation at this revision

Comitter:
bcostm
Date:
Mon Jan 04 15:19:15 2016 +0000
Parent:
0:c9112f0c67e3
Child:
2:458ab1edf6b2
Commit message:
Add missing files

Changed in this revision

audio.h Show annotated file Show diff for this revision Revisions of this file
camera.h Show annotated file Show diff for this revision Revisions of this file
n25q128a.h Show annotated file Show diff for this revision Revisions of this file
ov9655.c Show annotated file Show diff for this revision Revisions of this file
ov9655.h Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_audio.c Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_audio.h Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_camera.c Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_camera.h Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_eeprom.c Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_eeprom.h Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_qspi.c Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_qspi.h Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_sd.c Show annotated file Show diff for this revision Revisions of this file
stm32746g_discovery_sd.h Show annotated file Show diff for this revision Revisions of this file
wm8994.c Show annotated file Show diff for this revision Revisions of this file
wm8994.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/audio.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,122 @@
+/**
+  ******************************************************************************
+  * @file    audio.h
+  * @author  MCD Application Team
+  * @version V4.0.0
+  * @date    22-June-2015
+  * @brief   This header file contains the common defines and functions prototypes
+  *          for the Audio driver.  
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __AUDIO_H
+#define __AUDIO_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include <stdint.h>
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup Components
+  * @{
+  */
+    
+/** @addtogroup AUDIO
+  * @{
+  */
+
+/** @defgroup AUDIO_Exported_Constants
+  * @{
+  */
+
+/* Codec audio Standards */
+#define CODEC_STANDARD                0x04
+#define I2S_STANDARD                  I2S_STANDARD_PHILIPS
+
+/**
+  * @}
+  */
+
+/** @defgroup AUDIO_Exported_Types
+  * @{
+  */
+
+/** @defgroup AUDIO_Driver_structure  Audio Driver structure
+  * @{
+  */
+typedef struct
+{
+  uint32_t  (*Init)(uint16_t, uint16_t, uint8_t, uint32_t);
+  void      (*DeInit)(void);
+  uint32_t  (*ReadID)(uint16_t);
+  uint32_t  (*Play)(uint16_t, uint16_t*, uint16_t);
+  uint32_t  (*Pause)(uint16_t);
+  uint32_t  (*Resume)(uint16_t);
+  uint32_t  (*Stop)(uint16_t, uint32_t);
+  uint32_t  (*SetFrequency)(uint16_t, uint32_t);
+  uint32_t  (*SetVolume)(uint16_t, uint8_t);
+  uint32_t  (*SetMute)(uint16_t, uint32_t);
+  uint32_t  (*SetOutputMode)(uint16_t, uint8_t);
+  uint32_t  (*Reset)(uint16_t);
+}AUDIO_DrvTypeDef;
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __AUDIO_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/camera.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,141 @@
+/**
+  ******************************************************************************
+  * @file    camera.h
+  * @author  MCD Application Team
+  * @version V4.0.0
+  * @date    22-June-2015
+  * @brief   This header file contains the common defines and functions prototypes
+  *          for the camera driver.   
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __CAMERA_H
+#define __CAMERA_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+#include <stdint.h>
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup Components
+  * @{
+  */
+    
+/** @addtogroup CAMERA
+  * @{
+  */
+
+
+/** @defgroup CAMERA_Exported_Types
+  * @{
+  */ 
+
+/** @defgroup CAMERA_Driver_structure  Camera Driver structure
+  * @{
+  */
+typedef struct
+{
+  void     (*Init)(uint16_t, uint32_t);
+  uint16_t (*ReadID)(uint16_t);  
+  void     (*Config)(uint16_t, uint32_t, uint32_t, uint32_t);
+}CAMERA_DrvTypeDef;
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup CAMERA_Exported_Constants
+  * @{
+  */
+#define CAMERA_R160x120                 0x00   /* QQVGA Resolution                     */
+#define CAMERA_R320x240                 0x01   /* QVGA Resolution                      */
+#define CAMERA_R480x272                 0x02   /* 480x272 Resolution                   */
+#define CAMERA_R640x480                 0x03   /* VGA Resolution                       */  
+
+#define CAMERA_CONTRAST_BRIGHTNESS      0x00   /* Camera contrast brightness features  */
+#define CAMERA_BLACK_WHITE              0x01   /* Camera black white feature           */
+#define CAMERA_COLOR_EFFECT             0x03   /* Camera color effect feature          */
+
+#define CAMERA_BRIGHTNESS_LEVEL0        0x00   /* Brightness level -2         */
+#define CAMERA_BRIGHTNESS_LEVEL1        0x01   /* Brightness level -1         */
+#define CAMERA_BRIGHTNESS_LEVEL2        0x02   /* Brightness level 0          */
+#define CAMERA_BRIGHTNESS_LEVEL3        0x03   /* Brightness level +1         */
+#define CAMERA_BRIGHTNESS_LEVEL4        0x04   /* Brightness level +2         */
+
+#define CAMERA_CONTRAST_LEVEL0          0x05   /* Contrast level -2           */
+#define CAMERA_CONTRAST_LEVEL1          0x06   /* Contrast level -1           */
+#define CAMERA_CONTRAST_LEVEL2          0x07   /* Contrast level  0           */
+#define CAMERA_CONTRAST_LEVEL3          0x08   /* Contrast level +1           */
+#define CAMERA_CONTRAST_LEVEL4          0x09   /* Contrast level +2           */    
+    
+#define CAMERA_BLACK_WHITE_BW           0x00   /* Black and white effect      */
+#define CAMERA_BLACK_WHITE_NEGATIVE     0x01   /* Negative effect             */
+#define CAMERA_BLACK_WHITE_BW_NEGATIVE  0x02   /* BW and Negative effect      */
+#define CAMERA_BLACK_WHITE_NORMAL       0x03   /* Normal effect               */
+                                        
+#define CAMERA_COLOR_EFFECT_NONE        0x00   /* No effects                  */
+#define CAMERA_COLOR_EFFECT_BLUE        0x01   /* Blue effect                 */
+#define CAMERA_COLOR_EFFECT_GREEN       0x02   /* Green effect                */
+#define CAMERA_COLOR_EFFECT_RED         0x03   /* Red effect                  */
+#define CAMERA_COLOR_EFFECT_ANTIQUE     0x04   /* Antique effect              */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CAMERA_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/n25q128a.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,219 @@
+/**
+  ******************************************************************************
+  * @file    n25q128a.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    29-May-2015
+  * @brief   This file contains all the description of the N25Q128A QSPI memory.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __N25Q128A_H
+#define __N25Q128A_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup Components
+  * @{
+  */ 
+  
+/** @addtogroup n25q128a
+  * @{
+  */
+
+/** @defgroup N25Q128A_Exported_Types
+  * @{
+  */
+   
+/**
+  * @}
+  */ 
+
+/** @defgroup N25Q128A_Exported_Constants
+  * @{
+  */
+   
+/** 
+  * @brief  N25Q128A Configuration  
+  */  
+#define N25Q128A_FLASH_SIZE                  0x1000000 /* 128 MBits => 16MBytes */
+#define N25Q128A_SECTOR_SIZE                 0x10000   /* 256 sectors of 64KBytes */
+#define N25Q128A_SUBSECTOR_SIZE              0x1000    /* 4096 subsectors of 4kBytes */
+#define N25Q128A_PAGE_SIZE                   0x100     /* 65536 pages of 256 bytes */
+
+#define N25Q128A_DUMMY_CYCLES_READ           8
+#define N25Q128A_DUMMY_CYCLES_READ_QUAD      10
+
+#define N25Q128A_BULK_ERASE_MAX_TIME         250000
+#define N25Q128A_SECTOR_ERASE_MAX_TIME       3000
+#define N25Q128A_SUBSECTOR_ERASE_MAX_TIME    800
+
+/** 
+  * @brief  N25Q128A Commands  
+  */  
+/* Reset Operations */
+#define RESET_ENABLE_CMD                     0x66
+#define RESET_MEMORY_CMD                     0x99
+
+/* Identification Operations */
+#define READ_ID_CMD                          0x9E
+#define READ_ID_CMD2                         0x9F
+#define MULTIPLE_IO_READ_ID_CMD              0xAF
+#define READ_SERIAL_FLASH_DISCO_PARAM_CMD    0x5A
+
+/* Read Operations */
+#define READ_CMD                             0x03
+#define FAST_READ_CMD                        0x0B
+#define DUAL_OUT_FAST_READ_CMD               0x3B
+#define DUAL_INOUT_FAST_READ_CMD             0xBB
+#define QUAD_OUT_FAST_READ_CMD               0x6B
+#define QUAD_INOUT_FAST_READ_CMD             0xEB
+
+/* Write Operations */
+#define WRITE_ENABLE_CMD                     0x06
+#define WRITE_DISABLE_CMD                    0x04
+
+/* Register Operations */
+#define READ_STATUS_REG_CMD                  0x05
+#define WRITE_STATUS_REG_CMD                 0x01
+
+#define READ_LOCK_REG_CMD                    0xE8
+#define WRITE_LOCK_REG_CMD                   0xE5
+
+#define READ_FLAG_STATUS_REG_CMD             0x70
+#define CLEAR_FLAG_STATUS_REG_CMD            0x50
+
+#define READ_NONVOL_CFG_REG_CMD              0xB5
+#define WRITE_NONVOL_CFG_REG_CMD             0xB1
+
+#define READ_VOL_CFG_REG_CMD                 0x85
+#define WRITE_VOL_CFG_REG_CMD                0x81
+
+#define READ_ENHANCED_VOL_CFG_REG_CMD        0x65
+#define WRITE_ENHANCED_VOL_CFG_REG_CMD       0x61
+
+/* Program Operations */
+#define PAGE_PROG_CMD                        0x02
+#define DUAL_IN_FAST_PROG_CMD                0xA2
+#define EXT_DUAL_IN_FAST_PROG_CMD            0xD2
+#define QUAD_IN_FAST_PROG_CMD                0x32
+#define EXT_QUAD_IN_FAST_PROG_CMD            0x12
+
+/* Erase Operations */
+#define SUBSECTOR_ERASE_CMD                  0x20
+#define SECTOR_ERASE_CMD                     0xD8
+#define BULK_ERASE_CMD                       0xC7
+
+#define PROG_ERASE_RESUME_CMD                0x7A
+#define PROG_ERASE_SUSPEND_CMD               0x75
+
+/* One-Time Programmable Operations */
+#define READ_OTP_ARRAY_CMD                   0x4B
+#define PROG_OTP_ARRAY_CMD                   0x42
+
+/** 
+  * @brief  N25Q128A Registers  
+  */ 
+/* Status Register */
+#define N25Q128A_SR_WIP                      ((uint8_t)0x01)    /*!< Write in progress */
+#define N25Q128A_SR_WREN                     ((uint8_t)0x02)    /*!< Write enable latch */
+#define N25Q128A_SR_BLOCKPR                  ((uint8_t)0x5C)    /*!< Block protected against program and erase operations */
+#define N25Q128A_SR_PRBOTTOM                 ((uint8_t)0x20)    /*!< Protected memory area defined by BLOCKPR starts from top or bottom */
+#define N25Q128A_SR_SRWREN                   ((uint8_t)0x80)    /*!< Status register write enable/disable */
+
+/* Nonvolatile Configuration Register */
+#define N25Q128A_NVCR_LOCK                   ((uint16_t)0x0001) /*!< Lock nonvolatile configuration register */
+#define N25Q128A_NVCR_DUAL                   ((uint16_t)0x0004) /*!< Dual I/O protocol */
+#define N25Q128A_NVCR_QUAB                   ((uint16_t)0x0008) /*!< Quad I/O protocol */
+#define N25Q128A_NVCR_RH                     ((uint16_t)0x0010) /*!< Reset/hold */
+#define N25Q128A_NVCR_ODS                    ((uint16_t)0x01C0) /*!< Output driver strength */
+#define N25Q128A_NVCR_XIP                    ((uint16_t)0x0E00) /*!< XIP mode at power-on reset */
+#define N25Q128A_NVCR_NB_DUMMY               ((uint16_t)0xF000) /*!< Number of dummy clock cycles */
+
+/* Volatile Configuration Register */
+#define N25Q128A_VCR_WRAP                    ((uint8_t)0x03)    /*!< Wrap */
+#define N25Q128A_VCR_XIP                     ((uint8_t)0x08)    /*!< XIP */
+#define N25Q128A_VCR_NB_DUMMY                ((uint8_t)0xF0)    /*!< Number of dummy clock cycles */
+
+/* Enhanced Volatile Configuration Register */
+#define N25Q128A_EVCR_ODS                    ((uint8_t)0x07)    /*!< Output driver strength */
+#define N25Q128A_EVCR_VPPA                   ((uint8_t)0x08)    /*!< Vpp accelerator */
+#define N25Q128A_EVCR_RH                     ((uint8_t)0x10)    /*!< Reset/hold */
+#define N25Q128A_EVCR_DUAL                   ((uint8_t)0x40)    /*!< Dual I/O protocol */
+#define N25Q128A_EVCR_QUAD                   ((uint8_t)0x80)    /*!< Quad I/O protocol */
+
+/* Flag Status Register */
+#define N25Q128A_FSR_PRERR                   ((uint8_t)0x02)    /*!< Protection error */
+#define N25Q128A_FSR_PGSUS                   ((uint8_t)0x04)    /*!< Program operation suspended */
+#define N25Q128A_FSR_VPPERR                  ((uint8_t)0x08)    /*!< Invalid voltage during program or erase */
+#define N25Q128A_FSR_PGERR                   ((uint8_t)0x10)    /*!< Program error */
+#define N25Q128A_FSR_ERERR                   ((uint8_t)0x20)    /*!< Erase error */
+#define N25Q128A_FSR_ERSUS                   ((uint8_t)0x40)    /*!< Erase operation suspended */
+#define N25Q128A_FSR_READY                   ((uint8_t)0x80)    /*!< Ready or command in progress */
+
+/**
+  * @}
+  */
+  
+/** @defgroup N25Q128A_Exported_Functions
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+      
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+  
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __N25Q128A_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ov9655.c	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,861 @@
+/**
+  ******************************************************************************
+  * @file    ov9655.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file provides the OV9655 camera driver
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Includes ------------------------------------------------------------------*/
+#include "ov9655.h"
+
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup Components
+  * @{
+  */ 
+  
+/** @addtogroup OV9655
+  * @brief     This file provides a set of functions needed to drive the 
+  *            OV9655 Camera module.
+  * @{
+  */
+
+/** @defgroup OV9655_Private_TypesDefinitions
+  * @{
+  */ 
+
+/**
+  * @}
+  */ 
+
+/** @defgroup OV9655_Private_Defines
+  * @{
+  */
+
+/**
+  * @}
+  */ 
+  
+/** @defgroup OV9655_Private_Macros
+  * @{
+  */
+     
+/**
+  * @}
+  */  
+  
+/** @defgroup OV9655_Private_FunctionPrototypes
+  * @{
+  */
+static uint64_t ov9655_ConvertValue(uint32_t feature, uint32_t value);
+/**
+  * @}
+  */ 
+  
+/** @defgroup OV9655_Private_Variables
+  * @{
+  */        
+
+CAMERA_DrvTypeDef   ov9655_drv = 
+{
+  ov9655_Init,
+  ov9655_ReadID,  
+  ov9655_Config,
+};
+
+/* Initialization sequence for VGA resolution (640x480)*/
+const unsigned char OV9655_VGA[][2]=
+{
+  {0x00, 0x00},
+  {0x01, 0x80},   
+  {0x02, 0x80},   
+  {0xb5, 0x00},   
+  {0x35, 0x00},   
+  {0xa8, 0xc1},   
+  {0x3a, 0xcc},   
+  {0x3d, 0x99},   
+  {0x77, 0x02},   
+  {0x13, 0xe7},   
+  {0x26, 0x72},   
+  {0x27, 0x08},   
+  {0x28, 0x08},   
+  {0x2c, 0x08},   
+  {0xab, 0x04},   
+  {0x6e, 0x00},   
+  {0x6d, 0x55},   
+  {0x00, 0x11},   
+  {0x10, 0x7b},   
+  {0xbb, 0xae},   
+  {0x11, 0x03},   
+  {0x72, 0x00},   
+  {0x3e, 0x0c},   
+  {0x74, 0x3a},   
+  {0x76, 0x01},   
+  {0x75, 0x35},   
+  {0x73, 0x00},   
+  {0xc7, 0x80},   
+  {0x62, 0x00},   
+  {0x63, 0x00},   
+  {0x64, 0x02},   
+  {0x65, 0x20},   
+  {0x66, 0x01},   
+  {0xc3, 0x4e},   
+  {0x33, 0x00},   
+  {0xa4, 0x50},   
+  {0xaa, 0x92},   
+  {0xc2, 0x01},   
+  {0xc1, 0xc8},   
+  {0x1e, 0x04},   
+  {0xa9, 0xef},   
+  {0x0e, 0x61},   
+  {0x39, 0x57},   
+  {0x0f, 0x48},
+  {0x24, 0x3c},   
+  {0x25, 0x36},   
+  {0x12, 0x63},   
+  {0x03, 0x12},   
+  {0x32, 0xff},   
+  {0x17, 0x16},   
+  {0x18, 0x02},   
+  {0x19, 0x01},   
+  {0x1a, 0x3d},   
+  {0x36, 0xfa},   
+  {0x69, 0x0a},   
+  {0x8c, 0x8d},   
+  {0xc0, 0xaa},   
+  {0x40, 0xd0},   
+  {0x43, 0x14},   
+  {0x44, 0xf0},   
+  {0x45, 0x46},   
+  {0x46, 0x62},   
+  {0x47, 0x2a},   
+  {0x48, 0x3c},   
+  {0x59, 0x85},   
+  {0x5a, 0xa9},   
+  {0x5b, 0x64},   
+  {0x5c, 0x84},   
+  {0x5d, 0x53},   
+  {0x5e, 0x0e},   
+  {0x6c, 0x0c},   
+  {0xc6, 0x85},   
+  {0xcb, 0xf0},   
+  {0xcc, 0xd8},   
+  {0x71, 0x78},   
+  {0xa5, 0x68},   
+  {0x6f, 0x9e},   
+  {0x42, 0xc0},   
+  {0x3f, 0x82},   
+  {0x8a, 0x23},   
+  {0x14, 0x3a},   
+  {0x3b, 0xcc},   
+  {0x34, 0x3d},   
+  {0x41, 0x40},   
+  {0xc9, 0xe0},   
+  {0xca, 0xe8},   
+  {0xcd, 0x93},   
+  {0x7a, 0x20},   
+  {0x7b, 0x1c},   
+  {0x7c, 0x28},   
+  {0x7d, 0x3c},   
+  {0x7e, 0x5a},   
+  {0x7f, 0x68},   
+  {0x80, 0x76},   
+  {0x81, 0x80},   
+  {0x82, 0x88},   
+  {0x83, 0x8f},   
+  {0x84, 0x96},   
+  {0x85, 0xa3},   
+  {0x86, 0xaf},   
+  {0x87, 0xc4},   
+  {0x88, 0xd7},   
+  {0x89, 0xe8},   
+  {0x4f, 0x98},   
+  {0x50, 0x98},   
+  {0x51, 0x00},   
+  {0x52, 0x28},   
+  {0x53, 0x70},   
+  {0x54, 0x98},   
+  {0x58, 0x1a},   
+  {0x6b, 0x5a},   
+  {0x90, 0x92},   
+  {0x91, 0x92},   
+  {0x9f, 0x90},   
+  {0xa0, 0x90},   
+  {0x16, 0x24},   
+  {0x2a, 0x00},   
+  {0x2b, 0x00},   
+  {0xac, 0x80},   
+  {0xad, 0x80},   
+  {0xae, 0x80},   
+  {0xaf, 0x80},   
+  {0xb2, 0xf2},   
+  {0xb3, 0x20},   
+  {0xb4, 0x20},   
+  {0xb6, 0xaf},   
+  {0x29, 0x15},   
+  {0x9d, 0x02},   
+  {0x9e, 0x02},   
+  {0x9e, 0x02},   
+  {0x04, 0x03},   
+  {0x05, 0x2e},   
+  {0x06, 0x2e},   
+  {0x07, 0x2e},   
+  {0x08, 0x2e},   
+  {0x2f, 0x2e},   
+  {0x4a, 0xe9},   
+  {0x4b, 0xdd},   
+  {0x4c, 0xdd},   
+  {0x4d, 0xdd},   
+  {0x4e, 0xdd},   
+  {0x70, 0x06},   
+  {0xa6, 0x40},   
+  {0xbc, 0x02},   
+  {0xbd, 0x01},   
+  {0xbe, 0x02},   
+  {0xbf, 0x01},
+};
+
+/* Initialization sequence for QVGA resolution (320x240) */
+const unsigned char OV9655_QVGA[][2]=
+{
+  {0x00, 0x00},
+  {0x01, 0x80},
+  {0x02, 0x80},
+  {0x03, 0x02},
+  {0x04, 0x03},
+  {0x09, 0x01},
+  {0x0b, 0x57},
+  {0x0e, 0x61},
+  {0x0f, 0x40},
+  {0x11, 0x01},
+  {0x12, 0x62},
+  {0x13, 0xc7},
+  {0x14, 0x3a},
+  {0x16, 0x24},
+  {0x17, 0x18},
+  {0x18, 0x04},
+  {0x19, 0x01},
+  {0x1a, 0x81},
+  {0x1e, 0x00},
+  {0x24, 0x3c},
+  {0x25, 0x36},
+  {0x26, 0x72},
+  {0x27, 0x08},
+  {0x28, 0x08},
+  {0x29, 0x15},
+  {0x2a, 0x00},
+  {0x2b, 0x00},
+  {0x2c, 0x08},
+  {0x32, 0x12},
+  {0x33, 0x00},
+  {0x34, 0x3f},
+  {0x35, 0x00},
+  {0x36, 0x3a},
+  {0x38, 0x72},
+  {0x39, 0x57},
+  {0x3a, 0xcc},
+  {0x3b, 0x04},
+  {0x3d, 0x99},
+  {0x3e, 0x02},
+  {0x3f, 0xc1},
+  {0x40, 0xc0},
+  {0x41, 0x41},
+  {0x42, 0xc0},
+  {0x43, 0x0a},
+  {0x44, 0xf0},
+  {0x45, 0x46},
+  {0x46, 0x62},
+  {0x47, 0x2a},
+  {0x48, 0x3c},
+  {0x4a, 0xfc},
+  {0x4b, 0xfc},
+  {0x4c, 0x7f},
+  {0x4d, 0x7f},
+  {0x4e, 0x7f},
+  {0x4f, 0x98},
+  {0x50, 0x98},
+  {0x51, 0x00},
+  {0x52, 0x28},
+  {0x53, 0x70},
+  {0x54, 0x98},
+  {0x58, 0x1a},
+  {0x59, 0x85},
+  {0x5a, 0xa9},
+  {0x5b, 0x64},
+  {0x5c, 0x84},
+  {0x5d, 0x53},
+  {0x5e, 0x0e},
+  {0x5f, 0xf0},
+  {0x60, 0xf0},
+  {0x61, 0xf0},
+  {0x62, 0x00},
+  {0x63, 0x00},
+  {0x64, 0x02},
+  {0x65, 0x20},
+  {0x66, 0x00},
+  {0x69, 0x0a},
+  {0x6b, 0x5a},
+  {0x6c, 0x04},
+  {0x6d, 0x55},
+  {0x6e, 0x00},
+  {0x6f, 0x9d},
+  {0x70, 0x21},
+  {0x71, 0x78},
+  {0x72, 0x11},
+  {0x73, 0x01},
+  {0x74, 0x10},
+  {0x75, 0x10},
+  {0x76, 0x01},
+  {0x77, 0x02},
+  {0x7A, 0x12},
+  {0x7B, 0x08},
+  {0x7C, 0x16},
+  {0x7D, 0x30},
+  {0x7E, 0x5e},
+  {0x7F, 0x72},
+  {0x80, 0x82},
+  {0x81, 0x8e},
+  {0x82, 0x9a},
+  {0x83, 0xa4},
+  {0x84, 0xac},
+  {0x85, 0xb8},
+  {0x86, 0xc3},
+  {0x87, 0xd6},
+  {0x88, 0xe6},
+  {0x89, 0xf2},
+  {0x8a, 0x24},
+  {0x8c, 0x80},
+  {0x90, 0x7d},
+  {0x91, 0x7b},
+  {0x9d, 0x02},
+  {0x9e, 0x02},
+  {0x9f, 0x7a},
+  {0xa0, 0x79},
+  {0xa1, 0x40},
+  {0xa4, 0x50},
+  {0xa5, 0x68},
+  {0xa6, 0x4a},
+  {0xa8, 0xc1},
+  {0xa9, 0xef},
+  {0xaa, 0x92},
+  {0xab, 0x04},
+  {0xac, 0x80},
+  {0xad, 0x80},
+  {0xae, 0x80},
+  {0xaf, 0x80},
+  {0xb2, 0xf2},
+  {0xb3, 0x20},
+  {0xb4, 0x20},
+  {0xb5, 0x00},
+  {0xb6, 0xaf},
+  {0xb6, 0xaf},
+  {0xbb, 0xae},
+  {0xbc, 0x7f},
+  {0xbd, 0x7f},
+  {0xbe, 0x7f},
+  {0xbf, 0x7f},
+  {0xbf, 0x7f},
+  {0xc0, 0xaa},
+  {0xc1, 0xc0},
+  {0xc2, 0x01},
+  {0xc3, 0x4e},
+  {0xc6, 0x05},
+  {0xc7, 0x81},
+  {0xc9, 0xe0},
+  {0xca, 0xe8},
+  {0xcb, 0xf0},
+  {0xcc, 0xd8},
+  {0xcd, 0x93},
+  {0x12, 0x63},
+  {0x40, 0x10},
+};
+
+/* Initialization sequence for QQVGA resolution (160x120) */
+const char OV9655_QQVGA[][2]=
+{
+  {0x00, 0x00},
+  {0x01, 0x80},
+  {0x02, 0x80},
+  {0x03, 0x02},
+  {0x04, 0x03},
+  {0x09, 0x01},
+  {0x0b, 0x57},
+  {0x0e, 0x61},
+  {0x0f, 0x40},
+  {0x11, 0x01},
+  {0x12, 0x62},
+  {0x13, 0xc7},
+  {0x14, 0x3a},
+  {0x16, 0x24},
+  {0x17, 0x18},
+  {0x18, 0x04},
+  {0x19, 0x01},
+  {0x1a, 0x81},
+  {0x1e, 0x00},
+  {0x24, 0x3c},
+  {0x25, 0x36},
+  {0x26, 0x72},
+  {0x27, 0x08},
+  {0x28, 0x08},
+  {0x29, 0x15},
+  {0x2a, 0x00},
+  {0x2b, 0x00},
+  {0x2c, 0x08},
+  {0x32, 0xa4},
+  {0x33, 0x00},
+  {0x34, 0x3f},
+  {0x35, 0x00},
+  {0x36, 0x3a},
+  {0x38, 0x72},
+  {0x39, 0x57},
+  {0x3a, 0xcc},
+  {0x3b, 0x04},
+  {0x3d, 0x99},
+  {0x3e, 0x0e},
+  {0x3f, 0xc1},
+  {0x40, 0xc0},
+  {0x41, 0x41},
+  {0x42, 0xc0},
+  {0x43, 0x0a},
+  {0x44, 0xf0},
+  {0x45, 0x46},
+  {0x46, 0x62},
+  {0x47, 0x2a},
+  {0x48, 0x3c},
+  {0x4a, 0xfc},
+  {0x4b, 0xfc},
+  {0x4c, 0x7f},
+  {0x4d, 0x7f},
+  {0x4e, 0x7f},
+  {0x4f, 0x98},
+  {0x50, 0x98},
+  {0x51, 0x00},
+  {0x52, 0x28},
+  {0x53, 0x70},
+  {0x54, 0x98},
+  {0x58, 0x1a},
+  {0x59, 0x85},
+  {0x5a, 0xa9},
+  {0x5b, 0x64},
+  {0x5c, 0x84},
+  {0x5d, 0x53},
+  {0x5e, 0x0e},
+  {0x5f, 0xf0},
+  {0x60, 0xf0},
+  {0x61, 0xf0},
+  {0x62, 0x00},
+  {0x63, 0x00},
+  {0x64, 0x02},
+  {0x65, 0x20},
+  {0x66, 0x00},
+  {0x69, 0x0a},
+  {0x6b, 0x5a},
+  {0x6c, 0x04},
+  {0x6d, 0x55},
+  {0x6e, 0x00},
+  {0x6f, 0x9d},
+  {0x70, 0x21},
+  {0x71, 0x78},
+  {0x72, 0x22},
+  {0x73, 0x02},
+  {0x74, 0x10},
+  {0x75, 0x10},
+  {0x76, 0x01},
+  {0x77, 0x02},
+  {0x7A, 0x12},
+  {0x7B, 0x08},
+  {0x7C, 0x16},
+  {0x7D, 0x30},
+  {0x7E, 0x5e},
+  {0x7F, 0x72},
+  {0x80, 0x82},
+  {0x81, 0x8e},
+  {0x82, 0x9a},
+  {0x83, 0xa4},
+  {0x84, 0xac},
+  {0x85, 0xb8},
+  {0x86, 0xc3},
+  {0x87, 0xd6},
+  {0x88, 0xe6},
+  {0x89, 0xf2},
+  {0x8a, 0x24},
+  {0x8c, 0x80},
+  {0x90, 0x7d},
+  {0x91, 0x7b},
+  {0x9d, 0x02},
+  {0x9e, 0x02},
+  {0x9f, 0x7a},
+  {0xa0, 0x79},
+  {0xa1, 0x40},
+  {0xa4, 0x50},
+  {0xa5, 0x68},
+  {0xa6, 0x4a},
+  {0xa8, 0xc1},
+  {0xa9, 0xef},
+  {0xaa, 0x92},
+  {0xab, 0x04},
+  {0xac, 0x80},
+  {0xad, 0x80},
+  {0xae, 0x80},
+  {0xaf, 0x80},
+  {0xb2, 0xf2},
+  {0xb3, 0x20},
+  {0xb4, 0x20},
+  {0xb5, 0x00},
+  {0xb6, 0xaf},
+  {0xb6, 0xaf},
+  {0xbb, 0xae},
+  {0xbc, 0x7f},
+  {0xbd, 0x7f},
+  {0xbe, 0x7f},
+  {0xbf, 0x7f},
+  {0xbf, 0x7f},
+  {0xc0, 0xaa},
+  {0xc1, 0xc0},
+  {0xc2, 0x01},
+  {0xc3, 0x4e},
+  {0xc6, 0x05},
+  {0xc7, 0x82},
+  {0xc9, 0xe0},
+  {0xca, 0xe8},
+  {0xcb, 0xf0},
+  {0xcc, 0xd8},
+  {0xcd, 0x93},
+  {0x12, 0x63},
+  {0x40, 0x10},
+};
+
+/**
+  * @}
+  */
+  
+/** @defgroup OV9655_Private_Functions
+  * @{
+  */ 
+  
+/**
+  * @brief  Initializes the OV9655 CAMERA component.
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  resolution: Camera resolution
+  * @retval None
+  */
+void ov9655_Init(uint16_t DeviceAddr, uint32_t resolution)
+{
+  uint32_t index;
+  
+  /* Initialize I2C */
+  CAMERA_IO_Init();    
+  
+  /* Prepare the camera to be configured by resetting all its registers */
+  CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_COM7, 0x80);
+  CAMERA_Delay(200);
+  
+  /* Initialize OV9655 */
+  switch (resolution)
+  {
+  case CAMERA_R160x120:
+    {
+      for(index=0; index<(sizeof(OV9655_QQVGA)/2); index++)
+      {
+        CAMERA_IO_Write(DeviceAddr, OV9655_QQVGA[index][0], OV9655_QQVGA[index][1]);
+        CAMERA_Delay(2);
+      } 
+      break;
+    }    
+  case CAMERA_R320x240:
+    {
+      for(index=0; index<(sizeof(OV9655_QVGA)/2); index++)
+      {
+        CAMERA_IO_Write(DeviceAddr, OV9655_QVGA[index][0], OV9655_QVGA[index][1]);
+        CAMERA_Delay(2);
+      } 
+      break;
+    }
+  case CAMERA_R480x272:
+    {
+      /* Not supported resolution */
+      break;
+    }
+  case CAMERA_R640x480:
+    {
+      for(index=0; index<(sizeof(OV9655_VGA)/2); index++)
+      {
+        CAMERA_IO_Write(DeviceAddr, OV9655_VGA[index][0], OV9655_VGA[index][1]);
+        CAMERA_Delay(2);
+      }
+      break;
+    }    
+  default:
+    {
+      break;
+    }
+  }
+}
+
+/**
+  * @brief  Configures the OV9655 camera feature.
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @param  feature: Camera feature to be configured
+  * @param  value: Value to be configured
+  * @param  brightness_value: Brightness value to be configured
+  * @retval None
+  */
+void ov9655_Config(uint16_t DeviceAddr, uint32_t feature, uint32_t value, uint32_t brightness_value)
+{
+  uint8_t tslb, mtx1, mtx2, mtx3, mtx4, mtx5, mtx6;
+  uint64_t value_tmp;
+  uint32_t br_value;
+  
+  /* Convert the input value into ov9655 parameters */
+  value_tmp = ov9655_ConvertValue(feature, value); 
+  br_value = (uint32_t)ov9655_ConvertValue(CAMERA_CONTRAST_BRIGHTNESS, brightness_value);
+    
+  switch(feature)
+  {
+  case CAMERA_CONTRAST_BRIGHTNESS:
+    {
+      CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_BRTN, br_value);
+      CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_CNST1, value_tmp);
+      break;
+    }
+  case CAMERA_BLACK_WHITE:
+  case CAMERA_COLOR_EFFECT:
+    {     
+      tslb = (uint8_t)(value_tmp >> 48);
+      mtx1 = (uint8_t)(value_tmp >> 40);
+      mtx2 = (uint8_t)(value_tmp >> 32);
+      mtx3 = (uint8_t)(value_tmp >> 24);
+      mtx4 = (uint8_t)(value_tmp >> 16);
+      mtx5 = (uint8_t)(value_tmp >> 8);
+      mtx6 = (uint8_t)(value_tmp);
+      CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_TSLB, tslb);
+      CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_MTX1, mtx1);
+      CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_MTX2, mtx2);
+      CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_MTX3, mtx3);
+      CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_MTX4, mtx4);
+      CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_MTX5, mtx5);
+      CAMERA_IO_Write(DeviceAddr, OV9655_SENSOR_MTX6, mtx6);
+      break;
+    }     
+  default:
+    {
+      break;
+    }
+  }
+}
+
+/**
+  * @brief  Read the OV9655 Camera identity.
+  * @param  DeviceAddr: Device address on communication Bus.
+  * @retval the OV9655 ID
+  */
+uint16_t ov9655_ReadID(uint16_t DeviceAddr)
+{
+  /* Initialize I2C */
+  CAMERA_IO_Init();
+  
+  /* Get the camera ID */
+  return (CAMERA_IO_Read(DeviceAddr, OV9655_SENSOR_PIDH));
+}
+
+/******************************************************************************
+                            Static Functions
+*******************************************************************************/
+/**
+  * @brief  Convert input values into ov9655 parameters.
+  * @param  feature: Camera feature to be configured
+  * @param  value: Value to be configured
+  * @retval The converted value
+  */
+static uint64_t ov9655_ConvertValue(uint32_t feature, uint32_t value)
+{
+  uint64_t ret = 0;
+  
+  switch(feature)
+  {
+  case CAMERA_BLACK_WHITE:
+    {
+      switch(value)
+      {
+      case CAMERA_BLACK_WHITE_BW:
+        {
+          ret =  OV9655_BLACK_WHITE_BW;
+          break;
+        }
+      case CAMERA_BLACK_WHITE_NEGATIVE:
+        {
+          ret =  OV9655_BLACK_WHITE_NEGATIVE;
+          break;
+        }
+      case CAMERA_BLACK_WHITE_BW_NEGATIVE:
+        {
+          ret =  OV9655_BLACK_WHITE_BW_NEGATIVE;
+          break;
+        }
+      case CAMERA_BLACK_WHITE_NORMAL:
+        {
+          ret =  OV9655_BLACK_WHITE_NORMAL;
+          break;
+        }
+      default:
+        {
+          ret =  OV9655_BLACK_WHITE_NORMAL;
+          break;
+        }
+      }
+      break;
+    }
+  case CAMERA_CONTRAST_BRIGHTNESS:
+    {
+      switch(value)
+      {
+      case CAMERA_BRIGHTNESS_LEVEL0:
+        {
+          ret =  OV9655_BRIGHTNESS_LEVEL0;
+          break;
+        }
+      case CAMERA_BRIGHTNESS_LEVEL1:
+        {
+          ret =  OV9655_BRIGHTNESS_LEVEL1;
+          break;
+        }
+      case CAMERA_BRIGHTNESS_LEVEL2:
+        {
+          ret =  OV9655_BRIGHTNESS_LEVEL2;
+          break;
+        }
+      case CAMERA_BRIGHTNESS_LEVEL3:
+        {
+          ret =  OV9655_BRIGHTNESS_LEVEL3;
+          break;
+        }
+      case CAMERA_BRIGHTNESS_LEVEL4:
+        {
+          ret =  OV9655_BRIGHTNESS_LEVEL4;
+          break;
+        }        
+      case CAMERA_CONTRAST_LEVEL0:
+        {
+          ret =  OV9655_CONTRAST_LEVEL0;
+          break;
+        }
+      case CAMERA_CONTRAST_LEVEL1:
+        {
+          ret =  OV9655_CONTRAST_LEVEL1;
+          break;
+        }
+      case CAMERA_CONTRAST_LEVEL2:
+        {
+          ret =  OV9655_CONTRAST_LEVEL2;
+          break;
+        }
+      case CAMERA_CONTRAST_LEVEL3:
+        {
+          ret =  OV9655_CONTRAST_LEVEL3;
+          break;
+        }
+      case CAMERA_CONTRAST_LEVEL4:
+        {
+          ret =  OV9655_CONTRAST_LEVEL4;
+          break;
+        }
+      default:
+        {
+          ret =  OV9655_CONTRAST_LEVEL0;
+          break;
+        }
+      }
+      break;
+    }
+  case CAMERA_COLOR_EFFECT:
+    {
+      switch(value)
+      {
+      case CAMERA_COLOR_EFFECT_ANTIQUE:
+        {
+          ret =  OV9655_COLOR_EFFECT_ANTIQUE;
+          break;
+        }
+      case CAMERA_COLOR_EFFECT_BLUE:
+        {
+          ret =  OV9655_COLOR_EFFECT_BLUE;
+          break;
+        }
+      case CAMERA_COLOR_EFFECT_GREEN:
+        {
+          ret =  OV9655_COLOR_EFFECT_GREEN;
+          break;
+        }
+      case CAMERA_COLOR_EFFECT_RED:
+        {
+          ret =  OV9655_COLOR_EFFECT_RED;
+          break;
+        }
+      case CAMERA_COLOR_EFFECT_NONE:
+      default:
+        {
+          ret =  OV9655_COLOR_EFFECT_NONE;
+          break;
+        }
+      }
+      break;
+    default:
+      {
+        ret = 0;
+        break;
+      }    
+    }
+  }
+  
+  return ret;
+}
+         
+/**
+  * @}
+  */ 
+  
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+  
+/**
+  * @}
+  */  
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ov9655.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,159 @@
+/**
+  ******************************************************************************
+  * @file    ov9655.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file contains all the functions prototypes for the ov9655.c
+  *          driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __OV9655_H
+#define __OV9655_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+#include "camera.h"
+   
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup Components
+  * @{
+  */ 
+  
+/** @addtogroup ov9655
+  * @{
+  */
+
+/** @defgroup OV9655_Exported_Types
+  * @{
+  */
+     
+/**
+  * @}
+  */ 
+
+/** @defgroup OV9655_Exported_Constants
+  * @{
+  */
+/** 
+  * @brief  OV9655 ID  
+  */  
+#define  OV9655_ID    0x96
+/** 
+  * @brief  OV9655 Registers  
+  */
+
+/* OV9655 Registers definition */
+#define OV9655_SENSOR_PIDH              0x0A
+#define OV9655_SENSOR_PIDL              0x0B
+#define OV9655_SENSOR_COM7              0x12
+#define OV9655_SENSOR_TSLB              0x3A
+#define OV9655_SENSOR_MTX1              0x4F
+#define OV9655_SENSOR_MTX2              0x50
+#define OV9655_SENSOR_MTX3              0x51
+#define OV9655_SENSOR_MTX4              0x52
+#define OV9655_SENSOR_MTX5              0x53
+#define OV9655_SENSOR_MTX6              0x54
+#define OV9655_SENSOR_BRTN              0x55
+#define OV9655_SENSOR_CNST1             0x56
+#define OV9655_SENSOR_CNST2             0x57
+
+/** 
+ * @brief  OV9655 Features Parameters  
+ */
+#define OV9655_BRIGHTNESS_LEVEL0        0xB0     /* Brightness level -2         */
+#define OV9655_BRIGHTNESS_LEVEL1        0x98     /* Brightness level -1         */
+#define OV9655_BRIGHTNESS_LEVEL2        0x00     /* Brightness level 0          */
+#define OV9655_BRIGHTNESS_LEVEL3        0x18     /* Brightness level +1         */
+#define OV9655_BRIGHTNESS_LEVEL4        0x30     /* Brightness level +2         */
+
+#define OV9655_BLACK_WHITE_BW           0xCC000000000000  /* Black and white effect      */
+#define OV9655_BLACK_WHITE_NEGATIVE     0xEC808000008080  /* Negative effect             */
+#define OV9655_BLACK_WHITE_BW_NEGATIVE  0xEC000000000000  /* BW and Negative effect      */
+#define OV9655_BLACK_WHITE_NORMAL       0xCC808000008080  /* Normal effect               */
+
+#define OV9655_CONTRAST_LEVEL0          0x30     /* Contrast level -2           */
+#define OV9655_CONTRAST_LEVEL1          0x38     /* Contrast level -1           */
+#define OV9655_CONTRAST_LEVEL2          0x40     /* Contrast level 0            */
+#define OV9655_CONTRAST_LEVEL3          0x50     /* Contrast level +1           */
+#define OV9655_CONTRAST_LEVEL4          0x60     /* Contrast level +2           */
+
+#define OV9655_COLOR_EFFECT_NONE        0xCC808000008080  /* No color effect             */
+#define OV9655_COLOR_EFFECT_ANTIQUE     0xCC000020F00000  /* Antique effect              */
+#define OV9655_COLOR_EFFECT_BLUE        0xCC000000000060  /* Blue effect                 */
+#define OV9655_COLOR_EFFECT_GREEN       0xCC000000008000  /* Green effect                */
+#define OV9655_COLOR_EFFECT_RED         0xCC600000000000  /* Red effect                  */
+/**
+  * @}
+  */
+  
+/** @defgroup OV9655_Exported_Functions
+  * @{
+  */ 
+void     ov9655_Init(uint16_t DeviceAddr, uint32_t resolution);
+void     ov9655_Config(uint16_t DeviceAddr, uint32_t feature, uint32_t value, uint32_t BR_value);
+uint16_t ov9655_ReadID(uint16_t DeviceAddr);
+
+void     CAMERA_IO_Init(void);
+void     CAMERA_IO_Write(uint8_t addr, uint8_t reg, uint8_t value);
+uint8_t  CAMERA_IO_Read(uint8_t addr, uint8_t reg);
+void     CAMERA_Delay(uint32_t delay);
+
+/* CAMERA driver structure */
+extern CAMERA_DrvTypeDef   ov9655_drv;
+/**
+  * @}
+  */    
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __OV9655_H */
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_audio.c	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,1360 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_audio.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file provides the Audio driver for the STM32746G-Discovery board.
+  @verbatim
+    How To use this driver:
+    -----------------------
+       + This driver supports STM32F7xx devices on STM32746G-Discovery (MB1191) board.
+       + Call the function BSP_AUDIO_OUT_Init(
+                                        OutputDevice: physical output mode (OUTPUT_DEVICE_SPEAKER, 
+                                                      OUTPUT_DEVICE_HEADPHONE 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, SAI, 
+          GPIOs, DMA and interrupt if needed). This function returns AUDIO_OK if configuration is OK.
+          If the returned value is different from AUDIO_OK or the function is stuck then the communication with
+          the codec or the MFX has failed (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_BOTH     : both Speaker and Headphone are used as outputs for the audio stream
+                                     at the same time.
+          Note. On STM32746G-Discovery SAI_DMA is configured in CIRCULAR mode. Due to this the application
+            does NOT need to call BSP_AUDIO_OUT_ChangeBuffer() to assure streaming.
+       + Call the function BSP_DISCOVERY_AUDIO_OUT_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 BSP_AUDIO_OUT_Pause() to pause playing   
+       + Call the function BSP_AUDIO_OUT_Resume() to resume playing.
+           Note. After calling BSP_AUDIO_OUT_Pause() function for pause, only BSP_AUDIO_OUT_Resume() should be called
+              for resume (it is not allowed to call BSP_AUDIO_OUT_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 AUDIO_OUT_XXX_CallBack() and only their prototypes are declared in 
+          the stm32746g_discovery_audio.h file. (refer to the example for more details on the callbacks implementations)
+       + To Stop playing, to modify the volume level, the frequency, the audio frame slot, 
+          the device output mode the mute or the stop, use the functions: BSP_AUDIO_OUT_SetVolume(), 
+          AUDIO_OUT_SetFrequency(), BSP_AUDIO_OUT_SetAudioFrameSlot(), BSP_AUDIO_OUT_SetOutputMode(),
+          BSP_AUDIO_OUT_SetMute() and BSP_AUDIO_OUT_Stop().
+       + The driver API and the callback functions are at the end of the stm32746g_discovery_audio.h file.
+     
+    Driver architecture:
+    --------------------
+       + This driver provides the High Audio Layer: consists of the function API exported in the stm32746g_discovery_audio.h file
+         (BSP_AUDIO_OUT_Init(), BSP_AUDIO_OUT_Play() ...)
+       + This driver provide also the 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 stm32746g_discovery_audio_codec.c file (SAIx_Out_Init() and SAIx_Out_DeInit(), SAIx_In_Init() and SAIx_In_DeInit())
+    
+    Known Limitations:
+    ------------------
+       1- If the TDM Format used to play in parallel 2 audio Stream (the first Stream is configured in codec SLOT0 and second 
+          Stream in SLOT1) the Pause/Resume, volume and mute feature will control the both streams.
+       2- 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.
+       3- Supports only Stereo audio streaming.
+       4- Supports only 16-bits audio data size.
+  @endverbatim  
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32746g_discovery_audio.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_AUDIO STM32746G_DISCOVERY AUDIO
+  * @brief This file includes the low layer driver for wm8994 Audio Codec
+  *        available on STM32746G-Discovery board(MB1191).
+  * @{
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Types STM32746G_DISCOVERY AUDIO Private Types
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Defines STM32746G_DISCOVERY AUDIO Private Defines
+  * @{
+  */
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Macros STM32746G_DISCOVERY AUDIO Private Macros
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Variables STM32746G_DISCOVERY AUDIO Private Variables
+  * @{
+  */
+AUDIO_DrvTypeDef          *audio_drv;
+SAI_HandleTypeDef         haudio_out_sai={0};
+SAI_HandleTypeDef         haudio_in_sai={0};
+TIM_HandleTypeDef         haudio_tim;
+
+uint16_t __IO AudioInVolume = DEFAULT_AUDIO_IN_VOLUME;
+    
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Private_Function_Prototypes STM32746G_DISCOVERY AUDIO Private Function Prototypes
+  * @{
+  */
+static void SAIx_Out_Init(uint32_t AudioFreq);
+static void SAIx_Out_DeInit(void);
+static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq);
+static void SAIx_In_DeInit(void);
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_AUDIO_OUT_Exported_Functions STM32746G_DISCOVERY AUDIO Out Exported Functions
+  * @{
+  */ 
+
+/**
+  * @brief  Configures the audio peripherals.
+  * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
+  *                       or OUTPUT_DEVICE_BOTH.
+  * @param  Volume: Initial volume level (from 0 (Mute) to 100 (Max))
+  * @param  AudioFreq: Audio frequency used to play the audio stream.
+  * @note   The I2S PLL input clock must be done in the user application.  
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
+{ 
+  uint8_t ret = AUDIO_ERROR;
+  uint32_t deviceid = 0x00;
+
+  /* Disable SAI */
+  SAIx_Out_DeInit();
+
+  /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
+  BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
+ 
+  /* SAI data transfer preparation:
+  Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
+  haudio_out_sai.Instance = AUDIO_OUT_SAIx;
+  if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
+  {
+    /* Init the SAI MSP: this __weak function can be redefined by the application*/
+    BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
+  }
+  SAIx_Out_Init(AudioFreq);
+
+  /* wm8994 codec initialization */
+  deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
+  
+  if((deviceid) == WM8994_ID)
+  {  
+    /* Reset the Codec Registers */
+    wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
+    /* Initialize the audio driver structure */
+    audio_drv = &wm8994_drv; 
+    ret = AUDIO_OK;
+  }
+  else
+  {
+    ret = AUDIO_ERROR;
+  }
+
+  if(ret == AUDIO_OK)
+  {
+    /* Initialize the codec internal registers */
+    audio_drv->Init(AUDIO_I2C_ADDRESS, OutputDevice, Volume, AudioFreq);
+  }
+ 
+  return ret;
+}
+
+/**
+  * @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 in BYTES unit.
+  *         In memory, first element is for left channel, second element is for right channel
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size)
+{
+  /* Call the audio Codec Play function */
+  if(audio_drv->Play(AUDIO_I2C_ADDRESS, pBuffer, Size) != 0)
+  {  
+    return AUDIO_ERROR;
+  }
+  else
+  {
+    /* Update the Media layer and enable it for play */  
+    HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pBuffer, DMA_MAX(Size / AUDIODATA_SIZE));
+    
+    return AUDIO_OK;
+  }
+}
+
+/**
+  * @brief  Sends n-Bytes on the SAI interface.
+  * @param  pData: pointer on data address 
+  * @param  Size: number of data to be written
+  * @retval None
+  */
+void BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size)
+{
+   HAL_SAI_Transmit_DMA(&haudio_out_sai, (uint8_t*) pData, Size);
+}
+
+/**
+  * @brief  This function Pauses the audio file stream. In case
+  *         of using DMA, the DMA Pause feature is used.
+  * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
+  *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
+  *          function for resume could lead to unexpected behaviour).
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_OUT_Pause(void)
+{    
+  /* Call the Audio Codec Pause/Resume function */
+  if(audio_drv->Pause(AUDIO_I2C_ADDRESS) != 0)
+  {
+    return AUDIO_ERROR;
+  }
+  else
+  {
+    /* Call the Media layer pause function */
+    HAL_SAI_DMAPause(&haudio_out_sai);
+    
+    /* Return AUDIO_OK when all operations are correctly done */
+    return AUDIO_OK;
+  }
+}
+
+/**
+  * @brief  This function  Resumes the audio file stream.  
+  * @note When calling BSP_AUDIO_OUT_Pause() function for pause, only
+  *          BSP_AUDIO_OUT_Resume() function should be called for resume (use of BSP_AUDIO_OUT_Play() 
+  *          function for resume could lead to unexpected behaviour).
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_OUT_Resume(void)
+{    
+  /* Call the Audio Codec Pause/Resume function */
+  if(audio_drv->Resume(AUDIO_I2C_ADDRESS) != 0)
+  {
+    return AUDIO_ERROR;
+  }
+  else
+  {
+    /* Call the Media layer pause/resume function */
+    HAL_SAI_DMAResume(&haudio_out_sai);
+    
+    /* Return AUDIO_OK when all operations are correctly done */
+    return AUDIO_OK;
+  }
+}
+
+/**
+  * @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 AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option)
+{
+  /* Call the Media layer stop function */
+  HAL_SAI_DMAStop(&haudio_out_sai);
+  
+  /* Call Audio Codec Stop function */
+  if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
+  {
+    return AUDIO_ERROR;
+  }
+  else
+  {
+    if(Option == CODEC_PDWN_HW)
+    { 
+      /* Wait at least 100us */
+      HAL_Delay(1);
+    }
+    /* Return AUDIO_OK when all operations are correctly done */
+    return AUDIO_OK;
+  }
+}
+
+/**
+  * @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 AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume)
+{
+  /* Call the codec volume control function with converted volume value */
+  if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
+  {
+    return AUDIO_ERROR;
+  }
+  else
+  {
+    /* Return AUDIO_OK when all operations are correctly done */
+    return AUDIO_OK;
+  }
+}
+
+/**
+  * @brief  Enables or disables the MUTE mode by software 
+  * @param  Cmd: Could be AUDIO_MUTE_ON to mute sound or AUDIO_MUTE_OFF to 
+  *         unmute the codec and restore previous volume level.
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd)
+{ 
+  /* Call the Codec Mute function */
+  if(audio_drv->SetMute(AUDIO_I2C_ADDRESS, Cmd) != 0)
+  {
+    return AUDIO_ERROR;
+  }
+  else
+  {
+    /* Return AUDIO_OK when all operations are correctly done */
+    return AUDIO_OK;
+  }
+}
+
+/**
+  * @brief  Switch dynamically (while audio file is played) the output target 
+  *         (speaker or headphone).
+  * @param  Output: The audio output target: OUTPUT_DEVICE_SPEAKER,
+  *         OUTPUT_DEVICE_HEADPHONE or OUTPUT_DEVICE_BOTH
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output)
+{
+  /* Call the Codec output device function */
+  if(audio_drv->SetOutputMode(AUDIO_I2C_ADDRESS, Output) != 0)
+  {
+    return AUDIO_ERROR;
+  }
+  else
+  {
+    /* Return AUDIO_OK when all operations are correctly done */
+    return AUDIO_OK;
+  }
+}
+
+/**
+  * @brief  Updates the audio frequency.
+  * @param  AudioFreq: Audio frequency used to play the audio stream.
+  * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
+  *         audio frequency.
+  * @retval None
+  */
+void BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq)
+{ 
+  /* PLL clock is set depending by the AudioFreq (44.1khz vs 48khz groups) */ 
+  BSP_AUDIO_OUT_ClockConfig(&haudio_out_sai, AudioFreq, NULL);
+
+  /* Disable SAI peripheral to allow access to SAI internal registers */
+  __HAL_SAI_DISABLE(&haudio_out_sai);
+  
+  /* Update the SAI audio frequency configuration */
+  haudio_out_sai.Init.AudioFrequency = AudioFreq;
+  HAL_SAI_Init(&haudio_out_sai);
+  
+  /* Enable SAI peripheral to generate MCLK */
+  __HAL_SAI_ENABLE(&haudio_out_sai);
+}
+
+/**
+  * @brief  Updates the Audio frame slot configuration.
+  * @param  AudioFrameSlot: specifies the audio Frame slot
+  *         This parameter can be one of the following values
+  *            @arg CODEC_AUDIOFRAME_SLOT_0123
+  *            @arg CODEC_AUDIOFRAME_SLOT_02
+  *            @arg CODEC_AUDIOFRAME_SLOT_13
+  * @note   This API should be called after the BSP_AUDIO_OUT_Init() to adjust the
+  *         audio frame slot.
+  * @retval None
+  */
+void BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot)
+{ 
+  /* Disable SAI peripheral to allow access to SAI internal registers */
+  __HAL_SAI_DISABLE(&haudio_out_sai);
+  
+  /* Update the SAI audio frame slot configuration */
+  haudio_out_sai.SlotInit.SlotActive = AudioFrameSlot;
+  HAL_SAI_Init(&haudio_out_sai);
+  
+  /* Enable SAI peripheral to generate MCLK */
+  __HAL_SAI_ENABLE(&haudio_out_sai);
+}
+
+/**
+  * @brief  Deinit the audio peripherals.
+  * @retval None
+  */
+void BSP_AUDIO_OUT_DeInit(void)
+{
+  SAIx_Out_DeInit();
+  /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
+  BSP_AUDIO_OUT_MspDeInit(&haudio_out_sai, NULL);
+}
+
+/**
+  * @brief  Tx Transfer completed callbacks.
+  * @param  hsai: SAI handle
+  * @retval None
+  */
+void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
+{
+  /* Manage the remaining file size and new address offset: This function 
+     should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */
+  BSP_AUDIO_OUT_TransferComplete_CallBack();
+}
+
+/**
+  * @brief  Tx Half Transfer completed callbacks.
+  * @param  hsai: SAI handle
+  * @retval None
+  */
+void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
+{
+  /* Manage the remaining file size and new address offset: This function 
+     should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */
+  BSP_AUDIO_OUT_HalfTransfer_CallBack();
+}
+
+/**
+  * @brief  SAI error callbacks.
+  * @param  hsai: SAI handle
+  * @retval None
+  */
+void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai)
+{
+  HAL_SAI_StateTypeDef audio_out_state;
+  HAL_SAI_StateTypeDef audio_in_state;
+
+  audio_out_state = HAL_SAI_GetState(&haudio_out_sai);
+  audio_in_state = HAL_SAI_GetState(&haudio_in_sai);
+
+  /* Determines if it is an audio out or audio in error */
+  if ((audio_out_state == HAL_SAI_STATE_BUSY) || (audio_out_state == HAL_SAI_STATE_BUSY_TX)
+   || (audio_out_state == HAL_SAI_STATE_TIMEOUT) || (audio_out_state == HAL_SAI_STATE_ERROR))
+  {
+    BSP_AUDIO_OUT_Error_CallBack();
+  }
+
+  if ((audio_in_state == HAL_SAI_STATE_BUSY) || (audio_in_state == HAL_SAI_STATE_BUSY_RX)
+   || (audio_in_state == HAL_SAI_STATE_TIMEOUT) || (audio_in_state == HAL_SAI_STATE_ERROR))
+  {
+    BSP_AUDIO_IN_Error_CallBack();
+  }
+}
+
+/**
+  * @brief  Manages the DMA full Transfer complete event.
+  * @retval None
+  */
+__weak void BSP_AUDIO_OUT_TransferComplete_CallBack(void)
+{
+}
+
+/**
+  * @brief  Manages the DMA Half Transfer complete event.
+  * @retval None
+  */
+__weak void BSP_AUDIO_OUT_HalfTransfer_CallBack(void)
+{ 
+}
+
+/**
+  * @brief  Manages the DMA FIFO error event.
+  * @retval None
+  */
+__weak void BSP_AUDIO_OUT_Error_CallBack(void)
+{
+}
+
+/**
+  * @brief  Initializes BSP_AUDIO_OUT MSP.
+  * @param  hsai: SAI handle
+  * @param  Params
+  * @retval None
+  */
+__weak void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params)
+{ 
+  static DMA_HandleTypeDef hdma_sai_tx;
+  GPIO_InitTypeDef  gpio_init_structure;  
+
+  /* Enable SAI clock */
+  AUDIO_OUT_SAIx_CLK_ENABLE();
+  
+  /* Enable GPIO clock */
+  AUDIO_OUT_SAIx_MCLK_ENABLE();
+  AUDIO_OUT_SAIx_SCK_SD_ENABLE();
+  AUDIO_OUT_SAIx_FS_ENABLE();
+  /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/
+  gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN;
+  gpio_init_structure.Mode = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull = GPIO_NOPULL;
+  gpio_init_structure.Speed = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF;
+  HAL_GPIO_Init(AUDIO_OUT_SAIx_FS_GPIO_PORT, &gpio_init_structure);
+
+  gpio_init_structure.Pin = AUDIO_OUT_SAIx_SCK_PIN;
+  gpio_init_structure.Mode = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull = GPIO_NOPULL;
+  gpio_init_structure.Speed = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = AUDIO_OUT_SAIx_SCK_AF;
+  HAL_GPIO_Init(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure);
+
+  gpio_init_structure.Pin =  AUDIO_OUT_SAIx_SD_PIN;
+  gpio_init_structure.Mode = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull = GPIO_NOPULL;
+  gpio_init_structure.Speed = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF;
+  HAL_GPIO_Init(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure);
+
+  gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
+  gpio_init_structure.Mode = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull = GPIO_NOPULL;
+  gpio_init_structure.Speed = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF;
+  HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure);
+
+  /* Enable the DMA clock */
+  AUDIO_OUT_SAIx_DMAx_CLK_ENABLE();
+    
+  if(hsai->Instance == AUDIO_OUT_SAIx)
+  {
+    /* Configure the hdma_saiTx handle parameters */   
+    hdma_sai_tx.Init.Channel             = AUDIO_OUT_SAIx_DMAx_CHANNEL;
+    hdma_sai_tx.Init.Direction           = DMA_MEMORY_TO_PERIPH;
+    hdma_sai_tx.Init.PeriphInc           = DMA_PINC_DISABLE;
+    hdma_sai_tx.Init.MemInc              = DMA_MINC_ENABLE;
+    hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE;
+    hdma_sai_tx.Init.MemDataAlignment    = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE;
+    hdma_sai_tx.Init.Mode                = DMA_CIRCULAR;
+    hdma_sai_tx.Init.Priority            = DMA_PRIORITY_HIGH;
+    hdma_sai_tx.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;         
+    hdma_sai_tx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+    hdma_sai_tx.Init.MemBurst            = DMA_MBURST_SINGLE;
+    hdma_sai_tx.Init.PeriphBurst         = DMA_PBURST_SINGLE; 
+    
+    hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM;
+    
+    /* Associate the DMA handle */
+    __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx);
+    
+    /* Deinitialize the Stream for new transfer */
+    HAL_DMA_DeInit(&hdma_sai_tx);
+    
+    /* Configure the DMA Stream */
+    HAL_DMA_Init(&hdma_sai_tx);      
+  }
+  
+  /* SAI DMA IRQ Channel configuration */
+  HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0);
+  HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); 
+}
+
+/**
+  * @brief  Deinitializes SAI MSP.
+  * @param  hsai: SAI handle
+  * @param  Params
+  * @retval None
+  */
+__weak void BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
+{
+    GPIO_InitTypeDef  gpio_init_structure;
+
+    /* SAI DMA IRQ Channel deactivation */
+    HAL_NVIC_DisableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ);
+
+    if(hsai->Instance == AUDIO_OUT_SAIx)
+    {
+      /* Deinitialize the DMA stream */
+      HAL_DMA_DeInit(hsai->hdmatx);
+    }
+
+    /* Disable SAI peripheral */
+    __HAL_SAI_DISABLE(hsai);  
+
+    /* Deactives CODEC_SAI pins FS, SCK, MCK and SD by putting them in input mode */
+    gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN;
+    HAL_GPIO_DeInit(AUDIO_OUT_SAIx_FS_GPIO_PORT, gpio_init_structure.Pin);
+
+    gpio_init_structure.Pin = AUDIO_OUT_SAIx_SCK_PIN;
+    HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin);
+
+    gpio_init_structure.Pin =  AUDIO_OUT_SAIx_SD_PIN;
+    HAL_GPIO_DeInit(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, gpio_init_structure.Pin);
+
+    gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN;
+    HAL_GPIO_DeInit(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, gpio_init_structure.Pin);
+  
+    /* Disable SAI clock */
+    AUDIO_OUT_SAIx_CLK_DISABLE();
+
+    /* GPIO pins clock and DMA clock can be shut down in the application
+       by surcharging this __weak function */
+}
+
+/**
+  * @brief  Clock Config.
+  * @param  hsai: might be required to set audio peripheral predivider if any.
+  * @param  AudioFreq: Audio frequency used to play the audio stream.
+  * @param  Params  
+  * @note   This API is called by BSP_AUDIO_OUT_Init() and BSP_AUDIO_OUT_SetFrequency()
+  *         Being __weak it can be overwritten by the application     
+  * @retval None
+  */
+__weak void BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params)
+{ 
+  RCC_PeriphCLKInitTypeDef rcc_ex_clk_init_struct;
+
+  HAL_RCCEx_GetPeriphCLKConfig(&rcc_ex_clk_init_struct);
+  
+  /* Set the PLL configuration according to the audio frequency */
+  if((AudioFreq == AUDIO_FREQUENCY_11K) || (AudioFreq == AUDIO_FREQUENCY_22K) || (AudioFreq == AUDIO_FREQUENCY_44K))
+  {
+    /* Configure PLLI2S prescalers */
+    /* PLLI2S_VCO: VCO_429M
+    I2S_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 429/2 = 214.5 Mhz
+    I2S_CLK_x = I2S_CLK(first level)/PLLI2SDIVQ = 214.5/19 = 11.289 Mhz */
+    rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
+    rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
+    rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 429;
+    rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 2;
+    rcc_ex_clk_init_struct.PLLI2SDivQ = 19;
+    
+    HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
+    
+  }
+  else /* AUDIO_FREQUENCY_8K, AUDIO_FREQUENCY_16K, AUDIO_FREQUENCY_48K), AUDIO_FREQUENCY_96K */
+  {
+    /* I2S clock config
+    PLLI2S_VCO: VCO_344M
+    I2S_CLK(first level) = PLLI2S_VCO/PLLI2SQ = 344/7 = 49.142 Mhz
+    I2S_CLK_x = I2S_CLK(first level)/PLLI2SDIVQ = 49.142/1 = 49.142 Mhz */
+    rcc_ex_clk_init_struct.PeriphClockSelection = RCC_PERIPHCLK_SAI2;
+    rcc_ex_clk_init_struct.Sai2ClockSelection = RCC_SAI2CLKSOURCE_PLLI2S;
+    rcc_ex_clk_init_struct.PLLI2S.PLLI2SN = 344;
+    rcc_ex_clk_init_struct.PLLI2S.PLLI2SQ = 7;
+    rcc_ex_clk_init_struct.PLLI2SDivQ = 1;
+    
+    HAL_RCCEx_PeriphCLKConfig(&rcc_ex_clk_init_struct);
+  }
+}
+
+/*******************************************************************************
+                            Static Functions
+*******************************************************************************/
+
+/**
+  * @brief  Initializes the output Audio Codec audio interface (SAI).
+  * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
+  * @note   The default SlotActive configuration is set to CODEC_AUDIOFRAME_SLOT_0123 
+  *         and user can update this configuration using 
+  * @retval None
+  */
+static void SAIx_Out_Init(uint32_t AudioFreq)
+{
+  /* Initialize the haudio_out_sai Instance parameter */
+  haudio_out_sai.Instance = AUDIO_OUT_SAIx;
+  
+  /* Disable SAI peripheral to allow access to SAI internal registers */
+  __HAL_SAI_DISABLE(&haudio_out_sai);
+  
+  /* Configure SAI_Block_x 
+  LSBFirst: Disabled 
+  DataSize: 16 */
+  haudio_out_sai.Init.AudioFrequency = AudioFreq;
+  haudio_out_sai.Init.AudioMode = SAI_MODEMASTER_TX;
+  haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
+  haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
+  haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
+  haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
+  haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
+  haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
+  haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED;
+  haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
+  
+  /* Configure SAI_Block_x Frame 
+  Frame Length: 64
+  Frame active Length: 32
+  FS Definition: Start frame + Channel Side identification
+  FS Polarity: FS active Low
+  FS Offset: FS asserted one bit before the first bit of slot 0 */ 
+  haudio_out_sai.FrameInit.FrameLength = 64; 
+  haudio_out_sai.FrameInit.ActiveFrameLength = 32;
+  haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
+  haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
+  haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
+  
+  /* Configure SAI Block_x Slot 
+  Slot First Bit Offset: 0
+  Slot Size  : 16
+  Slot Number: 4
+  Slot Active: All slot actives */
+  haudio_out_sai.SlotInit.FirstBitOffset = 0;
+  haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
+  haudio_out_sai.SlotInit.SlotNumber = 4; 
+  haudio_out_sai.SlotInit.SlotActive = CODEC_AUDIOFRAME_SLOT_0123;
+
+  HAL_SAI_Init(&haudio_out_sai);
+  
+  /* Enable SAI peripheral to generate MCLK */
+  __HAL_SAI_ENABLE(&haudio_out_sai);
+}
+
+
+
+/**
+  * @brief  Deinitializes the output Audio Codec audio interface (SAI).
+  * @retval None
+  */
+static void SAIx_Out_DeInit(void)
+{
+  /* Initialize the haudio_out_sai Instance parameter */
+  haudio_out_sai.Instance = AUDIO_OUT_SAIx;
+
+  /* Disable SAI peripheral */
+  __HAL_SAI_DISABLE(&haudio_out_sai);
+
+  HAL_SAI_DeInit(&haudio_out_sai);
+}
+
+/**
+  * @}
+  */
+
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Out_Private_Functions STM32746G_DISCOVERY_AUDIO Out Private Functions
+  * @{
+  */ 
+  
+/**
+  * @brief  Initializes wave recording.
+  * @param  InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2 or INPUT_DEVICE_INPUT_LINE_1
+  * @param  Volume: Initial volume level (in range 0(Mute)..80(+0dB)..100(+17.625dB))
+  * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_IN_Init(uint16_t InputDevice, uint8_t Volume, uint32_t AudioFreq)
+{
+  uint8_t ret = AUDIO_ERROR;
+  uint32_t deviceid = 0x00;
+  uint32_t slot_active;
+
+  if ((InputDevice != INPUT_DEVICE_INPUT_LINE_1) &&       /* Only INPUT_LINE_1 and MICROPHONE_2 inputs supported */
+      (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2))
+  {
+    ret = AUDIO_ERROR;
+  }
+  else
+  {
+    /* Disable SAI */
+    SAIx_In_DeInit();
+
+    /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
+    BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
+
+    /* SAI data transfer preparation:
+    Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
+    haudio_in_sai.Instance = AUDIO_IN_SAIx;
+    if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
+    {
+      /* Init the SAI MSP: this __weak function can be redefined by the application*/
+      BSP_AUDIO_OUT_MspInit(&haudio_in_sai, NULL);  /* Initialize GPIOs for SAI2 block A Master signals */
+      BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL);
+    }
+
+    /* Configure SAI in master RX mode :
+     *   - SAI2_block_A in master RX mode
+     *   - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
+     */
+    if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2)
+    {
+      slot_active = CODEC_AUDIOFRAME_SLOT_13;
+    }
+    else
+    {
+      slot_active = CODEC_AUDIOFRAME_SLOT_02;
+    }
+    SAIx_In_Init(SAI_MODEMASTER_RX, slot_active, AudioFreq);
+
+    /* wm8994 codec initialization */
+    deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
+
+    if((deviceid) == WM8994_ID)
+    {
+      /* Reset the Codec Registers */
+      wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
+      /* Initialize the audio driver structure */
+      audio_drv = &wm8994_drv;
+      ret = AUDIO_OK;
+    }
+    else
+    {
+      ret = AUDIO_ERROR;
+    }
+
+    if(ret == AUDIO_OK)
+    {
+      /* Initialize the codec internal registers */
+      audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice, Volume, AudioFreq);
+    }
+  }
+  return ret;
+}
+
+/**
+  * @brief  Initializes wave recording and playback in parallel.
+  * @param  InputDevice: INPUT_DEVICE_DIGITAL_MICROPHONE_2
+  * @param  OutputDevice: OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
+  *                       or OUTPUT_DEVICE_BOTH.
+  * @param  Volume: Initial volume level (in range 0(Mute)..80(+0dB)..100(+17.625dB))
+  * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_IN_OUT_Init(uint16_t InputDevice, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq)
+{
+  uint8_t ret = AUDIO_ERROR;
+  uint32_t deviceid = 0x00;
+  uint32_t slot_active;
+
+  if (InputDevice != INPUT_DEVICE_DIGITAL_MICROPHONE_2)  /* Only MICROPHONE_2 input supported */
+  {
+    ret = AUDIO_ERROR;
+  }
+  else
+  {
+    /* Disable SAI */
+    SAIx_In_DeInit();
+    SAIx_Out_DeInit();
+
+    /* PLL clock is set depending on the AudioFreq (44.1khz vs 48khz groups) */
+    BSP_AUDIO_OUT_ClockConfig(&haudio_in_sai, AudioFreq, NULL); /* Clock config is shared between AUDIO IN and OUT */
+
+    /* SAI data transfer preparation:
+    Prepare the Media to be used for the audio transfer from SAI peripheral to memory */
+    haudio_in_sai.Instance = AUDIO_IN_SAIx;
+    if(HAL_SAI_GetState(&haudio_in_sai) == HAL_SAI_STATE_RESET)
+    {
+      /* Init the SAI MSP: this __weak function can be redefined by the application*/
+      BSP_AUDIO_IN_MspInit(&haudio_in_sai, NULL);
+    }
+
+    /* SAI data transfer preparation:
+    Prepare the Media to be used for the audio transfer from memory to SAI peripheral */
+    haudio_out_sai.Instance = AUDIO_OUT_SAIx;
+    if(HAL_SAI_GetState(&haudio_out_sai) == HAL_SAI_STATE_RESET)
+    {
+      /* Init the SAI MSP: this __weak function can be redefined by the application*/
+      BSP_AUDIO_OUT_MspInit(&haudio_out_sai, NULL);
+    }
+
+    /* Configure SAI in master mode :
+     *   - SAI2_block_A in master TX mode
+     *   - SAI2_block_B in slave RX mode synchronous from SAI2_block_A
+     */
+    if (InputDevice == INPUT_DEVICE_DIGITAL_MICROPHONE_2)
+    {
+      slot_active = CODEC_AUDIOFRAME_SLOT_13;
+    }
+    else
+    {
+      slot_active = CODEC_AUDIOFRAME_SLOT_02;
+    }
+    SAIx_In_Init(SAI_MODEMASTER_TX, slot_active, AudioFreq);
+
+    /* wm8994 codec initialization */
+    deviceid = wm8994_drv.ReadID(AUDIO_I2C_ADDRESS);
+
+    if((deviceid) == WM8994_ID)
+    {
+      /* Reset the Codec Registers */
+      wm8994_drv.Reset(AUDIO_I2C_ADDRESS);
+      /* Initialize the audio driver structure */
+      audio_drv = &wm8994_drv;
+      ret = AUDIO_OK;
+    }
+    else
+    {
+      ret = AUDIO_ERROR;
+    }
+
+    if(ret == AUDIO_OK)
+    {
+      /* Initialize the codec internal registers */
+      audio_drv->Init(AUDIO_I2C_ADDRESS, InputDevice | OutputDevice, Volume, AudioFreq);
+    }
+  }
+  return ret;
+}
+
+
+/**
+  * @brief  Starts audio recording.
+  * @param  pbuf: Main buffer pointer for the recorded data storing  
+  * @param  size: size of the recorded buffer in number of elements (typically number of half-words)
+  *               Be careful that it is not the same unit than BSP_AUDIO_OUT_Play function
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t  BSP_AUDIO_IN_Record(uint16_t* pbuf, uint32_t size)
+{
+  uint32_t ret = AUDIO_ERROR;
+  
+  /* Start the process receive DMA */
+  HAL_SAI_Receive_DMA(&haudio_in_sai, (uint8_t*)pbuf, size);
+  
+  /* Return AUDIO_OK when all operations are correctly done */
+  ret = AUDIO_OK;
+  
+  return ret;
+}
+
+/**
+  * @brief  Stops audio recording.
+  * @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 AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_IN_Stop(uint32_t Option)
+{
+  /* Call the Media layer stop function */
+  HAL_SAI_DMAStop(&haudio_in_sai);
+  
+  /* Call Audio Codec Stop function */
+  if(audio_drv->Stop(AUDIO_I2C_ADDRESS, Option) != 0)
+  {
+    return AUDIO_ERROR;
+  }
+  else
+  {
+    if(Option == CODEC_PDWN_HW)
+    {
+      /* Wait at least 100us */
+      HAL_Delay(1);
+    }
+    /* Return AUDIO_OK when all operations are correctly done */
+    return AUDIO_OK;
+  }
+}
+
+/**
+  * @brief  Pauses the audio file stream.
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_IN_Pause(void)
+{    
+  /* Call the Media layer pause function */
+  HAL_SAI_DMAPause(&haudio_in_sai);
+  /* Return AUDIO_OK when all operations are correctly done */
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  Resumes the audio file stream.
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_IN_Resume(void)
+{    
+  /* Call the Media layer pause/resume function */
+  HAL_SAI_DMAResume(&haudio_in_sai);
+  /* Return AUDIO_OK when all operations are correctly done */
+  return AUDIO_OK;
+}
+
+/**
+  * @brief  Controls the audio in volume level. 
+  * @param  Volume: Volume level in range 0(Mute)..80(+0dB)..100(+17.625dB)
+  * @retval AUDIO_OK if correct communication, else wrong communication
+  */
+uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume)
+{
+  /* Call the codec volume control function with converted volume value */
+  if(audio_drv->SetVolume(AUDIO_I2C_ADDRESS, Volume) != 0)
+  {
+    return AUDIO_ERROR;
+  }
+  else
+  {
+    /* Set the Global variable AudioInVolume  */
+    AudioInVolume = Volume;
+    /* Return AUDIO_OK when all operations are correctly done */
+    return AUDIO_OK;
+  }
+}
+
+/**
+  * @brief  Deinit the audio IN peripherals.
+  * @retval None
+  */
+void BSP_AUDIO_IN_DeInit(void)
+{
+  SAIx_In_DeInit();
+  /* DeInit the SAI MSP : this __weak function can be rewritten by the application */
+  BSP_AUDIO_IN_MspDeInit(&haudio_in_sai, NULL);
+}
+
+ /**
+  * @brief  Rx Transfer completed callbacks.
+  * @param  hsai: SAI handle
+  * @retval None
+  */
+void HAL_SAI_RxCpltCallback(SAI_HandleTypeDef *hsai)
+{
+  /* Call the record update function to get the next buffer to fill and its size (size is ignored) */
+  BSP_AUDIO_IN_TransferComplete_CallBack();
+}
+
+/**
+  * @brief  Rx Half Transfer completed callbacks.
+  * @param  hsai: SAI handle
+  * @retval None
+  */
+void HAL_SAI_RxHalfCpltCallback(SAI_HandleTypeDef *hsai)
+{
+  /* Manage the remaining file size and new address offset: This function 
+     should be coded by user (its prototype is already declared in stm32746g_discovery_audio.h) */
+  BSP_AUDIO_IN_HalfTransfer_CallBack();
+}
+
+/**
+  * @brief  User callback when record buffer is filled.
+  * @retval None
+  */
+__weak void BSP_AUDIO_IN_TransferComplete_CallBack(void)
+{
+  /* This function should be implemented by the user application.
+     It is called into this driver when the current buffer is filled
+     to prepare the next buffer pointer and its size. */
+}
+
+/**
+  * @brief  Manages the DMA Half Transfer complete event.
+  * @retval None
+  */
+__weak void BSP_AUDIO_IN_HalfTransfer_CallBack(void)
+{ 
+  /* This function should be implemented by the user application.
+     It is called into this driver when the current buffer is filled
+     to prepare the next buffer pointer and its size. */
+}
+
+/**
+  * @brief  Audio IN Error callback function.
+  * @retval None
+  */
+__weak void BSP_AUDIO_IN_Error_CallBack(void)
+{   
+  /* This function is called when an Interrupt due to transfer error on or peripheral
+     error occurs. */
+}
+
+/**
+  * @brief  Initializes BSP_AUDIO_IN MSP.
+  * @param  hsai: SAI handle
+  * @param  Params
+  * @retval None
+  */
+__weak void BSP_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params)
+{
+  static DMA_HandleTypeDef hdma_sai_rx;
+  GPIO_InitTypeDef  gpio_init_structure;  
+
+  /* Enable SAI clock */
+  AUDIO_IN_SAIx_CLK_ENABLE();
+  
+  /* Enable SD GPIO clock */
+  AUDIO_IN_SAIx_SD_ENABLE();
+  /* CODEC_SAI pin configuration: SD pin */
+  gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
+  gpio_init_structure.Mode = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull = GPIO_NOPULL;
+  gpio_init_structure.Speed = GPIO_SPEED_FAST;
+  gpio_init_structure.Alternate = AUDIO_IN_SAIx_SD_AF;
+  HAL_GPIO_Init(AUDIO_IN_SAIx_SD_GPIO_PORT, &gpio_init_structure);
+
+  /* Enable Audio INT GPIO clock */
+  AUDIO_IN_INT_GPIO_ENABLE();
+  /* Audio INT pin configuration: input */
+  gpio_init_structure.Pin = AUDIO_IN_INT_GPIO_PIN;
+  gpio_init_structure.Mode = GPIO_MODE_INPUT;
+  gpio_init_structure.Pull = GPIO_NOPULL;
+  gpio_init_structure.Speed = GPIO_SPEED_FAST;
+  HAL_GPIO_Init(AUDIO_IN_INT_GPIO_PORT, &gpio_init_structure);
+
+  /* Enable the DMA clock */
+  AUDIO_IN_SAIx_DMAx_CLK_ENABLE();
+    
+  if(hsai->Instance == AUDIO_IN_SAIx)
+  {
+    /* Configure the hdma_sai_rx handle parameters */
+    hdma_sai_rx.Init.Channel             = AUDIO_IN_SAIx_DMAx_CHANNEL;
+    hdma_sai_rx.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+    hdma_sai_rx.Init.PeriphInc           = DMA_PINC_DISABLE;
+    hdma_sai_rx.Init.MemInc              = DMA_MINC_ENABLE;
+    hdma_sai_rx.Init.PeriphDataAlignment = AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE;
+    hdma_sai_rx.Init.MemDataAlignment    = AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE;
+    hdma_sai_rx.Init.Mode                = DMA_CIRCULAR;
+    hdma_sai_rx.Init.Priority            = DMA_PRIORITY_HIGH;
+    hdma_sai_rx.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
+    hdma_sai_rx.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+    hdma_sai_rx.Init.MemBurst            = DMA_MBURST_SINGLE;
+    hdma_sai_rx.Init.PeriphBurst         = DMA_MBURST_SINGLE;
+    
+    hdma_sai_rx.Instance = AUDIO_IN_SAIx_DMAx_STREAM;
+    
+    /* Associate the DMA handle */
+    __HAL_LINKDMA(hsai, hdmarx, hdma_sai_rx);
+    
+    /* Deinitialize the Stream for new transfer */
+    HAL_DMA_DeInit(&hdma_sai_rx);
+    
+    /* Configure the DMA Stream */
+    HAL_DMA_Init(&hdma_sai_rx);
+  }
+  
+  /* SAI DMA IRQ Channel configuration */
+  HAL_NVIC_SetPriority(AUDIO_IN_SAIx_DMAx_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
+  HAL_NVIC_EnableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
+
+  /* Audio INT IRQ Channel configuration */
+  HAL_NVIC_SetPriority(AUDIO_IN_INT_IRQ, AUDIO_IN_IRQ_PREPRIO, 0);
+  HAL_NVIC_EnableIRQ(AUDIO_IN_INT_IRQ);
+}
+
+/**
+  * @brief  DeInitializes BSP_AUDIO_IN MSP.
+  * @param  hsai: SAI handle
+  * @param  Params
+  * @retval None
+  */
+__weak void BSP_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params)
+{
+  GPIO_InitTypeDef  gpio_init_structure;
+
+  static DMA_HandleTypeDef hdma_sai_rx;
+
+  /* SAI IN DMA IRQ Channel deactivation */
+  HAL_NVIC_DisableIRQ(AUDIO_IN_SAIx_DMAx_IRQ);
+
+  if(hsai->Instance == AUDIO_IN_SAIx)
+  {
+    /* Deinitialize the Stream for new transfer */
+    HAL_DMA_DeInit(&hdma_sai_rx);
+  }
+
+ /* Disable SAI block */
+  __HAL_SAI_DISABLE(hsai);
+
+  /* Disable pin: SD pin */
+  gpio_init_structure.Pin = AUDIO_IN_SAIx_SD_PIN;
+  HAL_GPIO_DeInit(AUDIO_IN_SAIx_SD_GPIO_PORT, gpio_init_structure.Pin);
+
+  /* Disable SAI clock */
+  AUDIO_IN_SAIx_CLK_DISABLE();
+
+  /* GPIO pins clock and DMA clock can be shut down in the application
+     by surcharging this __weak function */
+}
+
+
+/*******************************************************************************
+                            Static Functions
+*******************************************************************************/
+
+/**
+  * @brief  Initializes the input Audio Codec audio interface (SAI).
+  * @param  SaiOutMode: SAI_MODEMASTER_TX (for record and playback in parallel)
+  *                     or SAI_MODEMASTER_RX (for record only).
+  * @param  SlotActive: CODEC_AUDIOFRAME_SLOT_02 or CODEC_AUDIOFRAME_SLOT_13
+  * @param  AudioFreq: Audio frequency to be configured for the SAI peripheral.
+  * @retval None
+  */
+static void SAIx_In_Init(uint32_t SaiOutMode, uint32_t SlotActive, uint32_t AudioFreq)
+{
+  /* Initialize SAI2 block A in MASTER RX */
+  /* Initialize the haudio_out_sai Instance parameter */
+  haudio_out_sai.Instance = AUDIO_OUT_SAIx;
+
+  /* Disable SAI peripheral to allow access to SAI internal registers */
+  __HAL_SAI_DISABLE(&haudio_out_sai);
+
+  /* Configure SAI_Block_x
+  LSBFirst: Disabled
+  DataSize: 16 */
+  haudio_out_sai.Init.AudioFrequency = AudioFreq;
+  haudio_out_sai.Init.AudioMode = SaiOutMode;
+  haudio_out_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
+  haudio_out_sai.Init.Protocol = SAI_FREE_PROTOCOL;
+  haudio_out_sai.Init.DataSize = SAI_DATASIZE_16;
+  haudio_out_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
+  haudio_out_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
+  haudio_out_sai.Init.Synchro = SAI_ASYNCHRONOUS;
+  haudio_out_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLED;
+  haudio_out_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
+
+  /* Configure SAI_Block_x Frame
+  Frame Length: 64
+  Frame active Length: 32
+  FS Definition: Start frame + Channel Side identification
+  FS Polarity: FS active Low
+  FS Offset: FS asserted one bit before the first bit of slot 0 */
+  haudio_out_sai.FrameInit.FrameLength = 64;
+  haudio_out_sai.FrameInit.ActiveFrameLength = 32;
+  haudio_out_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
+  haudio_out_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
+  haudio_out_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
+
+  /* Configure SAI Block_x Slot
+  Slot First Bit Offset: 0
+  Slot Size  : 16
+  Slot Number: 4
+  Slot Active: All slot actives */
+  haudio_out_sai.SlotInit.FirstBitOffset = 0;
+  haudio_out_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
+  haudio_out_sai.SlotInit.SlotNumber = 4;
+  haudio_out_sai.SlotInit.SlotActive = SlotActive;
+
+  HAL_SAI_Init(&haudio_out_sai);
+
+  /* Initialize SAI2 block B in SLAVE RX synchronous from SAI2 block A */
+  /* Initialize the haudio_in_sai Instance parameter */
+  haudio_in_sai.Instance = AUDIO_IN_SAIx;
+  
+  /* Disable SAI peripheral to allow access to SAI internal registers */
+  __HAL_SAI_DISABLE(&haudio_in_sai);
+  
+  /* Configure SAI_Block_x
+  LSBFirst: Disabled
+  DataSize: 16 */
+  haudio_in_sai.Init.AudioFrequency = AudioFreq;
+  haudio_in_sai.Init.AudioMode = SAI_MODESLAVE_RX;
+  haudio_in_sai.Init.NoDivider = SAI_MASTERDIVIDER_ENABLED;
+  haudio_in_sai.Init.Protocol = SAI_FREE_PROTOCOL;
+  haudio_in_sai.Init.DataSize = SAI_DATASIZE_16;
+  haudio_in_sai.Init.FirstBit = SAI_FIRSTBIT_MSB;
+  haudio_in_sai.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE;
+  haudio_in_sai.Init.Synchro = SAI_SYNCHRONOUS;
+  haudio_in_sai.Init.OutputDrive = SAI_OUTPUTDRIVE_DISABLED;
+  haudio_in_sai.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF;
+  
+  /* Configure SAI_Block_x Frame
+  Frame Length: 64
+  Frame active Length: 32
+  FS Definition: Start frame + Channel Side identification
+  FS Polarity: FS active Low
+  FS Offset: FS asserted one bit before the first bit of slot 0 */
+  haudio_in_sai.FrameInit.FrameLength = 64;
+  haudio_in_sai.FrameInit.ActiveFrameLength = 32;
+  haudio_in_sai.FrameInit.FSDefinition = SAI_FS_CHANNEL_IDENTIFICATION;
+  haudio_in_sai.FrameInit.FSPolarity = SAI_FS_ACTIVE_LOW;
+  haudio_in_sai.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT;
+  
+  /* Configure SAI Block_x Slot
+  Slot First Bit Offset: 0
+  Slot Size  : 16
+  Slot Number: 4
+  Slot Active: All slot active */
+  haudio_in_sai.SlotInit.FirstBitOffset = 0;
+  haudio_in_sai.SlotInit.SlotSize = SAI_SLOTSIZE_DATASIZE;
+  haudio_in_sai.SlotInit.SlotNumber = 4;
+  haudio_in_sai.SlotInit.SlotActive = SlotActive;
+
+  HAL_SAI_Init(&haudio_in_sai);
+
+  /* Enable SAI peripheral to generate MCLK */
+  __HAL_SAI_ENABLE(&haudio_out_sai);
+
+  /* Enable SAI peripheral */
+  __HAL_SAI_ENABLE(&haudio_in_sai);
+}
+
+
+
+/**
+  * @brief  Deinitializes the output Audio Codec audio interface (SAI).
+  * @retval None
+  */
+static void SAIx_In_DeInit(void)
+{
+  /* Initialize the haudio_in_sai Instance parameter */
+  haudio_in_sai.Instance = AUDIO_IN_SAIx;
+
+  /* Disable SAI peripheral */
+  __HAL_SAI_DISABLE(&haudio_in_sai);
+
+  HAL_SAI_DeInit(&haudio_in_sai);
+}
+
+
+/**
+  * @}
+  */ 
+  
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_audio.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,295 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_audio.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file contains the common defines and functions prototypes for
+  *          the stm32746g_discovery_audio.c driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32746G_DISCOVERY_AUDIO_H
+#define __STM32746G_DISCOVERY_AUDIO_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+/* Include audio component Driver */
+#include "wm8994.h"
+#include "stm32746g_discovery.h"
+
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */
+    
+/** @defgroup STM32746G_DISCOVERY_AUDIO STM32746G_DISCOVERY_AUDIO
+  * @{
+  */
+
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Exported_Types STM32746G_DISCOVERY_AUDIO Exported Types
+  * @{
+  */
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Exported_Constants STM32746G_DISCOVERY_AUDIO Exported Constants
+  * @{
+  */
+ 
+/*------------------------------------------------------------------------------
+                          USER SAI defines parameters
+ -----------------------------------------------------------------------------*/
+/*  CODEC_AudioFrame_SLOT_TDMMode 
+   In W8994 codec the Audio frame contains 4 slots : TDM Mode
+   TDM format :
+   +------------------|------------------|--------------------|-------------------+ 
+   | CODEC_SLOT0 Left | CODEC_SLOT1 Left | CODEC_SLOT0 Right  | CODEC_SLOT1 Right |
+   +------------------------------------------------------------------------------+
+  */
+/* To have 2 separate audio stream in Both headphone and speaker the 4 slot must be activated */
+#define CODEC_AUDIOFRAME_SLOT_0123           SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1 | SAI_SLOTACTIVE_2 | SAI_SLOTACTIVE_3
+/* To have an audio stream in headphone only SAI Slot 0 and Slot 2 must be activated */ 
+#define CODEC_AUDIOFRAME_SLOT_02             SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_2
+/* To have an audio stream in speaker only SAI Slot 1 and Slot 3 must be activated */ 
+#define CODEC_AUDIOFRAME_SLOT_13             SAI_SLOTACTIVE_1 | SAI_SLOTACTIVE_3
+
+/* SAI OUT peripheral configuration defines */
+#define AUDIO_OUT_SAIx                           SAI2_Block_A
+#define AUDIO_OUT_SAIx_CLK_ENABLE()              __HAL_RCC_SAI2_CLK_ENABLE()
+#define AUDIO_OUT_SAIx_CLK_DISABLE()             __HAL_RCC_SAI2_CLK_DISABLE()
+#define AUDIO_OUT_SAIx_SCK_AF                    GPIO_AF10_SAI2
+#define AUDIO_OUT_SAIx_FS_SD_MCLK_AF             GPIO_AF10_SAI2
+
+#define AUDIO_OUT_SAIx_MCLK_ENABLE()             __HAL_RCC_GPIOI_CLK_ENABLE()
+#define AUDIO_OUT_SAIx_MCLK_GPIO_PORT            GPIOI
+#define AUDIO_OUT_SAIx_MCLK_PIN                  GPIO_PIN_4
+#define AUDIO_OUT_SAIx_SCK_SD_ENABLE()           __HAL_RCC_GPIOI_CLK_ENABLE()
+#define AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT          GPIOI
+#define AUDIO_OUT_SAIx_SCK_PIN                   GPIO_PIN_5
+#define AUDIO_OUT_SAIx_SD_PIN                    GPIO_PIN_6
+#define AUDIO_OUT_SAIx_FS_ENABLE()               __HAL_RCC_GPIOI_CLK_ENABLE()
+#define AUDIO_OUT_SAIx_FS_GPIO_PORT              GPIOI
+#define AUDIO_OUT_SAIx_FS_PIN                    GPIO_PIN_7
+
+/* SAI DMA Stream definitions */
+#define AUDIO_OUT_SAIx_DMAx_CLK_ENABLE()         __HAL_RCC_DMA2_CLK_ENABLE()
+#define AUDIO_OUT_SAIx_DMAx_STREAM               DMA2_Stream4
+#define AUDIO_OUT_SAIx_DMAx_CHANNEL              DMA_CHANNEL_3
+#define AUDIO_OUT_SAIx_DMAx_IRQ                  DMA2_Stream4_IRQn
+#define AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE     DMA_PDATAALIGN_HALFWORD
+#define AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE        DMA_MDATAALIGN_HALFWORD
+#define DMA_MAX_SZE                              ((uint16_t)0xFFFF)
+   
+#define AUDIO_OUT_SAIx_DMAx_IRQHandler           DMA2_Stream4_IRQHandler
+
+/* Select the interrupt preemption priority for the DMA interrupt */
+#define AUDIO_OUT_IRQ_PREPRIO                    ((uint32_t)5)   /* Select the preemption priority level(0 is the highest) */
+
+/*------------------------------------------------------------------------------
+                        AUDIO IN CONFIGURATION
+------------------------------------------------------------------------------*/
+/* SAI IN peripheral configuration defines */
+#define AUDIO_IN_SAIx                            SAI2_Block_B
+#define AUDIO_IN_SAIx_CLK_ENABLE()               __HAL_RCC_SAI2_CLK_ENABLE()
+#define AUDIO_IN_SAIx_CLK_DISABLE()              __HAL_RCC_SAI2_CLK_DISABLE()
+#define AUDIO_IN_SAIx_SD_AF                      GPIO_AF10_SAI2
+
+#define AUDIO_IN_SAIx_SD_ENABLE()                __HAL_RCC_GPIOG_CLK_ENABLE()
+#define AUDIO_IN_SAIx_SD_GPIO_PORT               GPIOG
+#define AUDIO_IN_SAIx_SD_PIN                     GPIO_PIN_10
+
+#define AUDIO_IN_INT_GPIO_ENABLE()               __HAL_RCC_GPIOH_CLK_ENABLE()
+#define AUDIO_IN_INT_GPIO_PORT                   GPIOH
+#define AUDIO_IN_INT_GPIO_PIN                    GPIO_PIN_15
+#define AUDIO_IN_INT_IRQ                         EXTI15_10_IRQn
+
+/* SAI DMA Stream definitions */
+#define AUDIO_IN_SAIx_DMAx_CLK_ENABLE()          __HAL_RCC_DMA2_CLK_ENABLE()
+#define AUDIO_IN_SAIx_DMAx_STREAM                DMA2_Stream7
+#define AUDIO_IN_SAIx_DMAx_CHANNEL               DMA_CHANNEL_0
+#define AUDIO_IN_SAIx_DMAx_IRQ                   DMA2_Stream7_IRQn
+#define AUDIO_IN_SAIx_DMAx_PERIPH_DATA_SIZE      DMA_PDATAALIGN_HALFWORD
+#define AUDIO_IN_SAIx_DMAx_MEM_DATA_SIZE         DMA_MDATAALIGN_HALFWORD
+
+#define AUDIO_IN_SAIx_DMAx_IRQHandler            DMA2_Stream7_IRQHandler
+#define AUDIO_IN_INT_IRQHandler                  EXTI15_10_IRQHandler
+
+/* Select the interrupt preemption priority and subpriority for the IT/DMA interrupt */
+#define AUDIO_IN_IRQ_PREPRIO                     ((uint32_t)6)   /* Select the preemption priority level(0 is the highest) */
+
+/*------------------------------------------------------------------------------
+             CONFIGURATION: Audio Driver Configuration parameters
+------------------------------------------------------------------------------*/
+
+#define AUDIODATA_SIZE                      ((uint16_t)2)   /* 16-bits audio data size */
+
+/* Audio status definition */     
+#define AUDIO_OK                            ((uint8_t)0)
+#define AUDIO_ERROR                         ((uint8_t)1)
+#define AUDIO_TIMEOUT                       ((uint8_t)2)
+
+/* AudioFreq * DataSize (2 bytes) * NumChannels (Stereo: 2) */
+#define DEFAULT_AUDIO_IN_FREQ               I2S_AUDIOFREQ_16K
+#define DEFAULT_AUDIO_IN_BIT_RESOLUTION     ((uint8_t)16)
+#define DEFAULT_AUDIO_IN_CHANNEL_NBR        ((uint8_t)2) /* Mono = 1, Stereo = 2 */
+#define DEFAULT_AUDIO_IN_VOLUME             ((uint16_t)64)
+
+/*------------------------------------------------------------------------------
+                    OPTIONAL Configuration defines parameters
+------------------------------------------------------------------------------*/
+
+/* Delay for the Codec to be correctly reset */
+#define CODEC_RESET_DELAY                   ((uint8_t)5)
+   
+
+/*------------------------------------------------------------------------------
+                            OUTPUT DEVICES definition
+------------------------------------------------------------------------------*/
+
+/* Alias on existing output devices to adapt to Birdie discovery board 2 headphones output */
+#define OUTPUT_DEVICE_HEADPHONE1 OUTPUT_DEVICE_HEADPHONE
+#define OUTPUT_DEVICE_HEADPHONE2 OUTPUT_DEVICE_SPEAKER /* Headphone2 is connected to Speaker output of the wm8994 */
+   
+/**
+  * @}
+  */
+ 
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Exported_Variables STM32746G_DISCOVERY_AUDIO Exported Variables
+  * @{
+  */
+extern __IO uint16_t AudioInVolume;
+ /**
+  * @}
+  */
+   
+/** @defgroup STM32746G_DISCOVERY_AUDIO_Exported_Macros STM32746G_DISCOVERY_AUDIO Exported Macros
+  * @{
+  */
+#define DMA_MAX(x)           (((x) <= DMA_MAX_SZE)? (x):DMA_MAX_SZE)
+/**
+  * @}
+  */ 
+
+/** @addtogroup STM32746G_DISCOVERY_AUDIO_OUT_Exported_Functions
+  * @{
+  */
+uint8_t BSP_AUDIO_OUT_Init(uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq);
+uint8_t BSP_AUDIO_OUT_Play(uint16_t* pBuffer, uint32_t Size);
+void    BSP_AUDIO_OUT_ChangeBuffer(uint16_t *pData, uint16_t Size);
+uint8_t BSP_AUDIO_OUT_Pause(void);
+uint8_t BSP_AUDIO_OUT_Resume(void);
+uint8_t BSP_AUDIO_OUT_Stop(uint32_t Option);
+uint8_t BSP_AUDIO_OUT_SetVolume(uint8_t Volume);
+void    BSP_AUDIO_OUT_SetFrequency(uint32_t AudioFreq);
+void    BSP_AUDIO_OUT_SetAudioFrameSlot(uint32_t AudioFrameSlot);
+uint8_t BSP_AUDIO_OUT_SetMute(uint32_t Cmd);
+uint8_t BSP_AUDIO_OUT_SetOutputMode(uint8_t Output);
+void    BSP_AUDIO_OUT_DeInit(void);
+
+/* User Callbacks: user has to implement these functions in his code if they are needed. */
+/* This function is called when the requested data has been completely transferred.*/
+void    BSP_AUDIO_OUT_TransferComplete_CallBack(void);
+
+/* This function is called when half of the requested buffer has been transferred. */
+void    BSP_AUDIO_OUT_HalfTransfer_CallBack(void);
+
+/* This function is called when an Interrupt due to transfer error on or peripheral
+   error occurs. */
+void    BSP_AUDIO_OUT_Error_CallBack(void);
+
+/* These function can be modified in case the current settings (e.g. DMA stream)
+   need to be changed for specific application needs */
+void  BSP_AUDIO_OUT_ClockConfig(SAI_HandleTypeDef *hsai, uint32_t AudioFreq, void *Params);
+void  BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params);
+void  BSP_AUDIO_OUT_MspDeInit(SAI_HandleTypeDef *hsai, void *Params);
+
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_AUDIO_IN_Exported_Functions STM32746G_DISCOVERY_AUDIO_IN Exported Functions
+  * @{
+  */
+uint8_t BSP_AUDIO_IN_Init(uint16_t InputDevice, uint8_t Volume, uint32_t AudioFreq);
+uint8_t BSP_AUDIO_IN_OUT_Init(uint16_t InputDevice, uint16_t OutputDevice, uint8_t Volume, uint32_t AudioFreq);
+uint8_t BSP_AUDIO_IN_Record(uint16_t *pData, uint32_t Size);
+uint8_t BSP_AUDIO_IN_Stop(uint32_t Option);
+uint8_t BSP_AUDIO_IN_Pause(void);
+uint8_t BSP_AUDIO_IN_Resume(void);
+uint8_t BSP_AUDIO_IN_SetVolume(uint8_t Volume);
+void    BSP_AUDIO_IN_DeInit(void);
+/* User Callbacks: user has to implement these functions in his code if they are needed. */
+/* This function should be implemented by the user application.
+   It is called into this driver when the current buffer is filled to prepare the next
+   buffer pointer and its size. */
+void    BSP_AUDIO_IN_TransferComplete_CallBack(void);
+void    BSP_AUDIO_IN_HalfTransfer_CallBack(void);
+
+/* This function is called when an Interrupt due to transfer error on or peripheral
+   error occurs. */
+void    BSP_AUDIO_IN_Error_CallBack(void);
+
+/* These function can be modified in case the current settings (e.g. DMA stream)
+   need to be changed for specific application needs */
+void  BSP_AUDIO_IN_MspInit(SAI_HandleTypeDef *hsai, void *Params);
+void  BSP_AUDIO_IN_MspDeInit(SAI_HandleTypeDef *hsai, void *Params);
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32746G_DISCOVERY_AUDIO_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_camera.c	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,674 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_camera.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file includes the driver for Camera modules mounted on
+  *          STM32746G-Discovery board.
+  @verbatim
+    How to use this driver:
+    ------------------------
+     - This driver is used to drive the camera.
+     - The OV9655 component driver MUST be included with this driver.
+    
+    Driver description:
+    -------------------
+    + Initialization steps:
+       o Initialize the camera using the BSP_CAMERA_Init() function.
+       o Start the camera capture/snapshot using the CAMERA_Start() function.
+       o Suspend, resume or stop the camera capture using the following functions:
+        - BSP_CAMERA_Suspend()
+        - BSP_CAMERA_Resume()
+        - BSP_CAMERA_Stop()
+        
+    + Options
+       o Increase or decrease on the fly the brightness and/or contrast
+         using the following function:
+         - BSP_CAMERA_ContrastBrightnessConfig 
+       o Add a special effect on the fly using the following functions:
+         - BSP_CAMERA_BlackWhiteConfig()
+         - BSP_CAMERA_ColorEffectConfig()
+  @endverbatim
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32746g_discovery_camera.h"
+#include "stm32746g_discovery.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */
+    
+/** @addtogroup STM32746G_DISCOVERY_CAMERA
+  * @{
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_CAMERA_Private_TypesDefinitions STM32746G_DISCOVERY_CAMERA Private Types Definitions
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_CAMERA_Private_Defines STM32746G_DISCOVERY_CAMERA Private Defines
+  * @{
+  */
+#define CAMERA_VGA_RES_X          640
+#define CAMERA_VGA_RES_Y          480
+#define CAMERA_480x272_RES_X      480
+#define CAMERA_480x272_RES_Y      272
+#define CAMERA_QVGA_RES_X         320
+#define CAMERA_QVGA_RES_Y         240
+#define CAMERA_QQVGA_RES_X        160
+#define CAMERA_QQVGA_RES_Y        120
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_CAMERA_Private_Macros STM32746G_DISCOVERY_CAMERA Private Macros
+  * @{
+  */
+/**
+  * @}
+  */  
+
+/** @defgroup STM32746G_DISCOVERY_CAMERA_Private_Variables STM32746G_DISCOVERY_CAMERA Private Variables
+  * @{
+  */ 
+static DCMI_HandleTypeDef  hDcmiHandler;
+       CAMERA_DrvTypeDef   *camera_drv;
+/* Camera current resolution naming (QQVGA, VGA, ...) */
+static uint32_t CameraCurrentResolution;
+
+/* Camera module I2C HW address */
+static uint32_t CameraHwAddress;
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_CAMERA_Private_FunctionPrototypes STM32746G_DISCOVERY_CAMERA Private Function Prototypes
+  * @{
+  */
+static uint32_t GetSize(uint32_t resolution);
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_CAMERA_Exported_Functions STM32746G_DISCOVERY_CAMERA Exported Functions
+  * @{
+  */
+
+/**
+  * @brief  Initializes the camera.
+  * @param  Resolution : camera sensor requested resolution (x, y) : standard resolution
+  *         naming QQVGA, QVGA, VGA ...
+  * @retval Camera status
+  */
+uint8_t BSP_CAMERA_Init(uint32_t Resolution)
+{ 
+  DCMI_HandleTypeDef *phdcmi;
+  uint8_t status = CAMERA_ERROR;
+
+  /* Get the DCMI handle structure */
+  phdcmi = &hDcmiHandler;
+
+  /*** Configures the DCMI to interface with the camera module ***/
+  /* DCMI configuration */
+  phdcmi->Init.CaptureRate      = DCMI_CR_ALL_FRAME;
+  phdcmi->Init.HSPolarity       = DCMI_HSPOLARITY_LOW;
+  phdcmi->Init.SynchroMode      = DCMI_SYNCHRO_HARDWARE;
+  phdcmi->Init.VSPolarity       = DCMI_VSPOLARITY_HIGH;
+  phdcmi->Init.ExtendedDataMode = DCMI_EXTEND_DATA_8B;
+  phdcmi->Init.PCKPolarity      = DCMI_PCKPOLARITY_RISING;
+  phdcmi->Instance              = DCMI;
+
+  /* Power up camera */
+  BSP_CAMERA_PwrUp();
+
+  /* Read ID of Camera module via I2C */
+  if(ov9655_ReadID(CAMERA_I2C_ADDRESS) == OV9655_ID)
+  {
+    /* Initialize the camera driver structure */
+    camera_drv = &ov9655_drv;
+    CameraHwAddress = CAMERA_I2C_ADDRESS;
+
+    /* DCMI Initialization */
+    BSP_CAMERA_MspInit(&hDcmiHandler, NULL);
+    HAL_DCMI_Init(phdcmi);
+
+    /* Camera Module Initialization via I2C to the wanted 'Resolution' */
+    if (Resolution == CAMERA_R480x272)
+    {     /* For 480x272 resolution, the OV9655 sensor is set to VGA resolution
+           * as OV9655 doesn't supports 480x272 resolution,
+           * then DCMI is configured to output a 480x272 cropped window */
+      camera_drv->Init(CameraHwAddress, CAMERA_R640x480);
+      HAL_DCMI_ConfigCROP(phdcmi,           /* Crop in the middle of the VGA picture */
+                         (CAMERA_VGA_RES_X - CAMERA_480x272_RES_X)/2,
+                         (CAMERA_VGA_RES_Y - CAMERA_480x272_RES_Y)/2,
+                         (CAMERA_480x272_RES_X * 2) - 1,
+                          CAMERA_480x272_RES_Y - 1);
+      HAL_DCMI_EnableCROP(phdcmi);
+    }
+    else
+    {
+      camera_drv->Init(CameraHwAddress, Resolution);
+      HAL_DCMI_DisableCROP(phdcmi);
+    }
+
+    CameraCurrentResolution = Resolution;
+
+    /* Return CAMERA_OK status */
+    status = CAMERA_OK;
+  }
+  else
+  {
+    /* Return CAMERA_NOT_SUPPORTED status */
+    status = CAMERA_NOT_SUPPORTED;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  DeInitializes the camera.
+  * @retval Camera status
+  */
+uint8_t BSP_CAMERA_DeInit(void)
+{ 
+  hDcmiHandler.Instance              = DCMI;
+
+  HAL_DCMI_DeInit(&hDcmiHandler);
+  BSP_CAMERA_MspDeInit(&hDcmiHandler, NULL);
+  return CAMERA_OK;
+}
+
+/**
+  * @brief  Starts the camera capture in continuous mode.
+  * @param  buff: pointer to the camera output buffer
+  * @retval None
+  */
+void BSP_CAMERA_ContinuousStart(uint8_t *buff)
+{ 
+  /* Start the camera capture */
+  HAL_DCMI_Start_DMA(&hDcmiHandler, DCMI_MODE_CONTINUOUS, (uint32_t)buff, GetSize(CameraCurrentResolution));
+}
+
+/**
+  * @brief  Starts the camera capture in snapshot mode.
+  * @param  buff: pointer to the camera output buffer
+  * @retval None
+  */
+void BSP_CAMERA_SnapshotStart(uint8_t *buff)
+{ 
+  /* Start the camera capture */
+  HAL_DCMI_Start_DMA(&hDcmiHandler, DCMI_MODE_SNAPSHOT, (uint32_t)buff, GetSize(CameraCurrentResolution));
+}
+
+/**
+  * @brief Suspend the CAMERA capture 
+  * @retval None
+  */
+void BSP_CAMERA_Suspend(void) 
+{
+  /* Disable the DMA */
+  __HAL_DMA_DISABLE(hDcmiHandler.DMA_Handle);
+  /* Disable the DCMI */
+  __HAL_DCMI_DISABLE(&hDcmiHandler);
+  
+}
+
+/**
+  * @brief Resume the CAMERA capture 
+  * @retval None
+  */
+void BSP_CAMERA_Resume(void) 
+{
+  /* Enable the DCMI */
+  __HAL_DCMI_ENABLE(&hDcmiHandler);
+  /* Enable the DMA */
+  __HAL_DMA_ENABLE(hDcmiHandler.DMA_Handle);
+}
+
+/**
+  * @brief  Stop the CAMERA capture 
+  * @retval Camera status
+  */
+uint8_t BSP_CAMERA_Stop(void) 
+{
+  uint8_t status = CAMERA_ERROR;
+
+  if(HAL_DCMI_Stop(&hDcmiHandler) == HAL_OK)
+  {
+     status = CAMERA_OK;
+  }
+  
+  /* Set Camera in Power Down */
+  BSP_CAMERA_PwrDown();
+
+  return status;
+}
+
+/**
+  * @brief  CANERA power up
+  * @retval None
+  */
+void BSP_CAMERA_PwrUp(void)
+{
+  GPIO_InitTypeDef gpio_init_structure;
+
+  /* Enable GPIO clock */
+  __HAL_RCC_GPIOH_CLK_ENABLE();
+
+  /*** Configure the GPIO ***/
+  /* Configure DCMI GPIO as alternate function */
+  gpio_init_structure.Pin       = GPIO_PIN_13;
+  gpio_init_structure.Mode      = GPIO_MODE_OUTPUT_PP;
+  gpio_init_structure.Pull      = GPIO_NOPULL;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  HAL_GPIO_Init(GPIOH, &gpio_init_structure);
+
+  /* De-assert the camera POWER_DOWN pin (active high) */
+  HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_RESET);
+
+  HAL_Delay(3);     /* POWER_DOWN de-asserted during 3ms */
+}
+
+/**
+  * @brief  CAMERA power down
+  * @retval None
+  */
+void BSP_CAMERA_PwrDown(void)
+{
+  GPIO_InitTypeDef gpio_init_structure;
+
+  /* Enable GPIO clock */
+  __HAL_RCC_GPIOH_CLK_ENABLE();
+
+  /*** Configure the GPIO ***/
+  /* Configure DCMI GPIO as alternate function */
+  gpio_init_structure.Pin       = GPIO_PIN_13;
+  gpio_init_structure.Mode      = GPIO_MODE_OUTPUT_PP;
+  gpio_init_structure.Pull      = GPIO_NOPULL;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  HAL_GPIO_Init(GPIOH, &gpio_init_structure);
+
+  /* Assert the camera POWER_DOWN pin (active high) */
+  HAL_GPIO_WritePin(GPIOH, GPIO_PIN_13, GPIO_PIN_SET);
+}
+
+/**
+  * @brief  Configures the camera contrast and brightness.
+  * @param  contrast_level: Contrast level
+  *          This parameter can be one of the following values:
+  *            @arg  CAMERA_CONTRAST_LEVEL4: for contrast +2
+  *            @arg  CAMERA_CONTRAST_LEVEL3: for contrast +1
+  *            @arg  CAMERA_CONTRAST_LEVEL2: for contrast  0
+  *            @arg  CAMERA_CONTRAST_LEVEL1: for contrast -1
+  *            @arg  CAMERA_CONTRAST_LEVEL0: for contrast -2
+  * @param  brightness_level: Contrast level
+  *          This parameter can be one of the following values:
+  *            @arg  CAMERA_BRIGHTNESS_LEVEL4: for brightness +2
+  *            @arg  CAMERA_BRIGHTNESS_LEVEL3: for brightness +1
+  *            @arg  CAMERA_BRIGHTNESS_LEVEL2: for brightness  0
+  *            @arg  CAMERA_BRIGHTNESS_LEVEL1: for brightness -1
+  *            @arg  CAMERA_BRIGHTNESS_LEVEL0: for brightness -2    
+  * @retval None
+  */
+void BSP_CAMERA_ContrastBrightnessConfig(uint32_t contrast_level, uint32_t brightness_level)
+{
+  if(camera_drv->Config != NULL)
+  {
+    camera_drv->Config(CameraHwAddress, CAMERA_CONTRAST_BRIGHTNESS, contrast_level, brightness_level);
+  }  
+}
+
+/**
+  * @brief  Configures the camera white balance.
+  * @param  Mode: black_white mode
+  *          This parameter can be one of the following values:
+  *            @arg  CAMERA_BLACK_WHITE_BW
+  *            @arg  CAMERA_BLACK_WHITE_NEGATIVE
+  *            @arg  CAMERA_BLACK_WHITE_BW_NEGATIVE
+  *            @arg  CAMERA_BLACK_WHITE_NORMAL       
+  * @retval None
+  */
+void BSP_CAMERA_BlackWhiteConfig(uint32_t Mode)
+{
+  if(camera_drv->Config != NULL)
+  {
+    camera_drv->Config(CameraHwAddress, CAMERA_BLACK_WHITE, Mode, 0);
+  }  
+}
+
+/**
+  * @brief  Configures the camera color effect.
+  * @param  Effect: Color effect
+  *          This parameter can be one of the following values:
+  *            @arg  CAMERA_COLOR_EFFECT_ANTIQUE               
+  *            @arg  CAMERA_COLOR_EFFECT_BLUE        
+  *            @arg  CAMERA_COLOR_EFFECT_GREEN    
+  *            @arg  CAMERA_COLOR_EFFECT_RED        
+  * @retval None
+  */
+void BSP_CAMERA_ColorEffectConfig(uint32_t Effect)
+{
+  if(camera_drv->Config != NULL)
+  {
+    camera_drv->Config(CameraHwAddress, CAMERA_COLOR_EFFECT, Effect, 0);
+  }  
+}
+
+/**
+  * @brief  Handles DCMI interrupt request.
+  * @retval None
+  */
+void BSP_CAMERA_IRQHandler(void) 
+{
+  HAL_DCMI_IRQHandler(&hDcmiHandler);
+}
+
+/**
+  * @brief  Handles DMA interrupt request.
+  * @retval None
+  */
+void BSP_CAMERA_DMA_IRQHandler(void) 
+{
+  HAL_DMA_IRQHandler(hDcmiHandler.DMA_Handle);
+}
+
+/**
+  * @brief  Get the capture size in pixels unit.
+  * @param  resolution: the current resolution.
+  * @retval capture size in pixels unit.
+  */
+static uint32_t GetSize(uint32_t resolution)
+{ 
+  uint32_t size = 0;
+  
+  /* Get capture size */
+  switch (resolution)
+  {
+  case CAMERA_R160x120:
+    {
+      size =  0x2580;
+    }
+    break;    
+  case CAMERA_R320x240:
+    {
+      size =  0x9600;
+    }
+    break;
+  case CAMERA_R480x272:
+    {
+      size =  0xFF00;
+    }
+    break;
+  case CAMERA_R640x480:
+    {
+      size =  0x25800;
+    }    
+    break;
+  default:
+    {
+      break;
+    }
+  }
+  
+  return size;
+}
+
+/**
+  * @brief  Initializes the DCMI MSP.
+  * @param  hdcmi: HDMI handle 
+  * @param  Params
+  * @retval None
+  */
+__weak void BSP_CAMERA_MspInit(DCMI_HandleTypeDef *hdcmi, void *Params)
+{
+  static DMA_HandleTypeDef hdma_handler;
+  GPIO_InitTypeDef gpio_init_structure;
+  
+  /*** Enable peripherals and GPIO clocks ***/
+  /* Enable DCMI clock */
+  __HAL_RCC_DCMI_CLK_ENABLE();
+
+  /* Enable DMA2 clock */
+  __HAL_RCC_DMA2_CLK_ENABLE();
+  
+  /* Enable GPIO clocks */
+  __HAL_RCC_GPIOA_CLK_ENABLE();
+  __HAL_RCC_GPIOD_CLK_ENABLE();
+  __HAL_RCC_GPIOE_CLK_ENABLE();
+  __HAL_RCC_GPIOG_CLK_ENABLE();
+  __HAL_RCC_GPIOH_CLK_ENABLE();
+
+  /*** Configure the GPIO ***/
+  /* Configure DCMI GPIO as alternate function */
+  gpio_init_structure.Pin       = GPIO_PIN_4 | GPIO_PIN_6;
+  gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull      = GPIO_PULLUP;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = GPIO_AF13_DCMI;
+  HAL_GPIO_Init(GPIOA, &gpio_init_structure);
+
+  gpio_init_structure.Pin       = GPIO_PIN_3;
+  gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull      = GPIO_PULLUP;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = GPIO_AF13_DCMI;
+  HAL_GPIO_Init(GPIOD, &gpio_init_structure);
+
+  gpio_init_structure.Pin       = GPIO_PIN_5 | GPIO_PIN_6;
+  gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull      = GPIO_PULLUP;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = GPIO_AF13_DCMI;
+  HAL_GPIO_Init(GPIOE, &gpio_init_structure);
+
+  gpio_init_structure.Pin       = GPIO_PIN_9;
+  gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull      = GPIO_PULLUP;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = GPIO_AF13_DCMI;
+  HAL_GPIO_Init(GPIOG, &gpio_init_structure);
+
+  gpio_init_structure.Pin       = GPIO_PIN_9 | GPIO_PIN_10  | GPIO_PIN_11  |\
+                                  GPIO_PIN_12 | GPIO_PIN_14;
+  gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull      = GPIO_PULLUP;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = GPIO_AF13_DCMI;
+  HAL_GPIO_Init(GPIOH, &gpio_init_structure);
+
+  /*** Configure the DMA ***/
+  /* Set the parameters to be configured */
+  hdma_handler.Init.Channel             = DMA_CHANNEL_1;
+  hdma_handler.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+  hdma_handler.Init.PeriphInc           = DMA_PINC_DISABLE;
+  hdma_handler.Init.MemInc              = DMA_MINC_ENABLE;
+  hdma_handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+  hdma_handler.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
+  hdma_handler.Init.Mode                = DMA_CIRCULAR;
+  hdma_handler.Init.Priority            = DMA_PRIORITY_HIGH;
+  hdma_handler.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;
+  hdma_handler.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+  hdma_handler.Init.MemBurst            = DMA_MBURST_SINGLE;
+  hdma_handler.Init.PeriphBurst         = DMA_PBURST_SINGLE; 
+
+  hdma_handler.Instance = DMA2_Stream1;
+
+  /* Associate the initialized DMA handle to the DCMI handle */
+  __HAL_LINKDMA(hdcmi, DMA_Handle, hdma_handler);
+  
+  /*** Configure the NVIC for DCMI and DMA ***/
+  /* NVIC configuration for DCMI transfer complete interrupt */
+  HAL_NVIC_SetPriority(DCMI_IRQn, 5, 0);
+  HAL_NVIC_EnableIRQ(DCMI_IRQn);  
+  
+  /* NVIC configuration for DMA2D transfer complete interrupt */
+  HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 5, 0);
+  HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
+  
+  /* Configure the DMA stream */
+  HAL_DMA_Init(hdcmi->DMA_Handle);  
+}
+
+
+/**
+  * @brief  DeInitializes the DCMI MSP.
+  * @param  hdcmi: HDMI handle 
+  * @param  Params
+  * @retval None
+  */
+__weak void BSP_CAMERA_MspDeInit(DCMI_HandleTypeDef *hdcmi, void *Params)
+{
+  /* Disable NVIC  for DCMI transfer complete interrupt */
+  HAL_NVIC_DisableIRQ(DCMI_IRQn);  
+  
+  /* Disable NVIC for DMA2 transfer complete interrupt */
+  HAL_NVIC_DisableIRQ(DMA2_Stream1_IRQn);
+  
+  /* Configure the DMA stream */
+  HAL_DMA_DeInit(hdcmi->DMA_Handle);  
+
+  /* Disable DCMI clock */
+  __HAL_RCC_DCMI_CLK_DISABLE();
+
+  /* GPIO pins clock and DMA clock can be shut down in the application 
+     by surcharging this __weak function */ 
+}
+
+/**
+  * @brief  Line event callback
+  * @param  hdcmi: pointer to the DCMI handle  
+  * @retval None
+  */
+void HAL_DCMI_LineEventCallback(DCMI_HandleTypeDef *hdcmi)
+{        
+  BSP_CAMERA_LineEventCallback();
+}
+
+/**
+  * @brief  Line Event callback.
+  * @retval None
+  */
+__weak void BSP_CAMERA_LineEventCallback(void)
+{
+  /* NOTE : This function Should not be modified, when the callback is needed,
+            the HAL_DCMI_LineEventCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  VSYNC event callback
+  * @param  hdcmi: pointer to the DCMI handle  
+  * @retval None
+  */
+void HAL_DCMI_VsyncEventCallback(DCMI_HandleTypeDef *hdcmi)
+{        
+  BSP_CAMERA_VsyncEventCallback();
+}
+
+/**
+  * @brief  VSYNC Event callback.
+  * @retval None
+  */
+__weak void BSP_CAMERA_VsyncEventCallback(void)
+{
+  /* NOTE : This function Should not be modified, when the callback is needed,
+            the HAL_DCMI_VsyncEventCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Frame event callback
+  * @param  hdcmi: pointer to the DCMI handle  
+  * @retval None
+  */
+void HAL_DCMI_FrameEventCallback(DCMI_HandleTypeDef *hdcmi)
+{        
+  BSP_CAMERA_FrameEventCallback();
+}
+
+/**
+  * @brief  Frame Event callback.
+  * @retval None
+  */
+__weak void BSP_CAMERA_FrameEventCallback(void)
+{
+  /* NOTE : This function Should not be modified, when the callback is needed,
+            the HAL_DCMI_FrameEventCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @brief  Error callback
+  * @param  hdcmi: pointer to the DCMI handle  
+  * @retval None
+  */
+void HAL_DCMI_ErrorCallback(DCMI_HandleTypeDef *hdcmi)
+{        
+  BSP_CAMERA_ErrorCallback();
+}
+
+/**
+  * @brief  Error callback.
+  * @retval None
+  */
+__weak void BSP_CAMERA_ErrorCallback(void)
+{
+  /* NOTE : This function Should not be modified, when the callback is needed,
+            the HAL_DCMI_ErrorCallback could be implemented in the user file
+   */
+}
+
+/**
+  * @}
+  */  
+  
+/**
+  * @}
+  */
+  
+/**
+  * @}
+  */
+  
+/**
+  * @}
+  */      
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_camera.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,151 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_camera.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file contains the common defines and functions prototypes for
+  *          the stm32746g_discovery_camera.c driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32746G_DISCOVERY_CAMERA_H
+#define __STM32746G_DISCOVERY_CAMERA_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+/* Include Camera component Driver */
+#include "ov9655.h"
+#include "stm32746g_discovery.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */
+    
+/** @addtogroup STM32746G_DISCOVERY_CAMERA
+  * @{
+  */ 
+   
+/** @defgroup STM32746G_DISCOVERY_CAMERA_Exported_Types STM32746G_DISCOVERY_CAMERA Exported Types
+  * @{
+  */
+  
+/** 
+  * @brief  Camera State structures definition  
+  */  
+typedef enum 
+{
+  CAMERA_OK            = 0x00,
+  CAMERA_ERROR         = 0x01,
+  CAMERA_TIMEOUT       = 0x02,
+  CAMERA_NOT_DETECTED  = 0x03,
+  CAMERA_NOT_SUPPORTED = 0x04
+
+} Camera_StatusTypeDef;
+
+#define RESOLUTION_R160x120      CAMERA_R160x120      /* QQVGA Resolution     */
+#define RESOLUTION_R320x240      CAMERA_R320x240      /* QVGA Resolution      */
+#define RESOLUTION_R480x272      CAMERA_R480x272      /* 480x272 Resolution   */
+#define RESOLUTION_R640x480      CAMERA_R640x480      /* VGA Resolution       */  
+/**
+  * @}
+  */ 
+ 
+/** @defgroup STM32746G_DISCOVERY_CAMERA_Exported_Constants STM32746G_DISCOVERY_CAMERA Exported Constants
+  * @{
+  */
+/**
+  * @}
+  */
+
+/** @addtogroup STM32746G_DISCOVERY_CAMERA_Exported_Functions
+  * @{
+  */    
+uint8_t BSP_CAMERA_Init(uint32_t Resolution);  
+uint8_t BSP_CAMERA_DeInit(void);
+void    BSP_CAMERA_ContinuousStart(uint8_t *buff);
+void    BSP_CAMERA_SnapshotStart(uint8_t *buff);
+void    BSP_CAMERA_Suspend(void);
+void    BSP_CAMERA_Resume(void);
+uint8_t BSP_CAMERA_Stop(void); 
+void    BSP_CAMERA_PwrUp(void);
+void    BSP_CAMERA_PwrDown(void);
+void    BSP_CAMERA_LineEventCallback(void);
+void    BSP_CAMERA_VsyncEventCallback(void);
+void    BSP_CAMERA_FrameEventCallback(void);
+void    BSP_CAMERA_ErrorCallback(void);
+
+/* Camera features functions prototype */
+void    BSP_CAMERA_ContrastBrightnessConfig(uint32_t contrast_level, uint32_t brightness_level);
+void    BSP_CAMERA_BlackWhiteConfig(uint32_t Mode);
+void    BSP_CAMERA_ColorEffectConfig(uint32_t Effect);
+
+/* To be called in DCMI_IRQHandler function */
+void    BSP_CAMERA_IRQHandler(void);
+/* To be called in DMA2_Stream1_IRQHandler function */
+void    BSP_CAMERA_DMA_IRQHandler(void);
+   
+/* These functions can be modified in case the current settings (e.g. DMA stream)
+   need to be changed for specific application needs */
+void BSP_CAMERA_MspInit(DCMI_HandleTypeDef *hdcmi, void *Params);
+void BSP_CAMERA_MspDeInit(DCMI_HandleTypeDef *hdcmi, void *Params);
+
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32746G_DISCOVERY_CAMERA_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_eeprom.c	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,474 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_eeprom.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file provides a set of functions needed to manage an I2C M24LR64 
+  *          EEPROM memory.
+  @verbatim
+             To be able to use this driver, the switch EE_M24LR64 must be defined
+             in your toolchain compiler preprocessor
+             
+             =================================================================== 
+             Notes:
+              - The I2C EEPROM memory (M24LR64) is available on separate daughter 
+                board ANT7-M24LR-A, which is not provided with the STM32746G_DISCOVERY
+                board.
+                To use this driver you have to connect the ANT7-M24LR-A to CN3 
+                connector of STM32746G_DISCOVERY board.
+             ===================================================================
+                 
+             It implements a high level communication layer for read and write 
+             from/to this memory. The needed STM32F7xx hardware resources (I2C and
+             GPIO) are defined in stm32746g_discovery.h file, and the initialization is
+             performed in EEPROM_IO_Init() function declared in stm32746g_discovery.c
+             file.
+             You can easily tailor this driver to any other development board, 
+             by just adapting the defines for hardware resources and 
+             EEPROM_IO_Init() function. 
+           
+             @note In this driver, basic read and write functions (BSP_EEPROM_ReadBuffer() 
+                   and BSP_EEPROM_WritePage()) use DMA mode to perform the data 
+                   transfer to/from EEPROM memory.
+   
+            @note   Regarding BSP_EEPROM_WritePage(), it is an optimized function to perform
+                   small write (less than 1 page) BUT the number of bytes (combined to write start address) must not
+                   cross the EEPROM page boundary. This function can only writes into
+                   the boundaries of an EEPROM page.
+                   This function doesn't check on boundaries condition (in this driver 
+                   the function BSP_EEPROM_WriteBuffer() which calls BSP_EEPROM_WritePage() is 
+                   responsible of checking on Page boundaries).
+    
+                
+        +-----------------------------------------------------------------+
+        |               Pin assignment for M24LR64 EEPROM                 |
+        +---------------------------------------+-----------+-------------+
+        |  STM32F7xx I2C Pins                   |   EEPROM  |   Pin       |
+        +---------------------------------------+-----------+-------------+
+        | .                                     |   E0(GND) |    1  (0V)  |
+        | .                                     |   AC0     |    2        |
+        | .                                     |   AC1     |    3        |
+        | .                                     |   VSS     |    4  (0V)  |
+        | SDA                                   |   SDA     |    5        |
+        | SCL                                   |   SCL     |    6        |
+        | .                                     |   E1(GND) |    7  (0V)  |
+        | .                                     |   VDD     |    8 (3.3V) |
+        +---------------------------------------+-----------+-------------+
+  @endverbatim   
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+/* Includes ------------------------------------------------------------------*/
+#include "stm32746g_discovery_eeprom.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+  
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */ 
+  
+/** @addtogroup STM32746G_DISCOVERY_EEPROM
+  * @brief This file includes the I2C EEPROM driver of STM32746G-Discovery board.
+  * @{
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_EEPROM_Private_Types STM32746G_DISCOVERY_EEPROM Private Types
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_EEPROM_Private_Defines STM32746G_DISCOVERY_EEPROM Private Defines
+  * @{
+  */  
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_EEPROM_Private_Macros STM32746G_DISCOVERY_EEPROM Private Macros
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_EEPROM_Private_Variables STM32746G_DISCOVERY_EEPROM Private Variables
+  * @{
+  */
+__IO uint16_t EEPROMAddress = 0;
+__IO uint16_t EEPROMDataRead;
+__IO uint8_t  EEPROMDataWrite;
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_EEPROM_Private_Function_Prototypes STM32746G_DISCOVERY_EEPROM Private Function Prototypes
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_EEPROM_Exported_Functions STM32746G_DISCOVERY_EEPROM Exported Functions
+  * @{
+  */ 
+
+/**
+  * @brief  Initializes peripherals used by the I2C EEPROM driver.
+  * 
+  * @note   There are 2 different versions of M24LR64 (A01 & A02).
+  *             Then try to connect on 1st one (EEPROM_I2C_ADDRESS_A01) 
+  *             and if problem, check the 2nd one (EEPROM_I2C_ADDRESS_A02)
+  * @retval EEPROM_OK (0) if operation is correctly performed, else return value 
+  *         different from EEPROM_OK (0)
+  */
+uint32_t BSP_EEPROM_Init(void)
+{ 
+  /* I2C Initialization */
+  EEPROM_IO_Init();
+  
+  /* Select the EEPROM address for A01 and check if OK */
+  EEPROMAddress = EEPROM_I2C_ADDRESS_A01;
+  if(EEPROM_IO_IsDeviceReady(EEPROMAddress, EEPROM_MAX_TRIALS) != HAL_OK) 
+  {
+    /* Select the EEPROM address for A02 and check if OK */
+    EEPROMAddress = EEPROM_I2C_ADDRESS_A02;
+    if(EEPROM_IO_IsDeviceReady(EEPROMAddress, EEPROM_MAX_TRIALS) != HAL_OK)
+    {
+      return EEPROM_FAIL;
+    }
+  }
+  return EEPROM_OK;
+}
+
+/**
+  * @brief  DeInitializes the EEPROM.
+  * @retval EEPROM state
+  */
+uint8_t BSP_EEPROM_DeInit(void)
+{ 
+  /* I2C won't be disabled because common to other functionalities */
+  return EEPROM_OK;
+}
+
+/**
+  * @brief  Reads a block of data from the EEPROM.
+  * @param  pBuffer: pointer to the buffer that receives the data read from 
+  *         the EEPROM.
+  * @param  ReadAddr: EEPROM's internal address to start reading from.
+  * @param  NumByteToRead: pointer to the variable holding number of bytes to 
+  *         be read from the EEPROM.
+  * 
+  *        @note The variable pointed by NumByteToRead is reset to 0 when all the 
+  *              data are read from the EEPROM. Application should monitor this 
+  *              variable in order know when the transfer is complete.
+  * 
+  * @retval EEPROM_OK (0) if operation is correctly performed, else return value 
+  *         different from EEPROM_OK (0) or the timeout user callback.
+  */
+uint32_t BSP_EEPROM_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead)
+{  
+  uint32_t buffersize = *NumByteToRead;
+  
+  /* Set the pointer to the Number of data to be read. This pointer will be used 
+     by the DMA Transfer Completer interrupt Handler in order to reset the 
+     variable to 0. User should check on this variable in order to know if the 
+     DMA transfer has been complete or not. */
+  EEPROMDataRead = *NumByteToRead;
+  
+  if(EEPROM_IO_ReadData(EEPROMAddress, ReadAddr, pBuffer, buffersize) != HAL_OK)
+  {
+    BSP_EEPROM_TIMEOUT_UserCallback();
+    return EEPROM_FAIL;
+  }
+
+  /* If all operations OK, return EEPROM_OK (0) */
+  return EEPROM_OK;
+}
+
+/**
+  * @brief  Writes more than one byte to the EEPROM with a single WRITE cycle.
+  *
+  * @note   The number of bytes (combined to write start address) must not 
+  *         cross the EEPROM page boundary. This function can only write into
+  *         the boundaries of an EEPROM page.
+  *         This function doesn't check on boundaries condition (in this driver 
+  *         the function BSP_EEPROM_WriteBuffer() which calls BSP_EEPROM_WritePage() is 
+  *         responsible of checking on Page boundaries).
+  * 
+  * @param  pBuffer: pointer to the buffer containing the data to be written to 
+  *         the EEPROM.
+  * @param  WriteAddr: EEPROM's internal address to write to.
+  * @param  NumByteToWrite: pointer to the variable holding number of bytes to 
+  *         be written into the EEPROM. 
+  * 
+  *        @note The variable pointed by NumByteToWrite is reset to 0 when all the 
+  *              data are written to the EEPROM. Application should monitor this 
+  *              variable in order know when the transfer is complete.
+  * 
+  *        @note This function just configure the communication and enable the DMA 
+  *              channel to transfer data. Meanwhile, the user application may perform 
+  *              other tasks in parallel.
+  * 
+  * @retval EEPROM_OK (0) if operation is correctly performed, else return value 
+  *         different from EEPROM_OK (0) or the timeout user callback.
+  */
+uint32_t BSP_EEPROM_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite)
+{ 
+  uint32_t buffersize = *NumByteToWrite;
+  uint32_t status = EEPROM_OK;
+  
+  /* Set the pointer to the Number of data to be written. This pointer will be used 
+      by the DMA Transfer Completer interrupt Handler in order to reset the 
+      variable to 0. User should check on this variable in order to know if the 
+      DMA transfer has been complete or not. */
+  EEPROMDataWrite = *NumByteToWrite;  
+  
+  if(EEPROM_IO_WriteData(EEPROMAddress, WriteAddr, pBuffer, buffersize) != HAL_OK)
+  {
+    BSP_EEPROM_TIMEOUT_UserCallback();
+    status = EEPROM_FAIL;
+  }
+  
+  if(BSP_EEPROM_WaitEepromStandbyState() != EEPROM_OK) 
+  {
+    return EEPROM_FAIL;
+  }
+  
+  /* If all operations OK, return EEPROM_OK (0) */
+  return status;
+}
+
+/**
+  * @brief  Writes buffer of data to the I2C EEPROM.
+  * @param  pBuffer: pointer to the buffer  containing the data to be written 
+  *         to the EEPROM.
+  * @param  WriteAddr: EEPROM's internal address to write to.
+  * @param  NumByteToWrite: number of bytes to write to the EEPROM.
+  * @retval EEPROM_OK (0) if operation is correctly performed, else return value 
+  *         different from EEPROM_OK (0) or the timeout user callback.
+  */
+uint32_t BSP_EEPROM_WriteBuffer(uint8_t *pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite)
+{
+  uint16_t numofpage = 0, numofsingle = 0, count = 0;
+  uint16_t addr = 0;
+  uint8_t  dataindex = 0;
+  uint32_t status = EEPROM_OK;
+
+  addr = WriteAddr % EEPROM_PAGESIZE;
+  count = EEPROM_PAGESIZE - addr;
+  numofpage =  NumByteToWrite / EEPROM_PAGESIZE;
+  numofsingle = NumByteToWrite % EEPROM_PAGESIZE;
+ 
+  /* If WriteAddr is EEPROM_PAGESIZE aligned */
+  if(addr == 0) 
+  {
+    /* If NumByteToWrite < EEPROM_PAGESIZE */
+    if(numofpage == 0) 
+    {
+      /* Store the number of data to be written */
+      dataindex = numofsingle;
+      /* Start writing data */
+      status = BSP_EEPROM_WritePage(pBuffer, WriteAddr, (uint8_t*)(&dataindex));
+      if(status != EEPROM_OK)
+      {
+        return status;
+      }
+    }
+    /* If NumByteToWrite > EEPROM_PAGESIZE */
+    else  
+    {
+      while(numofpage--)
+      {
+        /* Store the number of data to be written */
+        dataindex = EEPROM_PAGESIZE;        
+        status = BSP_EEPROM_WritePage(pBuffer, WriteAddr, (uint8_t*)(&dataindex));
+        if(status != EEPROM_OK)
+        {
+          return status;
+        }
+        
+        WriteAddr +=  EEPROM_PAGESIZE;
+        pBuffer += EEPROM_PAGESIZE;
+      }
+      
+      if(numofsingle!=0)
+      {
+        /* Store the number of data to be written */
+        dataindex = numofsingle;          
+        status = BSP_EEPROM_WritePage(pBuffer, WriteAddr, (uint8_t*)(&dataindex));
+        if(status != EEPROM_OK)
+        {
+          return status;
+        }
+      }
+    }
+  }
+  /* If WriteAddr is not EEPROM_PAGESIZE aligned */
+  else 
+  {
+    /* If NumByteToWrite < EEPROM_PAGESIZE */
+    if(numofpage== 0) 
+    {
+      /* If the number of data to be written is more than the remaining space 
+      in the current page: */
+      if(NumByteToWrite > count)
+      {
+        /* Store the number of data to be written */
+        dataindex = count;        
+        /* Write the data contained in same page */
+        status = BSP_EEPROM_WritePage(pBuffer, WriteAddr, (uint8_t*)(&dataindex));
+        if(status != EEPROM_OK)
+        {
+          return status;
+        }
+        
+        /* Store the number of data to be written */
+        dataindex = (NumByteToWrite - count);          
+        /* Write the remaining data in the following page */
+        status = BSP_EEPROM_WritePage((uint8_t*)(pBuffer + count), (WriteAddr + count), (uint8_t*)(&dataindex));
+        if(status != EEPROM_OK)
+        {
+          return status;
+        }
+      }      
+      else      
+      {
+        /* Store the number of data to be written */
+        dataindex = numofsingle;         
+        status = BSP_EEPROM_WritePage(pBuffer, WriteAddr, (uint8_t*)(&dataindex));
+        if(status != EEPROM_OK)
+        {
+          return status;
+        }
+      }     
+    }
+    /* If NumByteToWrite > EEPROM_PAGESIZE */
+    else
+    {
+      NumByteToWrite -= count;
+      numofpage =  NumByteToWrite / EEPROM_PAGESIZE;
+      numofsingle = NumByteToWrite % EEPROM_PAGESIZE;
+      
+      if(count != 0)
+      {  
+        /* Store the number of data to be written */
+        dataindex = count;         
+        status = BSP_EEPROM_WritePage(pBuffer, WriteAddr, (uint8_t*)(&dataindex));
+        if(status != EEPROM_OK)
+        {
+          return status;
+        }
+        WriteAddr += count;
+        pBuffer += count;
+      } 
+      
+      while(numofpage--)
+      {
+        /* Store the number of data to be written */
+        dataindex = EEPROM_PAGESIZE;          
+        status = BSP_EEPROM_WritePage(pBuffer, WriteAddr, (uint8_t*)(&dataindex));
+        if(status != EEPROM_OK)
+        {
+          return status;
+        }
+        WriteAddr +=  EEPROM_PAGESIZE;
+        pBuffer += EEPROM_PAGESIZE;  
+      }
+      if(numofsingle != 0)
+      {
+        /* Store the number of data to be written */
+        dataindex = numofsingle;           
+        status = BSP_EEPROM_WritePage(pBuffer, WriteAddr, (uint8_t*)(&dataindex));
+        if(status != EEPROM_OK)
+        {
+          return status;
+        }
+      }
+    }
+  }  
+                                   
+  /* If all operations OK, return EEPROM_OK (0) */
+  return EEPROM_OK;
+}
+
+/**
+  * @brief  Wait for EEPROM Standby state.
+  * 
+  * @note  This function allows to wait and check that EEPROM has finished the 
+  *        last operation. It is mostly used after Write operation: after receiving
+  *        the buffer to be written, the EEPROM may need additional time to actually
+  *        perform the write operation. During this time, it doesn't answer to
+  *        I2C packets addressed to it. Once the write operation is complete
+  *        the EEPROM responds to its address.
+  * 
+  * @retval EEPROM_OK (0) if operation is correctly performed, else return value 
+  *         different from EEPROM_OK (0) or the timeout user callback.
+  */
+uint32_t BSP_EEPROM_WaitEepromStandbyState(void)      
+{
+  /* Check if the maximum allowed number of trials has bee reached */
+  if(EEPROM_IO_IsDeviceReady(EEPROMAddress, EEPROM_MAX_TRIALS) != HAL_OK)
+  {
+    /* If the maximum number of trials has been reached, exit the function */
+    BSP_EEPROM_TIMEOUT_UserCallback();
+    return EEPROM_TIMEOUT;
+  }
+  return EEPROM_OK;
+}
+
+/**
+  * @brief  Basic management of the timeout situation.
+  * @retval None
+  */
+__weak void BSP_EEPROM_TIMEOUT_UserCallback(void)
+{
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_eeprom.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,140 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_eeprom.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file contains all the functions prototypes for 
+  *          the stm32746g_discovery_eeprom.c firmware driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32746G_DISCOVERY_EEPROM_H
+#define __STM32746G_DISCOVERY_EEPROM_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32746g_discovery.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+  
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */ 
+  
+/** @addtogroup STM32746G_DISCOVERY_EEPROM
+  * @brief This file includes the I2C EEPROM driver of STM32746G-Discovery board.
+  * @{
+  */
+
+/** @defgroup STM32746G_DISCOVERY_EEPROM_Exported_Types STM32746G_DISCOVERY_EEPROM Exported Types
+  * @{
+  */ 
+/**
+  * @}
+  */
+  
+/** @defgroup STM32746G_DISCOVERY_EEPROM_Exported_Constants STM32746G_DISCOVERY_EEPROM Exported Constants
+  * @{
+  */
+/* EEPROM hardware address and page size */ 
+#define EEPROM_PAGESIZE             ((uint8_t)4)
+#define EEPROM_MAX_SIZE             ((uint16_t)0x2000) /* 64Kbit */
+                                
+
+/* Maximum number of trials for EEPROM_WaitEepromStandbyState() function */
+#define EEPROM_MAX_TRIALS           ((uint32_t)3000)
+      
+#define EEPROM_OK                   ((uint32_t)0)
+#define EEPROM_FAIL                 ((uint32_t)1)
+#define EEPROM_TIMEOUT              ((uint32_t)2)
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_EEPROM_Exported_Macros STM32746G_DISCOVERY_EEPROM Exported Macros
+  * @{
+  */    
+/**
+  * @}
+  */ 
+
+/** @addtogroup STM32746G_DISCOVERY_EEPROM_Exported_Functions
+  * @{
+  */ 
+uint32_t BSP_EEPROM_Init(void);
+uint8_t BSP_EEPROM_DeInit(void);
+uint32_t BSP_EEPROM_ReadBuffer(uint8_t* pBuffer, uint16_t ReadAddr, uint16_t* NumByteToRead);
+uint32_t BSP_EEPROM_WritePage(uint8_t* pBuffer, uint16_t WriteAddr, uint8_t* NumByteToWrite);
+uint32_t BSP_EEPROM_WriteBuffer(uint8_t* pBuffer, uint16_t WriteAddr, uint16_t NumByteToWrite);
+uint32_t BSP_EEPROM_WaitEepromStandbyState(void);
+
+/* USER Callbacks: This function is declared as __weak in EEPROM driver and 
+   should be implemented into user application.  
+   BSP_EEPROM_TIMEOUT_UserCallback() function is called whenever a timeout condition 
+   occurs during communication (waiting on an event that doesn't occur, bus
+   errors, busy devices ...). */
+void     BSP_EEPROM_TIMEOUT_UserCallback(void);
+
+/* Link function for I2C EEPROM peripheral */
+void              EEPROM_IO_Init(void);
+HAL_StatusTypeDef EEPROM_IO_WriteData(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pBuffer, uint32_t BufferSize);
+HAL_StatusTypeDef EEPROM_IO_ReadData(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pBuffer, uint32_t BufferSize);
+HAL_StatusTypeDef EEPROM_IO_IsDeviceReady(uint16_t DevAddress, uint32_t Trials);
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32746G_DISCOVERY_EEPROM_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_qspi.c	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,792 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_qspi.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file includes a standard driver for the N25Q128A QSPI
+  *          memory mounted on STM32746G-Discovery board.
+  @verbatim
+  ==============================================================================
+                     ##### How to use this driver #####
+  ==============================================================================  
+  [..] 
+   (#) This driver is used to drive the N25Q128A QSPI external
+       memory mounted on STM32746G-Discovery board.
+       
+   (#) This driver need a specific component driver (N25Q128A) to be included with.
+
+   (#) Initialization steps:
+       (++) Initialize the QPSI external memory using the BSP_QSPI_Init() function. This 
+            function includes the MSP layer hardware resources initialization and the
+            QSPI interface with the external memory.
+  
+   (#) QSPI memory operations
+       (++) QSPI memory can be accessed with read/write operations once it is
+            initialized.
+            Read/write operation can be performed with AHB access using the functions
+            BSP_QSPI_Read()/BSP_QSPI_Write(). 
+       (++) The function BSP_QSPI_GetInfo() returns the configuration of the QSPI memory. 
+            (see the QSPI memory data sheet)
+       (++) Perform erase block operation using the function BSP_QSPI_Erase_Block() and by
+            specifying the block address. You can perform an erase operation of the whole 
+            chip by calling the function BSP_QSPI_Erase_Chip(). 
+       (++) The function BSP_QSPI_GetStatus() returns the current status of the QSPI memory. 
+            (see the QSPI memory data sheet)
+  @endverbatim
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32746g_discovery_qspi.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_QSPI STM32746G-Discovery QSPI
+  * @{
+  */ 
+
+
+/* Private variables ---------------------------------------------------------*/
+
+/** @defgroup STM32746G_DISCOVERY_QSPI_Private_Variables STM32746G_DISCOVERY QSPI Private Variables
+  * @{
+  */       
+QSPI_HandleTypeDef QSPIHandle;
+
+/**
+  * @}
+  */ 
+
+
+
+/* Private functions ---------------------------------------------------------*/
+    
+/** @defgroup STM32746G_DISCOVERY_QSPI_Private_Functions STM32746G_DISCOVERY QSPI Private Functions
+  * @{
+  */ 
+static uint8_t QSPI_ResetMemory          (QSPI_HandleTypeDef *hqspi);
+static uint8_t QSPI_DummyCyclesCfg       (QSPI_HandleTypeDef *hqspi);
+static uint8_t QSPI_WriteEnable          (QSPI_HandleTypeDef *hqspi);
+static uint8_t QSPI_AutoPollingMemReady  (QSPI_HandleTypeDef *hqspi, uint32_t Timeout);
+
+/**
+  * @}
+  */
+    
+/** @defgroup STM32746G_DISCOVERY_QSPI_Exported_Functions STM32746G_DISCOVERY QSPI Exported Functions
+  * @{
+  */ 
+
+/**
+  * @brief  Initializes the QSPI interface.
+  * @retval QSPI memory status
+  */
+uint8_t BSP_QSPI_Init(void)
+{ 
+  QSPIHandle.Instance = QUADSPI;
+
+  /* Call the DeInit function to reset the driver */
+  if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+        
+  /* System level initialization */
+  BSP_QSPI_MspInit(&QSPIHandle, NULL);
+  
+  /* QSPI initialization */
+  QSPIHandle.Init.ClockPrescaler     = 1; /* QSPI freq = 216 MHz/(1+1) = 108 Mhz */
+  QSPIHandle.Init.FifoThreshold      = 4;
+  QSPIHandle.Init.SampleShifting     = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
+  QSPIHandle.Init.FlashSize          = POSITION_VAL(N25Q128A_FLASH_SIZE) - 1;
+  QSPIHandle.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_2_CYCLE;
+  QSPIHandle.Init.ClockMode          = QSPI_CLOCK_MODE_0;
+  QSPIHandle.Init.FlashID            = QSPI_FLASH_ID_1;
+  QSPIHandle.Init.DualFlash          = QSPI_DUALFLASH_DISABLE;
+
+  if (HAL_QSPI_Init(&QSPIHandle) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* QSPI memory reset */
+  if (QSPI_ResetMemory(&QSPIHandle) != QSPI_OK)
+  {
+    return QSPI_NOT_SUPPORTED;
+  }
+ 
+  /* Configuration of the dummy cycles on QSPI memory side */
+  if (QSPI_DummyCyclesCfg(&QSPIHandle) != QSPI_OK)
+  {
+    return QSPI_NOT_SUPPORTED;
+  }
+  
+  return QSPI_OK;
+}
+
+/**
+  * @brief  De-Initializes the QSPI interface.
+  * @retval QSPI memory status
+  */
+uint8_t BSP_QSPI_DeInit(void)
+{ 
+  QSPIHandle.Instance = QUADSPI;
+
+  /* Call the DeInit function to reset the driver */
+  if (HAL_QSPI_DeInit(&QSPIHandle) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+        
+  /* System level De-initialization */
+  BSP_QSPI_MspDeInit(&QSPIHandle, NULL);
+  
+  return QSPI_OK;
+}
+
+/**
+  * @brief  Reads an amount of data from the QSPI memory.
+  * @param  pData: Pointer to data to be read
+  * @param  ReadAddr: Read start address
+  * @param  Size: Size of data to read    
+  * @retval QSPI memory status
+  */
+uint8_t BSP_QSPI_Read(uint8_t* pData, uint32_t ReadAddr, uint32_t Size)
+{
+  QSPI_CommandTypeDef s_command;
+
+  /* Initialize the read command */
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = QUAD_INOUT_FAST_READ_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_4_LINES;
+  s_command.AddressSize       = QSPI_ADDRESS_24_BITS;
+  s_command.Address           = ReadAddr;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_4_LINES;
+  s_command.DummyCycles       = N25Q128A_DUMMY_CYCLES_READ_QUAD;
+  s_command.NbData            = Size;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+  
+  /* Configure the command */
+  if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+  
+  /* Reception of the data */
+  if (HAL_QSPI_Receive(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  return QSPI_OK;
+}
+
+/**
+  * @brief  Writes an amount of data to the QSPI memory.
+  * @param  pData: Pointer to data to be written
+  * @param  WriteAddr: Write start address
+  * @param  Size: Size of data to write    
+  * @retval QSPI memory status
+  */
+uint8_t BSP_QSPI_Write(uint8_t* pData, uint32_t WriteAddr, uint32_t Size)
+{
+  QSPI_CommandTypeDef s_command;
+  uint32_t end_addr, current_size, current_addr;
+
+  /* Calculation of the size between the write address and the end of the page */
+  current_addr = 0;
+
+  while (current_addr <= WriteAddr)
+  {
+    current_addr += N25Q128A_PAGE_SIZE;
+  }
+  current_size = current_addr - WriteAddr;
+
+  /* Check if the size of the data is less than the remaining place in the page */
+  if (current_size > Size)
+  {
+    current_size = Size;
+  }
+
+  /* Initialize the adress variables */
+  current_addr = WriteAddr;
+  end_addr = WriteAddr + Size;
+
+  /* Initialize the program command */
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = EXT_QUAD_IN_FAST_PROG_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_4_LINES;
+  s_command.AddressSize       = QSPI_ADDRESS_24_BITS;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_4_LINES;
+  s_command.DummyCycles       = 0;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+  
+  /* Perform the write page by page */
+  do
+  {
+    s_command.Address = current_addr;
+    s_command.NbData  = current_size;
+
+    /* Enable write operations */
+    if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
+    {
+      return QSPI_ERROR;
+    }
+    
+    /* Configure the command */
+    if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+    {
+      return QSPI_ERROR;
+    }
+    
+    /* Transmission of the data */
+    if (HAL_QSPI_Transmit(&QSPIHandle, pData, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+    {
+      return QSPI_ERROR;
+    }
+    
+    /* Configure automatic polling mode to wait for end of program */  
+    if (QSPI_AutoPollingMemReady(&QSPIHandle, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)
+    {
+      return QSPI_ERROR;
+    }
+    
+    /* Update the address and size variables for next page programming */
+    current_addr += current_size;
+    pData += current_size;
+    current_size = ((current_addr + N25Q128A_PAGE_SIZE) > end_addr) ? (end_addr - current_addr) : N25Q128A_PAGE_SIZE;
+  } while (current_addr < end_addr);
+  
+  return QSPI_OK;
+}
+
+/**
+  * @brief  Erases the specified block of the QSPI memory. 
+  * @param  BlockAddress: Block address to erase  
+  * @retval QSPI memory status
+  */
+uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress)
+{
+  QSPI_CommandTypeDef s_command;
+
+  /* Initialize the erase command */
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = SUBSECTOR_ERASE_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_1_LINE;
+  s_command.AddressSize       = QSPI_ADDRESS_24_BITS;
+  s_command.Address           = BlockAddress;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_NONE;
+  s_command.DummyCycles       = 0;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+
+  /* Enable write operations */
+  if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* Send the command */
+  if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+  
+  /* Configure automatic polling mode to wait for end of erase */  
+  if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_SUBSECTOR_ERASE_MAX_TIME) != QSPI_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  return QSPI_OK;
+}
+
+/**
+  * @brief  Erases the entire QSPI memory.
+  * @retval QSPI memory status
+  */
+uint8_t BSP_QSPI_Erase_Chip(void)
+{
+  QSPI_CommandTypeDef s_command;
+
+  /* Initialize the erase command */
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = BULK_ERASE_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_NONE;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_NONE;
+  s_command.DummyCycles       = 0;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+
+  /* Enable write operations */
+  if (QSPI_WriteEnable(&QSPIHandle) != QSPI_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* Send the command */
+  if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+  
+  /* Configure automatic polling mode to wait for end of erase */  
+  if (QSPI_AutoPollingMemReady(&QSPIHandle, N25Q128A_BULK_ERASE_MAX_TIME) != QSPI_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  return QSPI_OK;
+}
+
+/**
+  * @brief  Reads current status of the QSPI memory.
+  * @retval QSPI memory status
+  */
+uint8_t BSP_QSPI_GetStatus(void)
+{
+  QSPI_CommandTypeDef s_command;
+  uint8_t reg;
+
+  /* Initialize the read flag status register command */
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = READ_FLAG_STATUS_REG_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_NONE;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_1_LINE;
+  s_command.DummyCycles       = 0;
+  s_command.NbData            = 1;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+
+  /* Configure the command */
+  if (HAL_QSPI_Command(&QSPIHandle, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* Reception of the data */
+  if (HAL_QSPI_Receive(&QSPIHandle, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+  
+  /* Check the value of the register */
+  if ((reg & (N25Q128A_FSR_PRERR | N25Q128A_FSR_VPPERR | N25Q128A_FSR_PGERR | N25Q128A_FSR_ERERR)) != 0)
+  {
+    return QSPI_ERROR;
+  }
+  else if ((reg & (N25Q128A_FSR_PGSUS | N25Q128A_FSR_ERSUS)) != 0)
+  {
+    return QSPI_SUSPENDED;
+  }
+  else if ((reg & N25Q128A_FSR_READY) != 0)
+  {
+    return QSPI_OK;
+  }
+  else
+  {
+    return QSPI_BUSY;
+  }
+}
+
+/**
+  * @brief  Return the configuration of the QSPI memory.
+  * @param  pInfo: pointer on the configuration structure  
+  * @retval QSPI memory status
+  */
+uint8_t BSP_QSPI_GetInfo(QSPI_Info* pInfo)
+{
+  /* Configure the structure with the memory configuration */
+  pInfo->FlashSize          = N25Q128A_FLASH_SIZE;
+  pInfo->EraseSectorSize    = N25Q128A_SUBSECTOR_SIZE;
+  pInfo->EraseSectorsNumber = (N25Q128A_FLASH_SIZE/N25Q128A_SUBSECTOR_SIZE);
+  pInfo->ProgPageSize       = N25Q128A_PAGE_SIZE;
+  pInfo->ProgPagesNumber    = (N25Q128A_FLASH_SIZE/N25Q128A_PAGE_SIZE);
+  
+  return QSPI_OK;
+}
+
+/**
+  * @brief  Configure the QSPI in memory-mapped mode
+  * @retval QSPI memory status
+  */
+uint8_t BSP_QSPI_MemoryMappedMode(void)
+{
+  QSPI_CommandTypeDef      s_command;
+  QSPI_MemoryMappedTypeDef s_mem_mapped_cfg;
+
+  /* Configure the command for the read instruction */
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = QUAD_INOUT_FAST_READ_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_4_LINES;
+  s_command.AddressSize       = QSPI_ADDRESS_24_BITS;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_4_LINES;
+  s_command.DummyCycles       = N25Q128A_DUMMY_CYCLES_READ_QUAD;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+  
+  /* Configure the memory mapped mode */
+  s_mem_mapped_cfg.TimeOutActivation = QSPI_TIMEOUT_COUNTER_ENABLE;
+  s_mem_mapped_cfg.TimeOutPeriod     = 1;
+  
+  if (HAL_QSPI_MemoryMapped(&QSPIHandle, &s_command, &s_mem_mapped_cfg) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  return QSPI_OK;
+}
+
+/**
+  * @}
+  */
+
+/** @addtogroup STM32746G_DISCOVERY_QSPI_Private_Functions
+  * @{
+  */ 
+
+/**
+  * @brief QSPI MSP Initialization
+  *        This function configures the hardware resources used in this example:
+  *           - Peripheral's clock enable
+  *           - Peripheral's GPIO Configuration
+  *           - NVIC configuration for QSPI interrupt
+  * @retval None
+  */
+__weak void BSP_QSPI_MspInit(QSPI_HandleTypeDef *hqspi, void *Params)
+{
+  GPIO_InitTypeDef gpio_init_structure;
+
+  /*##-1- Enable peripherals and GPIO Clocks #################################*/
+  /* Enable the QuadSPI memory interface clock */
+  QSPI_CLK_ENABLE();
+  /* Reset the QuadSPI memory interface */
+  QSPI_FORCE_RESET();
+  QSPI_RELEASE_RESET();
+  /* Enable GPIO clocks */
+  QSPI_CS_GPIO_CLK_ENABLE();
+  QSPI_CLK_GPIO_CLK_ENABLE();
+  QSPI_D0_GPIO_CLK_ENABLE();
+  QSPI_D1_GPIO_CLK_ENABLE();
+  QSPI_D2_GPIO_CLK_ENABLE();
+  QSPI_D3_GPIO_CLK_ENABLE();
+
+  /*##-2- Configure peripheral GPIO ##########################################*/
+  /* QSPI CS GPIO pin configuration  */
+  gpio_init_structure.Pin       = QSPI_CS_PIN;
+  gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull      = GPIO_PULLUP;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = GPIO_AF10_QUADSPI;
+  HAL_GPIO_Init(QSPI_CS_GPIO_PORT, &gpio_init_structure);
+
+  /* QSPI CLK GPIO pin configuration  */
+  gpio_init_structure.Pin       = QSPI_CLK_PIN;
+  gpio_init_structure.Pull      = GPIO_NOPULL;
+  gpio_init_structure.Alternate = GPIO_AF9_QUADSPI;
+  HAL_GPIO_Init(QSPI_CLK_GPIO_PORT, &gpio_init_structure);
+
+  /* QSPI D0 GPIO pin configuration  */
+  gpio_init_structure.Pin       = QSPI_D0_PIN;
+  gpio_init_structure.Alternate = GPIO_AF9_QUADSPI;
+  HAL_GPIO_Init(QSPI_D0_GPIO_PORT, &gpio_init_structure);
+
+  /* QSPI D1 GPIO pin configuration  */
+  gpio_init_structure.Pin       = QSPI_D1_PIN;
+  gpio_init_structure.Alternate = GPIO_AF9_QUADSPI;
+  HAL_GPIO_Init(QSPI_D1_GPIO_PORT, &gpio_init_structure);
+
+  /* QSPI D2 GPIO pin configuration  */
+  gpio_init_structure.Pin       = QSPI_D2_PIN;
+  gpio_init_structure.Alternate = GPIO_AF9_QUADSPI;
+  HAL_GPIO_Init(QSPI_D2_GPIO_PORT, &gpio_init_structure);
+
+  /* QSPI D3 GPIO pin configuration  */
+  gpio_init_structure.Pin       = QSPI_D3_PIN;
+  gpio_init_structure.Alternate = GPIO_AF9_QUADSPI;
+  HAL_GPIO_Init(QSPI_D3_GPIO_PORT, &gpio_init_structure);
+
+  /*##-3- Configure the NVIC for QSPI #########################################*/
+  /* NVIC configuration for QSPI interrupt */
+  HAL_NVIC_SetPriority(QUADSPI_IRQn, 0x0F, 0);
+  HAL_NVIC_EnableIRQ(QUADSPI_IRQn);
+}
+
+/**
+  * @brief QSPI MSP De-Initialization
+  *        This function frees the hardware resources used in this example:
+  *          - Disable the Peripheral's clock
+  *          - Revert GPIO and NVIC configuration to their default state
+  * @retval None
+  */
+__weak void BSP_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi, void *Params)
+{
+  /*##-1- Disable the NVIC for QSPI ###########################################*/
+  HAL_NVIC_DisableIRQ(QUADSPI_IRQn);
+
+  /*##-2- Disable peripherals and GPIO Clocks ################################*/
+  /* De-Configure QSPI pins */
+  HAL_GPIO_DeInit(QSPI_CS_GPIO_PORT, QSPI_CS_PIN);
+  HAL_GPIO_DeInit(QSPI_CLK_GPIO_PORT, QSPI_CLK_PIN);
+  HAL_GPIO_DeInit(QSPI_D0_GPIO_PORT, QSPI_D0_PIN);
+  HAL_GPIO_DeInit(QSPI_D1_GPIO_PORT, QSPI_D1_PIN);
+  HAL_GPIO_DeInit(QSPI_D2_GPIO_PORT, QSPI_D2_PIN);
+  HAL_GPIO_DeInit(QSPI_D3_GPIO_PORT, QSPI_D3_PIN);
+
+  /*##-3- Reset peripherals ##################################################*/
+  /* Reset the QuadSPI memory interface */
+  QSPI_FORCE_RESET();
+  QSPI_RELEASE_RESET();
+
+  /* Disable the QuadSPI memory interface clock */
+  QSPI_CLK_DISABLE();
+}
+
+/**
+  * @brief  This function reset the QSPI memory.
+  * @param  hqspi: QSPI handle
+  * @retval None
+  */
+static uint8_t QSPI_ResetMemory(QSPI_HandleTypeDef *hqspi)
+{
+  QSPI_CommandTypeDef s_command;
+
+  /* Initialize the reset enable command */
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = RESET_ENABLE_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_NONE;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_NONE;
+  s_command.DummyCycles       = 0;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+
+  /* Send the command */
+  if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* Send the reset memory command */
+  s_command.Instruction = RESET_MEMORY_CMD;
+  if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* Configure automatic polling mode to wait the memory is ready */  
+  if (QSPI_AutoPollingMemReady(hqspi, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != QSPI_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  return QSPI_OK;
+}
+
+/**
+  * @brief  This function configure the dummy cycles on memory side.
+  * @param  hqspi: QSPI handle
+  * @retval None
+  */
+static uint8_t QSPI_DummyCyclesCfg(QSPI_HandleTypeDef *hqspi)
+{
+  QSPI_CommandTypeDef s_command;
+  uint8_t reg;
+
+  /* Initialize the read volatile configuration register command */
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = READ_VOL_CFG_REG_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_NONE;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_1_LINE;
+  s_command.DummyCycles       = 0;
+  s_command.NbData            = 1;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+
+  /* Configure the command */
+  if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* Reception of the data */
+  if (HAL_QSPI_Receive(hqspi, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* Enable write operations */
+  if (QSPI_WriteEnable(hqspi) != QSPI_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* Update volatile configuration register (with new dummy cycles) */  
+  s_command.Instruction = WRITE_VOL_CFG_REG_CMD;
+  MODIFY_REG(reg, N25Q128A_VCR_NB_DUMMY, (N25Q128A_DUMMY_CYCLES_READ_QUAD << POSITION_VAL(N25Q128A_VCR_NB_DUMMY)));
+      
+  /* Configure the write volatile configuration register command */
+  if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  /* Transmission of the data */
+  if (HAL_QSPI_Transmit(hqspi, &reg, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+  
+  return QSPI_OK;
+}
+
+/**
+  * @brief  This function send a Write Enable and wait it is effective.
+  * @param  hqspi: QSPI handle
+  * @retval None
+  */
+static uint8_t QSPI_WriteEnable(QSPI_HandleTypeDef *hqspi)
+{
+  QSPI_CommandTypeDef     s_command;
+  QSPI_AutoPollingTypeDef s_config;
+
+  /* Enable write operations */
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = WRITE_ENABLE_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_NONE;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_NONE;
+  s_command.DummyCycles       = 0;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+
+  if (HAL_QSPI_Command(hqspi, &s_command, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+  
+  /* Configure automatic polling mode to wait for write enabling */  
+  s_config.Match           = N25Q128A_SR_WREN;
+  s_config.Mask            = N25Q128A_SR_WREN;
+  s_config.MatchMode       = QSPI_MATCH_MODE_AND;
+  s_config.StatusBytesSize = 1;
+  s_config.Interval        = 0x10;
+  s_config.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;
+
+  s_command.Instruction    = READ_STATUS_REG_CMD;
+  s_command.DataMode       = QSPI_DATA_1_LINE;
+
+  if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  return QSPI_OK;
+}
+
+/**
+  * @brief  This function read the SR of the memory and wait the EOP.
+  * @param  hqspi: QSPI handle
+  * @param  Timeout
+  * @retval None
+  */
+static uint8_t QSPI_AutoPollingMemReady(QSPI_HandleTypeDef *hqspi, uint32_t Timeout)
+{
+  QSPI_CommandTypeDef     s_command;
+  QSPI_AutoPollingTypeDef s_config;
+
+  /* Configure automatic polling mode to wait for memory ready */  
+  s_command.InstructionMode   = QSPI_INSTRUCTION_1_LINE;
+  s_command.Instruction       = READ_STATUS_REG_CMD;
+  s_command.AddressMode       = QSPI_ADDRESS_NONE;
+  s_command.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
+  s_command.DataMode          = QSPI_DATA_1_LINE;
+  s_command.DummyCycles       = 0;
+  s_command.DdrMode           = QSPI_DDR_MODE_DISABLE;
+  s_command.DdrHoldHalfCycle  = QSPI_DDR_HHC_ANALOG_DELAY;
+  s_command.SIOOMode          = QSPI_SIOO_INST_EVERY_CMD;
+
+  s_config.Match           = 0;
+  s_config.Mask            = N25Q128A_SR_WIP;
+  s_config.MatchMode       = QSPI_MATCH_MODE_AND;
+  s_config.StatusBytesSize = 1;
+  s_config.Interval        = 0x10;
+  s_config.AutomaticStop   = QSPI_AUTOMATIC_STOP_ENABLE;
+
+  if (HAL_QSPI_AutoPolling(hqspi, &s_command, &s_config, Timeout) != HAL_OK)
+  {
+    return QSPI_ERROR;
+  }
+
+  return QSPI_OK;
+}
+/**
+  * @}
+  */  
+  
+/**
+  * @}
+  */ 
+  
+/**
+  * @}
+  */ 
+  
+/**
+  * @}
+  */ 
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_qspi.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,170 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_qspi.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file contains the common defines and functions prototypes for
+  *          the stm32746g_discovery_qspi.c driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */
+    
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32746G_DISCOVERY_QSPI_H
+#define __STM32746G_DISCOVERY_QSPI_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32f7xx_hal.h"
+#include "n25q128a.h"
+
+/** @addtogroup STM32746G_DISCOVERY_QSPI
+  * @{
+  */    
+
+  
+/* Exported constants --------------------------------------------------------*/ 
+/** @defgroup STM32746G_DISCOVERY_QSPI_Exported_Constants STM32746G_DISCOVERY_QSPI Exported Constants
+  * @{
+  */
+/* QSPI Error codes */
+#define QSPI_OK            ((uint8_t)0x00)
+#define QSPI_ERROR         ((uint8_t)0x01)
+#define QSPI_BUSY          ((uint8_t)0x02)
+#define QSPI_NOT_SUPPORTED ((uint8_t)0x04)
+#define QSPI_SUSPENDED     ((uint8_t)0x08)
+
+
+/* Definition for QSPI clock resources */
+#define QSPI_CLK_ENABLE()          __HAL_RCC_QSPI_CLK_ENABLE()
+#define QSPI_CLK_DISABLE()         __HAL_RCC_QSPI_CLK_DISABLE()
+#define QSPI_CS_GPIO_CLK_ENABLE()  __HAL_RCC_GPIOB_CLK_ENABLE()
+#define QSPI_CLK_GPIO_CLK_ENABLE() __HAL_RCC_GPIOB_CLK_ENABLE()
+#define QSPI_D0_GPIO_CLK_ENABLE()  __HAL_RCC_GPIOD_CLK_ENABLE()
+#define QSPI_D1_GPIO_CLK_ENABLE()  __HAL_RCC_GPIOD_CLK_ENABLE()
+#define QSPI_D2_GPIO_CLK_ENABLE()  __HAL_RCC_GPIOE_CLK_ENABLE()
+#define QSPI_D3_GPIO_CLK_ENABLE()  __HAL_RCC_GPIOD_CLK_ENABLE()
+
+#define QSPI_FORCE_RESET()         __HAL_RCC_QSPI_FORCE_RESET()
+#define QSPI_RELEASE_RESET()       __HAL_RCC_QSPI_RELEASE_RESET()
+
+/* Definition for QSPI Pins */
+#define QSPI_CS_PIN                GPIO_PIN_6
+#define QSPI_CS_GPIO_PORT          GPIOB
+#define QSPI_CLK_PIN               GPIO_PIN_2
+#define QSPI_CLK_GPIO_PORT         GPIOB
+#define QSPI_D0_PIN                GPIO_PIN_11
+#define QSPI_D0_GPIO_PORT          GPIOD
+#define QSPI_D1_PIN                GPIO_PIN_12
+#define QSPI_D1_GPIO_PORT          GPIOD
+#define QSPI_D2_PIN                GPIO_PIN_2
+#define QSPI_D2_GPIO_PORT          GPIOE
+#define QSPI_D3_PIN                GPIO_PIN_13
+#define QSPI_D3_GPIO_PORT          GPIOD
+
+/* N25Q128A13EF840E Micron memory */
+/* Size of the flash */
+#define QSPI_FLASH_SIZE            23     /* Address bus width to access whole memory space */
+#define QSPI_PAGE_SIZE             256
+
+/**
+  * @}
+  */
+
+/* Exported types ------------------------------------------------------------*/
+/** @defgroup STM32746G_DISCOVERY_QSPI_Exported_Types STM32746G_DISCOVERY_QSPI Exported Types
+  * @{
+  */
+/* QSPI Info */
+typedef struct {
+  uint32_t FlashSize;          /*!< Size of the flash */
+  uint32_t EraseSectorSize;    /*!< Size of sectors for the erase operation */
+  uint32_t EraseSectorsNumber; /*!< Number of sectors for the erase operation */
+  uint32_t ProgPageSize;       /*!< Size of pages for the program operation */
+  uint32_t ProgPagesNumber;    /*!< Number of pages for the program operation */
+} QSPI_Info;
+
+/**
+  * @}
+  */
+
+  
+/* Exported functions --------------------------------------------------------*/
+/** @addtogroup STM32746G_DISCOVERY_QSPI_Exported_Functions
+  * @{
+  */  
+uint8_t BSP_QSPI_Init       (void);
+uint8_t BSP_QSPI_DeInit     (void);
+uint8_t BSP_QSPI_Read       (uint8_t* pData, uint32_t ReadAddr, uint32_t Size);
+uint8_t BSP_QSPI_Write      (uint8_t* pData, uint32_t WriteAddr, uint32_t Size);
+uint8_t BSP_QSPI_Erase_Block(uint32_t BlockAddress);
+uint8_t BSP_QSPI_Erase_Chip (void);
+uint8_t BSP_QSPI_GetStatus  (void);
+uint8_t BSP_QSPI_GetInfo    (QSPI_Info* pInfo);
+uint8_t BSP_QSPI_MemoryMappedMode(void);
+
+/* These functions can be modified in case the current settings
+   need to be changed for specific application needs */
+void BSP_QSPI_MspInit(QSPI_HandleTypeDef *hqspi, void *Params);
+void BSP_QSPI_MspDeInit(QSPI_HandleTypeDef *hqspi, void *Params);
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32746G_DISCOVERY_QSPI_H */
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_sd.c	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,596 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_sd.c
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file includes the uSD card driver mounted on STM32746G-Discovery
+  *          board.
+  @verbatim
+   1. How To use this driver:
+   --------------------------
+      - This driver is used to drive the micro SD external card mounted on STM32746G-Discovery
+        board.
+      - This driver does not need a specific component driver for the micro SD device
+        to be included with.
+   
+   2. Driver description:
+   ---------------------
+     + Initialization steps:
+        o Initialize the micro SD card using the BSP_SD_Init() function. This 
+          function includes the MSP layer hardware resources initialization and the
+          SDIO interface configuration to interface with the external micro SD. It 
+          also includes the micro SD initialization sequence.
+        o To check the SD card presence you can use the function BSP_SD_IsDetected() which 
+          returns the detection status 
+        o If SD presence detection interrupt mode is desired, you must configure the 
+          SD detection interrupt mode by calling the function BSP_SD_ITConfig(). The interrupt 
+          is generated as an external interrupt whenever the micro SD card is 
+          plugged/unplugged in/from the board.
+        o The function BSP_SD_GetCardInfo() is used to get the micro SD card information 
+          which is stored in the structure "HAL_SD_CardInfoTypedef".
+     
+     + Micro SD card operations
+        o The micro SD card can be accessed with read/write block(s) operations once 
+          it is ready for access. The access can be performed whether using the polling
+          mode by calling the functions BSP_SD_ReadBlocks()/BSP_SD_WriteBlocks(), or by DMA 
+          transfer using the functions BSP_SD_ReadBlocks_DMA()/BSP_SD_WriteBlocks_DMA()
+        o The DMA transfer complete is used with interrupt mode. Once the SD transfer
+          is complete, the SD interrupt is handled using the function BSP_SD_IRQHandler(),
+          the DMA Tx/Rx transfer complete are handled using the functions
+          BSP_SD_DMA_Tx_IRQHandler()/BSP_SD_DMA_Rx_IRQHandler(). The corresponding user callbacks 
+          are implemented by the user at application level. 
+        o The SD erase block(s) is performed using the function BSP_SD_Erase() with specifying
+          the number of blocks to erase.
+        o The SD runtime status is returned when calling the function BSP_SD_GetStatus().
+  @endverbatim
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32746g_discovery_sd.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_SD STM32746G_DISCOVERY_SD
+  * @{
+  */ 
+
+
+/** @defgroup STM32746G_DISCOVERY_SD_Private_TypesDefinitions STM32746G_DISCOVERY_SD Private Types Definitions
+  * @{
+  */
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32746G_DISCOVERY_SD_Private_Defines STM32746G_DISCOVERY_SD Private Defines
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_SD_Private_Macros STM32746G_DISCOVERY_SD Private Macros
+  * @{
+  */    
+/**
+  * @}
+  */  
+
+/** @defgroup STM32746G_DISCOVERY_SD_Private_Variables STM32746G_DISCOVERY_SD Private Variables
+  * @{
+  */
+static SD_HandleTypeDef uSdHandle;
+static SD_CardInfo      uSdCardInfo;
+
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_SD_Private_FunctionPrototypes STM32746G_DISCOVERY_SD Private Function Prototypes
+  * @{
+  */
+/**
+  * @}
+  */ 
+  
+/** @defgroup STM32746G_DISCOVERY_SD_Exported_Functions STM32746G_DISCOVERY_SD Exported Functions
+  * @{
+  */
+
+/**
+  * @brief  Initializes the SD card device.
+  * @retval SD status
+  */
+uint8_t BSP_SD_Init(void)
+{ 
+  uint8_t sd_state = MSD_OK;
+  
+  /* uSD device interface configuration */
+  uSdHandle.Instance = SDMMC1;
+
+  uSdHandle.Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
+  uSdHandle.Init.ClockBypass         = SDMMC_CLOCK_BYPASS_DISABLE;
+  uSdHandle.Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
+  uSdHandle.Init.BusWide             = SDMMC_BUS_WIDE_1B;
+  uSdHandle.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
+  uSdHandle.Init.ClockDiv            = SDMMC_TRANSFER_CLK_DIV;
+  
+  /* Msp SD Detect pin initialization */
+  BSP_SD_Detect_MspInit(&uSdHandle, NULL);
+  if(BSP_SD_IsDetected() != SD_PRESENT)   /* Check if SD card is present */
+  {
+    return MSD_ERROR_SD_NOT_PRESENT;
+  }
+  
+  /* Msp SD initialization */
+  BSP_SD_MspInit(&uSdHandle, NULL);
+
+  /* HAL SD initialization */
+  if(HAL_SD_Init(&uSdHandle, &uSdCardInfo) != SD_OK)
+  {
+    sd_state = MSD_ERROR;
+  }
+  
+  /* Configure SD Bus width */
+  if(sd_state == MSD_OK)
+  {
+    /* Enable wide operation */
+    if(HAL_SD_WideBusOperation_Config(&uSdHandle, SDMMC_BUS_WIDE_4B) != SD_OK)
+    {
+      sd_state = MSD_ERROR;
+    }
+    else
+    {
+      sd_state = MSD_OK;
+    }
+  }
+  
+  return  sd_state;
+}
+
+/**
+  * @brief  DeInitializes the SD card device.
+  * @retval SD status
+  */
+uint8_t BSP_SD_DeInit(void)
+{ 
+  uint8_t sd_state = MSD_OK;
+ 
+  uSdHandle.Instance = SDMMC1;
+  
+  /* HAL SD deinitialization */
+  if(HAL_SD_DeInit(&uSdHandle) != HAL_OK)
+  {
+    sd_state = MSD_ERROR;
+  }
+
+  /* Msp SD deinitialization */
+  uSdHandle.Instance = SDMMC1;
+  BSP_SD_MspDeInit(&uSdHandle, NULL);
+  
+  return  sd_state;
+}
+
+/**
+  * @brief  Configures Interrupt mode for SD detection pin.
+  * @retval Returns MSD_OK
+  */
+uint8_t BSP_SD_ITConfig(void)
+{  
+  GPIO_InitTypeDef gpio_init_structure;
+
+  /* Configure Interrupt mode for SD detection pin */  
+  gpio_init_structure.Pin = SD_DETECT_PIN;
+  gpio_init_structure.Pull = GPIO_PULLUP;
+  gpio_init_structure.Speed = GPIO_SPEED_FAST;
+  gpio_init_structure.Mode = GPIO_MODE_IT_RISING_FALLING;
+  HAL_GPIO_Init(SD_DETECT_GPIO_PORT, &gpio_init_structure);
+
+  /* Enable and set SD detect EXTI Interrupt to the lowest priority */
+  HAL_NVIC_SetPriority((IRQn_Type)(SD_DETECT_EXTI_IRQn), 0x0F, 0x00);
+  HAL_NVIC_EnableIRQ((IRQn_Type)(SD_DETECT_EXTI_IRQn));
+
+  return MSD_OK;
+}
+
+/**
+  * @brief  Detects if SD card is correctly plugged in the memory slot or not.
+  * @retval Returns if SD is detected or not
+  */
+uint8_t BSP_SD_IsDetected(void)
+{
+  __IO uint8_t      status = SD_PRESENT;
+  
+  /* Check SD card detect pin */
+  if (HAL_GPIO_ReadPin(SD_DETECT_GPIO_PORT, SD_DETECT_PIN) == GPIO_PIN_SET)
+  {
+    status = SD_NOT_PRESENT;
+  }
+
+  return status;
+}
+
+/**
+  * @brief  Reads block(s) from a specified address in an SD card, in polling mode.
+  * @param  pData: Pointer to the buffer that will contain the data to transmit
+  * @param  ReadAddr: Address from where data is to be read  
+  * @param  BlockSize: SD card data block size, that should be 512
+  * @param  NumOfBlocks: Number of SD blocks to read 
+  * @retval SD status
+  */
+uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks)
+{
+  if(HAL_SD_ReadBlocks(&uSdHandle, pData, ReadAddr, BlockSize, NumOfBlocks) != SD_OK)
+  {
+    return MSD_ERROR;
+  }
+  else
+  {
+    return MSD_OK;
+  }
+}
+
+/**
+  * @brief  Writes block(s) to a specified address in an SD card, in polling mode. 
+  * @param  pData: Pointer to the buffer that will contain the data to transmit
+  * @param  WriteAddr: Address from where data is to be written  
+  * @param  BlockSize: SD card data block size, that should be 512
+  * @param  NumOfBlocks: Number of SD blocks to write
+  * @retval SD status
+  */
+uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumOfBlocks)
+{
+  if(HAL_SD_WriteBlocks(&uSdHandle, pData, WriteAddr, BlockSize, NumOfBlocks) != SD_OK)
+  {
+    return MSD_ERROR;
+  }
+  else
+  {
+    return MSD_OK;
+  }
+}
+
+/**
+  * @brief  Reads block(s) from a specified address in an SD card, in DMA mode.
+  * @param  pData: Pointer to the buffer that will contain the data to transmit
+  * @param  ReadAddr: Address from where data is to be read  
+  * @param  BlockSize: SD card data block size, that should be 512
+  * @param  NumOfBlocks: Number of SD blocks to read 
+  * @retval SD status
+  */
+uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks)
+{
+  uint8_t sd_state = MSD_OK;
+  
+  /* Read block(s) in DMA transfer mode */
+  if(HAL_SD_ReadBlocks_DMA(&uSdHandle, pData, ReadAddr, BlockSize, NumOfBlocks) != SD_OK)
+  {
+    sd_state = MSD_ERROR;
+  }
+  
+  /* Wait until transfer is complete */
+  if(sd_state == MSD_OK)
+  {
+    if(HAL_SD_CheckReadOperation(&uSdHandle, (uint32_t)SD_DATATIMEOUT) != SD_OK)
+    {
+      sd_state = MSD_ERROR;
+    }
+    else
+    {
+      sd_state = MSD_OK;
+    }
+  }
+  
+  return sd_state;
+}
+
+/**
+  * @brief  Writes block(s) to a specified address in an SD card, in DMA mode.
+  * @param  pData: Pointer to the buffer that will contain the data to transmit
+  * @param  WriteAddr: Address from where data is to be written  
+  * @param  BlockSize: SD card data block size, that should be 512
+  * @param  NumOfBlocks: Number of SD blocks to write 
+  * @retval SD status
+  */
+uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumOfBlocks)
+{
+  uint8_t sd_state = MSD_OK;
+  
+  /* Write block(s) in DMA transfer mode */
+  if(HAL_SD_WriteBlocks_DMA(&uSdHandle, pData, WriteAddr, BlockSize, NumOfBlocks) != SD_OK)
+  {
+    sd_state = MSD_ERROR;
+  }
+  
+  /* Wait until transfer is complete */
+  if(sd_state == MSD_OK)
+  {
+    if(HAL_SD_CheckWriteOperation(&uSdHandle, (uint32_t)SD_DATATIMEOUT) != SD_OK)
+    {
+      sd_state = MSD_ERROR;
+    }
+    else
+    {
+      sd_state = MSD_OK;
+    }
+  }
+  
+  return sd_state;
+}
+
+/**
+  * @brief  Erases the specified memory area of the given SD card. 
+  * @param  StartAddr: Start byte address
+  * @param  EndAddr: End byte address
+  * @retval SD status
+  */
+uint8_t BSP_SD_Erase(uint64_t StartAddr, uint64_t EndAddr)
+{
+  if(HAL_SD_Erase(&uSdHandle, StartAddr, EndAddr) != SD_OK)
+  {
+    return MSD_ERROR;
+  }
+  else
+  {
+    return MSD_OK;
+  }
+}
+
+/**
+  * @brief  Initializes the SD MSP.
+  * @param  hsd: SD handle
+  * @param  Params
+  * @retval None
+  */
+__weak void BSP_SD_MspInit(SD_HandleTypeDef *hsd, void *Params)
+{
+  static DMA_HandleTypeDef dma_rx_handle;
+  static DMA_HandleTypeDef dma_tx_handle;
+  GPIO_InitTypeDef gpio_init_structure;
+
+  /* Enable SDIO clock */
+  __HAL_RCC_SDMMC1_CLK_ENABLE();
+  
+  /* Enable DMA2 clocks */
+  __DMAx_TxRx_CLK_ENABLE();
+
+  /* Enable GPIOs clock */
+  __HAL_RCC_GPIOC_CLK_ENABLE();
+  __HAL_RCC_GPIOD_CLK_ENABLE();
+  
+  /* Common GPIO configuration */
+  gpio_init_structure.Mode      = GPIO_MODE_AF_PP;
+  gpio_init_structure.Pull      = GPIO_PULLUP;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  gpio_init_structure.Alternate = GPIO_AF12_SDMMC1;
+  
+  /* GPIOC configuration */
+  gpio_init_structure.Pin = GPIO_PIN_8 | GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11 | GPIO_PIN_12;
+  HAL_GPIO_Init(GPIOC, &gpio_init_structure);
+
+  /* GPIOD configuration */
+  gpio_init_structure.Pin = GPIO_PIN_2;
+  HAL_GPIO_Init(GPIOD, &gpio_init_structure);
+
+  /* NVIC configuration for SDIO interrupts */
+  HAL_NVIC_SetPriority(SDMMC1_IRQn, 5, 0);
+  HAL_NVIC_EnableIRQ(SDMMC1_IRQn);
+    
+  /* Configure DMA Rx parameters */
+  dma_rx_handle.Init.Channel             = SD_DMAx_Rx_CHANNEL;
+  dma_rx_handle.Init.Direction           = DMA_PERIPH_TO_MEMORY;
+  dma_rx_handle.Init.PeriphInc           = DMA_PINC_DISABLE;
+  dma_rx_handle.Init.MemInc              = DMA_MINC_ENABLE;
+  dma_rx_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+  dma_rx_handle.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
+  dma_rx_handle.Init.Mode                = DMA_PFCTRL;
+  dma_rx_handle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
+  dma_rx_handle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
+  dma_rx_handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+  dma_rx_handle.Init.MemBurst            = DMA_MBURST_INC4;
+  dma_rx_handle.Init.PeriphBurst         = DMA_PBURST_INC4;
+  
+  dma_rx_handle.Instance = SD_DMAx_Rx_STREAM;
+  
+  /* Associate the DMA handle */
+  __HAL_LINKDMA(hsd, hdmarx, dma_rx_handle);
+  
+  /* Deinitialize the stream for new transfer */
+  HAL_DMA_DeInit(&dma_rx_handle);
+  
+  /* Configure the DMA stream */
+  HAL_DMA_Init(&dma_rx_handle);
+  
+  /* Configure DMA Tx parameters */
+  dma_tx_handle.Init.Channel             = SD_DMAx_Tx_CHANNEL;
+  dma_tx_handle.Init.Direction           = DMA_MEMORY_TO_PERIPH;
+  dma_tx_handle.Init.PeriphInc           = DMA_PINC_DISABLE;
+  dma_tx_handle.Init.MemInc              = DMA_MINC_ENABLE;
+  dma_tx_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
+  dma_tx_handle.Init.MemDataAlignment    = DMA_MDATAALIGN_WORD;
+  dma_tx_handle.Init.Mode                = DMA_PFCTRL;
+  dma_tx_handle.Init.Priority            = DMA_PRIORITY_VERY_HIGH;
+  dma_tx_handle.Init.FIFOMode            = DMA_FIFOMODE_ENABLE;
+  dma_tx_handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
+  dma_tx_handle.Init.MemBurst            = DMA_MBURST_INC4;
+  dma_tx_handle.Init.PeriphBurst         = DMA_PBURST_INC4;
+  
+  dma_tx_handle.Instance = SD_DMAx_Tx_STREAM;
+  
+  /* Associate the DMA handle */
+  __HAL_LINKDMA(hsd, hdmatx, dma_tx_handle);
+  
+  /* Deinitialize the stream for new transfer */
+  HAL_DMA_DeInit(&dma_tx_handle);
+  
+  /* Configure the DMA stream */
+  HAL_DMA_Init(&dma_tx_handle); 
+  
+  /* NVIC configuration for DMA transfer complete interrupt */
+  HAL_NVIC_SetPriority(SD_DMAx_Rx_IRQn, 6, 0);
+  HAL_NVIC_EnableIRQ(SD_DMAx_Rx_IRQn);
+  
+  /* NVIC configuration for DMA transfer complete interrupt */
+  HAL_NVIC_SetPriority(SD_DMAx_Tx_IRQn, 6, 0);
+  HAL_NVIC_EnableIRQ(SD_DMAx_Tx_IRQn);
+}
+
+/**
+  * @brief  Initializes the SD Detect pin MSP.
+  * @param  hsd: SD handle
+  * @param  Params
+  * @retval None
+  */
+__weak void BSP_SD_Detect_MspInit(SD_HandleTypeDef *hsd, void *Params)
+{
+  GPIO_InitTypeDef  gpio_init_structure;
+
+  SD_DETECT_GPIO_CLK_ENABLE();
+
+  /* GPIO configuration in input for uSD_Detect signal */
+  gpio_init_structure.Pin       = SD_DETECT_PIN;
+  gpio_init_structure.Mode      = GPIO_MODE_INPUT;
+  gpio_init_structure.Pull      = GPIO_PULLUP;
+  gpio_init_structure.Speed     = GPIO_SPEED_HIGH;
+  HAL_GPIO_Init(SD_DETECT_GPIO_PORT, &gpio_init_structure);
+}
+
+/**
+  * @brief  DeInitializes the SD MSP.
+  * @param  hsd: SD handle
+  * @param  Params
+  * @retval None
+  */
+__weak void BSP_SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params)
+{
+  static DMA_HandleTypeDef dma_rx_handle;
+  static DMA_HandleTypeDef dma_tx_handle;
+
+  /* Disable NVIC for DMA transfer complete interrupts */
+  HAL_NVIC_DisableIRQ(SD_DMAx_Rx_IRQn);
+  HAL_NVIC_DisableIRQ(SD_DMAx_Tx_IRQn);
+
+  /* Deinitialize the stream for new transfer */
+  dma_rx_handle.Instance = SD_DMAx_Rx_STREAM;
+  HAL_DMA_DeInit(&dma_rx_handle);
+
+  /* Deinitialize the stream for new transfer */
+  dma_tx_handle.Instance = SD_DMAx_Tx_STREAM;
+  HAL_DMA_DeInit(&dma_tx_handle);
+
+  /* Disable NVIC for SDIO interrupts */
+  HAL_NVIC_DisableIRQ(SDMMC1_IRQn);
+
+  /* DeInit GPIO pins can be done in the application
+     (by surcharging this __weak function) */
+
+  /* Disable SDMMC1 clock */
+  __HAL_RCC_SDMMC1_CLK_DISABLE();
+
+  /* GPIO pins clock and DMA clocks can be shut down in the application
+     by surcharging this __weak function */
+}
+
+/**
+  * @brief  Handles SD card interrupt request.
+  * @retval None
+  */
+void BSP_SD_IRQHandler(void)
+{
+  HAL_SD_IRQHandler(&uSdHandle);
+}
+
+/**
+  * @brief  Handles SD DMA Tx transfer interrupt request.
+  * @retval None
+  */
+void BSP_SD_DMA_Tx_IRQHandler(void)
+{
+  HAL_DMA_IRQHandler(uSdHandle.hdmatx); 
+}
+
+/**
+  * @brief  Handles SD DMA Rx transfer interrupt request.
+  * @retval None
+  */
+void BSP_SD_DMA_Rx_IRQHandler(void)
+{
+  HAL_DMA_IRQHandler(uSdHandle.hdmarx);
+}
+
+/**
+  * @brief  Gets the current SD card data status.
+  * @retval Data transfer state.
+  *          This value can be one of the following values:
+  *            @arg  SD_TRANSFER_OK: No data transfer is acting
+  *            @arg  SD_TRANSFER_BUSY: Data transfer is acting
+  *            @arg  SD_TRANSFER_ERROR: Data transfer error 
+  */
+HAL_SD_TransferStateTypedef BSP_SD_GetStatus(void)
+{
+  return(HAL_SD_GetStatus(&uSdHandle));
+}
+
+/**
+  * @brief  Get SD information about specific SD card.
+  * @param  CardInfo: Pointer to HAL_SD_CardInfoTypedef structure
+  * @retval None 
+  */
+void BSP_SD_GetCardInfo(HAL_SD_CardInfoTypedef *CardInfo)
+{
+  /* Get SD card Information */
+  HAL_SD_Get_CardInfo(&uSdHandle, CardInfo);
+}
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+ 
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32746g_discovery_sd.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,159 @@
+/**
+  ******************************************************************************
+  * @file    stm32746g_discovery_sd.h
+  * @author  MCD Application Team
+  * @version V1.0.0
+  * @date    25-June-2015
+  * @brief   This file contains the common defines and functions prototypes for
+  *          the stm32746g_discovery_sd.c driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */ 
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __STM32746G_DISCOVERY_SD_H
+#define __STM32746G_DISCOVERY_SD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif 
+
+/* Includes ------------------------------------------------------------------*/
+#include "stm32746g_discovery.h"
+
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup STM32746G_DISCOVERY
+  * @{
+  */
+    
+/** @addtogroup STM32746G_DISCOVERY_SD
+  * @{
+  */    
+
+/** @defgroup STM32746G_DISCOVERY_SD_Exported_Types STM32746G_DISCOVERY_SD Exported Types
+  * @{
+  */
+
+/** 
+  * @brief SD Card information structure 
+  */
+#define SD_CardInfo HAL_SD_CardInfoTypedef
+/**
+  * @}
+  */
+   
+/** 
+  * @brief  SD status structure definition  
+  */     
+#define MSD_OK                        ((uint8_t)0x00)
+#define MSD_ERROR                     ((uint8_t)0x01)
+#define MSD_ERROR_SD_NOT_PRESENT      ((uint8_t)0x02)
+   
+/** @defgroup STM32746G_DISCOVERY_SD_Exported_Constants STM32746G_DISCOVERY_SD Exported Constants
+  * @{
+  */ 
+#define SD_PRESENT               ((uint8_t)0x01)
+#define SD_NOT_PRESENT           ((uint8_t)0x00)
+
+#define SD_DATATIMEOUT           ((uint32_t)100000000)
+    
+/* DMA definitions for SD DMA transfer */
+#define __DMAx_TxRx_CLK_ENABLE            __HAL_RCC_DMA2_CLK_ENABLE
+#define SD_DMAx_Tx_CHANNEL                DMA_CHANNEL_4
+#define SD_DMAx_Rx_CHANNEL                DMA_CHANNEL_4
+#define SD_DMAx_Tx_STREAM                 DMA2_Stream6  
+#define SD_DMAx_Rx_STREAM                 DMA2_Stream3  
+#define SD_DMAx_Tx_IRQn                   DMA2_Stream6_IRQn
+#define SD_DMAx_Rx_IRQn                   DMA2_Stream3_IRQn
+#define SD_DMAx_Tx_IRQHandler             DMA2_Stream6_IRQHandler   
+#define SD_DMAx_Rx_IRQHandler             DMA2_Stream3_IRQHandler 
+#define SD_DetectIRQHandler()             HAL_GPIO_EXTI_IRQHandler(SD_DETECT_PIN)
+/**
+  * @}
+  */
+  
+/** @defgroup STM32746G_DISCOVERY_SD_Exported_Macro STM32746G_DISCOVERY_SD Exported Macro
+  * @{
+  */ 
+/**
+  * @}
+  */
+   
+/** @addtogroup STM32746G_DISCOVERY_SD_Exported_Functions
+  * @{
+  */   
+uint8_t BSP_SD_Init(void);
+uint8_t BSP_SD_DeInit(void);
+uint8_t BSP_SD_ITConfig(void);
+void    BSP_SD_DetectIT(void);
+void    BSP_SD_DetectCallback(void);
+uint8_t BSP_SD_ReadBlocks(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks);
+uint8_t BSP_SD_WriteBlocks(uint32_t *pData, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumOfBlocks);
+uint8_t BSP_SD_ReadBlocks_DMA(uint32_t *pData, uint64_t ReadAddr, uint32_t BlockSize, uint32_t NumOfBlocks);
+uint8_t BSP_SD_WriteBlocks_DMA(uint32_t *pData, uint64_t WriteAddr, uint32_t BlockSize, uint32_t NumOfBlocks);
+uint8_t BSP_SD_Erase(uint64_t StartAddr, uint64_t EndAddr);
+void    BSP_SD_IRQHandler(void);
+void    BSP_SD_DMA_Tx_IRQHandler(void);
+void    BSP_SD_DMA_Rx_IRQHandler(void);
+HAL_SD_TransferStateTypedef BSP_SD_GetStatus(void);
+void    BSP_SD_GetCardInfo(HAL_SD_CardInfoTypedef *CardInfo);
+uint8_t BSP_SD_IsDetected(void);
+
+/* These functions can be modified in case the current settings (e.g. DMA stream)
+   need to be changed for specific application needs */
+void    BSP_SD_MspInit(SD_HandleTypeDef *hsd, void *Params);
+void    BSP_SD_Detect_MspInit(SD_HandleTypeDef *hsd, void *Params);
+void    BSP_SD_MspDeInit(SD_HandleTypeDef *hsd, void *Params);
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32746G_DISCOVERY_SD_H */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wm8994.c	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,924 @@
+/**
+  ******************************************************************************
+  * @file    wm8994.c
+  * @author  MCD Application Team
+  * @version V2.0.0
+  * @date    24-June-2015
+  * @brief   This file provides the WM8994 Audio Codec driver.   
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Includes ------------------------------------------------------------------*/
+#include "wm8994.h"
+
+/** @addtogroup BSP
+  * @{
+  */
+  
+/** @addtogroup Components
+  * @{
+  */ 
+
+/** @addtogroup wm8994
+  * @brief     This file provides a set of functions needed to drive the 
+  *            WM8994 audio codec.
+  * @{
+  */
+
+/** @defgroup WM8994_Private_Types
+  * @{
+  */
+
+/**
+  * @}
+  */ 
+  
+/** @defgroup WM8994_Private_Defines
+  * @{
+  */
+/* Uncomment this line to enable verifying data sent to codec after each write 
+   operation (for debug purpose) */
+#if !defined (VERIFY_WRITTENDATA)  
+/* #define VERIFY_WRITTENDATA */
+#endif /* VERIFY_WRITTENDATA */
+/**
+  * @}
+  */ 
+
+/** @defgroup WM8994_Private_Macros
+  * @{
+  */
+
+/**
+  * @}
+  */ 
+  
+/** @defgroup WM8994_Private_Variables
+  * @{
+  */
+
+/* Audio codec driver structure initialization */  
+AUDIO_DrvTypeDef wm8994_drv = 
+{
+  wm8994_Init,
+  wm8994_DeInit,
+  wm8994_ReadID,
+
+  wm8994_Play,
+  wm8994_Pause,
+  wm8994_Resume,
+  wm8994_Stop,  
+
+  wm8994_SetFrequency,
+  wm8994_SetVolume,
+  wm8994_SetMute,  
+  wm8994_SetOutputMode,
+
+  wm8994_Reset
+};
+
+static uint32_t outputEnabled = 0;
+static uint32_t inputEnabled = 0;
+/**
+  * @}
+  */ 
+
+/** @defgroup WM8994_Function_Prototypes
+  * @{
+  */
+static uint8_t CODEC_IO_Write(uint8_t Addr, uint16_t Reg, uint16_t Value);
+/**
+  * @}
+  */ 
+
+/** @defgroup WM8994_Private_Functions
+  * @{
+  */ 
+
+/**
+  * @brief Initializes the audio codec and the control interface.
+  * @param DeviceAddr: Device address on communication Bus.   
+  * @param OutputInputDevice: can be OUTPUT_DEVICE_SPEAKER, OUTPUT_DEVICE_HEADPHONE,
+  *  OUTPUT_DEVICE_BOTH, OUTPUT_DEVICE_AUTO, INPUT_DEVICE_DIGITAL_MICROPHONE_1,
+  *  INPUT_DEVICE_DIGITAL_MICROPHONE_2, INPUT_DEVICE_INPUT_LINE_1 or INPUT_DEVICE_INPUT_LINE_2.
+  * @param Volume: Initial volume level (from 0 (Mute) to 100 (Max))
+  * @param AudioFreq: Audio Frequency 
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t wm8994_Init(uint16_t DeviceAddr, uint16_t OutputInputDevice, uint8_t Volume, uint32_t AudioFreq)
+{
+  uint32_t counter = 0;
+  uint16_t output_device = OutputInputDevice & 0xFF;
+  uint16_t input_device = OutputInputDevice & 0xFF00;
+  uint16_t power_mgnt_reg_1 = 0;
+  
+  /* Initialize the Control interface of the Audio Codec */
+  AUDIO_IO_Init();
+  /* wm8994 Errata Work-Arounds */
+  counter += CODEC_IO_Write(DeviceAddr, 0x102, 0x0003);
+  counter += CODEC_IO_Write(DeviceAddr, 0x817, 0x0000);
+  counter += CODEC_IO_Write(DeviceAddr, 0x102, 0x0000);
+  
+  /* Enable VMID soft start (fast), Start-up Bias Current Enabled */
+  counter += CODEC_IO_Write(DeviceAddr, 0x39, 0x006C);
+  
+  /* Enable bias generator, Enable VMID */
+  counter += CODEC_IO_Write(DeviceAddr, 0x01, 0x0003);
+  
+  /* Add Delay */
+  AUDIO_IO_Delay(50);
+
+  /* Path Configurations for output */
+  if (output_device > 0)
+  {
+    outputEnabled = 1;
+    switch (output_device)
+    {
+    case OUTPUT_DEVICE_SPEAKER:
+      /* Enable DAC1 (Left), Enable DAC1 (Right),
+      Disable DAC2 (Left), Disable DAC2 (Right)*/
+      counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0C0C);
+
+      /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0000);
+
+      /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0000);
+
+      /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0002);
+
+      /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0002);
+      break;
+
+    case OUTPUT_DEVICE_HEADPHONE:
+      /* Disable DAC1 (Left), Disable DAC1 (Right),
+      Enable DAC2 (Left), Enable DAC2 (Right)*/
+      counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303);
+
+      /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001);
+
+      /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001);
+
+      /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0000);
+
+      /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0000);
+      break;
+
+    case OUTPUT_DEVICE_BOTH:
+      /* Enable DAC1 (Left), Enable DAC1 (Right),
+      also Enable DAC2 (Left), Enable DAC2 (Right)*/
+      counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303 | 0x0C0C);
+
+      /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001);
+
+      /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001);
+
+      /* Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0002);
+
+      /* Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0002);
+      break;
+
+    case OUTPUT_DEVICE_AUTO :
+    default:
+      /* Disable DAC1 (Left), Disable DAC1 (Right),
+      Enable DAC2 (Left), Enable DAC2 (Right)*/
+      counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303);
+
+      /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001);
+
+      /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001);
+
+      /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0000);
+
+      /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0000);
+      break;
+    }
+  }
+  else
+  {
+    outputEnabled = 0;
+  }
+
+  /* Path Configurations for input */
+  if (input_device > 0)
+  {
+    inputEnabled = 1;
+    switch (input_device)
+    {
+    case INPUT_DEVICE_DIGITAL_MICROPHONE_2 :
+      /* Enable AIF1ADC2 (Left), Enable AIF1ADC2 (Right)
+       * Enable DMICDAT2 (Left), Enable DMICDAT2 (Right)
+       * Enable Left ADC, Enable Right ADC */
+      counter += CODEC_IO_Write(DeviceAddr, 0x04, 0x0C30);
+
+      /* Enable AIF1 DRC2 Signal Detect & DRC in AIF1ADC2 Left/Right Timeslot 1 */
+      counter += CODEC_IO_Write(DeviceAddr, 0x450, 0x00DB);
+
+      /* Disable IN1L, IN1R, IN2L, IN2R, Enable Thermal sensor & shutdown */
+      counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x6000);
+
+      /* Enable the DMIC2(Left) to AIF1 Timeslot 1 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x608, 0x0002);
+
+      /* Enable the DMIC2(Right) to AIF1 Timeslot 1 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x609, 0x0002);
+
+      /* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC2 signal detect */
+      counter += CODEC_IO_Write(DeviceAddr, 0x700, 0x000E);
+      break;
+
+    case INPUT_DEVICE_INPUT_LINE_1 :
+      /* Enable AIF1ADC1 (Left), Enable AIF1ADC1 (Right)
+       * Enable Left ADC, Enable Right ADC */
+      counter += CODEC_IO_Write(DeviceAddr, 0x04, 0x0303);
+
+      /* Enable AIF1 DRC1 Signal Detect & DRC in AIF1ADC1 Left/Right Timeslot 0 */
+      counter += CODEC_IO_Write(DeviceAddr, 0x440, 0x00DB);
+
+      /* Enable IN1L and IN1R, Disable IN2L and IN2R, Enable Thermal sensor & shutdown */
+      counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x6350);
+
+      /* Enable the ADCL(Left) to AIF1 Timeslot 0 (Left) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x606, 0x0002);
+
+      /* Enable the ADCR(Right) to AIF1 Timeslot 0 (Right) mixer path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x607, 0x0002);
+
+      /* GPIO1 pin configuration GP1_DIR = output, GP1_FN = AIF1 DRC1 signal detect */
+      counter += CODEC_IO_Write(DeviceAddr, 0x700, 0x000D);
+      break;
+
+    case INPUT_DEVICE_DIGITAL_MICROPHONE_1 :
+    case INPUT_DEVICE_INPUT_LINE_2 :
+    default:
+      /* Actually, no other input devices supported */
+      counter++;
+      break;
+    }
+  }
+  else
+  {
+    inputEnabled = 0;
+  }
+  
+  /*  Clock Configurations */
+  switch (AudioFreq)
+  {
+  case  AUDIO_FREQUENCY_8K:
+    /* AIF1 Sample Rate = 8 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0003);
+    break;
+    
+  case  AUDIO_FREQUENCY_16K:
+    /* AIF1 Sample Rate = 16 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0033);
+    break;
+    
+  case  AUDIO_FREQUENCY_48K:
+    /* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0083);
+    break;
+    
+  case  AUDIO_FREQUENCY_96K:
+    /* AIF1 Sample Rate = 96 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x00A3);
+    break;
+    
+  case  AUDIO_FREQUENCY_11K:
+    /* AIF1 Sample Rate = 11.025 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0013);
+    break;
+    
+  case  AUDIO_FREQUENCY_22K:
+    /* AIF1 Sample Rate = 22.050 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0043);
+    break;
+    
+  case  AUDIO_FREQUENCY_44K:
+    /* AIF1 Sample Rate = 44.1 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0073);
+    break; 
+    
+  default:
+    /* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0083);
+    break; 
+  }
+  /* AIF1 Word Length = 16-bits, AIF1 Format = I2S (Default Register Value) */
+  counter += CODEC_IO_Write(DeviceAddr, 0x300, 0x4010);
+  
+  /* slave mode */
+  counter += CODEC_IO_Write(DeviceAddr, 0x302, 0x0000);
+  
+  /* Enable the DSP processing clock for AIF1, Enable the core clock */
+  counter += CODEC_IO_Write(DeviceAddr, 0x208, 0x000A);
+  
+  /* Enable AIF1 Clock, AIF1 Clock Source = MCLK1 pin */
+  counter += CODEC_IO_Write(DeviceAddr, 0x200, 0x0001);
+
+  if (output_device > 0)  /* Audio output selected */
+  {
+    /* Analog Output Configuration */
+
+    /* Enable SPKRVOL PGA, Enable SPKMIXR, Enable SPKLVOL PGA, Enable SPKMIXL */
+    counter += CODEC_IO_Write(DeviceAddr, 0x03, 0x0300);
+
+    /* Left Speaker Mixer Volume = 0dB */
+    counter += CODEC_IO_Write(DeviceAddr, 0x22, 0x0000);
+
+    /* Speaker output mode = Class D, Right Speaker Mixer Volume = 0dB ((0x23, 0x0100) = class AB)*/
+    counter += CODEC_IO_Write(DeviceAddr, 0x23, 0x0000);
+
+    /* Unmute DAC2 (Left) to Left Speaker Mixer (SPKMIXL) path,
+    Unmute DAC2 (Right) to Right Speaker Mixer (SPKMIXR) path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x36, 0x0300);
+
+    /* Enable bias generator, Enable VMID, Enable SPKOUTL, Enable SPKOUTR */
+    counter += CODEC_IO_Write(DeviceAddr, 0x01, 0x3003);
+
+    /* Headphone/Speaker Enable */
+
+    /* Enable Class W, Class W Envelope Tracking = AIF1 Timeslot 0 */
+    counter += CODEC_IO_Write(DeviceAddr, 0x51, 0x0005);
+
+    /* Enable bias generator, Enable VMID, Enable HPOUT1 (Left) and Enable HPOUT1 (Right) input stages */
+    /* idem for Speaker */
+    power_mgnt_reg_1 |= 0x0303 | 0x3003;
+    counter += CODEC_IO_Write(DeviceAddr, 0x01, power_mgnt_reg_1);
+
+    /* Enable HPOUT1 (Left) and HPOUT1 (Right) intermediate stages */
+    counter += CODEC_IO_Write(DeviceAddr, 0x60, 0x0022);
+
+    /* Enable Charge Pump */
+    counter += CODEC_IO_Write(DeviceAddr, 0x4C, 0x9F25);
+
+    /* Add Delay */
+    AUDIO_IO_Delay(15);
+
+    /* Select DAC1 (Left) to Left Headphone Output PGA (HPOUT1LVOL) path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x2D, 0x0001);
+
+    /* Select DAC1 (Right) to Right Headphone Output PGA (HPOUT1RVOL) path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x2E, 0x0001);
+
+    /* Enable Left Output Mixer (MIXOUTL), Enable Right Output Mixer (MIXOUTR) */
+    /* idem for SPKOUTL and SPKOUTR */
+    counter += CODEC_IO_Write(DeviceAddr, 0x03, 0x0030 | 0x0300);
+
+    /* Enable DC Servo and trigger start-up mode on left and right channels */
+    counter += CODEC_IO_Write(DeviceAddr, 0x54, 0x0033);
+
+    /* Add Delay */
+    AUDIO_IO_Delay(250);
+
+    /* Enable HPOUT1 (Left) and HPOUT1 (Right) intermediate and output stages. Remove clamps */
+    counter += CODEC_IO_Write(DeviceAddr, 0x60, 0x00EE);
+
+    /* Unmutes */
+
+    /* Unmute DAC 1 (Left) */
+    counter += CODEC_IO_Write(DeviceAddr, 0x610, 0x00C0);
+
+    /* Unmute DAC 1 (Right) */
+    counter += CODEC_IO_Write(DeviceAddr, 0x611, 0x00C0);
+
+    /* Unmute the AIF1 Timeslot 0 DAC path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x420, 0x0000);
+
+    /* Unmute DAC 2 (Left) */
+    counter += CODEC_IO_Write(DeviceAddr, 0x612, 0x00C0);
+
+    /* Unmute DAC 2 (Right) */
+    counter += CODEC_IO_Write(DeviceAddr, 0x613, 0x00C0);
+
+    /* Unmute the AIF1 Timeslot 1 DAC2 path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x422, 0x0000);
+    
+    /* Volume Control */
+    wm8994_SetVolume(DeviceAddr, Volume);
+  }
+
+  if (input_device > 0) /* Audio input selected */
+  {
+    if ((input_device == INPUT_DEVICE_DIGITAL_MICROPHONE_1) || (input_device == INPUT_DEVICE_DIGITAL_MICROPHONE_2))
+    {
+      /* Enable Microphone bias 1 generator, Enable VMID */
+      power_mgnt_reg_1 |= 0x0013;
+      counter += CODEC_IO_Write(DeviceAddr, 0x01, power_mgnt_reg_1);
+
+      /* ADC oversample enable */
+      counter += CODEC_IO_Write(DeviceAddr, 0x620, 0x0002);
+
+      /* AIF ADC2 HPF enable, HPF cut = voice mode 1 fc=127Hz at fs=8kHz */
+      counter += CODEC_IO_Write(DeviceAddr, 0x411, 0x3800);
+    }
+    else if ((input_device == INPUT_DEVICE_INPUT_LINE_1) || (input_device == INPUT_DEVICE_INPUT_LINE_2))
+    {
+      /* Enable normal bias generator, Enable VMID */
+      power_mgnt_reg_1 |= 0x0003;
+      counter += CODEC_IO_Write(DeviceAddr, 0x01, power_mgnt_reg_1);
+
+      /* Disable mute on IN1L, IN1L Volume = +0dB */
+      counter += CODEC_IO_Write(DeviceAddr, 0x18, 0x000B);
+
+      /* Disable mute on IN1R, IN1R Volume = +0dB */
+      counter += CODEC_IO_Write(DeviceAddr, 0x1A, 0x000B);
+
+      /* Disable mute on IN1L_TO_MIXINL, Gain = +0dB */
+      counter += CODEC_IO_Write(DeviceAddr, 0x29, 0x0025);
+
+      /* Disable mute on IN1R_TO_MIXINL, Gain = +0dB */
+      counter += CODEC_IO_Write(DeviceAddr, 0x2A, 0x0025);
+
+      /* IN1LN_TO_IN1L, IN1LP_TO_VMID, IN1RN_TO_IN1R, IN1RP_TO_VMID */
+      counter += CODEC_IO_Write(DeviceAddr, 0x28, 0x0011);
+
+      /* AIF ADC1 HPF enable, HPF cut = hifi mode fc=4Hz at fs=48kHz */
+      counter += CODEC_IO_Write(DeviceAddr, 0x410, 0x1800);
+    }
+    /* Volume Control */
+    wm8994_SetVolume(DeviceAddr, Volume);
+  }
+  /* Return communication control value */
+  return counter;  
+}
+
+/**
+  * @brief  Deinitializes the audio codec.
+  * @param  None
+  * @retval  None
+  */
+void wm8994_DeInit(void)
+{
+  /* Deinitialize Audio Codec interface */
+  AUDIO_IO_DeInit();
+}
+
+/**
+  * @brief  Get the WM8994 ID.
+  * @param DeviceAddr: Device address on communication Bus.
+  * @retval The WM8994 ID 
+  */
+uint32_t wm8994_ReadID(uint16_t DeviceAddr)
+{
+  /* Initialize the Control interface of the Audio Codec */
+  AUDIO_IO_Init();
+
+  return ((uint32_t)AUDIO_IO_Read(DeviceAddr, WM8994_CHIPID_ADDR));
+}
+
+/**
+  * @brief Start the audio Codec play feature.
+  * @note For this codec no Play options are required.
+  * @param DeviceAddr: Device address on communication Bus.   
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t wm8994_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size)
+{
+  uint32_t counter = 0;
+ 
+  /* Resumes the audio file playing */  
+  /* Unmute the output first */
+  counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
+  
+  return counter;
+}
+
+/**
+  * @brief Pauses playing on the audio codec.
+  * @param DeviceAddr: Device address on communication Bus. 
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t wm8994_Pause(uint16_t DeviceAddr)
+{  
+  uint32_t counter = 0;
+ 
+  /* Pause the audio file playing */
+  /* Mute the output first */
+  counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_ON);
+  
+  /* Put the Codec in Power save mode */
+  counter += CODEC_IO_Write(DeviceAddr, 0x02, 0x01);
+ 
+  return counter;
+}
+
+/**
+  * @brief Resumes playing on the audio codec.
+  * @param DeviceAddr: Device address on communication Bus. 
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t wm8994_Resume(uint16_t DeviceAddr)
+{
+  uint32_t counter = 0;
+ 
+  /* Resumes the audio file playing */  
+  /* Unmute the output first */
+  counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
+  
+  return counter;
+}
+
+/**
+  * @brief Stops audio Codec playing. It powers down the codec.
+  * @param DeviceAddr: Device address on communication Bus. 
+  * @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
+  */
+uint32_t wm8994_Stop(uint16_t DeviceAddr, uint32_t CodecPdwnMode)
+{
+  uint32_t counter = 0;
+
+  if (outputEnabled != 0)
+  {
+    /* Mute the output first */
+    counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_ON);
+
+    if (CodecPdwnMode == CODEC_PDWN_SW)
+    {
+       /* Only output mute required*/
+    }
+    else /* CODEC_PDWN_HW */
+    {
+      /* Mute the AIF1 Timeslot 0 DAC1 path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x420, 0x0200);
+
+      /* Mute the AIF1 Timeslot 1 DAC2 path */
+      counter += CODEC_IO_Write(DeviceAddr, 0x422, 0x0200);
+
+      /* Disable DAC1L_TO_HPOUT1L */
+      counter += CODEC_IO_Write(DeviceAddr, 0x2D, 0x0000);
+
+      /* Disable DAC1R_TO_HPOUT1R */
+      counter += CODEC_IO_Write(DeviceAddr, 0x2E, 0x0000);
+
+      /* Disable DAC1 and DAC2 */
+      counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0000);
+
+      /* Reset Codec by writing in 0x0000 address register */
+      counter += CODEC_IO_Write(DeviceAddr, 0x0000, 0x0000);
+
+      outputEnabled = 0;
+    }
+  }
+  return counter;
+}
+
+/**
+  * @brief Sets higher or lower the codec volume level.
+  * @param DeviceAddr: Device address on communication Bus.
+  * @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
+  */
+uint32_t wm8994_SetVolume(uint16_t DeviceAddr, uint8_t Volume)
+{
+  uint32_t counter = 0;
+  uint8_t convertedvol = VOLUME_CONVERT(Volume);
+
+  /* Output volume */
+  if (outputEnabled != 0)
+  {
+    if(convertedvol > 0x3E)
+    {
+      /* Unmute audio codec */
+      counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
+
+      /* Left Headphone Volume */
+      counter += CODEC_IO_Write(DeviceAddr, 0x1C, 0x3F | 0x140);
+
+      /* Right Headphone Volume */
+      counter += CODEC_IO_Write(DeviceAddr, 0x1D, 0x3F | 0x140);
+
+      /* Left Speaker Volume */
+      counter += CODEC_IO_Write(DeviceAddr, 0x26, 0x3F | 0x140);
+
+      /* Right Speaker Volume */
+      counter += CODEC_IO_Write(DeviceAddr, 0x27, 0x3F | 0x140);
+    }
+    else if (Volume == 0)
+    {
+      /* Mute audio codec */
+      counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_ON);
+    }
+    else
+    {
+      /* Unmute audio codec */
+      counter += wm8994_SetMute(DeviceAddr, AUDIO_MUTE_OFF);
+
+      /* Left Headphone Volume */
+      counter += CODEC_IO_Write(DeviceAddr, 0x1C, convertedvol | 0x140);
+
+      /* Right Headphone Volume */
+      counter += CODEC_IO_Write(DeviceAddr, 0x1D, convertedvol | 0x140);
+
+      /* Left Speaker Volume */
+      counter += CODEC_IO_Write(DeviceAddr, 0x26, convertedvol | 0x140);
+
+      /* Right Speaker Volume */
+      counter += CODEC_IO_Write(DeviceAddr, 0x27, convertedvol | 0x140);
+    }
+  }
+
+  /* Input volume */
+  if (inputEnabled != 0)
+  {
+    convertedvol = VOLUME_IN_CONVERT(Volume);
+
+    /* Left AIF1 ADC1 volume */
+    counter += CODEC_IO_Write(DeviceAddr, 0x400, convertedvol | 0x100);
+
+    /* Right AIF1 ADC1 volume */
+    counter += CODEC_IO_Write(DeviceAddr, 0x401, convertedvol | 0x100);
+
+    /* Left AIF1 ADC2 volume */
+    counter += CODEC_IO_Write(DeviceAddr, 0x404, convertedvol | 0x100);
+
+    /* Right AIF1 ADC2 volume */
+    counter += CODEC_IO_Write(DeviceAddr, 0x405, convertedvol | 0x100);
+  }
+  return counter;
+}
+
+/**
+  * @brief Enables or disables the mute feature on the audio codec.
+  * @param DeviceAddr: Device address on communication Bus.   
+  * @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
+  */
+uint32_t wm8994_SetMute(uint16_t DeviceAddr, uint32_t Cmd)
+{
+  uint32_t counter = 0;
+  
+  if (outputEnabled != 0)
+  {
+    /* Set the Mute mode */
+    if(Cmd == AUDIO_MUTE_ON)
+    {
+      /* Soft Mute the AIF1 Timeslot 0 DAC1 path L&R */
+      counter += CODEC_IO_Write(DeviceAddr, 0x420, 0x0200);
+
+      /* Soft Mute the AIF1 Timeslot 1 DAC2 path L&R */
+      counter += CODEC_IO_Write(DeviceAddr, 0x422, 0x0200);
+    }
+    else /* AUDIO_MUTE_OFF Disable the Mute */
+    {
+      /* Unmute the AIF1 Timeslot 0 DAC1 path L&R */
+      counter += CODEC_IO_Write(DeviceAddr, 0x420, 0x0000);
+
+      /* Unmute the AIF1 Timeslot 1 DAC2 path L&R */
+      counter += CODEC_IO_Write(DeviceAddr, 0x422, 0x0000);
+    }
+  }
+  return counter;
+}
+
+/**
+  * @brief Switch dynamically (while audio file is played) the output target 
+  *         (speaker or headphone).
+  * @param DeviceAddr: Device address on communication Bus.
+  * @param Output: specifies the audio output target: OUTPUT_DEVICE_SPEAKER,
+  *         OUTPUT_DEVICE_HEADPHONE, OUTPUT_DEVICE_BOTH or OUTPUT_DEVICE_AUTO 
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t wm8994_SetOutputMode(uint16_t DeviceAddr, uint8_t Output)
+{
+  uint32_t counter = 0; 
+  
+  switch (Output) 
+  {
+  case OUTPUT_DEVICE_SPEAKER:
+    /* Enable DAC1 (Left), Enable DAC1 (Right), 
+    Disable DAC2 (Left), Disable DAC2 (Right)*/
+    counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0C0C);
+    
+    /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0000);
+    
+    /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0000);
+    
+    /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0002);
+    
+    /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0002);
+    break;
+    
+  case OUTPUT_DEVICE_HEADPHONE:
+    /* Disable DAC1 (Left), Disable DAC1 (Right), 
+    Enable DAC2 (Left), Enable DAC2 (Right)*/
+    counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303);
+    
+    /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001);
+    
+    /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001);
+    
+    /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0000);
+    
+    /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0000);
+    break;
+    
+  case OUTPUT_DEVICE_BOTH:
+    /* Enable DAC1 (Left), Enable DAC1 (Right), 
+    also Enable DAC2 (Left), Enable DAC2 (Right)*/
+    counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303 | 0x0C0C);
+    
+    /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001);
+    
+    /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001);
+    
+    /* Enable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0002);
+    
+    /* Enable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0002);
+    break;
+    
+  default:
+    /* Disable DAC1 (Left), Disable DAC1 (Right), 
+    Enable DAC2 (Left), Enable DAC2 (Right)*/
+    counter += CODEC_IO_Write(DeviceAddr, 0x05, 0x0303);
+    
+    /* Enable the AIF1 Timeslot 0 (Left) to DAC 1 (Left) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x601, 0x0001);
+    
+    /* Enable the AIF1 Timeslot 0 (Right) to DAC 1 (Right) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x602, 0x0001);
+    
+    /* Disable the AIF1 Timeslot 1 (Left) to DAC 2 (Left) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x604, 0x0000);
+    
+    /* Disable the AIF1 Timeslot 1 (Right) to DAC 2 (Right) mixer path */
+    counter += CODEC_IO_Write(DeviceAddr, 0x605, 0x0000);
+    break;    
+  }  
+  return counter;
+}
+
+/**
+  * @brief Sets new frequency.
+  * @param DeviceAddr: Device address on communication Bus.
+  * @param AudioFreq: Audio frequency used to play the audio stream.
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t wm8994_SetFrequency(uint16_t DeviceAddr, uint32_t AudioFreq)
+{
+  uint32_t counter = 0;
+ 
+  /*  Clock Configurations */
+  switch (AudioFreq)
+  {
+  case  AUDIO_FREQUENCY_8K:
+    /* AIF1 Sample Rate = 8 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0003);
+    break;
+    
+  case  AUDIO_FREQUENCY_16K:
+    /* AIF1 Sample Rate = 16 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0033);
+    break;
+    
+  case  AUDIO_FREQUENCY_48K:
+    /* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0083);
+    break;
+    
+  case  AUDIO_FREQUENCY_96K:
+    /* AIF1 Sample Rate = 96 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x00A3);
+    break;
+    
+  case  AUDIO_FREQUENCY_11K:
+    /* AIF1 Sample Rate = 11.025 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0013);
+    break;
+    
+  case  AUDIO_FREQUENCY_22K:
+    /* AIF1 Sample Rate = 22.050 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0043);
+    break;
+    
+  case  AUDIO_FREQUENCY_44K:
+    /* AIF1 Sample Rate = 44.1 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0073);
+    break; 
+    
+  default:
+    /* AIF1 Sample Rate = 48 (KHz), ratio=256 */ 
+    counter += CODEC_IO_Write(DeviceAddr, 0x210, 0x0083);
+    break; 
+  }
+  return counter;
+}
+
+/**
+  * @brief Resets wm8994 registers.
+  * @param DeviceAddr: Device address on communication Bus. 
+  * @retval 0 if correct communication, else wrong communication
+  */
+uint32_t wm8994_Reset(uint16_t DeviceAddr)
+{
+  uint32_t counter = 0;
+  
+  /* Reset Codec by writing in 0x0000 address register */
+  counter = CODEC_IO_Write(DeviceAddr, 0x0000, 0x0000);
+  outputEnabled = 0;
+  inputEnabled=0;
+
+  return counter;
+}
+
+/**
+  * @brief  Writes/Read a single data.
+  * @param  Addr: I2C address
+  * @param  Reg: Reg address 
+  * @param  Value: Data to be written
+  * @retval None
+  */
+static uint8_t CODEC_IO_Write(uint8_t Addr, uint16_t Reg, uint16_t Value)
+{
+  uint32_t result = 0;
+  
+ AUDIO_IO_Write(Addr, Reg, Value);
+  
+#ifdef VERIFY_WRITTENDATA
+  /* Verify that the data has been correctly written */
+  result = (AUDIO_IO_Read(Addr, Reg) == Value)? 0:1;
+#endif /* VERIFY_WRITTENDATA */
+  
+  return result;
+}
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wm8994.h	Mon Jan 04 15:19:15 2016 +0000
@@ -0,0 +1,187 @@
+/**
+  ******************************************************************************
+  * @file    wm8994.h
+  * @author  MCD Application Team
+  * @version V2.0.0
+  * @date    24-June-2015
+  * @brief   This file contains all the functions prototypes for the 
+  *          wm8994.c driver.
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2015 STMicroelectronics</center></h2>
+  *
+  * Redistribution and use in source and binary forms, with or without modification,
+  * are permitted provided that the following conditions are met:
+  *   1. Redistributions of source code must retain the above copyright notice,
+  *      this list of conditions and the following disclaimer.
+  *   2. Redistributions in binary form must reproduce the above copyright notice,
+  *      this list of conditions and the following disclaimer in the documentation
+  *      and/or other materials provided with the distribution.
+  *   3. Neither the name of STMicroelectronics nor the names of its contributors
+  *      may be used to endorse or promote products derived from this software
+  *      without specific prior written permission.
+  *
+  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  *
+  ******************************************************************************
+  */
+
+/* Define to prevent recursive inclusion -------------------------------------*/
+#ifndef __WM8994_H
+#define __WM8994_H
+
+/* Includes ------------------------------------------------------------------*/
+#include "audio.h"
+
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup Component
+  * @{
+  */ 
+  
+/** @addtogroup WM8994
+  * @{
+  */
+
+/** @defgroup WM8994_Exported_Types
+  * @{
+  */
+
+/**
+  * @}
+  */
+
+/** @defgroup WM8994_Exported_Constants
+  * @{
+  */ 
+
+/******************************************************************************/
+/***************************  Codec User defines ******************************/
+/******************************************************************************/
+/* Codec output DEVICE */
+#define OUTPUT_DEVICE_SPEAKER                 ((uint16_t)0x0001)
+#define OUTPUT_DEVICE_HEADPHONE               ((uint16_t)0x0002)
+#define OUTPUT_DEVICE_BOTH                    ((uint16_t)0x0003)
+#define OUTPUT_DEVICE_AUTO                    ((uint16_t)0x0004)
+#define INPUT_DEVICE_DIGITAL_MICROPHONE_1     ((uint16_t)0x0100)
+#define INPUT_DEVICE_DIGITAL_MICROPHONE_2     ((uint16_t)0x0200)
+#define INPUT_DEVICE_INPUT_LINE_1             ((uint16_t)0x0300)
+#define INPUT_DEVICE_INPUT_LINE_2             ((uint16_t)0x0400)
+
+/* 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
+
+/* AUDIO FREQUENCY */
+#define AUDIO_FREQUENCY_192K          ((uint32_t)192000)
+#define AUDIO_FREQUENCY_96K           ((uint32_t)96000)
+#define AUDIO_FREQUENCY_48K           ((uint32_t)48000)
+#define AUDIO_FREQUENCY_44K           ((uint32_t)44100)
+#define AUDIO_FREQUENCY_32K           ((uint32_t)32000)
+#define AUDIO_FREQUENCY_22K           ((uint32_t)22050)
+#define AUDIO_FREQUENCY_16K           ((uint32_t)16000)
+#define AUDIO_FREQUENCY_11K           ((uint32_t)11025)
+#define AUDIO_FREQUENCY_8K            ((uint32_t)8000)  
+
+#define VOLUME_CONVERT(Volume)        (((Volume) > 100)? 100:((uint8_t)(((Volume) * 63) / 100)))
+#define VOLUME_IN_CONVERT(Volume)     (((Volume) >= 100)? 239:((uint8_t)(((Volume) * 240) / 100)))
+
+/******************************************************************************/
+/****************************** REGISTER MAPPING ******************************/
+/******************************************************************************/
+/** 
+  * @brief  WM8994 ID  
+  */  
+#define  WM8994_ID    0x8994
+
+/**
+  * @brief Device ID Register: Reading from this register will indicate device 
+  *                            family ID 8994h
+  */
+#define WM8994_CHIPID_ADDR                  0x00
+
+/**
+  * @}
+  */ 
+
+/** @defgroup WM8994_Exported_Macros
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+/** @defgroup WM8994_Exported_Functions
+  * @{
+  */
+    
+/*------------------------------------------------------------------------------
+                           Audio Codec functions 
+------------------------------------------------------------------------------*/
+/* High Layer codec functions */
+uint32_t wm8994_Init(uint16_t DeviceAddr, uint16_t OutputInputDevice, uint8_t Volume, uint32_t AudioFreq);
+void     wm8994_DeInit(void);
+uint32_t wm8994_ReadID(uint16_t DeviceAddr);
+uint32_t wm8994_Play(uint16_t DeviceAddr, uint16_t* pBuffer, uint16_t Size);
+uint32_t wm8994_Pause(uint16_t DeviceAddr);
+uint32_t wm8994_Resume(uint16_t DeviceAddr);
+uint32_t wm8994_Stop(uint16_t DeviceAddr, uint32_t Cmd);
+uint32_t wm8994_SetVolume(uint16_t DeviceAddr, uint8_t Volume);
+uint32_t wm8994_SetMute(uint16_t DeviceAddr, uint32_t Cmd);
+uint32_t wm8994_SetOutputMode(uint16_t DeviceAddr, uint8_t Output);
+uint32_t wm8994_SetFrequency(uint16_t DeviceAddr, uint32_t AudioFreq);
+uint32_t wm8994_Reset(uint16_t DeviceAddr);
+
+/* AUDIO IO functions */
+void    AUDIO_IO_Init(void);
+void    AUDIO_IO_DeInit(void);
+void    AUDIO_IO_Write(uint8_t Addr, uint16_t Reg, uint16_t Value);
+uint8_t AUDIO_IO_Read(uint8_t Addr, uint16_t Reg);
+void    AUDIO_IO_Delay(uint32_t Delay);
+
+/* Audio driver structure */
+extern AUDIO_DrvTypeDef   wm8994_drv;
+
+#endif /* __WM8994_H */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */ 
+
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/