A demo application for HXC900 LoRaWAN module using Nucleo-L053R8.

Dependencies:   mbed

Revision:
0:a0c5877bd360
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stm32l0xx_nucleo.c	Thu Jul 12 00:50:48 2018 +0000
@@ -0,0 +1,942 @@
+/**
+  ******************************************************************************
+  * @file    stm32l0xx_nucleo.c
+  * @author  MCD Application Team
+  * @version V2.1.0
+  * @date    25-November-2016
+  * @brief   This file provides set of firmware functions to manage:
+  *          - LEDs and push-button available on STM32L0XX-Nucleo Kit 
+  *            from STMicroelectronics
+  *          - LCD, joystick and microSD available on Adafruit 1.8" TFT LCD 
+  *            shield (reference ID 802)
+  ******************************************************************************
+  * @attention
+  *
+  * <h2><center>&copy; COPYRIGHT(c) 2016 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 "stm32l0xx_nucleo.h"
+
+/** @addtogroup BSP
+  * @{
+  */ 
+
+/** @addtogroup STM32L0XX_NUCLEO
+  * @{
+  */   
+    
+/** @addtogroup STM32L0XX_NUCLEO_LOW_LEVEL 
+  * @brief This file provides set of firmware functions to manage Leds and push-button
+  *        available on STM32L0XX-Nucleo Kit from STMicroelectronics.
+  * @{
+  */ 
+
+/** @defgroup STM32L0XX_NUCLEO_LOW_LEVEL_Private_TypesDefinitions Private Types Definitions
+  * @{
+  */ 
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32L0XX_NUCLEO_LOW_LEVEL_Private_Defines Private Defines
+  * @{
+  */ 
+
+/**
+  * @brief STM32L0XX NUCLEO BSP Driver version number V2.1.0
+  */
+#define __STM32L0XX_NUCLEO_BSP_VERSION_MAIN   (0x02) /*!< [31:24] main version */
+#define __STM32L0XX_NUCLEO_BSP_VERSION_SUB1   (0x01) /*!< [23:16] sub1 version */
+#define __STM32L0XX_NUCLEO_BSP_VERSION_SUB2   (0x00) /*!< [15:8]  sub2 version */
+#define __STM32L0XX_NUCLEO_BSP_VERSION_RC     (0x00) /*!< [7:0]  release candidate */
+#define __STM32L0XX_NUCLEO_BSP_VERSION         ((__STM32L0XX_NUCLEO_BSP_VERSION_MAIN << 24)\
+                                             |(__STM32L0XX_NUCLEO_BSP_VERSION_SUB1 << 16)\
+                                             |(__STM32L0XX_NUCLEO_BSP_VERSION_SUB2 << 8 )\
+                                             |(__STM32L0XX_NUCLEO_BSP_VERSION_RC))
+
+/**
+  * @brief LINK SD Card
+  */
+#define SD_DUMMY_BYTE            0xFF    
+#define SD_NO_RESPONSE_EXPECTED  0x80
+
+/**
+  * @}
+  */ 
+
+
+/** @defgroup STM32L0XX_NUCLEO_LOW_LEVEL_Private_Variables Private Variables
+  * @{
+  */ 
+GPIO_TypeDef* LED_PORT[LEDn] = {LED2_GPIO_PORT};
+
+const uint16_t LED_PIN[LEDn] = {LED2_PIN};
+                                
+GPIO_TypeDef* BUTTON_PORT[BUTTONn] = {USER_BUTTON_GPIO_PORT }; 
+const uint16_t BUTTON_PIN[BUTTONn] = {USER_BUTTON_PIN }; 
+const uint8_t BUTTON_IRQn[BUTTONn] = {USER_BUTTON_EXTI_IRQn };
+
+/**
+ * @brief BUS variables
+ */
+
+#ifdef HAL_SPI_MODULE_ENABLED
+uint32_t SpixTimeout = NUCLEO_SPIx_TIMEOUT_MAX; /*<! Value of Timeout when SPI communication fails */
+static SPI_HandleTypeDef hnucleo_Spi;
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+static ADC_HandleTypeDef hnucleo_Adc;
+/* ADC channel configuration structure declaration */
+static ADC_ChannelConfTypeDef sConfig;
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32L0XX_NUCLEO_LOW_LEVEL_Private_FunctionPrototypes Private Function Prototypes
+  * @{
+  */ 
+#ifdef HAL_SPI_MODULE_ENABLED
+static void               SPIx_Init(void);
+static void               SPIx_Write(uint8_t Value);
+static void               SPIx_WriteData(uint8_t *DataIn, uint16_t DataLength);
+static void               SPIx_WriteReadData(const uint8_t *DataIn, uint8_t *DataOut, uint16_t DataLegnth);
+static void               SPIx_Error (void);
+static void               SPIx_MspInit(void);
+
+/* SD IO functions */
+void                      SD_IO_Init(void);
+void                      SD_IO_CSState(uint8_t state);
+void                      SD_IO_WriteReadData(const uint8_t *DataIn, uint8_t *DataOut, uint16_t DataLength);
+void                      SD_IO_ReadData(uint8_t *DataOut, uint16_t DataLength);
+void                      SD_IO_WriteData(const uint8_t *Data, uint16_t DataLength);
+uint8_t                   SD_IO_WriteByte(uint8_t Data);
+uint8_t                   SD_IO_ReadByte(void);
+
+/* LCD IO functions */
+void                      LCD_IO_Init(void);
+void                      LCD_IO_WriteData(uint8_t Data);
+void                      LCD_IO_WriteMultipleData(uint8_t *pData, uint32_t Size);
+void                      LCD_IO_WriteReg(uint8_t LCDReg);
+void                      LCD_Delay(uint32_t delay);
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+#ifdef HAL_ADC_MODULE_ENABLED
+static HAL_StatusTypeDef               ADCx_Init(void);
+static void               ADCx_DeInit(void);
+static void               ADCx_MspInit(ADC_HandleTypeDef *hadc);
+static void               ADCx_MspDeInit(ADC_HandleTypeDef *hadc);
+#endif /* HAL_ADC_MODULE_ENABLED */
+/**
+  * @}
+  */ 
+
+/** @defgroup STM32L0XX_NUCLEO_LOW_LEVEL_Private_Functions Private Functions
+  * @{
+  */ 
+
+/**
+  * @brief  This method returns the STM32L0XX NUCLEO BSP Driver revision
+  * @retval version : 0xXYZR (8bits for each decimal, R for RC)
+  */
+uint32_t BSP_GetVersion(void)
+{
+  return __STM32L0XX_NUCLEO_BSP_VERSION;
+}
+
+/**
+  * @brief  Configures LED GPIO.
+  * @param  Led: Led to be configured. 
+  *          This parameter can be one of the following values:
+  *            @arg  LED2
+  * @retval None
+  */
+void BSP_LED_Init(Led_TypeDef Led)
+{
+  GPIO_InitTypeDef  gpioinitstruct;
+  
+  /* Enable the GPIO_LED Clock */
+  LEDx_GPIO_CLK_ENABLE(Led);
+
+  /* Configure the GPIO_LED pin */
+  gpioinitstruct.Pin = LED_PIN[Led];
+  gpioinitstruct.Mode = GPIO_MODE_OUTPUT_PP;
+  gpioinitstruct.Pull = GPIO_NOPULL;
+  gpioinitstruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  
+  HAL_GPIO_Init(LED_PORT[Led], &gpioinitstruct);
+
+  /* Reset PIN to switch off the LED */
+  HAL_GPIO_WritePin(LED_PORT[Led], LED_PIN[Led], GPIO_PIN_RESET); 
+}
+
+/**
+  * @brief  DeInit LEDs.
+  * @param  Led: LED to be de-init. 
+  *   This parameter can be one of the following values:
+  *     @arg  LED2
+  * @note Led DeInit does not disable the GPIO clock nor disable the Mfx 
+  * @retval None
+  */
+void BSP_LED_DeInit(Led_TypeDef Led)
+{
+  GPIO_InitTypeDef  gpio_init_structure;
+
+  /* Turn off LED */
+  HAL_GPIO_WritePin(LED_PORT[Led],LED_PIN[Led], GPIO_PIN_RESET);
+  /* DeInit the GPIO_LED pin */
+  gpio_init_structure.Pin = LED_PIN[Led];
+  HAL_GPIO_DeInit(LED_PORT[Led], gpio_init_structure.Pin);
+}
+
+/**
+  * @brief  Turns selected LED On.
+  * @param  Led: Specifies the Led to be set on. 
+  *   This parameter can be one of following parameters:
+  *            @arg  LED2
+  * @retval None
+  */
+void BSP_LED_On(Led_TypeDef Led)
+{
+  HAL_GPIO_WritePin(LED_PORT[Led], LED_PIN[Led], GPIO_PIN_SET); 
+}
+
+/**
+  * @brief  Turns selected LED Off. 
+  * @param  Led: Specifies the Led to be set off. 
+  *   This parameter can be one of following parameters:
+  *            @arg  LED2
+  * @retval None
+  */
+void BSP_LED_Off(Led_TypeDef Led)
+{
+  HAL_GPIO_WritePin(LED_PORT[Led], LED_PIN[Led], GPIO_PIN_RESET); 
+}
+
+/**
+  * @brief  Toggles the selected LED.
+  * @param  Led: Specifies the Led to be toggled. 
+  *   This parameter can be one of following parameters:
+  *            @arg  LED2
+  * @retval None
+  */
+void BSP_LED_Toggle(Led_TypeDef Led)
+{
+  HAL_GPIO_TogglePin(LED_PORT[Led], LED_PIN[Led]);
+}
+
+/**
+  * @brief  Configures Button GPIO and EXTI Line.
+  * @param  Button: Specifies the Button to be configured.
+  *   This parameter should be: BUTTON_USER
+  * @param  ButtonMode: Specifies Button mode.
+  *   This parameter can be one of following parameters:   
+  *     @arg  BUTTON_MODE_GPIO: Button will be used as simple IO
+  *     @arg BUTTON_MODE_EXTI: Button will be connected to EXTI line with interrupt
+  *                            generation capability  
+  * @retval None
+  */
+void BSP_PB_Init(Button_TypeDef Button, ButtonMode_TypeDef ButtonMode)
+{
+  GPIO_InitTypeDef gpioinitstruct;
+  
+  /* Enable the BUTTON Clock */
+  BUTTONx_GPIO_CLK_ENABLE(Button);
+
+  gpioinitstruct.Pin = BUTTON_PIN[Button];
+  gpioinitstruct.Pull = GPIO_NOPULL;
+  gpioinitstruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
+  
+  if(ButtonMode == BUTTON_MODE_GPIO)
+  {
+    /* Configure Button pin as input */
+    gpioinitstruct.Mode = GPIO_MODE_INPUT;
+  
+    HAL_GPIO_Init(BUTTON_PORT[Button], &gpioinitstruct);
+  }
+  
+  if(ButtonMode == BUTTON_MODE_EXTI)
+  {
+    /* Configure Button pin as input with External interrupt */
+    gpioinitstruct.Mode   = GPIO_MODE_IT_FALLING; 
+    HAL_GPIO_Init(BUTTON_PORT[Button], &gpioinitstruct);
+    
+    /* Enable and set Button EXTI Interrupt to the lowest priority */
+    HAL_NVIC_SetPriority((IRQn_Type)(BUTTON_IRQn[Button]), 0x0F, 0);
+    HAL_NVIC_EnableIRQ((IRQn_Type)(BUTTON_IRQn[Button]));
+  }
+}
+
+/**
+  * @brief  Push Button DeInit.
+  * @param  Button: Button to be configured
+  *   This parameter should be: BUTTON_USER  
+  * @note PB DeInit does not disable the GPIO clock
+  * @retval None
+  */
+void BSP_PB_DeInit(Button_TypeDef Button)
+{
+  GPIO_InitTypeDef gpio_init_structure;
+
+  gpio_init_structure.Pin = BUTTON_PIN[Button];
+  HAL_NVIC_DisableIRQ((IRQn_Type)(BUTTON_IRQn[Button]));
+  HAL_GPIO_DeInit(BUTTON_PORT[Button], gpio_init_structure.Pin);
+}
+
+/**
+  * @brief  Returns the selected Button state.
+  * @param  Button: Specifies the Button to be checked.
+  *   This parameter should be: BUTTON_USER
+  * @retval Button state.
+  */
+uint32_t BSP_PB_GetState(Button_TypeDef Button)
+{
+  return HAL_GPIO_ReadPin(BUTTON_PORT[Button], BUTTON_PIN[Button]);
+}
+
+
+#ifdef HAL_SPI_MODULE_ENABLED
+/******************************************************************************
+                            BUS OPERATIONS
+*******************************************************************************/
+/**
+  * @brief  Initialize SPI MSP.
+  * @retval None
+  */
+static void SPIx_MspInit(void)
+{
+  GPIO_InitTypeDef  gpioinitstruct = {0};
+  
+  /*** Configure the GPIOs ***/  
+  /* Enable GPIO clock */
+  NUCLEO_SPIx_SCK_GPIO_CLK_ENABLE();
+  NUCLEO_SPIx_MISO_MOSI_GPIO_CLK_ENABLE();
+  
+  /* Configure SPI SCK */
+  gpioinitstruct.Pin = NUCLEO_SPIx_SCK_PIN;
+  gpioinitstruct.Mode = GPIO_MODE_AF_PP;
+  gpioinitstruct.Pull  = GPIO_PULLUP;
+  gpioinitstruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  gpioinitstruct.Alternate = NUCLEO_SPIx_SCK_AF;
+  HAL_GPIO_Init(NUCLEO_SPIx_SCK_GPIO_PORT, &gpioinitstruct);
+
+  /* Configure SPI MISO and MOSI */ 
+  gpioinitstruct.Pin = NUCLEO_SPIx_MOSI_PIN;
+  gpioinitstruct.Alternate = NUCLEO_SPIx_MISO_MOSI_AF;
+  gpioinitstruct.Pull  = GPIO_PULLDOWN;
+  HAL_GPIO_Init(NUCLEO_SPIx_MISO_MOSI_GPIO_PORT, &gpioinitstruct);
+  
+  gpioinitstruct.Pin = NUCLEO_SPIx_MISO_PIN;
+  HAL_GPIO_Init(NUCLEO_SPIx_MISO_MOSI_GPIO_PORT, &gpioinitstruct);
+
+  /*** Configure the SPI peripheral ***/ 
+  /* Enable SPI clock */
+  NUCLEO_SPIx_CLK_ENABLE();
+}
+
+/**
+  * @brief  Initialize SPI HAL.
+  * @retval None
+  */
+static void SPIx_Init(void)
+{
+  if(HAL_SPI_GetState(&hnucleo_Spi) == HAL_SPI_STATE_RESET)
+  {
+    /* SPI Config */
+    hnucleo_Spi.Instance = NUCLEO_SPIx;
+      /* SPI baudrate is set to 8 MHz maximum (PCLK2/SPI_BaudRatePrescaler = 32/4 = 8 MHz) 
+       to verify these constraints:
+          - ST7735 LCD SPI interface max baudrate is 15MHz for write and 6.66MHz for read
+            Since the provided driver doesn't use read capability from LCD, only constraint 
+            on write baudrate is considered.
+          - SD card SPI interface max baudrate is 25MHz for write/read
+          - PCLK2 max frequency is 32 MHz 
+       */ 
+    hnucleo_Spi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
+    hnucleo_Spi.Init.Direction = SPI_DIRECTION_2LINES;
+    hnucleo_Spi.Init.CLKPhase = SPI_PHASE_1EDGE;
+    hnucleo_Spi.Init.CLKPolarity = SPI_POLARITY_LOW;
+    hnucleo_Spi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
+    hnucleo_Spi.Init.CRCPolynomial = 7;
+    hnucleo_Spi.Init.DataSize = SPI_DATASIZE_8BIT;
+    hnucleo_Spi.Init.FirstBit = SPI_FIRSTBIT_MSB;
+    hnucleo_Spi.Init.NSS = SPI_NSS_SOFT;
+    hnucleo_Spi.Init.TIMode = SPI_TIMODE_DISABLE;
+    hnucleo_Spi.Init.Mode = SPI_MODE_MASTER;
+    
+    SPIx_MspInit();
+    HAL_SPI_Init(&hnucleo_Spi);
+  }
+}
+
+/**
+  * @brief  SPI Write a byte to device
+  * @param  DataIn: value to be written
+  * @param  DataOut: read value
+  * @param  DataLength: number of bytes to write
+  * @retval None
+  */
+static void SPIx_WriteReadData(const uint8_t *DataIn, uint8_t *DataOut, uint16_t DataLength)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  status = HAL_SPI_TransmitReceive(&hnucleo_Spi, (uint8_t*) DataIn, DataOut, DataLength, SpixTimeout);
+    
+  /* Check the communication status */
+  if(status != HAL_OK)
+  {
+    /* Execute user timeout callback */
+    SPIx_Error();
+  }
+}
+
+/**
+  * @brief  SPI Write an amount of data to device
+  * @param  DataIn: value to be written
+  * @param  DataLength: number of bytes to write
+  * @retval None
+  */
+static void SPIx_WriteData(uint8_t *DataIn, uint16_t DataLength)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+
+  status = HAL_SPI_Transmit(&hnucleo_Spi, DataIn, DataLength, SpixTimeout);
+  
+  /* Check the communication status */
+  if(status != HAL_OK)
+  {
+    /* Execute user timeout callback */
+    SPIx_Error();
+  }
+}
+
+/**
+  * @brief  SPI Write a byte to device
+  * @param  Value: value to be written
+  * @retval None
+  */
+static void SPIx_Write(uint8_t Value)
+{
+  HAL_StatusTypeDef status = HAL_OK;
+  uint8_t data;
+
+  status = HAL_SPI_TransmitReceive(&hnucleo_Spi, (uint8_t*) &Value, &data, 1, SpixTimeout);
+    
+  /* Check the communication status */
+  if(status != HAL_OK)
+  {
+    /* Execute user timeout callback */
+    SPIx_Error();
+  }
+}
+
+/**
+  * @brief  SPI error treatment function
+  * @retval None
+  */
+static void SPIx_Error (void)
+{
+  /* De-initialize the SPI communication BUS */
+  HAL_SPI_DeInit(&hnucleo_Spi);
+  
+  /* Re-Initiaize the SPI communication BUS */
+  SPIx_Init();
+}
+
+/******************************************************************************
+                            LINK OPERATIONS
+*******************************************************************************/
+
+/********************************* LINK SD ************************************/
+/**
+  * @brief  Initialize the SD Card and put it into StandBy State (Ready for 
+  *         data transfer).
+  * @retval None
+  */
+void SD_IO_Init(void)
+{
+  GPIO_InitTypeDef  gpioinitstruct = {0};
+  uint8_t counter = 0;
+
+  /* SD_CS_GPIO Periph clock enable */
+  SD_CS_GPIO_CLK_ENABLE();
+
+  /* Configure SD_CS_PIN pin: SD Card CS pin */
+  gpioinitstruct.Pin = SD_CS_PIN;
+  gpioinitstruct.Mode = GPIO_MODE_OUTPUT_PP;
+  gpioinitstruct.Pull = GPIO_PULLUP;
+  gpioinitstruct.Speed  = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(SD_CS_GPIO_PORT, &gpioinitstruct);
+
+  /* Configure LCD_CS_PIN pin: LCD Card CS pin */
+  gpioinitstruct.Pin = LCD_CS_PIN;
+  gpioinitstruct.Mode = GPIO_MODE_OUTPUT_PP;
+  gpioinitstruct.Pull = GPIO_NOPULL;
+  gpioinitstruct.Speed = GPIO_SPEED_FREQ_HIGH;
+  HAL_GPIO_Init(SD_CS_GPIO_PORT, &gpioinitstruct);
+  LCD_CS_HIGH();
+  /*------------Put SD in SPI mode--------------*/
+  /* SD SPI Config */
+  SPIx_Init();
+  
+  /* SD chip select high */
+  SD_CS_HIGH();
+  
+  /* Send dummy byte 0xFF, 10 times with CS high */
+  /* Rise CS and MOSI for 80 clocks cycles */
+  for (counter = 0; counter <= 9; counter++)
+  {
+    /* Send dummy byte 0xFF */
+    SD_IO_WriteByte(SD_DUMMY_BYTE);
+  }
+}
+
+/**
+  * @brief  Set the SD_CS pin.
+  * @param  val: pin value.
+  * @retval None
+  */
+void SD_IO_CSState(uint8_t val)
+{
+  if(val == 1) 
+  {
+    SD_CS_HIGH();
+  }
+  else
+  {
+    SD_CS_LOW();
+  }
+}
+
+/**
+  * @brief  Write byte(s) on the SD
+  * @param  DataIn: Pointer to data buffer to write
+  * @param  DataOut: Pointer to data buffer for read data
+  * @param  DataLength: number of bytes to write
+  * @retval None
+  */
+void SD_IO_WriteReadData(const uint8_t *DataIn, uint8_t *DataOut, uint16_t DataLength)
+{
+  /* Send the byte */
+  SPIx_WriteReadData(DataIn, DataOut, DataLength);
+}
+
+/**
+  * @brief  Write a byte on the SD.
+  * @param  Data: byte to send.
+  * @retval Data written
+  */
+uint8_t SD_IO_WriteByte(uint8_t Data)
+{
+  uint8_t tmp;
+
+  /* Send the byte */
+  SPIx_WriteReadData(&Data,&tmp,1);
+  return tmp;
+}
+
+/**
+  * @brief  Write an amount of data on the SD.
+  * @param  DataOut: byte to send.
+  * @param  DataLength: number of bytes to write
+  * @retval none
+  */
+void SD_IO_ReadData(uint8_t *DataOut, uint16_t DataLength)
+{
+  /* Send the byte */
+  SD_IO_WriteReadData(DataOut, DataOut, DataLength);
+  }  
+ 
+/**
+  * @brief  Write an amount of data on the SD.
+  * @param  Data: byte to send.
+  * @param  DataLength: number of bytes to write
+  * @retval none
+  */
+void SD_IO_WriteData(const uint8_t *Data, uint16_t DataLength)
+{
+  /* Send the byte */
+  SPIx_WriteData((uint8_t *)Data, DataLength);
+}
+
+/********************************* LINK LCD ***********************************/
+/**
+  * @brief  Initialize the LCD
+  * @retval None
+  */
+void LCD_IO_Init(void)
+{
+  GPIO_InitTypeDef  gpioinitstruct = {0};
+   
+  /* LCD_CS_GPIO and LCD_DC_GPIO Periph clock enable */
+  LCD_CS_GPIO_CLK_ENABLE();
+  LCD_DC_GPIO_CLK_ENABLE();
+  
+  /* Configure LCD_CS_PIN pin: LCD Card CS pin */
+  gpioinitstruct.Pin = LCD_CS_PIN;
+  gpioinitstruct.Mode = GPIO_MODE_OUTPUT_PP;
+  gpioinitstruct.Pull = GPIO_NOPULL;
+  gpioinitstruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
+  HAL_GPIO_Init(SD_CS_GPIO_PORT, &gpioinitstruct);
+
+  /* Configure LCD_DC_PIN pin: LCD Card DC pin */
+  gpioinitstruct.Pin = LCD_DC_PIN;
+  HAL_GPIO_Init(LCD_DC_GPIO_PORT, &gpioinitstruct);
+  
+  /* LCD chip select high */
+  LCD_CS_HIGH();
+  
+  /* LCD SPI Config */
+  SPIx_Init();
+}
+
+/**
+  * @brief  Write command to select the LCD register.
+  * @param  LCDReg: Address of the selected register.
+  * @retval None
+  */
+void LCD_IO_WriteReg(uint8_t LCDReg)
+{
+  /* Reset LCD control line CS */
+  LCD_CS_LOW();
+  
+  /* Set LCD data/command line DC to Low */
+  LCD_DC_LOW();
+    
+  /* Send Command */
+  SPIx_Write(LCDReg);
+  
+  /* Deselect : Chip Select high */
+  LCD_CS_HIGH();
+}
+
+/**
+  * @brief  Writes data to select the LCD register.
+  *         This function must be used after st7735_WriteReg() function
+  * @param  Data: data to write to the selected register.
+  * @retval None
+  */
+void LCD_IO_WriteData(uint8_t Data)
+{
+  /* Reset LCD control line CS */
+  LCD_CS_LOW();
+  
+  /* Set LCD data/command line DC to High */
+  LCD_DC_HIGH();
+
+  /* Send Data */
+  SPIx_Write(Data);
+  
+  /* Deselect : Chip Select high */
+  LCD_CS_HIGH();
+}
+
+/**
+* @brief  Write register value.
+* @param  pData Pointer on the register value
+* @param  Size Size of byte to transmit to the register
+* @retval None
+*/
+void LCD_IO_WriteMultipleData(uint8_t *pData, uint32_t Size)
+{
+  uint32_t counter = 0;
+  __IO uint32_t data = 0;
+  
+  /* Reset LCD control line CS */
+  LCD_CS_LOW();
+  
+  /* Set LCD data/command line DC to High */
+  LCD_DC_HIGH();
+
+  if (Size == 1)
+  {
+    /* Only 1 byte to be sent to LCD - general interface can be used */
+    /* Send Data */
+    SPIx_Write(*pData);
+  }
+  else
+  {
+    /* Several data should be sent in a raw */
+    /* Direct SPI accesses for optimization */
+    for (counter = Size; counter != 0; counter--)
+    {
+      while(((hnucleo_Spi.Instance->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE)
+      {
+      }  
+      /* Need to invert bytes for LCD*/
+      *((__IO uint8_t*)&hnucleo_Spi.Instance->DR) = *(pData+1);
+      
+      while(((hnucleo_Spi.Instance->SR) & SPI_FLAG_TXE) != SPI_FLAG_TXE)
+      {
+      }  
+      *((__IO uint8_t*)&hnucleo_Spi.Instance->DR) = *pData;
+      counter--;
+      pData += 2;
+    }
+    
+    /* Wait until the bus is ready before releasing Chip select */ 
+    while(((hnucleo_Spi.Instance->SR) & SPI_FLAG_BSY) != RESET)
+    {
+    }  
+  } 
+
+  /* Empty the Rx fifo */
+  data = *(&hnucleo_Spi.Instance->DR);
+  UNUSED(data);  /* Remove GNU warning */
+
+  /* Deselect : Chip Select high */
+  LCD_CS_HIGH();
+}
+
+/**
+  * @brief  Wait for loop in ms.
+  * @param  Delay in ms.
+  * @retval None
+  */
+void LCD_Delay(uint32_t Delay)
+{
+  HAL_Delay(Delay);
+}
+#endif /* HAL_SPI_MODULE_ENABLED */
+
+/******************************* LINK JOYSTICK ********************************/
+#ifdef HAL_ADC_MODULE_ENABLED
+/**
+  * @brief  Initialize ADC MSP.
+  * @retval None
+  */
+static void ADCx_MspInit(ADC_HandleTypeDef *hadc)
+{
+  GPIO_InitTypeDef  gpioinitstruct = {0};
+  
+  /*** Configure the GPIOs ***/  
+  /* Enable GPIO clock */
+  NUCLEO_ADCx_GPIO_CLK_ENABLE();
+  
+  /* Configure ADC1 Channel8 as analog input */
+  gpioinitstruct.Pin = NUCLEO_ADCx_GPIO_PIN ;
+  gpioinitstruct.Mode = GPIO_MODE_ANALOG;
+  gpioinitstruct.Pull   = GPIO_NOPULL;
+  HAL_GPIO_Init(NUCLEO_ADCx_GPIO_PORT, &gpioinitstruct);
+
+  /*** Configure the ADC peripheral ***/ 
+  /* Enable ADC clock */
+  NUCLEO_ADCx_CLK_ENABLE(); 
+}
+
+/**
+  * @brief  DeInitializes ADC MSP.
+  * @param  hadc: ADC peripheral
+  * @note ADC DeInit does not disable the GPIO clock
+  * @retval None
+  */
+static void ADCx_MspDeInit(ADC_HandleTypeDef *hadc)
+{
+  GPIO_InitTypeDef  gpioinitstruct;
+
+  /*** DeInit the ADC peripheral ***/ 
+  /* Disable ADC clock */
+  NUCLEO_ADCx_CLK_DISABLE(); 
+
+  /* Configure the selected ADC Channel as analog input */
+  gpioinitstruct.Pin = NUCLEO_ADCx_GPIO_PIN ;
+  HAL_GPIO_DeInit(NUCLEO_ADCx_GPIO_PORT, gpioinitstruct.Pin);
+
+  /* Disable GPIO clock has to be done by the application*/
+  /* NUCLEO_ADCx_GPIO_CLK_DISABLE(); */
+}
+
+/**
+  * @brief  Initializes ADC HAL.
+  * @retval None
+  */
+static HAL_StatusTypeDef ADCx_Init(void)
+{
+  /* Set ADC instance */
+  hnucleo_Adc.Instance = NUCLEO_ADCx;
+
+  if(HAL_ADC_GetState(&hnucleo_Adc) == HAL_ADC_STATE_RESET)
+  {
+    /* ADC Config */
+    hnucleo_Adc.Instance = NUCLEO_ADCx;
+    hnucleo_Adc.Init.OversamplingMode      = DISABLE;
+    hnucleo_Adc.Init.ClockPrescaler        = ADC_CLOCK_SYNC_PCLK_DIV2; /* (must not exceed 16MHz) */
+    hnucleo_Adc.Init.LowPowerAutoPowerOff  = DISABLE;
+    hnucleo_Adc.Init.LowPowerFrequencyMode = ENABLE;
+    hnucleo_Adc.Init.LowPowerAutoWait      = ENABLE;
+    hnucleo_Adc.Init.Resolution            = ADC_RESOLUTION_12B;
+    hnucleo_Adc.Init.SamplingTime          = ADC_SAMPLETIME_1CYCLE_5;
+    hnucleo_Adc.Init.ScanConvMode          = ADC_SCAN_DIRECTION_FORWARD;
+    hnucleo_Adc.Init.DataAlign             = ADC_DATAALIGN_RIGHT;
+    hnucleo_Adc.Init.ContinuousConvMode    = DISABLE;
+    hnucleo_Adc.Init.DiscontinuousConvMode = DISABLE;
+    hnucleo_Adc.Init.ExternalTrigConv       = ADC_SOFTWARE_START;            /* Trig of conversion start done manually by software, without external event */
+    hnucleo_Adc.Init.ExternalTrigConvEdge   = ADC_EXTERNALTRIGCONVEDGE_NONE; /* Parameter discarded because trig by software start */
+    hnucleo_Adc.Init.EOCSelection           = ADC_EOC_SEQ_CONV;
+    hnucleo_Adc.Init.DMAContinuousRequests  = DISABLE;
+    
+    /* Initialize MSP related to ADC */
+    ADCx_MspInit(&hnucleo_Adc);
+    
+    /* Initialize ADC */
+    if (HAL_ADC_Init(&hnucleo_Adc) != HAL_OK)
+    {
+      return HAL_ERROR;
+    }
+    
+    if (HAL_ADCEx_Calibration_Start(&hnucleo_Adc,ADC_SINGLE_ENDED) != HAL_OK)
+    {
+      return HAL_ERROR;
+    }
+  }
+
+  return HAL_OK;
+}
+
+/**
+  * @brief  Initializes ADC HAL.
+  * @retval None
+  */
+static void ADCx_DeInit(void)
+{
+    hnucleo_Adc.Instance   = NUCLEO_ADCx;
+    
+    HAL_ADC_DeInit(&hnucleo_Adc);
+    ADCx_MspDeInit(&hnucleo_Adc);
+}
+
+/******************************* LINK JOYSTICK ********************************/
+
+/**
+  * @brief  Configures joystick available on adafruit 1.8" TFT shield 
+  *         managed through ADC to detect motion.
+  * @retval Joystickstatus (0=> success, 1=> fail) 
+  */
+uint8_t BSP_JOY_Init(void)
+{
+  if (ADCx_Init() != HAL_OK)
+  {
+    return (uint8_t) HAL_ERROR; 
+  }
+  
+  /* Select Channel 8 to be converted */
+  sConfig.Channel = ADC_CHANNEL_8;
+  sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
+
+  /* Return Joystick initialization status */
+  return (uint8_t) HAL_ADC_ConfigChannel(&hnucleo_Adc, &sConfig);
+}
+
+/**
+  * @brief  DeInit joystick GPIOs.
+  * @note   JOY DeInit does not disable the Mfx, just set the Mfx pins in Off mode
+  * @retval None.
+  */
+void BSP_JOY_DeInit(void)
+{
+    ADCx_DeInit();
+}
+
+/**
+  * @brief  Returns the Joystick key pressed.
+  * @note   To know which Joystick key is pressed we need to detect the voltage
+  *         level on each key output
+  *           - None  : 3.3 V / 4095
+  *           - SEL   : 1.055 V / 1308
+  *           - DOWN  : 0.71 V / 88
+  *           - LEFT  : 3.0 V / 3720 
+  *           - RIGHT : 0.595 V / 737
+  *           - UP    : 1.65 V / 2046
+  * @retval JOYState_TypeDef: Code of the Joystick key pressed.
+  */
+JOYState_TypeDef BSP_JOY_GetState(void)
+{
+  JOYState_TypeDef state = JOY_NONE;
+  uint16_t  keyconvertedvalue = 0;
+  
+ /* Start the conversion process */
+  HAL_ADC_Start(&hnucleo_Adc);
+  
+  /* Wait for the end of conversion */
+  if (HAL_ADC_PollForConversion(&hnucleo_Adc, 10) != HAL_TIMEOUT)
+  {
+    /* Get the converted value of regular channel */
+    keyconvertedvalue = HAL_ADC_GetValue(&hnucleo_Adc);
+  }
+ 
+  if((keyconvertedvalue > 2010) && (keyconvertedvalue < 2090))
+  {
+    state = JOY_UP;
+  }
+  else if((keyconvertedvalue > 680) && (keyconvertedvalue < 780))
+  {
+    state = JOY_RIGHT;
+  }
+  else if((keyconvertedvalue > 1270) && (keyconvertedvalue < 1350))
+  {
+    state = JOY_SEL;
+  }
+  else if((keyconvertedvalue > 50) && (keyconvertedvalue < 130))
+  {
+    state = JOY_DOWN;
+  }
+  else if((keyconvertedvalue > 3570) && (keyconvertedvalue < 3800))
+  {
+    state = JOY_LEFT;
+  }
+  else
+  {
+    state = JOY_NONE;
+  }
+  
+  /* Return the code of the Joystick key pressed */
+  return state;
+}
+#endif /* HAL_ADC_MODULE_ENABLED */
+
+/**
+  * @}
+  */ 
+
+/**
+  * @}
+  */
+
+/**
+  * @}
+  */    
+
+/**
+  * @}
+  */ 
+    
+/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
+