| /**************************************************************************** |
| * drivers/lcd/ili9341.c |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. The |
| * ASF licenses this file to you under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 |
| * |
| * 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. |
| * |
| ****************************************************************************/ |
| |
| /* References: ILI9341_DS_V1.10.pdf (Rev: 1.10), "a-Si TFT LCD Single Chip |
| * Driver 240RGBx320 Resolution and 262K color", |
| * ILI TECHNOLOGY CORP., http://www.ilitek.com. |
| */ |
| |
| /**************************************************************************** |
| * Included Files |
| ****************************************************************************/ |
| |
| #include <nuttx/config.h> |
| |
| #include <sys/types.h> |
| #include <stdint.h> |
| #include <stdbool.h> |
| #include <string.h> |
| #include <assert.h> |
| #include <errno.h> |
| #include <debug.h> |
| |
| #include <nuttx/arch.h> |
| #include <nuttx/lcd/lcd.h> |
| #include <nuttx/lcd/ili9341.h> |
| |
| #include <arch/irq.h> |
| |
| /**************************************************************************** |
| * Pre-processor Definitions |
| ****************************************************************************/ |
| |
| /* This is the generic lcd driver interface for the ili9341 Single Chip LCD |
| * driver. The driver supports multiple displays, each connected with an own |
| * ili9341 Single Chip LCD driver. The communication with the LCD single chip |
| * driver must be provide by a subdriver accessible through the ili9341_dev_s |
| * structure which is platform and MCU interface specific. |
| * |
| * Supported MCU interfaces (planned to support) |
| * |
| * Interface I |
| * |
| * 8080 MCU 8-bit bus interface |
| * 8080 MCU 16-bit bus interface |
| * 8080 MCU 9-bit bus interface |
| * 8080 MCU 18-bit bus interface |
| * 3-wire 9-bit data serial interface |
| * 4-wire 8-bit data serial interface |
| * |
| * Interface II |
| * |
| * 8080 MCU 8-bit bus interface |
| * 8080 MCU 16-bit bus interface |
| * 8080 MCU 9-bit bus interface |
| * 8080 MCU 18-bit bus interface |
| * 3-wire 9-bit data serial Interface |
| * 4-wire 8-bit data serial Interface |
| * |
| * Note! RGB interface will not supported by the lcd driver. |
| * It should be use with the platform specific RGB graphic controller and the |
| * nuttx framebuffer interface. |
| * |
| */ |
| |
| /* Fundamental command and parameter definition */ |
| |
| /* Interface control (IFCTL) |
| * |
| * |
| * Parameter 1: 0x0001 |
| * |
| * MY_EOR: 0 |
| * MX_EOR: 0 |
| * MV_EOR: 0 |
| * BGR_EOR: 0 |
| * WEMODE: 1 Reset column and page if data transfer exceeds |
| */ |
| #define ILI9341_IFCTL_MYEOR 0 |
| #define ILI9341_IFCTL_MXEOR 0 |
| #define ILI9341_IFCTL_MVEOR 0 |
| #define ILI9341_IFCTL_BGREOR 0 |
| #define ILI9341_IFCTL_WEMODE ILI9341_INTERFACE_CONTROL_WEMODE |
| |
| #define ILI9341_IFCTL_PARAM1 ILI9341_IFCTL_MYEOR | ILI9341_IFCTL_MXEOR | \ |
| ILI9341_IFCTL_MVEOR | ILI9341_IFCTL_BGREOR | \ |
| ILI9341_IFCTL_WEMODE |
| |
| /* Parameter 2: 0x0000 |
| * |
| * EPF: 0 65k color format for RGB interface, not used set to default |
| * MDT: 0 Display data transfer mode, not used |
| * |
| * Note! |
| * If RGB666 and 16-bit 8080-I interface supported by the driver, MDT must |
| * be defined for each selected driver instance. Leave it empty for now. |
| */ |
| |
| #define ILI9341_IFCTL_EPF ILI9341_INTERFACE_CONTROL_EPF(0) |
| #define ILI9341_IFCTL_MDT ILI9341_INTERFACE_CONTROL_MDT(0) |
| |
| #define ILI9341_IFCTL_PARAM2 ILI9341_IFCTL_EPF | ILI9341_IFCTL_MDT |
| |
| /* Parameter 3: 0x0000/0x0020 |
| * |
| * ENDIAN: 0/1 Depending on endian mode of the mcu? |
| * DM: 0 Internal clock operation |
| * RM: 0 System interface/VSYNC interface |
| * RIM: 0 RGB interface mode, unimportant set to default |
| * |
| */ |
| |
| #ifdef CONFIG_ENDIAN_BIG |
| # define ILI9341_IFCTL_ENDIAN 0 |
| #else |
| # define ILI9341_IFCTL_ENDIAN ILI9341_INTERFACE_CONTROL_ENDIAN |
| #endif |
| #define ILI9341_IFCTL_DM ILI9341_INTERFACE_CONTROL_DM(0) |
| #define ILI9341_IFCTL_RM 0 |
| #define ILI9341_IFCTL_RIM 0 |
| |
| #define ILI9341_IFCTL_PARAM3 ILI9341_IFCTL_RIM | ILI9341_IFCTL_RM | \ |
| ILI9341_IFCTL_DM | ILI9341_IFCTL_ENDIAN |
| |
| /* Memory access control (MADCTL) */ |
| |
| /* Landscape: 00100000 / 00101000 / h28 |
| * |
| * MY: 0 |
| * MX: 0 |
| * MV: 1 |
| * ML: 0 |
| * BGR: 0/1 Depending on endian mode of the mcu? |
| * MH: 0 |
| */ |
| |
| #define ILI9341_MADCTL_LANDSCAPE_MY 0 |
| #define ILI9341_MADCTL_LANDSCAPE_MX 0 |
| #define ILI9341_MADCTL_LANDSCAPE_MV ILI9341_MEMORY_ACCESS_CONTROL_MV |
| #define ILI9341_MADCTL_LANDSCAPE_ML 0 |
| #ifdef CONFIG_ENDIAN_BIG |
| # define ILI9341_MADCTL_LANDSCAPE_BGR 0 |
| #else |
| # define ILI9341_MADCTL_LANDSCAPE_BGR ILI9341_MEMORY_ACCESS_CONTROL_BGR |
| #endif |
| #define ILI9341_MADCTL_LANDSCAPE_MH 0 |
| |
| #define ILI9341_MADCTL_LANDSCAPE_PARAM1 (ILI9341_MADCTL_LANDSCAPE_MY | \ |
| ILI9341_MADCTL_LANDSCAPE_MX | \ |
| ILI9341_MADCTL_LANDSCAPE_MV | \ |
| ILI9341_MADCTL_LANDSCAPE_ML | \ |
| ILI9341_MADCTL_LANDSCAPE_BGR | \ |
| ILI9341_MADCTL_LANDSCAPE_MH) |
| |
| /* Portrait: 00000000 / 00001000 / h08 |
| * |
| * MY: 0 |
| * MX: 0 |
| * MV: 0 |
| * ML: 0 |
| * BGR: 0/1 Depending on endian mode of the mcu? |
| * MH: 0 |
| */ |
| |
| #define ILI9341_MADCTL_PORTRAIT_MY 0 |
| #define ILI9341_MADCTL_PORTRAIT_MX ILI9341_MEMORY_ACCESS_CONTROL_MX |
| #define ILI9341_MADCTL_PORTRAIT_MV 0 |
| #define ILI9341_MADCTL_PORTRAIT_ML ILI9341_MEMORY_ACCESS_CONTROL_ML |
| #ifdef CONFIG_ENDIAN_BIG |
| # define ILI9341_MADCTL_PORTRAIT_BGR 0 |
| #else |
| # define ILI9341_MADCTL_PORTRAIT_BGR ILI9341_MEMORY_ACCESS_CONTROL_BGR |
| #endif |
| #define ILI9341_MADCTL_PORTRAIT_MH 0 |
| |
| #define ILI9341_MADCTL_PORTRAIT_PARAM1 (ILI9341_MADCTL_PORTRAIT_MY | \ |
| ILI9341_MADCTL_PORTRAIT_MX | \ |
| ILI9341_MADCTL_PORTRAIT_MV | \ |
| ILI9341_MADCTL_PORTRAIT_ML | \ |
| ILI9341_MADCTL_PORTRAIT_BGR | \ |
| ILI9341_MADCTL_PORTRAIT_MH) |
| /* RLandscape: 01100000 / 01101000 / h68 |
| * |
| * MY: 0 |
| * MX: 1 |
| * MV: 1 |
| * ML: 0 |
| * BGR: 0/1 Depending on endian mode of the mcu? |
| * MH: 0 |
| */ |
| |
| #define ILI9341_MADCTL_RLANDSCAPE_MY ILI9341_MEMORY_ACCESS_CONTROL_MY |
| #define ILI9341_MADCTL_RLANDSCAPE_MX ILI9341_MEMORY_ACCESS_CONTROL_MX |
| #define ILI9341_MADCTL_RLANDSCAPE_MV ILI9341_MEMORY_ACCESS_CONTROL_MV |
| #define ILI9341_MADCTL_RLANDSCAPE_ML 0 |
| #ifdef CONFIG_ENDIAN_BIG |
| # define ILI9341_MADCTL_RLANDSCAPE_BGR 0 |
| #else |
| # define ILI9341_MADCTL_RLANDSCAPE_BGR ILI9341_MEMORY_ACCESS_CONTROL_BGR |
| #endif |
| #define ILI9341_MADCTL_RLANDSCAPE_MH 0 |
| |
| #define ILI9341_MADCTL_RLANDSCAPE_PARAM1 \ |
| (ILI9341_MADCTL_RLANDSCAPE_MY | \ |
| ILI9341_MADCTL_RLANDSCAPE_MX | \ |
| ILI9341_MADCTL_RLANDSCAPE_MV | \ |
| ILI9341_MADCTL_RLANDSCAPE_ML | \ |
| ILI9341_MADCTL_RLANDSCAPE_BGR | \ |
| ILI9341_MADCTL_RLANDSCAPE_MH) |
| |
| /* RPortrait: 11000000 / 11001000 / hc8 |
| * |
| * MY: 1 |
| * MX: 1 |
| * MV: 0 |
| * ML: 0 |
| * BGR: 0/1 Depending on endian mode of the mcu? |
| * MH: 0 |
| * |
| */ |
| |
| #define ILI9341_MADCTL_RPORTRAIT_MY ILI9341_MEMORY_ACCESS_CONTROL_MY |
| #define ILI9341_MADCTL_RPORTRAIT_MX 0 |
| #define ILI9341_MADCTL_RPORTRAIT_MV 0 |
| #define ILI9341_MADCTL_RPORTRAIT_ML ILI9341_MEMORY_ACCESS_CONTROL_ML |
| #ifdef CONFIG_ENDIAN_BIG |
| # define ILI9341_MADCTL_RPORTRAIT_BGR 0 |
| #else |
| # define ILI9341_MADCTL_RPORTRAIT_BGR ILI9341_MEMORY_ACCESS_CONTROL_BGR |
| #endif |
| #define ILI9341_MADCTL_RPORTRAIT_MH 0 |
| |
| #define ILI9341_MADCTL_RPORTRAIT_PARAM1 (ILI9341_MADCTL_RPORTRAIT_MY | \ |
| ILI9341_MADCTL_RPORTRAIT_MX | \ |
| ILI9341_MADCTL_RPORTRAIT_MV | \ |
| ILI9341_MADCTL_RPORTRAIT_ML | \ |
| ILI9341_MADCTL_RPORTRAIT_BGR | \ |
| ILI9341_MADCTL_RPORTRAIT_MH) |
| |
| /* Pixel Format Set (COLMOD) |
| * |
| * Note! RGB interface settings (DPI) is unimportant for the MCU interface |
| * mode but set the register to the defined state equal to the MCU interface |
| * pixel format. |
| * |
| * 16 Bit MCU: 01010101 / h55 |
| * |
| * DPI: 5 (RGB16-565 RGB interface, not used) |
| * DBI: 5 (RGB16-565 MCU interface |
| */ |
| |
| #define ILI9341_PIXSET_16BITDPI ILI9341_PIXEL_FORMAT_SET_DPI(5) |
| #define ILI9341_PIXSET_16BITDBI ILI9341_PIXEL_FORMAT_SET_DBI(5) |
| |
| #define ILI9341_PIXSET_16BITMCU_PARAM1 (ILI9341_PIXSET_16BITDPI | \ |
| ILI9341_PIXSET_16BITDBI) |
| |
| /* 18-bit MCU: 01100110 / h66 (not supported by nuttx until now) |
| * |
| * DPI: 6 (RGB18-666 RGB interface) |
| * DBI: 6 (RGB18-666 MCU interface) |
| */ |
| |
| #define ILI9341_PIXSET_18BITDPI ILI9341_PIXEL_FORMAT_SET_DPI(6) |
| #define ILI9341_PIXSET_18BITDBI ILI9341_PIXEL_FORMAT_SET_DBI(6) |
| |
| #define ILI9341_PIXSET_18BITMCU_PARAM1 (ILI9341_PIXSET_18BITDPI | \ |
| ILI9341_PIXSET_18BITDBI) |
| |
| /* General fix display resolution */ |
| |
| #define ILI9341_XRES 240 |
| #define ILI9341_YRES 320 |
| |
| /* Validate configuration */ |
| |
| #if CONFIG_LCD_ILI9341_NINTERFACES < 1 |
| # undef CONFIG_LCD_ILI9341_IFACE0 |
| #elif CONFIG_LCD_ILI9341_NINTERFACES < 2 |
| # undef CONFIG_LCD_ILI9341_IFACE1 |
| #endif |
| |
| /* First LCD display */ |
| |
| #ifdef CONFIG_LCD_ILI9341_IFACE0 |
| # if defined(CONFIG_LCD_ILI9341_IFACE0_LANDSCAPE) |
| # define ILI9341_IFACE0_ORIENT ILI9341_MADCTL_LANDSCAPE_PARAM1 |
| # define ILI9341_IFACE0_STRIDE ILI9341_YRES |
| # elif defined(CONFIG_LCD_ILI9341_IFACE0_PORTRAIT) |
| # define ILI9341_IFACE0_ORIENT ILI9341_MADCTL_PORTRAIT_PARAM1 |
| # define ILI9341_IFACE0_STRIDE ILI9341_XRES |
| # elif defined(CONFIG_LCD_ILI9341_IFACE0_RLANDSCAPE) |
| # define ILI9341_IFACE0_ORIENT ILI9341_MADCTL_RLANDSCAPE_PARAM1 |
| # define ILI9341_IFACE0_STRIDE ILI9341_YRES |
| # elif defined(CONFIG_LCD_ILI9341_IFACE0_RPORTRAIT) |
| # define ILI9341_IFACE0_ORIENT ILI9341_MADCTL_RPORTRAIT_PARAM1 |
| # define ILI9341_IFACE0_STRIDE ILI9341_XRES |
| # endif |
| # ifdef CONFIG_LCD_ILI9341_IFACE0_RGB565 |
| # define ILI9341_IFACE0_PXFMT FB_FMT_RGB16_565 |
| # define ILI9341_IFACE0_BPP 16 |
| # define ILI9341_IFACE0_BUFFER ILI9341_IFACE0_STRIDE |
| # else |
| # error "undefined pixel format for lcd interface 0" |
| # endif |
| #endif |
| |
| /* Second LCD display */ |
| |
| #ifdef CONFIG_LCD_ILI9341_IFACE1 |
| # ifdef CONFIG_LCD_ILI9341_IFACE1_LANDSCAPE |
| # define ILI9341_IFACE1_ORIENT ILI9341_MADCTL_LANDSCAPE_PARAM1 |
| # define ILI9341_IFACE1_STRIDE ILI9341_YRES |
| # elif CONFIG_LCD_ILI9341_IFACE1_PORTRAIT |
| # define ILI9341_IFACE1_ORIENT ILI9341_MADCTL_PORTRAIT_PARAM1 |
| # define ILI9341_IFACE1_STRIDE ILI9341_XRES |
| # elif CONFIG_LCD_ILI9341_IFACE1_RLANDSCAPE |
| # define ILI9341_IFACE1_ORIENT ILI9341_MADCTL_RLANDSCAPE_PARAM1 |
| # define ILI9341_IFACE1_STRIDE ILI9341_YRES |
| # elif CONFIG_LCD_ILI9341_IFACE1_RPORTRAIT |
| # define ILI9341_IFACE1_ORIENT ILI9341_MADCTL_RPORTRAIT_PARAM1 |
| # define ILI9341_IFACE1_STRIDE ILI9341_XRES |
| # endif |
| # ifdef CONFIG_LCD_ILI9341_IFACE1_RGB565 |
| # define ILI9341_IFACE1_PXFMT FB_FMT_RGB16_565 |
| # define ILI9341_IFACE1_BPP 16 |
| # define ILI9341_IFACE1_BUFFER ILI9341_IFACE1_STRIDE |
| # else |
| # error "undefined pixel format for lcd interface 1" |
| # endif |
| #endif |
| |
| /**************************************************************************** |
| * Private Type Definition |
| ****************************************************************************/ |
| |
| /* Each single connected ili9341 LCD driver needs an own driver instance |
| * to provide a unique getrun and putrun method. Also store fundamental |
| * parameter in driver internal structure. This minimal overhead should be |
| * acceptable. |
| */ |
| |
| struct ili9341_dev_s |
| { |
| /* Publicly visible device structure */ |
| |
| struct lcd_dev_s dev; |
| |
| /* Private driver-specific information follows */ |
| |
| FAR struct ili9341_lcd_s *lcd; |
| |
| /* Run buffer for the device */ |
| |
| uint16_t *runbuffer; |
| |
| /* Display orientation, e.g. Landscape, Portrait */ |
| |
| uint8_t orient; |
| |
| /* LCD driver pixel format */ |
| |
| uint8_t pxfmt; |
| |
| /* LCD driver color depth */ |
| |
| uint8_t bpp; |
| |
| /* Current power state of the device */ |
| |
| uint8_t power; |
| }; |
| |
| /**************************************************************************** |
| * Private Function Protototypes |
| ****************************************************************************/ |
| |
| /* Internal low level helpers */ |
| |
| static inline uint16_t ili9341_getxres(FAR struct ili9341_dev_s *dev); |
| static inline uint16_t ili9341_getyres(FAR struct ili9341_dev_s *dev); |
| |
| /* lcd data transfer methods */ |
| |
| static int ili9341_putrun(FAR struct lcd_dev_s *dev, fb_coord_t row, |
| fb_coord_t col, |
| FAR const uint8_t * buffer, size_t npixels); |
| #ifndef CONFIG_LCD_NOGETRUN |
| static int ili9341_getrun(FAR struct lcd_dev_s *dev, fb_coord_t row, |
| fb_coord_t col, FAR uint8_t * buffer, |
| size_t npixels); |
| #endif |
| |
| /* lcd configuration */ |
| |
| static int ili9341_getvideoinfo(FAR struct lcd_dev_s *dev, |
| FAR struct fb_videoinfo_s *vinfo); |
| static int ili9341_getplaneinfo(FAR struct lcd_dev_s *dev, |
| unsigned int planeno, |
| FAR struct lcd_planeinfo_s *pinfo); |
| |
| /* lcd specific controls */ |
| |
| static int ili9341_getpower(struct lcd_dev_s *dev); |
| static int ili9341_setpower(struct lcd_dev_s *dev, int power); |
| static int ili9341_getcontrast(struct lcd_dev_s *dev); |
| static int ili9341_setcontrast(struct lcd_dev_s *dev, unsigned int contrast); |
| |
| /**************************************************************************** |
| * Private Data |
| ****************************************************************************/ |
| |
| /* Initialize driver instance 1 < LCD_ILI9341_NINTERFACES */ |
| |
| #ifdef CONFIG_LCD_ILI9341_IFACE0 |
| static uint16_t g_runbuffer0[ILI9341_IFACE0_BUFFER]; |
| #endif |
| #ifdef CONFIG_LCD_ILI9341_IFACE1 |
| static uint16_t g_runbuffer1[ILI9341_IFACE1_BUFFER]; |
| #endif |
| |
| static struct ili9341_dev_s g_lcddev[CONFIG_LCD_ILI9341_NINTERFACES] = |
| { |
| #ifdef CONFIG_LCD_ILI9341_IFACE0 |
| { |
| .lcd = 0, |
| .runbuffer = g_runbuffer0, |
| .orient = ILI9341_IFACE0_ORIENT, |
| .pxfmt = ILI9341_IFACE0_PXFMT, |
| .bpp = ILI9341_IFACE0_BPP, |
| .power = 0, |
| }, |
| #endif |
| #ifdef CONFIG_LCD_ILI9341_IFACE1 |
| { |
| .lcd = 0, |
| .runbuffer = g_runbuffer1, |
| .orient = ILI9341_IFACE1_ORIENT, |
| .pxfmt = ILI9341_IFACE1_PXFMT, |
| .bpp = ILI9341_IFACE1_BPP, |
| .power = 0, |
| }, |
| #endif |
| }; |
| |
| /**************************************************************************** |
| * Private Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: ili9341_getxres |
| * |
| * Description: |
| * Get horizontal resolution of the connected LCD driver depending on the |
| * configured display orientation. |
| * |
| * Input Parameters: |
| * dev - Reference to private driver structure |
| * |
| * Returned Value: |
| * |
| * Horizontal resolution |
| * |
| ****************************************************************************/ |
| |
| static inline uint16_t ili9341_getxres(FAR struct ili9341_dev_s *dev) |
| { |
| if (dev->orient == ILI9341_MADCTL_LANDSCAPE_PARAM1 || |
| dev->orient == ILI9341_MADCTL_RLANDSCAPE_PARAM1) |
| { |
| return ILI9341_YRES; |
| } |
| |
| return ILI9341_XRES; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_getyres |
| * |
| * Description: |
| * Get vertical resolution of the connected LCD driver depending on the |
| * configured display orientation. |
| * |
| * Input Parameters: |
| * dev - Reference to private driver structure |
| * |
| * Returned Value: |
| * |
| * Vertical resolution |
| * |
| ****************************************************************************/ |
| |
| static inline uint16_t ili9341_getyres(FAR struct ili9341_dev_s *dev) |
| { |
| if (dev->orient == ILI9341_MADCTL_LANDSCAPE_PARAM1 || |
| dev->orient == ILI9341_MADCTL_RLANDSCAPE_PARAM1) |
| { |
| return ILI9341_XRES; |
| } |
| |
| return ILI9341_YRES; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_selectarea |
| * |
| * Description: |
| * Select the active area for displaying pixel |
| * |
| * Input Parameters: |
| * lcd - Reference to private driver structure |
| * x0 - Start x position |
| * y0 - Start y position |
| * x1 - End x position |
| * y1 - End y position |
| * |
| ****************************************************************************/ |
| |
| static void ili9341_selectarea(FAR struct ili9341_lcd_s *lcd, |
| uint16_t x0, uint16_t y0, |
| uint16_t x1, uint16_t y1) |
| { |
| /* Select column */ |
| |
| lcd->sendcmd(lcd, ILI9341_COLUMN_ADDRESS_SET); |
| lcd->sendparam(lcd, (x0 >> 8)); |
| lcd->sendparam(lcd, (x0 & 0xff)); |
| lcd->sendparam(lcd, (x1 >> 8)); |
| lcd->sendparam(lcd, (x1 & 0xff)); |
| |
| /* Select page */ |
| |
| lcd->sendcmd(lcd, ILI9341_PAGE_ADDRESS_SET); |
| lcd->sendparam(lcd, (y0 >> 8)); |
| lcd->sendparam(lcd, (y0 & 0xff)); |
| lcd->sendparam(lcd, (y1 >> 8)); |
| lcd->sendparam(lcd, (y1 & 0xff)); |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_putrun |
| * |
| * Description: |
| * Write a partial raster line to the LCD. |
| * |
| * Input Parameters: |
| * lcd_dev - The lcd device |
| * row - Starting row to write to (range: 0 <= row < yres) |
| * col - Starting column to write to (range: 0 <= col <= xres-npixels) |
| * buffer - The buffer containing the run to be written to the LCD |
| * npixels - The number of pixels to write to the |
| * (range: 0 < npixels <= xres-col) |
| * |
| * Returned Value: |
| * |
| * On success - OK |
| * On error - -EINVAL |
| * |
| ****************************************************************************/ |
| |
| static int ili9341_putrun(FAR struct lcd_dev_s *lcd_dev, fb_coord_t row, |
| fb_coord_t col, |
| FAR const uint8_t * buffer, size_t npixels) |
| { |
| FAR struct ili9341_dev_s *dev = (FAR struct ili9341_dev_s *)lcd_dev; |
| FAR struct ili9341_lcd_s *lcd = dev->lcd; |
| FAR const uint16_t *src = (FAR const uint16_t *)buffer; |
| |
| DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); |
| |
| /* Check if position outside of area */ |
| |
| if (col + npixels > ili9341_getxres(dev) || row > ili9341_getyres(dev)) |
| { |
| return -EINVAL; |
| } |
| |
| /* Select lcd driver */ |
| |
| lcd->select(lcd); |
| |
| /* Select column and area similar to the partial raster line */ |
| |
| ili9341_selectarea(lcd, col, row, col + npixels - 1, row); |
| |
| /* Send memory write cmd */ |
| |
| lcd->sendcmd(lcd, ILI9341_MEMORY_WRITE); |
| |
| /* Send pixel to gram */ |
| |
| lcd->sendgram(lcd, src, npixels); |
| |
| /* Deselect the lcd driver */ |
| |
| lcd->deselect(lcd); |
| |
| return OK; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_getrun |
| * |
| * Description: |
| * Read a partial raster line from the LCD. |
| * |
| * Input Parameters: |
| * lcd_dev - The lcd device |
| * row - Starting row to read from (range: 0 <= row < yres) |
| * col - Starting column to read read (range: 0 <= col <= xres-npixels) |
| * buffer - The buffer in which to return the run read from the LCD |
| * npixels - The number of pixels to read from the LCD |
| * (range: 0 < npixels <= xres-col) |
| * |
| * Returned Value: |
| * |
| * On success - OK |
| * On error - -EINVAL |
| * |
| ****************************************************************************/ |
| |
| # ifndef CONFIG_LCD_NOGETRUN |
| static int ili9341_getrun(FAR struct lcd_dev_s *lcd_dev, fb_coord_t row, |
| fb_coord_t col, FAR uint8_t * buffer, |
| size_t npixels) |
| { |
| FAR struct ili9341_dev_s *dev = (FAR struct ili9341_dev_s *)lcd_dev; |
| FAR struct ili9341_lcd_s *lcd = dev->lcd; |
| FAR uint16_t *dest = (FAR uint16_t *)buffer; |
| |
| DEBUGASSERT(buffer && ((uintptr_t)buffer & 1) == 0); |
| |
| /* Check if position outside of area */ |
| |
| if (col + npixels > ili9341_getxres(dev) || row > ili9341_getyres(dev)) |
| { |
| return -EINVAL; |
| } |
| |
| /* Select lcd driver */ |
| |
| lcd->select(lcd); |
| |
| /* Select column and area similar to the partial raster line */ |
| |
| ili9341_selectarea(lcd, col, row, col + npixels - 1, row); |
| |
| /* Send memory read cmd */ |
| |
| lcd->sendcmd(lcd, ILI9341_MEMORY_READ); |
| |
| /* Receive pixel to gram */ |
| |
| lcd->recvgram(lcd, dest, npixels); |
| |
| /* Deselect the lcd driver */ |
| |
| lcd->deselect(lcd); |
| |
| return OK; |
| } |
| #endif |
| |
| /**************************************************************************** |
| * Name: ili9341_hwinitialize |
| * |
| * Description: |
| * Initialize and configure the ILI9341 LCD driver hardware. |
| * |
| * Input Parameters: |
| * dev - A reference to the driver specific structure |
| * |
| * Returned Value: |
| * |
| * On success - OK |
| * On error - EINVAL |
| * |
| ****************************************************************************/ |
| |
| static int ili9341_hwinitialize(FAR struct ili9341_dev_s *dev) |
| { |
| #ifdef CONFIG_DEBUG_LCD_INFO |
| uint8_t param; |
| #endif |
| FAR struct ili9341_lcd_s *lcd = dev->lcd; |
| |
| /* Select spi device */ |
| |
| lcdinfo("Initialize lcd driver\n"); |
| lcd->select(lcd); |
| |
| #ifdef CONFIG_DEBUG_LCD_INFO |
| /* Read display identification */ |
| |
| lcd->sendcmd(lcd, ILI9341_READ_ID1); |
| lcd->recvparam(lcd, ¶m); |
| lcdinfo("ili9341 LCD driver: LCD modules manufacturer ID: %d\n", param); |
| |
| lcd->sendcmd(lcd, ILI9341_READ_ID2); |
| lcd->recvparam(lcd, ¶m); |
| lcdinfo("ili9341 LCD driver: LCD modules driver version ID: %d\n", param); |
| |
| lcd->sendcmd(lcd, ILI9341_READ_ID3); |
| lcd->recvparam(lcd, ¶m); |
| lcdinfo("ili9341 LCD driver: LCD modules driver ID: %d\n", param); |
| #endif |
| |
| /* Reset the lcd display to the default state */ |
| |
| lcdinfo("ili9341 LCD driver: Software Reset\n"); |
| lcd->sendcmd(lcd, ILI9341_SOFTWARE_RESET); |
| up_mdelay(5); |
| |
| lcdinfo("ili9341 LCD driver: set Memory Access Control: %04x\n", |
| dev->orient); |
| lcd->sendcmd(lcd, ILI9341_MEMORY_ACCESS_CONTROL); |
| lcd->sendparam(lcd, dev->orient); |
| |
| /* Select column and area */ |
| |
| ili9341_selectarea(lcd, 0, 0, ILI9341_XRES, ILI9341_YRES); |
| |
| /* Pixel Format set */ |
| |
| lcd->sendcmd(lcd, ILI9341_PIXEL_FORMAT_SET); |
| |
| /* 16 bit RGB565 */ |
| |
| lcdinfo("ili9341 LCD driver: Set Pixel Format: %04x\n", |
| ILI9341_PIXSET_16BITMCU_PARAM1); |
| lcd->sendparam(lcd, ILI9341_PIXSET_16BITMCU_PARAM1); |
| |
| /* 18 bit RGB666, add settings here */ |
| |
| lcdinfo("ili9341 LCD driver: Set Interface control\n"); |
| lcd->sendcmd(lcd, ILI9341_INTERFACE_CONTROL); |
| lcd->sendparam(lcd, ILI9341_IFCTL_PARAM1); |
| lcd->sendparam(lcd, ILI9341_IFCTL_PARAM2); |
| lcd->sendparam(lcd, ILI9341_IFCTL_PARAM3); |
| |
| /* Sleep out */ |
| |
| lcdinfo("ili9341 LCD driver: Sleep Out\n"); |
| lcd->sendcmd(lcd, ILI9341_SLEEP_OUT); |
| up_mdelay(120); |
| |
| /* Deselect the device */ |
| |
| lcd->deselect(lcd); |
| |
| /* Switch display off */ |
| |
| ili9341_setpower(&dev->dev, 0); |
| |
| return OK; |
| } |
| |
| /**************************************************************************** |
| * Public Functions |
| ****************************************************************************/ |
| |
| /**************************************************************************** |
| * Name: ili9341_getvideoinfo |
| * |
| * Description: |
| * Get information about the LCD video controller configuration. |
| * |
| * Input Parameters: |
| * dev - A reference to the driver specific structure |
| * vinfo - A reference to the videoinfo structure |
| * |
| * Returned Value: |
| * |
| * On success - OK |
| * On error - -EINVAL |
| * |
| ****************************************************************************/ |
| |
| static int ili9341_getvideoinfo(FAR struct lcd_dev_s *dev, |
| FAR struct fb_videoinfo_s *vinfo) |
| { |
| if (dev && vinfo) |
| { |
| FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev; |
| |
| vinfo->fmt = priv->pxfmt; |
| vinfo->xres = ili9341_getxres(priv); |
| vinfo->yres = ili9341_getyres(priv); |
| vinfo->nplanes = 1; |
| |
| lcdinfo("fmt: %d xres: %d yres: %d nplanes: %d\n", |
| vinfo->fmt, vinfo->xres, vinfo->yres, vinfo->nplanes); |
| |
| return OK; |
| } |
| |
| return -EINVAL; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_getplaneinfo |
| * |
| * Description: |
| * Get information about the configuration of each LCD color plane. |
| * |
| * Input Parameters: |
| * dev - A reference to the driver specific structure |
| * planeno - The plane number |
| * pinfo - A reference to the planeinfo structure |
| * |
| * Returned Value: |
| * |
| * On success - OK |
| * On error - -EINVAL |
| * |
| ****************************************************************************/ |
| |
| static int ili9341_getplaneinfo(FAR struct lcd_dev_s *dev, |
| unsigned int planeno, |
| FAR struct lcd_planeinfo_s *pinfo) |
| { |
| if (dev && pinfo && planeno == 0) |
| { |
| FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev; |
| |
| pinfo->putrun = ili9341_putrun; |
| #ifndef CONFIG_LCD_NOGETRUN |
| pinfo->getrun = ili9341_getrun; |
| #endif |
| pinfo->bpp = priv->bpp; |
| pinfo->buffer = (FAR uint8_t *)priv->runbuffer; /* Run scratch buffer */ |
| pinfo->dev = dev; |
| |
| lcdinfo("planeno: %d bpp: %d\n", planeno, pinfo->bpp); |
| |
| return OK; |
| } |
| |
| return -EINVAL; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_getpower |
| * |
| * Description: |
| * Get the LCD panel power status |
| * (0: full off - CONFIG_LCD_MAXPOWER: full on. |
| * On backlit LCDs, this setting may correspond to the backlight setting. |
| * |
| * Input Parameters: |
| * dev - A reference to the driver specific structure |
| * |
| * Returned Value: |
| * |
| * On success - OK |
| * On error - -EINVAL |
| * |
| ****************************************************************************/ |
| |
| static int ili9341_getpower(FAR struct lcd_dev_s *dev) |
| { |
| FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev; |
| |
| if (priv) |
| { |
| lcdinfo("%d\n", priv->power); |
| |
| return priv->power; |
| } |
| |
| return -EINVAL; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_setpower |
| * |
| * Description: |
| * Enable/disable LCD panel power |
| * (0: full off - CONFIG_LCD_MAXPOWER: full on). |
| * On backlight LCDs, this setting may correspond to the backlight setting. |
| * |
| * Input Parameters: |
| * dev - A reference to the driver specific structure |
| * power - Value of the power |
| * |
| * Returned Value: |
| * |
| * On success - OK |
| * On error - -EINVAL |
| * |
| ****************************************************************************/ |
| |
| static int ili9341_setpower(FAR struct lcd_dev_s *dev, int power) |
| { |
| FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev; |
| FAR struct ili9341_lcd_s *lcd = priv->lcd; |
| |
| if (dev) |
| { |
| lcdinfo("%d\n", power); |
| |
| lcd->select(lcd); |
| |
| if (power > 0) |
| { |
| /* Set backlight level */ |
| |
| lcd->backlight(lcd, power); |
| |
| /* And switch LCD on */ |
| |
| lcd->sendcmd(lcd, ILI9341_DISPLAY_ON); |
| up_mdelay(120); |
| } |
| else |
| { |
| /* Switch LCD off */ |
| |
| lcd->sendcmd(lcd, ILI9341_DISPLAY_OFF); |
| } |
| |
| lcd->deselect(lcd); |
| |
| priv->power = power; |
| |
| return OK; |
| } |
| |
| return -EINVAL; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_getcontrast |
| * |
| * Description: |
| * Get the current contrast setting (0-CONFIG_LCD_MAXCONTRAST). |
| * |
| * Input Parameters: |
| * dev - A reference to the lcd driver structure |
| * |
| * Returned Value: |
| * |
| * On success - current contrast value |
| * On error - -ENOSYS, not supported by the ili9341. |
| * |
| ****************************************************************************/ |
| |
| static int ili9341_getcontrast(struct lcd_dev_s *dev) |
| { |
| lcdinfo("Not implemented\n"); |
| return -ENOSYS; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_setcontrast |
| * |
| * Description: |
| * Set LCD panel contrast (0-CONFIG_LCD_MAXCONTRAST). |
| * |
| * Input Parameters: |
| * dev - A reference to the lcd driver structure |
| * |
| * Returned Value: |
| * |
| * On success - OK |
| * On error - -ENOSYS, not supported by the ili9341. |
| * |
| ****************************************************************************/ |
| |
| static int ili9341_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) |
| { |
| lcdinfo("contrast: %d\n", contrast); |
| return -ENOSYS; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_initialize |
| * |
| * Description: |
| * Initialize the LCD video driver internal structure. Also initialize the |
| * lcd hardware if not done. The control of the LCD driver is depend on the |
| * selected MCU interface and part of the platform specific subdriver (see |
| * config/stm32f429i-disco/src/stm32_ili93414ws.c) |
| * |
| * Input Parameters: |
| * |
| * lcd - A reference to the platform specific driver instance to control |
| * the ili9341 display driver. |
| * devno - A value in the range of 0 through CONFIG_ILI9341_NINTERFACES-1. |
| * This allows support for multiple LCD devices. |
| * |
| * Returned Value: |
| * |
| * On success, this function returns a reference to the LCD driver object |
| * for the specified LCD driver. NULL is returned on any failure. |
| * |
| ****************************************************************************/ |
| |
| FAR struct lcd_dev_s * |
| ili9341_initialize(FAR struct ili9341_lcd_s *lcd, int devno) |
| { |
| if (lcd && devno >= 0 && devno < CONFIG_LCD_ILI9341_NINTERFACES) |
| { |
| FAR struct ili9341_dev_s *priv = &g_lcddev[devno]; |
| |
| /* Check if initialized */ |
| |
| if (!priv->lcd) |
| { |
| FAR struct lcd_dev_s *dev = &priv->dev; |
| int ret; |
| |
| /* Initialize internal structure */ |
| |
| dev->getvideoinfo = ili9341_getvideoinfo; |
| dev->getplaneinfo = ili9341_getplaneinfo; |
| dev->getpower = ili9341_getpower; |
| dev->setpower = ili9341_setpower; |
| dev->getcontrast = ili9341_getcontrast; |
| dev->setcontrast = ili9341_setcontrast; |
| priv->lcd = lcd; |
| |
| /* Initialize the LCD driver */ |
| |
| ret = ili9341_hwinitialize(priv); |
| |
| if (ret == OK) |
| { |
| return &priv->dev; |
| } |
| } |
| } |
| |
| return NULL; |
| } |
| |
| /**************************************************************************** |
| * Name: ili9341_clear |
| * |
| * Description: |
| * This is a non-standard LCD interface. Because of the various rotations, |
| * clearing the display in the normal way by writing a sequences of runs |
| * that covers the entire display can be very slow. Here the display is |
| * cleared by simply setting all GRAM memory to the specified color. |
| * |
| * Input Parameters: |
| * dev - A reference to the lcd driver structure |
| * color - The background color |
| * |
| * Returned Value: |
| * |
| * On success - OK |
| * On error - -EINVAL |
| * |
| ****************************************************************************/ |
| |
| int ili9341_clear(FAR struct lcd_dev_s *dev, uint16_t color) |
| { |
| FAR struct ili9341_dev_s *priv = (FAR struct ili9341_dev_s *)dev; |
| FAR struct ili9341_lcd_s *lcd = priv->lcd; |
| uint16_t xres = ili9341_getxres(priv); |
| uint16_t yres = ili9341_getyres(priv); |
| uint32_t n; |
| |
| if (!lcd) |
| { |
| return -EINVAL; |
| } |
| |
| /* Select lcd driver */ |
| |
| lcd->select(lcd); |
| |
| /* Select column and area similar to the visible area */ |
| |
| ili9341_selectarea(lcd, 0, 0, xres, yres); |
| |
| /* Send memory write cmd */ |
| |
| lcd->sendcmd(lcd, ILI9341_MEMORY_WRITE); |
| |
| /* clear the visible area */ |
| |
| for (n = 0; n < xres * yres; n++) |
| { |
| /* Send pixel to gram */ |
| |
| lcd->sendgram(lcd, &color, 1); |
| } |
| |
| /* Deselect the lcd driver */ |
| |
| lcd->deselect(lcd); |
| |
| return OK; |
| } |