/** ****************************************************************************** * @file ls016b8uy.c * @author MCD Application Team * @version V1.0.0 * @date 22-April-2016 * @brief This file includes the LCD driver for LS016B8UY LCD. ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2016 STMicroelectronics

* * 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 "ls016b8uy.h" /** @addtogroup BSP * @{ */ /** @addtogroup Components * @{ */ /** @addtogroup ls016b8uy * @brief This file provides a set of functions needed to drive the * LS016B8UY LCD. * @{ */ /** @defgroup LS016B8UY_Private_TypesDefinitions * @{ */ typedef struct { uint8_t red; uint8_t green; uint8_t blue; } LS016B8UY_Rgb888; /** * @} */ /** @defgroup LS016B8UY_Private_Defines * @{ */ /** * @} */ /** @defgroup LS016B8UY_Private_Macros * @{ */ /** * @} */ /** @defgroup LS016B8UY_Private_Variables * @{ */ LCD_DrvTypeDef ls016b8uy_drv = { ls016b8uy_Init, ls016b8uy_ReadID, ls016b8uy_DisplayOn, ls016b8uy_DisplayOff, ls016b8uy_SetCursor, ls016b8uy_WritePixel, ls016b8uy_ReadPixel, ls016b8uy_SetDisplayWindow, ls016b8uy_DrawHLine, ls016b8uy_DrawVLine, ls016b8uy_GetLcdPixelWidth, ls016b8uy_GetLcdPixelHeight, ls016b8uy_DrawBitmap, ls016b8uy_DrawRGBImage, }; static uint16_t WindowsXstart = 0; static uint16_t WindowsYstart = 0; static uint16_t WindowsXend = LS016B8UY_LCD_PIXEL_WIDTH-1; static uint16_t WindowsYend = LS016B8UY_LCD_PIXEL_HEIGHT-1; /** * @} */ /** @defgroup LS016B8UY_Private_FunctionPrototypes * @{ */ static LS016B8UY_Rgb888 ls016b8uy_ReadPixel_rgb888(uint16_t Xpos, uint16_t Ypos); static void ls016b8uy_DrawRGBHLine(uint16_t Xpos, uint16_t Ypos, uint16_t Xsize, uint8_t *pdata); /** * @} */ /** @defgroup LS016B8UY_Private_Functions * @{ */ /** * @brief Initialize the LS016B8UY LCD Component. * @param None * @retval None */ void ls016b8uy_Init(void) { uint8_t parameter[4]; uint32_t i; /* Initialize LS016B8UY low level bus layer ----------------------------------*/ LCD_IO_Init(); parameter[0] = 0x00; /* VSYNC output */ ls016b8uy_WriteReg(LCD_CMD_VSYNC_OUTPUT, parameter, 1); parameter[0] = 0x06; /* 18 bits color mode */ ls016b8uy_WriteReg(LCD_CMD_COLOR_MODE, parameter, 1); parameter[0] = 0x01; /* Panel setting command */ parameter[1] = 0xFE; ls016b8uy_WriteReg(LCD_CMD_PANEL_SETTING_1, parameter, 2); parameter[0] = 0xDE; /* Panel setting command */ parameter[1] = 0x21; ls016b8uy_WriteReg(LCD_CMD_PANEL_SETTING_2, parameter, 2); parameter[0] = 0x05; /* V-Porch setting */ parameter[1] = 0x33; ls016b8uy_WriteReg(LCD_CMD_PANEL_V_PORCH, parameter, 2); parameter[0] = 0x05; /* Idle mode V-Porch setting */ parameter[1] = 0x33; ls016b8uy_WriteReg(LCD_CMD_PANEL_IDLE_V_PORCH, parameter, 2); parameter[0] = 0x04; /* panel timing setting */ parameter[1] = 0x03; ls016b8uy_WriteReg(LCD_CMD_PANEL_TIMING_1, parameter, 2); parameter[0] = 0x5E; /* panel timing setting */ parameter[1] = 0x08; ls016b8uy_WriteReg(LCD_CMD_PANEL_TIMING_2, parameter, 2); parameter[0] = 0x0A; /* panel timing setting */ parameter[1] = 0x0C; parameter[2] = 0x02; ls016b8uy_WriteReg(LCD_CMD_PANEL_TIMING_3, parameter, 3); parameter[0] = 0x03; /* panel timing setting */ parameter[1] = 0x04; ls016b8uy_WriteReg(LCD_CMD_PANEL_TIMING_4, parameter, 2); parameter[0] = 0x0C; /* panel power setting */ ls016b8uy_WriteReg(LCD_CMD_PANEL_POWER, parameter, 1); parameter[0] = 0x02; /* Oscillator Setting = 2MHz */ ls016b8uy_WriteReg(LCD_CMD_OSCILLATOR, parameter, 1); parameter[0] = 0x53; /* GVDD = 4.76V setting */ ls016b8uy_WriteReg(LCD_CMD_GVDD, parameter, 1); parameter[0] = 0x00; /* Reload MTP After SLPOUT */ parameter[1] = 0x45; /* VCOMH=3.76V */ ls016b8uy_WriteReg(LCD_CMD_RELOAD_MTP_VCOMH, parameter, 2); parameter[0] = 0x03; /* OP-Amp Ability. (Normal) */ parameter[1] = 0x12; /* Step-up Cycle for AVDD Booster Freq./4 */ ls016b8uy_WriteReg(LCD_CMD_OPAMP, parameter, 2); parameter[0] = 0x00; /* Tearing Effect Option (00h:VSYNC Interface OFF, 01h:VSYNC Interface ON) */ ls016b8uy_WriteReg(LCD_CMD_TEARING_EFFECT, parameter, 1); ls016b8uy_WriteReg(LCD_CMD_PANEL_SETTING_LOCK, parameter, 0); /* Panel setting command */ ls016b8uy_WriteReg(LCD_CMD_SLEEP_OUT, parameter, 0); /* Sleep Out Command */ LCD_IO_Delay(150); /* Wait for 150ms */ parameter[0] = 0x00; /* CASET */ parameter[1] = 0x1E; parameter[2] = 0x00; parameter[3] = 0xD1; ls016b8uy_WriteReg(LCD_CMD_CASET, parameter, 4); parameter[0] = 0x00; /* RASET */ parameter[1] = 0x00; parameter[2] = 0x00; parameter[3] = 0xB3; ls016b8uy_WriteReg(LCD_CMD_RASET, parameter, 4); parameter[0] = 0x83; /* Normal display for Driver Down side */ ls016b8uy_WriteReg(LCD_CMD_NORMAL_DISPLAY, parameter, 1); ls016b8uy_DisplayOn(); /* Display ON command */ /* Fill LCD frame memory with black pixels */ ls016b8uy_WriteReg(LCD_CMD_WRITE_RAM, parameter, 0); /* RAM Write Data */ for(i = 0; i < (LS016B8UY_LCD_PIXEL_WIDTH * LS016B8UY_LCD_PIXEL_HEIGHT * 3)/2; i++) { LCD_IO_WriteData(0x0000); } LCD_IO_Delay(20); /* Wait for 20ms */ } /** * @brief Enables the Display. * @param None * @retval None */ void ls016b8uy_DisplayOn(void) { ls016b8uy_WriteReg(LCD_CMD_DISPLAY_ON, (uint8_t*)NULL, 0); /* Display ON command */ ls016b8uy_WriteReg(LCD_CMD_IDLE_MODE_OFF, (uint8_t*)NULL, 0); /* Idle mode OFF command */ } /** * @brief Disables the Display. * @param None * @retval None */ void ls016b8uy_DisplayOff(void) { ls016b8uy_WriteReg(LCD_CMD_DISPLAY_OFF, (uint8_t*)NULL, 0); /* Display OFF command */ LCD_IO_Delay(20); /* Wait for 20ms */ ls016b8uy_WriteReg(LCD_CMD_SLEEP_IN, (uint8_t*)NULL, 0); /* Sleep In Command */ LCD_IO_Delay(150); /* Wait for 150ms */ } /** * @brief Get the LCD pixel Width. * @param None * @retval The Lcd Pixel Width */ uint16_t ls016b8uy_GetLcdPixelWidth(void) { return (uint16_t)LS016B8UY_LCD_PIXEL_WIDTH; } /** * @brief Get the LCD pixel Height. * @param None * @retval The Lcd Pixel Height */ uint16_t ls016b8uy_GetLcdPixelHeight(void) { return (uint16_t)LS016B8UY_LCD_PIXEL_HEIGHT; } /** * @brief Get the LS016B8UY ID. * @param None * @retval The LS016B8UY ID */ uint16_t ls016b8uy_ReadID(void) { LCD_IO_Init(); /* TODO : LCD read ID command not known for now, so assumption that the connected LCD is LS016B8UY */ return (LS016B8UY_ID); } /** * @brief Set Cursor position. * @param Xpos: specifies the X position. * @param Ypos: specifies the Y position. * @retval None */ void ls016b8uy_SetCursor(uint16_t Xpos, uint16_t Ypos) { uint8_t parameter[4]; parameter[0] = 0x00; /* CASET */ parameter[1] = 0x1E + Xpos; parameter[2] = 0x00; parameter[3] = 0xD1 + Xpos; ls016b8uy_WriteReg(LCD_CMD_CASET, parameter, 4); parameter[0] = 0x00; /* RASET */ parameter[1] = 0x00 + Ypos; parameter[2] = 0x00; parameter[3] = 0xB3 + Ypos; ls016b8uy_WriteReg(LCD_CMD_RASET, parameter, 4); } /** * @brief Write pixel. * @param Xpos: specifies the X position. * @param Ypos: specifies the Y position. * @param RGBCode: the RGB pixel color in RGB565 format * @retval None */ void ls016b8uy_WritePixel(uint16_t Xpos, uint16_t Ypos, uint16_t RGBCode) { uint16_t r, g, b; uint16_t rgb888_part1, rgb888_part2; r = (RGBCode & 0xF800) >> 11; /* Extract red component from RGB565 pixel data */ g = (RGBCode & 0x07E0) >> 5; /* Extract green component from RGB565 pixel data */ b = (RGBCode & 0x001F) >> 0; /* Extract blue component from RGB565 pixel data */ /* Prepare data to write with new pixel components and read old pixel component */ rgb888_part1 = (r << 11) + (g << 2); rgb888_part2 = (b << 11); /* Set Cursor */ ls016b8uy_SetCursor(Xpos, Ypos); /* Prepare to write to LCD RAM */ ls016b8uy_WriteReg(LCD_CMD_WRITE_RAM, (uint8_t*)NULL, 0); /* RAM write data command */ /* Write RAM data */ LCD_IO_WriteData(rgb888_part1); LCD_IO_WriteData(rgb888_part2); } /** * @brief Read pixel. * @param Xpos: specifies the X position. * @param Ypos: specifies the Y position. * @retval The RGB pixel color in RGB565 format */ uint16_t ls016b8uy_ReadPixel(uint16_t Xpos, uint16_t Ypos) { LS016B8UY_Rgb888 rgb888; uint8_t r, g, b; uint16_t rgb565; /* Set Cursor */ ls016b8uy_SetCursor(Xpos, Ypos); /* Read RGB888 data from LCD RAM */ rgb888 = ls016b8uy_ReadPixel_rgb888(Xpos, Ypos); /* Convert RGB888 to RGB565 */ r = ((rgb888.red & 0xF8) >> 3); /* Extract the red component 5 most significant bits */ g = ((rgb888.green & 0xFC) >> 2); /* Extract the green component 6 most significant bits */ b = ((rgb888.blue & 0xF8) >> 3); /* Extract the blue component 5 most significant bits */ rgb565 = ((uint16_t)(r) << 11) + ((uint16_t)(g) << 5) + ((uint16_t)(b) << 0); return (rgb565); } /** * @brief Writes to the selected LCD register. * @param Command: command value (or register address as named in LS016B8UY doc). * @param Parameters: pointer on parameters value (if command uses one or several parameters). * @param NbParameters: number of command parameters (0 if no parameter) * @retval None */ void ls016b8uy_WriteReg(uint8_t Command, uint8_t *Parameters, uint8_t NbParameters) { uint8_t i; /* Send command */ LCD_IO_WriteReg(Command); /* Send command's parameters if any */ for (i=0; i> 11; /* Extract red component from RGB565 pixel data */ g = (RGBCode & 0x07E0) >> 5; /* Extract green component from RGB565 pixel data */ b = (RGBCode & 0x001F) >> 0; /* Extract blue component from RGB565 pixel data */ rgb888_part1 = (r << 11) + (g << 2); /* Build pattern first part to write in LCD RAM */ rgb888_part2 = (b << 11) + (r << 3); /* Build pattern second part to write in LCD RAM */ rgb888_part3 = (g << 10) + (b << 3); /* Build pattern third part to write in LCD RAM */ /* Set Cursor */ ls016b8uy_SetCursor(Xpos, Ypos); /* Prepare to write to LCD RAM */ ls016b8uy_WriteReg(LCD_CMD_WRITE_RAM, (uint8_t*)NULL, 0); /* RAM write data command */ /* Sent a complete line */ for(counter = 0; counter < Length; counter+=2) { /* Write 2 pixels at a time by performing 3 access (pixels coded on 24 bits in LCD RAM whereas access are coded on 16 bits) */ LCD_IO_WriteData(rgb888_part1); LCD_IO_WriteData(rgb888_part2); if (counter != (Length-1)) /* When writing last pixel when Length is odd, the third part is not written */ { LCD_IO_WriteData(rgb888_part3); } } } /** * @brief Draw vertical line. * @param RGBCode: Specifies the RGB color * @param Xpos: specifies the X position. * @param Ypos: specifies the Y position. * @param Length: specifies the Line length. * @retval None */ void ls016b8uy_DrawVLine(uint16_t RGBCode, uint16_t Xpos, uint16_t Ypos, uint16_t Length) { uint16_t counter = 0; /* Set Cursor */ ls016b8uy_SetCursor(Xpos, Ypos); /* Prepare to write to LCD RAM */ ls016b8uy_WriteReg(LCD_CMD_WRITE_RAM, (uint8_t*)NULL, 0); /* RAM write data command */ /* Fill a complete vertical line */ for(counter = 0; counter < Length; counter++) { ls016b8uy_WritePixel(Xpos, Ypos + counter, RGBCode); } } /** * @brief Displays a bitmap picture. * @param BmpAddress: Bmp picture address. * @param Xpos: Bmp X position in the LCD * @param Ypos: Bmp Y position in the LCD * @retval None */ void ls016b8uy_DrawBitmap(uint16_t Xpos, uint16_t Ypos, uint8_t *pbmp) { uint32_t index = 0, size = 0; uint32_t posY; uint32_t nb_line = 0; uint16_t Xsize = WindowsXend - WindowsXstart + 1; uint16_t Ysize = WindowsYend - WindowsYstart + 1; /* Read bitmap size */ size = *(volatile uint16_t *) (pbmp + 2); size |= (*(volatile uint16_t *) (pbmp + 4)) << 16; /* Get bitmap data address offset */ index = *(volatile uint16_t *) (pbmp + 10); index |= (*(volatile uint16_t *) (pbmp + 12)) << 16; size = (size - index)/2; pbmp += index; for (posY = (Ypos + Ysize); posY > Ypos; posY--) /* In BMP files the line order is inverted */ { /* Set Cursor */ ls016b8uy_SetCursor(Xpos, posY - 1); /* Draw one line of the picture */ ls016b8uy_DrawRGBHLine(Xpos, posY - 1, Xsize, (pbmp + (nb_line * Xsize * 2))); nb_line++; } } /** * @brief Displays picture. * @param pdata: picture address. * @param Xpos: Image X position in the LCD * @param Ypos: Image Y position in the LCD * @param Xsize: Image X size in the LCD * @param Ysize: Image Y size in the LCD * @retval None */ void ls016b8uy_DrawRGBImage(uint16_t Xpos, uint16_t Ypos, uint16_t Xsize, uint16_t Ysize, uint8_t *pdata) { uint32_t posY; uint32_t nb_line = 0; for (posY = Ypos; posY < (Ypos + Ysize); posY ++) { /* Set Cursor */ ls016b8uy_SetCursor(Xpos, posY); /* Draw one line of the picture */ ls016b8uy_DrawRGBHLine(Xpos, posY, Xsize, (pdata + (nb_line * Xsize * 2))); nb_line++; } } /****************************************************************************** Static Functions *******************************************************************************/ /** * @brief Read pixel from LCD RAM in RGB888 format * @param Xpos: specifies the X position. * @param Ypos: specifies the Y position. * @retval Each RGB pixel color components in a structure */ static LS016B8UY_Rgb888 ls016b8uy_ReadPixel_rgb888(uint16_t Xpos, uint16_t Ypos) { LS016B8UY_Rgb888 rgb888; uint16_t rgb888_part1, rgb888_part2; /* In LCD RAM, pixels are 24 bits packed and read with 16 bits access * Here is the pixels components arrangement in memory : * bits: 15 14 13 12 11 10 09 08 | 07 06 05 04 03 02 01 00 * address 0 : red pixel 0 X X | green pixel 0 X X * address 1 : blue pixel 0 X X | red pixel 1 X X * address 2 : green pixel 1 X X | blue pixel 1 X X */ /* Set Cursor */ ls016b8uy_SetCursor(Xpos, Ypos); /* Prepare to read LCD RAM */ ls016b8uy_WriteReg(LCD_CMD_READ_RAM, (uint8_t*)NULL, 0); /* RAM read data command */ /* Dummy read */ LCD_IO_ReadData(); /* Read first part of the RGB888 data */ rgb888_part1 = LCD_IO_ReadData(); /* Read first part of the RGB888 data */ rgb888_part2 = LCD_IO_ReadData(); /* red component */ rgb888.red = (rgb888_part1 & 0xFC00) >> 8; /* green component */ rgb888.green = (rgb888_part1 & 0x00FC) >> 0; /* blue component */ rgb888.blue = (rgb888_part2 & 0xFC00) >> 8; return rgb888; } /** * @brief Displays a single picture line. * @param pdata: picture address. * @param Xpos: Image X position in the LCD * @param Ypos: Image Y position in the LCD * @param Xsize: Image X size in the LCD * @retval None */ static void ls016b8uy_DrawRGBHLine(uint16_t Xpos, uint16_t Ypos, uint16_t Xsize, uint8_t *pdata) { uint32_t i = 0; uint32_t posX; uint16_t r, g, b; uint16_t rgb888_part; uint16_t *rgb565 = (uint16_t*)pdata; /* Prepare to write to LCD RAM */ ls016b8uy_WriteReg(LCD_CMD_WRITE_RAM, (uint8_t*)NULL, 0); /* RAM write data command */ for (posX = Xpos; posX < (Xsize + Xpos); posX += 2) { if ((posX >= WindowsXstart) && (Ypos >= WindowsYstart) && /* Check we are in the defined window */ (posX <= WindowsXend) && (Ypos <= WindowsYend)) { /* Write pixels in LCD RAM after RGB565 -> RGB888 conversion */ /* As data in LCD RAM are 24bits packed, three 16 bits writes access are needed to transmit 2 pixels data */ r = (rgb565[i] & 0xF800) >> 11; /* Extract red component from first RGB565 pixel data */ g = (rgb565[i] & 0x07E0) >> 5; /* Extract green component from first RGB565 pixel data */ rgb888_part = (r << 11) + (g << 2); /* Build data to be written in LCD RAM */ LCD_IO_WriteData(rgb888_part); b = (rgb565[i] & 0x001F) >> 0; /* Extract blue component from first RGB565 pixel data */ r = (rgb565[i+1] & 0xF800) >> 11; /* Extract red component from second RGB565 pixel data */ rgb888_part = (b << 11) + (r << 3); /* Build data to be written in LCD RAM */ LCD_IO_WriteData(rgb888_part); if (posX != (Xsize + Xpos - 1)) /* When writing last pixel when size is odd, the third part is not written */ { g = (rgb565[i+1] & 0x07E0) >> 5; /* Extract green component from second RGB565 pixel data */ b = (rgb565[i+1] & 0x001F) >> 0; /* Extract blue component from second RGB565 pixel data */ rgb888_part = (g << 10) + (b << 3); /* Build data to be written in LCD RAM */ LCD_IO_WriteData(rgb888_part); } i += 2; } } } /** * @} */ /** * @} */ /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/