ref: 34dd7330431c99292c332c724e0e493b08e40bd6
dir: /demos/stm32f429_disco/stm/stm32f429/stm32f429i_discovery_lcd.c/
/**
******************************************************************************
* @file stm32f429i_discovery_lcd.c
* @author MCD Application Team
* @version V1.0.1
* @date 28-October-2013
* @brief This file includes the LCD driver for ILI9341 Liquid Crystal
* Display Modules of STM32F429I-DISCO kit (MB1075).
******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32f429i_discovery_lcd.h"
#include "fonts.h"
/** @addtogroup Utilities
* @{
*/
/** @addtogroup STM32F4_DISCOVERY
* @{
*/
/** @addtogroup STM32F429I_DISCOVERY
* @{
*/
/** @defgroup STM32F429I_DISCOVERY_LCD
* @brief This file includes the LCD driver for (ILI9341)
* @{
*/
/** @defgroup STM32F429I_DISCOVERY_LCD_Private_TypesDefinitions
* @{
*/
/**
* @}
*/
/** @defgroup STM32F429I_DISCOVERY_LCD_Private_Defines
* @{
*/
#define POLY_Y(Z) ((int32_t)((Points + Z)->X))
#define POLY_X(Z) ((int32_t)((Points + Z)->Y))
/**
* @}
*/
/** @defgroup STM32F429I_DISCOVERY_LCD_Private_Macros
* @{
*/
#define ABS(X) ((X) > 0 ? (X) : -(X))
/**
* @}
*/
/** @defgroup STM32F429I_DISCOVERY_LCD_Private_Variables
* @{
*/
static sFONT *LCD_Currentfonts;
/* Global variables to set the written text color */
static uint16_t CurrentTextColor = 0x0000;
static uint16_t CurrentBackColor = 0xFFFF;
/* Default LCD configuration with LCD Layer 1 */
static uint32_t CurrentFrameBuffer = LCD_FRAME_BUFFER;
static uint32_t CurrentLayer = LCD_BACKGROUND_LAYER;
/**
* @}
*/
/** @defgroup STM32F429I_DISCOVERY_LCD_Private_FunctionPrototypes
* @{
*/
#ifndef USE_Delay
static void delay(__IO uint32_t nCount);
#endif /* USE_Delay*/
static void PutPixel(int16_t x, int16_t y);
static void LCD_PolyLineRelativeClosed(pPoint Points, uint16_t PointCount, uint16_t Closed);
static void LCD_AF_GPIOConfig(void);
/**
* @}
*/
/** @defgroup STM32F429I_DISCOVERY_LCD_Private_Functions
* @{
*/
/**
* @brief DeInitializes the LCD.
* @param None
* @retval None
*/
void LCD_DeInit(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* LCD Display Off */
LCD_DisplayOff();
/* LCD_SPI disable */
SPI_Cmd(LCD_SPI, DISABLE);
/* LCD_SPI DeInit */
SPI_I2S_DeInit(LCD_SPI);
/* Disable SPI clock */
RCC_APB2PeriphClockCmd(LCD_SPI_CLK, DISABLE);
/* Configure NCS in Output Push-Pull mode */
GPIO_InitStructure.GPIO_Pin = LCD_NCS_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(LCD_NCS_GPIO_PORT, &GPIO_InitStructure);
/* Configure SPI pins: SCK, MISO and MOSI */
GPIO_InitStructure.GPIO_Pin = LCD_SPI_SCK_PIN;
GPIO_Init(LCD_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LCD_SPI_MISO_PIN;
GPIO_Init(LCD_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = LCD_SPI_MOSI_PIN;
GPIO_Init(LCD_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
/* GPIOA configuration */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_MCO);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_6 |
GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* GPIOB configuration */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_MCO);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 |
GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOB, &GPIO_InitStructure);
/* GPIOC configuration */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_MCO);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
/* GPIOD configuration */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource3, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_MCO);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* GPIOF configuration */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource10, GPIO_AF_MCO);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOF, &GPIO_InitStructure);
/* GPIOG configuration */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource6, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource7, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource10, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_MCO);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource12, GPIO_AF_MCO);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 |
GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOG, &GPIO_InitStructure);
}
/**
* @brief Initializes the LCD.
* @param None
* @retval None
*/
void LCD_Init(void)
{
LTDC_InitTypeDef LTDC_InitStruct;
/* Configure the LCD Control pins ------------------------------------------*/
LCD_CtrlLinesConfig();
LCD_ChipSelect(DISABLE);
LCD_ChipSelect(ENABLE);
/* Configure the LCD_SPI interface -----------------------------------------*/
LCD_SPIConfig();
/* Power on the LCD --------------------------------------------------------*/
LCD_PowerOn();
/* Enable the LTDC Clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_LTDC, ENABLE);
/* Enable the DMA2D Clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2D, ENABLE);
/* Configure the LCD Control pins */
LCD_AF_GPIOConfig();
/* Configure the FMC Parallel interface : SDRAM is used as Frame Buffer for LCD */
SDRAM_Init();
/* LTDC Configuration *********************************************************/
/* Polarity configuration */
/* Initialize the horizontal synchronization polarity as active low */
LTDC_InitStruct.LTDC_HSPolarity = LTDC_HSPolarity_AL;
/* Initialize the vertical synchronization polarity as active low */
LTDC_InitStruct.LTDC_VSPolarity = LTDC_VSPolarity_AL;
/* Initialize the data enable polarity as active low */
LTDC_InitStruct.LTDC_DEPolarity = LTDC_DEPolarity_AL;
/* Initialize the pixel clock polarity as input pixel clock */
LTDC_InitStruct.LTDC_PCPolarity = LTDC_PCPolarity_IPC;
/* Configure R,G,B component values for LCD background color */
LTDC_InitStruct.LTDC_BackgroundRedValue = 0;
LTDC_InitStruct.LTDC_BackgroundGreenValue = 0;
LTDC_InitStruct.LTDC_BackgroundBlueValue = 0;
/* Configure PLLSAI prescalers for LCD */
/* Enable Pixel Clock */
/* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 Mhz */
/* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAI_N = 192 Mhz */
/* PLLLCDCLK = PLLSAI_VCO Output/PLLSAI_R = 192/4 = 48 Mhz */
/* LTDC clock frequency = PLLLCDCLK / RCC_PLLSAIDivR = 48/8 = 6 Mhz */
RCC_PLLSAIConfig(192, 7, 4);
RCC_LTDCCLKDivConfig(RCC_PLLSAIDivR_Div8);
/* Enable PLLSAI Clock */
RCC_PLLSAICmd(ENABLE);
/* Wait for PLLSAI activation */
while(RCC_GetFlagStatus(RCC_FLAG_PLLSAIRDY) == RESET)
{
}
/* Timing configuration */
/* Configure horizontal synchronization width */
LTDC_InitStruct.LTDC_HorizontalSync = 9;
/* Configure vertical synchronization height */
LTDC_InitStruct.LTDC_VerticalSync = 1;
/* Configure accumulated horizontal back porch */
LTDC_InitStruct.LTDC_AccumulatedHBP = 29;
/* Configure accumulated vertical back porch */
LTDC_InitStruct.LTDC_AccumulatedVBP = 3;
/* Configure accumulated active width */
LTDC_InitStruct.LTDC_AccumulatedActiveW = 269;
/* Configure accumulated active height */
LTDC_InitStruct.LTDC_AccumulatedActiveH = 323;
/* Configure total width */
LTDC_InitStruct.LTDC_TotalWidth = 279;
/* Configure total height */
LTDC_InitStruct.LTDC_TotalHeigh = 327;
LTDC_Init(<DC_InitStruct);
}
/**
* @brief Initializes the LCD Layers.
* @param None
* @retval None
*/
void LCD_LayerInit(void)
{
LTDC_Layer_InitTypeDef LTDC_Layer_InitStruct;
/* Windowing configuration */
/* In this case all the active display area is used to display a picture then :
Horizontal start = horizontal synchronization + Horizontal back porch = 30
Horizontal stop = Horizontal start + window width -1 = 30 + 240 -1
Vertical start = vertical synchronization + vertical back porch = 4
Vertical stop = Vertical start + window height -1 = 4 + 320 -1 */
LTDC_Layer_InitStruct.LTDC_HorizontalStart = 30;
LTDC_Layer_InitStruct.LTDC_HorizontalStop = (LCD_PIXEL_WIDTH + 30 - 1);
LTDC_Layer_InitStruct.LTDC_VerticalStart = 4;
LTDC_Layer_InitStruct.LTDC_VerticalStop = (LCD_PIXEL_HEIGHT + 4 - 1);
/* Pixel Format configuration*/
LTDC_Layer_InitStruct.LTDC_PixelFormat = LTDC_Pixelformat_RGB565;
/* Alpha constant (255 totally opaque) */
LTDC_Layer_InitStruct.LTDC_ConstantAlpha = 255;
/* Default Color configuration (configure A,R,G,B component values) */
LTDC_Layer_InitStruct.LTDC_DefaultColorBlue = 0;
LTDC_Layer_InitStruct.LTDC_DefaultColorGreen = 0;
LTDC_Layer_InitStruct.LTDC_DefaultColorRed = 0;
LTDC_Layer_InitStruct.LTDC_DefaultColorAlpha = 0;
/* Configure blending factors */
LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_CA;
LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_CA;
/* the length of one line of pixels in bytes + 3 then :
Line Lenth = Active high width x number of bytes per pixel + 3
Active high width = LCD_PIXEL_WIDTH
number of bytes per pixel = 2 (pixel_format : RGB565)
*/
LTDC_Layer_InitStruct.LTDC_CFBLineLength = ((LCD_PIXEL_WIDTH * 2) + 3);
/* the pitch is the increment from the start of one line of pixels to the
start of the next line in bytes, then :
Pitch = Active high width x number of bytes per pixel */
LTDC_Layer_InitStruct.LTDC_CFBPitch = (LCD_PIXEL_WIDTH * 2);
/* Configure the number of lines */
LTDC_Layer_InitStruct.LTDC_CFBLineNumber = LCD_PIXEL_HEIGHT;
/* Start Address configuration : the LCD Frame buffer is defined on SDRAM */
LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_FRAME_BUFFER;
/* Initialize LTDC layer 1 */
LTDC_LayerInit(LTDC_Layer1, <DC_Layer_InitStruct);
/* Configure Layer2 */
/* Start Address configuration : the LCD Frame buffer is defined on SDRAM w/ Offset */
LTDC_Layer_InitStruct.LTDC_CFBStartAdress = LCD_FRAME_BUFFER + BUFFER_OFFSET;
/* Configure blending factors */
LTDC_Layer_InitStruct.LTDC_BlendingFactor_1 = LTDC_BlendingFactor1_PAxCA;
LTDC_Layer_InitStruct.LTDC_BlendingFactor_2 = LTDC_BlendingFactor2_PAxCA;
/* Initialize LTDC layer 2 */
LTDC_LayerInit(LTDC_Layer2, <DC_Layer_InitStruct);
/* LTDC configuration reload */
LTDC_ReloadConfig(LTDC_IMReload);
/* Enable foreground & background Layers */
LTDC_LayerCmd(LTDC_Layer1, ENABLE);
LTDC_LayerCmd(LTDC_Layer2, ENABLE);
/* LTDC configuration reload */
LTDC_ReloadConfig(LTDC_IMReload);
/* Set default font */
LCD_SetFont(&LCD_DEFAULT_FONT);
/* dithering activation */
LTDC_DitherCmd(ENABLE);
}
/**
* @brief Controls LCD Chip Select (CS) pin
* @param NewState CS pin state
* @retval None
*/
void LCD_ChipSelect(FunctionalState NewState)
{
if (NewState == DISABLE)
{
GPIO_ResetBits(LCD_NCS_GPIO_PORT, LCD_NCS_PIN); /* CS pin low: LCD disabled */
}
else
{
GPIO_SetBits(LCD_NCS_GPIO_PORT, LCD_NCS_PIN); /* CS pin high: LCD enabled */
}
}
/**
* @brief Sets the LCD Layer.
* @param Layerx: specifies the Layer foreground or background.
* @retval None
*/
void LCD_SetLayer(uint32_t Layerx)
{
if (Layerx == LCD_BACKGROUND_LAYER)
{
CurrentFrameBuffer = LCD_FRAME_BUFFER;
CurrentLayer = LCD_BACKGROUND_LAYER;
}
else
{
CurrentFrameBuffer = LCD_FRAME_BUFFER + BUFFER_OFFSET;
CurrentLayer = LCD_FOREGROUND_LAYER;
}
}
/**
* @brief Sets the LCD Text and Background colors.
* @param TextColor: specifies the Text Color.
* @param BackColor: specifies the Background Color.
* @retval None
*/
void LCD_SetColors(uint16_t TextColor, uint16_t BackColor)
{
CurrentTextColor = TextColor;
CurrentBackColor = BackColor;
}
/**
* @brief Gets the LCD Text and Background colors.
* @param TextColor: pointer to the variable that will contain the Text
Color.
* @param BackColor: pointer to the variable that will contain the Background
Color.
* @retval None
*/
void LCD_GetColors(uint16_t *TextColor, uint16_t *BackColor)
{
*TextColor = CurrentTextColor;
*BackColor = CurrentBackColor;
}
/**
* @brief Sets the Text color.
* @param Color: specifies the Text color code RGB(5-6-5).
* @retval None
*/
void LCD_SetTextColor(uint16_t Color)
{
CurrentTextColor = Color;
}
/**
* @brief Sets the Background color.
* @param Color: specifies the Background color code RGB(5-6-5).
* @retval None
*/
void LCD_SetBackColor(uint16_t Color)
{
CurrentBackColor = Color;
}
/**
* @brief Sets the Text Font.
* @param fonts: specifies the font to be used.
* @retval None
*/
void LCD_SetFont(sFONT *fonts)
{
LCD_Currentfonts = fonts;
}
/**
* @brief Configure the transparency.
* @param transparency: specifies the transparency,
* This parameter must range from 0x00 to 0xFF.
* @retval None
*/
void LCD_SetTransparency(uint8_t transparency)
{
if (CurrentLayer == LCD_BACKGROUND_LAYER)
{
LTDC_LayerAlpha(LTDC_Layer1, transparency);
}
else
{
LTDC_LayerAlpha(LTDC_Layer2, transparency);
}
LTDC_ReloadConfig(LTDC_IMReload);
}
/**
* @brief Gets the Text Font.
* @param None.
* @retval the used font.
*/
sFONT *LCD_GetFont(void)
{
return LCD_Currentfonts;
}
/**
* @brief Clears the selected line.
* @param Line: the Line to be cleared.
* This parameter can be one of the following values:
* @arg LCD_LINE_x: where x can be: 0..13 if LCD_Currentfonts is Font16x24
* 0..26 if LCD_Currentfonts is Font12x12 or Font8x12
* 0..39 if LCD_Currentfonts is Font8x8
* @retval None
*/
void LCD_ClearLine(uint16_t Line)
{
uint16_t refcolumn = 0;
/* Send the string character by character on lCD */
while ((refcolumn < LCD_PIXEL_WIDTH) && (((refcolumn + LCD_Currentfonts->Width)& 0xFFFF) >= LCD_Currentfonts->Width))
{
/* Display one character on LCD */
LCD_DisplayChar(Line, refcolumn, ' ');
/* Decrement the column position by 16 */
refcolumn += LCD_Currentfonts->Width;
}
}
/**
* @brief Clears the hole LCD.
* @param Color: the color of the background.
* @retval None
*/
void LCD_Clear(uint16_t Color)
{
uint32_t index = 0;
/* erase memory */
for (index = 0x00; index < BUFFER_OFFSET; index++)
{
*(__IO uint16_t*)(CurrentFrameBuffer + (2*index)) = Color;
}
}
/**
* @brief Sets the cursor position.
* @param Xpos: specifies the X position.
* @param Ypos: specifies the Y position.
* @retval Display Address
*/
uint32_t LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
return CurrentFrameBuffer + 2*(Xpos + (LCD_PIXEL_WIDTH*Ypos));
}
/**
* @brief Config and Sets the color Keying.
* @param RGBValue: Specifies the Color reference.
* @retval None
*/
void LCD_SetColorKeying(uint32_t RGBValue)
{
LTDC_ColorKeying_InitTypeDef LTDC_colorkeying_InitStruct;
/* configure the color Keying */
LTDC_colorkeying_InitStruct.LTDC_ColorKeyBlue = 0x0000FF & RGBValue;
LTDC_colorkeying_InitStruct.LTDC_ColorKeyGreen = (0x00FF00 & RGBValue) >> 8;
LTDC_colorkeying_InitStruct.LTDC_ColorKeyRed = (0xFF0000 & RGBValue) >> 16;
if (CurrentLayer == LCD_BACKGROUND_LAYER)
{
/* Enable the color Keying for Layer1 */
LTDC_ColorKeyingConfig(LTDC_Layer1, <DC_colorkeying_InitStruct, ENABLE);
LTDC_ReloadConfig(LTDC_IMReload);
}
else
{
/* Enable the color Keying for Layer2 */
LTDC_ColorKeyingConfig(LTDC_Layer2, <DC_colorkeying_InitStruct, ENABLE);
LTDC_ReloadConfig(LTDC_IMReload);
}
}
/**
* @brief Disable the color Keying.
* @param RGBValue: Specifies the Color reference.
* @retval None
*/
void LCD_ReSetColorKeying(void)
{
LTDC_ColorKeying_InitTypeDef LTDC_colorkeying_InitStruct;
if (CurrentLayer == LCD_BACKGROUND_LAYER)
{
/* Disable the color Keying for Layer1 */
LTDC_ColorKeyingConfig(LTDC_Layer1, <DC_colorkeying_InitStruct, DISABLE);
LTDC_ReloadConfig(LTDC_IMReload);
}
else
{
/* Disable the color Keying for Layer2 */
LTDC_ColorKeyingConfig(LTDC_Layer2, <DC_colorkeying_InitStruct, DISABLE);
LTDC_ReloadConfig(LTDC_IMReload);
}
}
/**
* @brief Draws a character on LCD.
* @param Xpos: the Line where to display the character shape.
* @param Ypos: start column address.
* @param c: pointer to the character data.
* @retval None
*/
void LCD_DrawChar(uint16_t Xpos, uint16_t Ypos, const uint16_t *c)
{
uint32_t index = 0, counter = 0, xpos =0;
uint32_t Xaddress = 0;
xpos = Xpos*LCD_PIXEL_WIDTH*2;
Xaddress += Ypos;
for(index = 0; index < LCD_Currentfonts->Height; index++)
{
for(counter = 0; counter < LCD_Currentfonts->Width; counter++)
{
if((((c[index] & ((0x80 << ((LCD_Currentfonts->Width / 12 ) * 8 ) ) >> counter)) == 0x00) &&(LCD_Currentfonts->Width <= 12))||
(((c[index] & (0x1 << counter)) == 0x00)&&(LCD_Currentfonts->Width > 12 )))
{
/* Write data value to all SDRAM memory */
*(__IO uint16_t*) (CurrentFrameBuffer + (2*Xaddress) + xpos) = CurrentBackColor;
}
else
{
/* Write data value to all SDRAM memory */
*(__IO uint16_t*) (CurrentFrameBuffer + (2*Xaddress) + xpos) = CurrentTextColor;
}
Xaddress++;
}
Xaddress += (LCD_PIXEL_WIDTH - LCD_Currentfonts->Width);
}
}
/**
* @brief Displays one character (16dots width, 24dots height).
* @param Line: the Line where to display the character shape .
* This parameter can be one of the following values:
* @arg Linex: where x can be 0..29
* @param Column: start column address.
* @param Ascii: character ascii code, must be between 0x20 and 0x7E.
* @retval None
*/
void LCD_DisplayChar(uint16_t Line, uint16_t Column, uint8_t Ascii)
{
Ascii -= 32;
LCD_DrawChar(Line, Column, &LCD_Currentfonts->table[Ascii * LCD_Currentfonts->Height]);
}
/**
* @brief Displays a maximum of 20 char on the LCD.
* @param Line: the Line where to display the character shape .
* This parameter can be one of the following values:
* @arg Linex: where x can be 0..9
* @param *ptr: pointer to string to display on LCD.
* @retval None
*/
void LCD_DisplayStringLine(uint16_t Line, uint8_t *ptr)
{
uint16_t refcolumn = 0;
/* Send the string character by character on lCD */
while ((refcolumn < LCD_PIXEL_WIDTH) && ((*ptr != 0) & (((refcolumn + LCD_Currentfonts->Width) & 0xFFFF) >= LCD_Currentfonts->Width)))
{
/* Display one character on LCD */
LCD_DisplayChar(Line, refcolumn, *ptr);
/* Decrement the column position by width */
refcolumn += LCD_Currentfonts->Width;
/* Point on the next character */
ptr++;
}
}
/**
* @brief Sets a display window
* @param Xpos: specifies the X bottom left position from 0 to 240.
* @param Ypos: specifies the Y bottom left position from 0 to 320.
* @param Height: display window height, can be a value from 0 to 320.
* @param Width: display window width, can be a value from 0 to 240.
* @retval None
*/
void LCD_SetDisplayWindow(uint16_t Xpos, uint16_t Ypos, uint16_t Height, uint16_t Width)
{
if (CurrentLayer == LCD_BACKGROUND_LAYER)
{
/* reconfigure the layer1 position */
LTDC_LayerPosition(LTDC_Layer1, Xpos, Ypos);
LTDC_ReloadConfig(LTDC_IMReload);
/* reconfigure the layer1 size */
LTDC_LayerSize(LTDC_Layer1, Width, Height);
LTDC_ReloadConfig(LTDC_IMReload);
}
else
{
/* reconfigure the layer2 position */
LTDC_LayerPosition(LTDC_Layer2, Xpos, Ypos);
LTDC_ReloadConfig(LTDC_IMReload);
/* reconfigure the layer2 size */
LTDC_LayerSize(LTDC_Layer2, Width, Height);
LTDC_ReloadConfig(LTDC_IMReload);
}
}
/**
* @brief Disables LCD Window mode.
* @param None
* @retval None
*/
void LCD_WindowModeDisable(void)
{
LCD_SetDisplayWindow(0, 0, LCD_PIXEL_HEIGHT, LCD_PIXEL_WIDTH);
}
/**
* @brief Displays a line.
* @param Xpos: specifies the X position, can be a value from 0 to 240.
* @param Ypos: specifies the Y position, can be a value from 0 to 320.
* @param Length: line length.
* @param Direction: line direction.
* This parameter can be one of the following values: LCD_DIR_HORIZONTAL or LCD_DIR_VERTICAL.
* @retval None
*/
void LCD_DrawLine(uint16_t Xpos, uint16_t Ypos, uint16_t Length, uint8_t Direction)
{
DMA2D_InitTypeDef DMA2D_InitStruct;
uint32_t Xaddress = 0;
uint16_t Red_Value = 0, Green_Value = 0, Blue_Value = 0;
Xaddress = CurrentFrameBuffer + 2*(LCD_PIXEL_WIDTH*Ypos + Xpos);
Red_Value = (0xF800 & CurrentTextColor) >> 11;
Blue_Value = 0x001F & CurrentTextColor;
Green_Value = (0x07E0 & CurrentTextColor) >> 5;
/* Configure DMA2D */
DMA2D_DeInit();
DMA2D_InitStruct.DMA2D_Mode = DMA2D_R2M;
DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB565;
DMA2D_InitStruct.DMA2D_OutputGreen = Green_Value;
DMA2D_InitStruct.DMA2D_OutputBlue = Blue_Value;
DMA2D_InitStruct.DMA2D_OutputRed = Red_Value;
DMA2D_InitStruct.DMA2D_OutputAlpha = 0x0F;
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = Xaddress;
if(Direction == LCD_DIR_HORIZONTAL)
{
DMA2D_InitStruct.DMA2D_OutputOffset = 0;
DMA2D_InitStruct.DMA2D_NumberOfLine = 1;
DMA2D_InitStruct.DMA2D_PixelPerLine = Length;
}
else
{
DMA2D_InitStruct.DMA2D_OutputOffset = LCD_PIXEL_WIDTH - 1;
DMA2D_InitStruct.DMA2D_NumberOfLine = Length;
DMA2D_InitStruct.DMA2D_PixelPerLine = 1;
}
DMA2D_Init(&DMA2D_InitStruct);
/* Start Transfer */
DMA2D_StartTransfer();
/* Wait for CTC Flag activation */
while(DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET)
{
}
}
/**
* @brief Displays a rectangle.
* @param Xpos: specifies the X position, can be a value from 0 to 240.
* @param Ypos: specifies the Y position, can be a value from 0 to 320.
* @param Height: display rectangle height, can be a value from 0 to 320.
* @param Width: display rectangle width, can be a value from 0 to 240.
* @retval None
*/
void LCD_DrawRect(uint16_t Xpos, uint16_t Ypos, uint16_t Height, uint16_t Width)
{
/* draw horizontal lines */
LCD_DrawLine(Xpos, Ypos, Width, LCD_DIR_HORIZONTAL);
LCD_DrawLine(Xpos, (Ypos+ Height), Width, LCD_DIR_HORIZONTAL);
/* draw vertical lines */
LCD_DrawLine(Xpos, Ypos, Height, LCD_DIR_VERTICAL);
LCD_DrawLine((Xpos + Width), Ypos, Height, LCD_DIR_VERTICAL);
}
/**
* @brief Draw a circle.
* @param Xpos: specifies the X position, can be a value from 0 to 240.
* @param Ypos: specifies the Y position, can be a value from 0 to 320.
* @param Radius: radius of the circle.
* @retval None
*/
void LCD_DrawCircle(uint16_t Xpos, uint16_t Ypos, uint16_t Radius)
{
int x = -Radius, y = 0, err = 2-2*Radius, e2;
do {
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos-x) + LCD_PIXEL_WIDTH*(Ypos+y)))) = CurrentTextColor;
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos+x) + LCD_PIXEL_WIDTH*(Ypos+y)))) = CurrentTextColor;
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos+x) + LCD_PIXEL_WIDTH*(Ypos-y)))) = CurrentTextColor;
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos-x) + LCD_PIXEL_WIDTH*(Ypos-y)))) = CurrentTextColor;
e2 = err;
if (e2 <= y) {
err += ++y*2+1;
if (-x == y && e2 <= x) e2 = 0;
}
if (e2 > x) err += ++x*2+1;
}
while (x <= 0);
}
/**
* @brief Draw a full ellipse.
* @param Xpos: specifies the X position, can be a value from 0 to 240.
* @param Ypos: specifies the Y position, can be a value from 0 to 320.
* @param Radius: minor radius of ellipse.
* @param Radius2: major radius of ellipse.
* @retval None
*/
void LCD_DrawFullEllipse(int Xpos, int Ypos, int Radius, int Radius2)
{
int x = -Radius, y = 0, err = 2-2*Radius, e2;
float K = 0, rad1 = 0, rad2 = 0;
rad1 = Radius;
rad2 = Radius2;
if (Radius > Radius2)
{
do
{
K = (float)(rad1/rad2);
LCD_DrawLine((Xpos+x), (Ypos-(uint16_t)(y/K)), (2*(uint16_t)(y/K) + 1), LCD_DIR_VERTICAL);
LCD_DrawLine((Xpos-x), (Ypos-(uint16_t)(y/K)), (2*(uint16_t)(y/K) + 1), LCD_DIR_VERTICAL);
e2 = err;
if (e2 <= y)
{
err += ++y*2+1;
if (-x == y && e2 <= x) e2 = 0;
}
if (e2 > x) err += ++x*2+1;
}
while (x <= 0);
}
else
{
y = -Radius2;
x = 0;
do
{
K = (float)(rad2/rad1);
LCD_DrawLine((Xpos-(uint16_t)(x/K)), (Ypos+y), (2*(uint16_t)(x/K) + 1), LCD_DIR_HORIZONTAL);
LCD_DrawLine((Xpos-(uint16_t)(x/K)), (Ypos-y), (2*(uint16_t)(x/K) + 1), LCD_DIR_HORIZONTAL);
e2 = err;
if (e2 <= x)
{
err += ++x*2+1;
if (-y == x && e2 <= y) e2 = 0;
}
if (e2 > y) err += ++y*2+1;
}
while (y <= 0);
}
}
/**
* @brief Displays an Ellipse.
* @param Xpos: specifies the X position, can be a value from 0 to 240.
* @param Ypos: specifies the Y position, can be a value from 0 to 320.
* @param Radius: specifies Radius.
* @param Radius2: specifies Radius2.
* @retval None
*/
void LCD_DrawEllipse(int Xpos, int Ypos, int Radius, int Radius2)
{
int x = -Radius, y = 0, err = 2-2*Radius, e2;
float K = 0, rad1 = 0, rad2 = 0;
rad1 = Radius;
rad2 = Radius2;
if (Radius > Radius2)
{
do {
K = (float)(rad1/rad2);
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos-x) + LCD_PIXEL_WIDTH*(Ypos+(uint16_t)(y/K))))) = CurrentTextColor;
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos+x) + LCD_PIXEL_WIDTH*(Ypos+(uint16_t)(y/K))))) = CurrentTextColor;
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos+x) + LCD_PIXEL_WIDTH*(Ypos-(uint16_t)(y/K))))) = CurrentTextColor;
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos-x) + LCD_PIXEL_WIDTH*(Ypos-(uint16_t)(y/K))))) = CurrentTextColor;
e2 = err;
if (e2 <= y) {
err += ++y*2+1;
if (-x == y && e2 <= x) e2 = 0;
}
if (e2 > x) err += ++x*2+1;
}
while (x <= 0);
}
else
{
y = -Radius2;
x = 0;
do {
K = (float)(rad2/rad1);
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos-(uint16_t)(x/K)) + LCD_PIXEL_WIDTH*(Ypos+y)))) = CurrentTextColor;
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos+(uint16_t)(x/K)) + LCD_PIXEL_WIDTH*(Ypos+y)))) = CurrentTextColor;
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos+(uint16_t)(x/K)) + LCD_PIXEL_WIDTH*(Ypos-y)))) = CurrentTextColor;
*(__IO uint16_t*) (CurrentFrameBuffer + (2*((Xpos-(uint16_t)(x/K)) + LCD_PIXEL_WIDTH*(Ypos-y)))) = CurrentTextColor;
e2 = err;
if (e2 <= x) {
err += ++x*2+1;
if (-y == x && e2 <= y) e2 = 0;
}
if (e2 > y) err += ++y*2+1;
}
while (y <= 0);
}
}
/**
* @brief Displays a mono-color picture.
* @param Pict: pointer to the picture array.
* @retval None
*/
void LCD_DrawMonoPict(const uint32_t *Pict)
{
uint32_t index = 0, counter = 0;
for(index = 0; index < 2400; index++)
{
for(counter = 0; counter < 32; counter++)
{
if((Pict[index] & (1 << counter)) == 0x00)
{
*(__IO uint16_t*)(CurrentFrameBuffer) = CurrentBackColor;
}
else
{
*(__IO uint16_t*)(CurrentFrameBuffer) = CurrentTextColor;
}
}
}
}
/**
* @brief Displays a bitmap picture loaded in the internal Flash.
* @param BmpAddress: Bmp picture address in the internal Flash.
* @retval None
*/
void LCD_WriteBMP(uint32_t BmpAddress)
{
uint32_t index = 0, size = 0, width = 0, height = 0, bit_pixel = 0;
uint32_t Address;
uint32_t currentline = 0, linenumber = 0;
Address = CurrentFrameBuffer;
/* Read bitmap size */
size = *(__IO uint16_t *) (BmpAddress + 2);
size |= (*(__IO uint16_t *) (BmpAddress + 4)) << 16;
/* Get bitmap data address offset */
index = *(__IO uint16_t *) (BmpAddress + 10);
index |= (*(__IO uint16_t *) (BmpAddress + 12)) << 16;
/* Read bitmap width */
width = *(uint16_t *) (BmpAddress + 18);
width |= (*(uint16_t *) (BmpAddress + 20)) << 16;
/* Read bitmap height */
height = *(uint16_t *) (BmpAddress + 22);
height |= (*(uint16_t *) (BmpAddress + 24)) << 16;
/* Read bit/pixel */
bit_pixel = *(uint16_t *) (BmpAddress + 28);
if (CurrentLayer == LCD_BACKGROUND_LAYER)
{
/* reconfigure layer size in accordance with the picture */
LTDC_LayerSize(LTDC_Layer1, width, height);
LTDC_ReloadConfig(LTDC_VBReload);
/* Reconfigure the Layer pixel format in accordance with the picture */
if ((bit_pixel/8) == 4)
{
LTDC_LayerPixelFormat(LTDC_Layer1, LTDC_Pixelformat_ARGB8888);
LTDC_ReloadConfig(LTDC_VBReload);
}
else if ((bit_pixel/8) == 2)
{
LTDC_LayerPixelFormat(LTDC_Layer1, LTDC_Pixelformat_RGB565);
LTDC_ReloadConfig(LTDC_VBReload);
}
else
{
LTDC_LayerPixelFormat(LTDC_Layer1, LTDC_Pixelformat_RGB888);
LTDC_ReloadConfig(LTDC_VBReload);
}
}
else
{
/* reconfigure layer size in accordance with the picture */
LTDC_LayerSize(LTDC_Layer2, width, height);
LTDC_ReloadConfig(LTDC_VBReload);
/* Reconfigure the Layer pixel format in accordance with the picture */
if ((bit_pixel/8) == 4)
{
LTDC_LayerPixelFormat(LTDC_Layer2, LTDC_Pixelformat_ARGB8888);
LTDC_ReloadConfig(LTDC_VBReload);
}
else if ((bit_pixel/8) == 2)
{
LTDC_LayerPixelFormat(LTDC_Layer2, LTDC_Pixelformat_RGB565);
LTDC_ReloadConfig(LTDC_VBReload);
}
else
{
LTDC_LayerPixelFormat(LTDC_Layer2, LTDC_Pixelformat_RGB888);
LTDC_ReloadConfig(LTDC_VBReload);
}
}
/* compute the real size of the picture (without the header)) */
size = (size - index);
/* bypass the bitmap header */
BmpAddress += index;
/* start copie image from the bottom */
Address += width*(height-1)*(bit_pixel/8);
for(index = 0; index < size; index++)
{
*(__IO uint8_t*) (Address) = *(__IO uint8_t *)BmpAddress;
/*jump on next byte */
BmpAddress++;
Address++;
currentline++;
if((currentline/(bit_pixel/8)) == width)
{
if(linenumber < height)
{
linenumber++;
Address -=(2*width*(bit_pixel/8));
currentline = 0;
}
}
}
}
/**
* @brief Displays a full rectangle.
* @param Xpos: specifies the X position, can be a value from 0 to 240.
* @param Ypos: specifies the Y position, can be a value from 0 to 320.
* @param Height: rectangle height.
* @param Width: rectangle width.
* @retval None
*/
void LCD_DrawFullRect(uint16_t Xpos, uint16_t Ypos, uint16_t Width, uint16_t Height)
{
DMA2D_InitTypeDef DMA2D_InitStruct;
uint32_t Xaddress = 0;
uint16_t Red_Value = 0, Green_Value = 0, Blue_Value = 0;
Red_Value = (0xF800 & CurrentTextColor) >> 11;
Blue_Value = 0x001F & CurrentTextColor;
Green_Value = (0x07E0 & CurrentTextColor) >> 5;
Xaddress = CurrentFrameBuffer + 2*(LCD_PIXEL_WIDTH*Ypos + Xpos);
/* configure DMA2D */
DMA2D_DeInit();
DMA2D_InitStruct.DMA2D_Mode = DMA2D_R2M;
DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB565;
DMA2D_InitStruct.DMA2D_OutputGreen = Green_Value;
DMA2D_InitStruct.DMA2D_OutputBlue = Blue_Value;
DMA2D_InitStruct.DMA2D_OutputRed = Red_Value;
DMA2D_InitStruct.DMA2D_OutputAlpha = 0x0F;
DMA2D_InitStruct.DMA2D_OutputMemoryAdd = Xaddress;
DMA2D_InitStruct.DMA2D_OutputOffset = (LCD_PIXEL_WIDTH - Width);
DMA2D_InitStruct.DMA2D_NumberOfLine = Height;
DMA2D_InitStruct.DMA2D_PixelPerLine = Width;
DMA2D_Init(&DMA2D_InitStruct);
/* Start Transfer */
DMA2D_StartTransfer();
/* Wait for CTC Flag activation */
while(DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET)
{
}
LCD_SetTextColor(CurrentTextColor);
}
/**
* @brief Displays a full circle.
* @param Xpos: specifies the X position, can be a value from 0 to 240.
* @param Ypos: specifies the Y position, can be a value from 0 to 320.
* @param Radius
* @retval None
*/
void LCD_DrawFullCircle(uint16_t Xpos, uint16_t Ypos, uint16_t Radius)
{
int32_t D; /* Decision Variable */
uint32_t CurX;/* Current X Value */
uint32_t CurY;/* Current Y Value */
D = 3 - (Radius << 1);
CurX = 0;
CurY = Radius;
while (CurX <= CurY)
{
if(CurY > 0)
{
LCD_DrawLine(Xpos - CurX, Ypos - CurY, 2*CurY, LCD_DIR_VERTICAL);
LCD_DrawLine(Xpos + CurX, Ypos - CurY, 2*CurY, LCD_DIR_VERTICAL);
}
if(CurX > 0)
{
LCD_DrawLine(Xpos - CurY, Ypos - CurX, 2*CurX, LCD_DIR_VERTICAL);
LCD_DrawLine(Xpos + CurY, Ypos - CurX, 2*CurX, LCD_DIR_VERTICAL);
}
if (D < 0)
{
D += (CurX << 2) + 6;
}
else
{
D += ((CurX - CurY) << 2) + 10;
CurY--;
}
CurX++;
}
LCD_DrawCircle(Xpos, Ypos, Radius);
}
/**
* @brief Displays an uni-line (between two points).
* @param x1: specifies the point 1 x position.
* @param y1: specifies the point 1 y position.
* @param x2: specifies the point 2 x position.
* @param y2: specifies the point 2 y position.
* @retval None
*/
void LCD_DrawUniLine(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2)
{
int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,
curpixel = 0;
deltax = ABS(x2 - x1); /* The difference between the x's */
deltay = ABS(y2 - y1); /* The difference between the y's */
x = x1; /* Start x off at the first pixel */
y = y1; /* Start y off at the first pixel */
if (x2 >= x1) /* The x-values are increasing */
{
xinc1 = 1;
xinc2 = 1;
}
else /* The x-values are decreasing */
{
xinc1 = -1;
xinc2 = -1;
}
if (y2 >= y1) /* The y-values are increasing */
{
yinc1 = 1;
yinc2 = 1;
}
else /* The y-values are decreasing */
{
yinc1 = -1;
yinc2 = -1;
}
if (deltax >= deltay) /* There is at least one x-value for every y-value */
{
xinc1 = 0; /* Don't change the x when numerator >= denominator */
yinc2 = 0; /* Don't change the y for every iteration */
den = deltax;
num = deltax / 2;
numadd = deltay;
numpixels = deltax; /* There are more x-values than y-values */
}
else /* There is at least one y-value for every x-value */
{
xinc2 = 0; /* Don't change the x for every iteration */
yinc1 = 0; /* Don't change the y when numerator >= denominator */
den = deltay;
num = deltay / 2;
numadd = deltax;
numpixels = deltay; /* There are more y-values than x-values */
}
for (curpixel = 0; curpixel <= numpixels; curpixel++)
{
PutPixel(x, y); /* Draw the current pixel */
num += numadd; /* Increase the numerator by the top of the fraction */
if (num >= den) /* Check if numerator >= denominator */
{
num -= den; /* Calculate the new numerator value */
x += xinc1; /* Change the x as appropriate */
y += yinc1; /* Change the y as appropriate */
}
x += xinc2; /* Change the x as appropriate */
y += yinc2; /* Change the y as appropriate */
}
}
/**
* @brief Displays an triangle.
* @param Points: pointer to the points array.
* @retval None
*/
void LCD_Triangle(pPoint Points, uint16_t PointCount)
{
int16_t X = 0, Y = 0;
pPoint First = Points;
if(PointCount != 3)
{
return;
}
while(--PointCount)
{
X = Points->X;
Y = Points->Y;
Points++;
LCD_DrawUniLine(X, Y, Points->X, Points->Y);
}
LCD_DrawUniLine(First->X, First->Y, Points->X, Points->Y);
}
/**
* @brief Fill an triangle (between 3 points).
* @param x1..3: x position of triangle point 1..3.
* @param y1..3: y position of triangle point 1..3.
* @retval None
*/
void LCD_FillTriangle(uint16_t x1, uint16_t x2, uint16_t x3, uint16_t y1, uint16_t y2, uint16_t y3)
{
int16_t deltax = 0, deltay = 0, x = 0, y = 0, xinc1 = 0, xinc2 = 0,
yinc1 = 0, yinc2 = 0, den = 0, num = 0, numadd = 0, numpixels = 0,
curpixel = 0;
deltax = ABS(x2 - x1); /* The difference between the x's */
deltay = ABS(y2 - y1); /* The difference between the y's */
x = x1; /* Start x off at the first pixel */
y = y1; /* Start y off at the first pixel */
if (x2 >= x1) /* The x-values are increasing */
{
xinc1 = 1;
xinc2 = 1;
}
else /* The x-values are decreasing */
{
xinc1 = -1;
xinc2 = -1;
}
if (y2 >= y1) /* The y-values are increasing */
{
yinc1 = 1;
yinc2 = 1;
}
else /* The y-values are decreasing */
{
yinc1 = -1;
yinc2 = -1;
}
if (deltax >= deltay) /* There is at least one x-value for every y-value */
{
xinc1 = 0; /* Don't change the x when numerator >= denominator */
yinc2 = 0; /* Don't change the y for every iteration */
den = deltax;
num = deltax / 2;
numadd = deltay;
numpixels = deltax; /* There are more x-values than y-values */
}
else /* There is at least one y-value for every x-value */
{
xinc2 = 0; /* Don't change the x for every iteration */
yinc1 = 0; /* Don't change the y when numerator >= denominator */
den = deltay;
num = deltay / 2;
numadd = deltax;
numpixels = deltay; /* There are more y-values than x-values */
}
for (curpixel = 0; curpixel <= numpixels; curpixel++)
{
LCD_DrawUniLine(x, y, x3, y3);
num += numadd; /* Increase the numerator by the top of the fraction */
if (num >= den) /* Check if numerator >= denominator */
{
num -= den; /* Calculate the new numerator value */
x += xinc1; /* Change the x as appropriate */
y += yinc1; /* Change the y as appropriate */
}
x += xinc2; /* Change the x as appropriate */
y += yinc2; /* Change the y as appropriate */
}
}
/**
* @brief Displays an poly-line (between many points).
* @param Points: pointer to the points array.
* @param PointCount: Number of points.
* @retval None
*/
void LCD_PolyLine(pPoint Points, uint16_t PointCount)
{
int16_t X = 0, Y = 0;
if(PointCount < 2)
{
return;
}
while(--PointCount)
{
X = Points->X;
Y = Points->Y;
Points++;
LCD_DrawUniLine(X, Y, Points->X, Points->Y);
}
}
/**
* @brief Displays an relative poly-line (between many points).
* @param Points: pointer to the points array.
* @param PointCount: Number of points.
* @param Closed: specifies if the draw is closed or not.
* 1: closed, 0 : not closed.
* @retval None
*/
static void LCD_PolyLineRelativeClosed(pPoint Points, uint16_t PointCount, uint16_t Closed)
{
int16_t X = 0, Y = 0;
pPoint First = Points;
if(PointCount < 2)
{
return;
}
X = Points->X;
Y = Points->Y;
while(--PointCount)
{
Points++;
LCD_DrawUniLine(X, Y, X + Points->X, Y + Points->Y);
X = X + Points->X;
Y = Y + Points->Y;
}
if(Closed)
{
LCD_DrawUniLine(First->X, First->Y, X, Y);
}
}
/**
* @brief Displays a closed poly-line (between many points).
* @param Points: pointer to the points array.
* @param PointCount: Number of points.
* @retval None
*/
void LCD_ClosedPolyLine(pPoint Points, uint16_t PointCount)
{
LCD_PolyLine(Points, PointCount);
LCD_DrawUniLine(Points->X, Points->Y, (Points+PointCount-1)->X, (Points+PointCount-1)->Y);
}
/**
* @brief Displays a relative poly-line (between many points).
* @param Points: pointer to the points array.
* @param PointCount: Number of points.
* @retval None
*/
void LCD_PolyLineRelative(pPoint Points, uint16_t PointCount)
{
LCD_PolyLineRelativeClosed(Points, PointCount, 0);
}
/**
* @brief Displays a closed relative poly-line (between many points).
* @param Points: pointer to the points array.
* @param PointCount: Number of points.
* @retval None
*/
void LCD_ClosedPolyLineRelative(pPoint Points, uint16_t PointCount)
{
LCD_PolyLineRelativeClosed(Points, PointCount, 1);
}
/**
* @brief Displays a full poly-line (between many points).
* @param Points: pointer to the points array.
* @param PointCount: Number of points.
* @retval None
*/
void LCD_FillPolyLine(pPoint Points, uint16_t PointCount)
{
int16_t X = 0, Y = 0, X2 = 0, Y2 = 0, X_center = 0, Y_center = 0, X_first = 0, Y_first = 0, pixelX = 0, pixelY = 0, counter = 0;
uint16_t IMAGE_LEFT = 0, IMAGE_RIGHT = 0, IMAGE_TOP = 0, IMAGE_BOTTOM = 0;
IMAGE_LEFT = IMAGE_RIGHT = Points->X;
IMAGE_TOP= IMAGE_BOTTOM = Points->Y;
for(counter = 1; counter < PointCount; counter++)
{
pixelX = POLY_X(counter);
if(pixelX < IMAGE_LEFT)
{
IMAGE_LEFT = pixelX;
}
if(pixelX > IMAGE_RIGHT)
{
IMAGE_RIGHT = pixelX;
}
pixelY = POLY_Y(counter);
if(pixelY < IMAGE_TOP)
{
IMAGE_TOP = pixelY;
}
if(pixelY > IMAGE_BOTTOM)
{
IMAGE_BOTTOM = pixelY;
}
}
if(PointCount < 2)
{
return;
}
X_center = (IMAGE_LEFT + IMAGE_RIGHT)/2;
Y_center = (IMAGE_BOTTOM + IMAGE_TOP)/2;
X_first = Points->X;
Y_first = Points->Y;
while(--PointCount)
{
X = Points->X;
Y = Points->Y;
Points++;
X2 = Points->X;
Y2 = Points->Y;
LCD_FillTriangle(X, X2, X_center, Y, Y2, Y_center);
LCD_FillTriangle(X, X_center, X2, Y, Y_center, Y2);
LCD_FillTriangle(X_center, X2, X, Y_center, Y2, Y);
}
LCD_FillTriangle(X_first, X2, X_center, Y_first, Y2, Y_center);
LCD_FillTriangle(X_first, X_center, X2, Y_first, Y_center, Y2);
LCD_FillTriangle(X_center, X2, X_first, Y_center, Y2, Y_first);
}
/**
* @brief Writes command to select the LCD register.
* @param LCD_Reg: address of the selected register.
* @retval None
*/
void LCD_WriteCommand(uint8_t LCD_Reg)
{
/* Reset WRX to send command */
LCD_CtrlLinesWrite(LCD_WRX_GPIO_PORT, LCD_WRX_PIN, Bit_RESET);
/* Reset LCD control line(/CS) and Send command */
LCD_ChipSelect(DISABLE);
SPI_I2S_SendData(LCD_SPI, LCD_Reg);
/* Wait until a data is sent(not busy), before config /CS HIGH */
while(SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_TXE) == RESET) ;
while(SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_BSY) != RESET);
LCD_ChipSelect(ENABLE);
}
/**
* @brief Writes data to select the LCD register.
* This function must be used after LCD_WriteCommand() function
* @param value: data to write to the selected register.
* @retval None
*/
void LCD_WriteData(uint8_t value)
{
/* Set WRX to send data */
LCD_CtrlLinesWrite(LCD_WRX_GPIO_PORT, LCD_WRX_PIN, Bit_SET);
/* Reset LCD control line(/CS) and Send data */
LCD_ChipSelect(DISABLE);
SPI_I2S_SendData(LCD_SPI, value);
/* Wait until a data is sent(not busy), before config /CS HIGH */
while(SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_TXE) == RESET) ;
while(SPI_I2S_GetFlagStatus(LCD_SPI, SPI_I2S_FLAG_BSY) != RESET);
LCD_ChipSelect(ENABLE);
}
/**
* @brief Configure the LCD controller (Power On sequence as described in ILI9341 Datasheet)
* @param None
* @retval None
*/
void LCD_PowerOn(void)
{
LCD_WriteCommand(0xCA);
LCD_WriteData(0xC3);
LCD_WriteData(0x08);
LCD_WriteData(0x50);
LCD_WriteCommand(LCD_POWERB);
LCD_WriteData(0x00);
LCD_WriteData(0xC1);
LCD_WriteData(0x30);
LCD_WriteCommand(LCD_POWER_SEQ);
LCD_WriteData(0x64);
LCD_WriteData(0x03);
LCD_WriteData(0x12);
LCD_WriteData(0x81);
LCD_WriteCommand(LCD_DTCA);
LCD_WriteData(0x85);
LCD_WriteData(0x00);
LCD_WriteData(0x78);
LCD_WriteCommand(LCD_POWERA);
LCD_WriteData(0x39);
LCD_WriteData(0x2C);
LCD_WriteData(0x00);
LCD_WriteData(0x34);
LCD_WriteData(0x02);
LCD_WriteCommand(LCD_PRC);
LCD_WriteData(0x20);
LCD_WriteCommand(LCD_DTCB);
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteCommand(LCD_FRC);
LCD_WriteData(0x00);
LCD_WriteData(0x1B);
LCD_WriteCommand(LCD_DFC);
LCD_WriteData(0x0A);
LCD_WriteData(0xA2);
LCD_WriteCommand(LCD_POWER1);
LCD_WriteData(0x10);
LCD_WriteCommand(LCD_POWER2);
LCD_WriteData(0x10);
LCD_WriteCommand(LCD_VCOM1);
LCD_WriteData(0x45);
LCD_WriteData(0x15);
LCD_WriteCommand(LCD_VCOM2);
LCD_WriteData(0x90);
LCD_WriteCommand(LCD_MAC);
LCD_WriteData(0xC8);
LCD_WriteCommand(LCD_3GAMMA_EN);
LCD_WriteData(0x00);
LCD_WriteCommand(LCD_RGB_INTERFACE);
LCD_WriteData(0xC2);
LCD_WriteCommand(LCD_DFC);
LCD_WriteData(0x0A);
LCD_WriteData(0xA7);
LCD_WriteData(0x27);
LCD_WriteData(0x04);
/* colomn address set */
LCD_WriteCommand(LCD_COLUMN_ADDR);
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0xEF);
/* Page Address Set */
LCD_WriteCommand(LCD_PAGE_ADDR);
LCD_WriteData(0x00);
LCD_WriteData(0x00);
LCD_WriteData(0x01);
LCD_WriteData(0x3F);
LCD_WriteCommand(LCD_INTERFACE);
LCD_WriteData(0x01);
LCD_WriteData(0x00);
LCD_WriteData(0x06);
LCD_WriteCommand(LCD_GRAM);
delay(200);
LCD_WriteCommand(LCD_GAMMA);
LCD_WriteData(0x01);
LCD_WriteCommand(LCD_PGAMMA);
LCD_WriteData(0x0F);
LCD_WriteData(0x29);
LCD_WriteData(0x24);
LCD_WriteData(0x0C);
LCD_WriteData(0x0E);
LCD_WriteData(0x09);
LCD_WriteData(0x4E);
LCD_WriteData(0x78);
LCD_WriteData(0x3C);
LCD_WriteData(0x09);
LCD_WriteData(0x13);
LCD_WriteData(0x05);
LCD_WriteData(0x17);
LCD_WriteData(0x11);
LCD_WriteData(0x00);
LCD_WriteCommand(LCD_NGAMMA);
LCD_WriteData(0x00);
LCD_WriteData(0x16);
LCD_WriteData(0x1B);
LCD_WriteData(0x04);
LCD_WriteData(0x11);
LCD_WriteData(0x07);
LCD_WriteData(0x31);
LCD_WriteData(0x33);
LCD_WriteData(0x42);
LCD_WriteData(0x05);
LCD_WriteData(0x0C);
LCD_WriteData(0x0A);
LCD_WriteData(0x28);
LCD_WriteData(0x2F);
LCD_WriteData(0x0F);
LCD_WriteCommand(LCD_SLEEP_OUT);
delay(200);
LCD_WriteCommand(LCD_DISPLAY_ON);
/* GRAM start writing */
LCD_WriteCommand(LCD_GRAM);
}
/**
* @brief Enables the Display.
* @param None
* @retval None
*/
void LCD_DisplayOn(void)
{
LCD_WriteCommand(LCD_DISPLAY_ON);
}
/**
* @brief Disables the Display.
* @param None
* @retval None
*/
void LCD_DisplayOff(void)
{
/* Display Off */
LCD_WriteCommand(LCD_DISPLAY_OFF);
}
/**
* @brief Configures LCD control lines in Output Push-Pull mode.
* @note The LCD_NCS line can be configured in Open Drain mode
* when VDDIO is lower than required LCD supply.
* @param None
* @retval None
*/
void LCD_CtrlLinesConfig(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOs clock*/
RCC_AHB1PeriphClockCmd(LCD_NCS_GPIO_CLK | LCD_WRX_GPIO_CLK, ENABLE);
/* Configure NCS in Output Push-Pull mode */
GPIO_InitStructure.GPIO_Pin = LCD_NCS_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(LCD_NCS_GPIO_PORT, &GPIO_InitStructure);
/* Configure WRX in Output Push-Pull mode */
GPIO_InitStructure.GPIO_Pin = LCD_WRX_PIN;
GPIO_Init(LCD_WRX_GPIO_PORT, &GPIO_InitStructure);
/* Set chip select pin high */
LCD_CtrlLinesWrite(LCD_NCS_GPIO_PORT, LCD_NCS_PIN, Bit_SET);
}
/**
* @brief Sets or reset LCD control lines.
* @param GPIOx: where x can be B or D to select the GPIO peripheral.
* @param CtrlPins: the Control line.
* This parameter can be:
* @arg LCD_NCS_PIN: Chip Select pin
* @arg LCD_NWR_PIN: Read/Write Selection pin
* @arg LCD_RS_PIN: Register/RAM Selection pin
* @param BitVal: specifies the value to be written to the selected bit.
* This parameter can be:
* @arg Bit_RESET: to clear the port pin
* @arg Bit_SET: to set the port pin
* @retval None
*/
void LCD_CtrlLinesWrite(GPIO_TypeDef* GPIOx, uint16_t CtrlPins, BitAction BitVal)
{
/* Set or Reset the control line */
GPIO_WriteBit(GPIOx, (uint16_t)CtrlPins, (BitAction)BitVal);
}
/**
* @brief Configures the LCD_SPI interface.
* @param None
* @retval None
*/
void LCD_SPIConfig(void)
{
SPI_InitTypeDef SPI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable LCD_SPI_SCK_GPIO_CLK, LCD_SPI_MISO_GPIO_CLK and LCD_SPI_MOSI_GPIO_CLK clock */
RCC_AHB1PeriphClockCmd(LCD_SPI_SCK_GPIO_CLK | LCD_SPI_MISO_GPIO_CLK | LCD_SPI_MOSI_GPIO_CLK, ENABLE);
/* Enable LCD_SPI and SYSCFG clock */
RCC_APB2PeriphClockCmd(LCD_SPI_CLK, ENABLE);
/* Configure LCD_SPI SCK pin */
GPIO_InitStructure.GPIO_Pin = LCD_SPI_SCK_PIN;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_25MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_Init(LCD_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);
/* Configure LCD_SPI MISO pin */
GPIO_InitStructure.GPIO_Pin = LCD_SPI_MISO_PIN;
GPIO_Init(LCD_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);
/* Configure LCD_SPI MOSI pin */
GPIO_InitStructure.GPIO_Pin = LCD_SPI_MOSI_PIN;
GPIO_Init(LCD_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);
/* Connect SPI SCK */
GPIO_PinAFConfig(LCD_SPI_SCK_GPIO_PORT, LCD_SPI_SCK_SOURCE, LCD_SPI_SCK_AF);
/* Connect SPI MISO */
GPIO_PinAFConfig(LCD_SPI_MISO_GPIO_PORT, LCD_SPI_MISO_SOURCE, LCD_SPI_MISO_AF);
/* Connect SPI MOSI */
GPIO_PinAFConfig(LCD_SPI_MOSI_GPIO_PORT, LCD_SPI_MOSI_SOURCE, LCD_SPI_MOSI_AF);
SPI_I2S_DeInit(LCD_SPI);
/* SPI configuration -------------------------------------------------------*/
/* If the SPI peripheral is already enabled, don't reconfigure it */
if ((LCD_SPI->CR1 & SPI_CR1_SPE) == 0)
{
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
/* SPI baudrate is set to 5.6 MHz (PCLK2/SPI_BaudRatePrescaler = 90/16 = 5.625 MHz)
to verify these constraints:
- ILI9341 LCD SPI interface max baudrate is 10MHz for write and 6.66MHz for read
- l3gd20 SPI interface max baudrate is 10MHz for write/read
- PCLK2 frequency is set to 90 MHz
*/
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(LCD_SPI, &SPI_InitStructure);
/* Enable L3GD20_SPI */
SPI_Cmd(LCD_SPI, ENABLE);
}
}
/**
* @brief GPIO config for LTDC.
* @param None
* @retval None
*/
static void LCD_AF_GPIOConfig(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* Enable GPIOA, GPIOB, GPIOC, GPIOD, GPIOF, GPIOG AHB Clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | \
RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | \
RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOG, ENABLE);
/* GPIOs Configuration */
/*
+------------------------+-----------------------+----------------------------+
+ LCD pins assignment +
+------------------------+-----------------------+----------------------------+
| LCD_TFT R2 <-> PC.10 | LCD_TFT G2 <-> PA.06 | LCD_TFT B2 <-> PD.06 |
| LCD_TFT R3 <-> PB.00 | LCD_TFT G3 <-> PG.10 | LCD_TFT B3 <-> PG.11 |
| LCD_TFT R4 <-> PA.11 | LCD_TFT G4 <-> PB.10 | LCD_TFT B4 <-> PG.12 |
| LCD_TFT R5 <-> PA.12 | LCD_TFT G5 <-> PB.11 | LCD_TFT B5 <-> PA.03 |
| LCD_TFT R6 <-> PB.01 | LCD_TFT G6 <-> PC.07 | LCD_TFT B6 <-> PB.08 |
| LCD_TFT R7 <-> PG.06 | LCD_TFT G7 <-> PD.03 | LCD_TFT B7 <-> PB.09 |
-------------------------------------------------------------------------------
| LCD_TFT HSYNC <-> PC.06 | LCDTFT VSYNC <-> PA.04 |
| LCD_TFT CLK <-> PG.07 | LCD_TFT DE <-> PF.10 |
-----------------------------------------------------
*/
/* GPIOA configuration */
GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource11, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource12, GPIO_AF_LTDC);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_6 | \
GPIO_Pin_11 | GPIO_Pin_12;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOA, &GPIO_InitStruct);
/* GPIOB configuration */
GPIO_PinAFConfig(GPIOB, GPIO_PinSource0, 0x09);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource1, 0x09);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_LTDC);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8 | \
GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;
GPIO_Init(GPIOB, &GPIO_InitStruct);
/* GPIOC configuration */
GPIO_PinAFConfig(GPIOC, GPIO_PinSource6, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource7, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_LTDC);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10;
GPIO_Init(GPIOC, &GPIO_InitStruct);
/* GPIOD configuration */
GPIO_PinAFConfig(GPIOD, GPIO_PinSource3, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_LTDC);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_6;
GPIO_Init(GPIOD, &GPIO_InitStruct);
/* GPIOF configuration */
GPIO_PinAFConfig(GPIOF, GPIO_PinSource10, GPIO_AF_LTDC);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
GPIO_Init(GPIOF, &GPIO_InitStruct);
/* GPIOG configuration */
GPIO_PinAFConfig(GPIOG, GPIO_PinSource6, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource7, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource10, 0x09);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource11, GPIO_AF_LTDC);
GPIO_PinAFConfig(GPIOG, GPIO_PinSource12, 0x09);
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_10 | \
GPIO_Pin_11 | GPIO_Pin_12;
GPIO_Init(GPIOG, &GPIO_InitStruct);
}
/**
* @brief Displays a pixel.
* @param x: pixel x.
* @param y: pixel y.
* @retval None
*/
static void PutPixel(int16_t x, int16_t y)
{
if(x < 0 || x > 239 || y < 0 || y > 319)
{
return;
}
LCD_DrawLine(x, y, 1, LCD_DIR_HORIZONTAL);
}
#ifndef USE_Delay
/**
* @brief Inserts a delay time.
* @param nCount: specifies the delay time length.
* @retval None
*/
static void delay(__IO uint32_t nCount)
{
__IO int32_t index = 0;
for(index = nCount; index > 0; index--)
{
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
asm volatile("nop");
}
}
#endif /* USE_Delay*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/**
* @}
*/
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/