Fahad Mirza
/
Nucleo_HXC900
A demo application for HXC900 LoRaWAN module using Nucleo-L053R8.
Diff: stm32l0xx_nucleo.c
- 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>© 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****/ +