STM32746G-Discovery board drivers V1.0.0
Dependents: F746_SD_GraphicEqualizer_ren0620
Fork of BSP_DISCO_F746NG by
Revision 1:ee089790cdbb, committed 2016-01-04
- 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
--- /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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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>© 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, ®, 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, ®, 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, ®, 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>© 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>© 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>© 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>© 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>© 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****/
