You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
433 lines
15 KiB
C
433 lines
15 KiB
C
/**
|
|
* @file ILI9341.c
|
|
*
|
|
* ILI9341.pdf [ILI9341_DS_V1.13_20110805]
|
|
*
|
|
* [references]
|
|
* - https://www.newhavendisplay.com/app_notes/ILI9341.pdf
|
|
* - Linux Source [v5.9-rc4] "drivers/staging/fbtft/fb_ili9341.c"
|
|
* - https://github.com/adafruit/Adafruit_ILI9341/blob/master/Adafruit_ILI9341.cpp
|
|
* - https://os.mbed.com/users/dreschpe/code/SPI_TFT_ILI9341
|
|
*
|
|
*/
|
|
|
|
/*********************
|
|
* INCLUDES
|
|
*********************/
|
|
#include "ILI9341.h"
|
|
#if USE_ILI9341 != 0
|
|
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include LV_DRV_DISP_INCLUDE
|
|
#include LV_DRV_DELAY_INCLUDE
|
|
|
|
/*********************
|
|
* DEFINES
|
|
*********************/
|
|
#define ILI9341_CMD_MODE 0
|
|
#define ILI9341_DATA_MODE 1
|
|
|
|
#define ILI9341_TFTWIDTH 240
|
|
#define ILI9341_TFTHEIGHT 320
|
|
|
|
/* Level 1 Commands -------------- [section] Description */
|
|
|
|
#define ILI9341_NOP 0x00 /* [8.2.1 ] No Operation / Terminate Frame Memory Write */
|
|
#define ILI9341_SWRESET 0x01 /* [8.2.2 ] Software Reset */
|
|
#define ILI9341_RDDIDIF 0x04 /* [8.2.3 ] Read Display Identification Information */
|
|
#define ILI9341_RDDST 0x09 /* [8.2.4 ] Read Display Status */
|
|
#define ILI9341_RDDPM 0x0A /* [8.2.5 ] Read Display Power Mode */
|
|
#define ILI9341_RDDMADCTL 0x0B /* [8.2.6 ] Read Display MADCTL */
|
|
#define ILI9341_RDDCOLMOD 0x0C /* [8.2.7 ] Read Display Pixel Format */
|
|
#define ILI9341_RDDIM 0x0D /* [8.2.8 ] Read Display Image Mode */
|
|
#define ILI9341_RDDSM 0x0E /* [8.2.9 ] Read Display Signal Mode */
|
|
#define ILI9341_RDDSDR 0x0F /* [8.2.10] Read Display Self-Diagnostic Result */
|
|
#define ILI9341_SLPIN 0x10 /* [8.2.11] Enter Sleep Mode */
|
|
#define ILI9341_SLPOUT 0x11 /* [8.2.12] Leave Sleep Mode */
|
|
#define ILI9341_PTLON 0x12 /* [8.2.13] Partial Display Mode ON */
|
|
#define ILI9341_NORON 0x13 /* [8.2.14] Normal Display Mode ON */
|
|
#define ILI9341_DINVOFF 0x20 /* [8.2.15] Display Inversion OFF */
|
|
#define ILI9341_DINVON 0x21 /* [8.2.16] Display Inversion ON */
|
|
#define ILI9341_GAMSET 0x26 /* [8.2.17] Gamma Set */
|
|
#define ILI9341_DISPOFF 0x28 /* [8.2.18] Display OFF*/
|
|
#define ILI9341_DISPON 0x29 /* [8.2.19] Display ON*/
|
|
#define ILI9341_CASET 0x2A /* [8.2.20] Column Address Set */
|
|
#define ILI9341_PASET 0x2B /* [8.2.21] Page Address Set */
|
|
#define ILI9341_RAMWR 0x2C /* [8.2.22] Memory Write */
|
|
#define ILI9341_RGBSET 0x2D /* [8.2.23] Color Set (LUT for 16-bit to 18-bit color depth conversion) */
|
|
#define ILI9341_RAMRD 0x2E /* [8.2.24] Memory Read */
|
|
#define ILI9341_PTLAR 0x30 /* [8.2.25] Partial Area */
|
|
#define ILI9341_VSCRDEF 0x33 /* [8.2.26] Veritcal Scrolling Definition */
|
|
#define ILI9341_TEOFF 0x34 /* [8.2.27] Tearing Effect Line OFF */
|
|
#define ILI9341_TEON 0x35 /* [8.2.28] Tearing Effect Line ON */
|
|
#define ILI9341_MADCTL 0x36 /* [8.2.29] Memory Access Control */
|
|
#define MADCTL_MY 0x80 /* MY row address order */
|
|
#define MADCTL_MX 0x40 /* MX column address order */
|
|
#define MADCTL_MV 0x20 /* MV row / column exchange */
|
|
#define MADCTL_ML 0x10 /* ML vertical refresh order */
|
|
#define MADCTL_MH 0x04 /* MH horizontal refresh order */
|
|
#define MADCTL_RGB 0x00 /* RGB Order [default] */
|
|
#define MADCTL_BGR 0x08 /* BGR Order */
|
|
#define ILI9341_VSCRSADD 0x37 /* [8.2.30] Vertical Scrolling Start Address */
|
|
#define ILI9341_IDMOFF 0x38 /* [8.2.31] Idle Mode OFF */
|
|
#define ILI9341_IDMON 0x39 /* [8.2.32] Idle Mode ON */
|
|
#define ILI9341_PIXSET 0x3A /* [8.2.33] Pixel Format Set */
|
|
#define ILI9341_WRMEMCONT 0x3C /* [8.2.34] Write Memory Continue */
|
|
#define ILI9341_RDMEMCONT 0x3E /* [8.2.35] Read Memory Continue */
|
|
#define ILI9341_SETSCANTE 0x44 /* [8.2.36] Set Tear Scanline */
|
|
#define ILI9341_GETSCAN 0x45 /* [8.2.37] Get Scanline */
|
|
#define ILI9341_WRDISBV 0x51 /* [8.2.38] Write Display Brightness Value */
|
|
#define ILI9341_RDDISBV 0x52 /* [8.2.39] Read Display Brightness Value */
|
|
#define ILI9341_WRCTRLD 0x53 /* [8.2.40] Write Control Display */
|
|
#define ILI9341_RDCTRLD 0x54 /* [8.2.41] Read Control Display */
|
|
#define ILI9341_WRCABC 0x55 /* [8.2.42] Write Content Adaptive Brightness Control Value */
|
|
#define ILI9341_RDCABC 0x56 /* [8.2.43] Read Content Adaptive Brightness Control Value */
|
|
#define ILI9341_WRCABCMIN 0x5E /* [8.2.44] Write CABC Minimum Brightness */
|
|
#define ILI9341_RDCABCMIN 0x5F /* [8.2.45] Read CABC Minimum Brightness */
|
|
#define ILI9341_RDID1 0xDA /* [8.2.46] Read ID1 - Manufacturer ID (user) */
|
|
#define ILI9341_RDID2 0xDB /* [8.2.47] Read ID2 - Module/Driver version (supplier) */
|
|
#define ILI9341_RDID3 0xDC /* [8.2.48] Read ID3 - Module/Driver version (user) */
|
|
|
|
/* Level 2 Commands -------------- [section] Description */
|
|
|
|
#define ILI9341_IFMODE 0xB0 /* [8.3.1 ] Interface Mode Control */
|
|
#define ILI9341_FRMCTR1 0xB1 /* [8.3.2 ] Frame Rate Control (In Normal Mode/Full Colors) */
|
|
#define ILI9341_FRMCTR2 0xB2 /* [8.3.3 ] Frame Rate Control (In Idle Mode/8 colors) */
|
|
#define ILI9341_FRMCTR3 0xB3 /* [8.3.4 ] Frame Rate control (In Partial Mode/Full Colors) */
|
|
#define ILI9341_INVTR 0xB4 /* [8.3.5 ] Display Inversion Control */
|
|
#define ILI9341_PRCTR 0xB5 /* [8.3.6 ] Blanking Porch Control */
|
|
#define ILI9341_DISCTRL 0xB6 /* [8.3.7 ] Display Function Control */
|
|
#define ILI9341_ETMOD 0xB7 /* [8.3.8 ] Entry Mode Set */
|
|
#define ILI9341_BLCTRL1 0xB8 /* [8.3.9 ] Backlight Control 1 - Grayscale Histogram UI mode */
|
|
#define ILI9341_BLCTRL2 0xB9 /* [8.3.10] Backlight Control 2 - Grayscale Histogram still picture mode */
|
|
#define ILI9341_BLCTRL3 0xBA /* [8.3.11] Backlight Control 3 - Grayscale Thresholds UI mode */
|
|
#define ILI9341_BLCTRL4 0xBB /* [8.3.12] Backlight Control 4 - Grayscale Thresholds still picture mode */
|
|
#define ILI9341_BLCTRL5 0xBC /* [8.3.13] Backlight Control 5 - Brightness Transition time */
|
|
#define ILI9341_BLCTRL7 0xBE /* [8.3.14] Backlight Control 7 - PWM Frequency */
|
|
#define ILI9341_BLCTRL8 0xBF /* [8.3.15] Backlight Control 8 - ON/OFF + PWM Polarity*/
|
|
#define ILI9341_PWCTRL1 0xC0 /* [8.3.16] Power Control 1 - GVDD */
|
|
#define ILI9341_PWCTRL2 0xC1 /* [8.3.17] Power Control 2 - step-up factor for operating voltage */
|
|
#define ILI9341_VMCTRL1 0xC5 /* [8.3.18] VCOM Control 1 - Set VCOMH and VCOML */
|
|
#define ILI9341_VMCTRL2 0xC7 /* [8.3.19] VCOM Control 2 - VCOM offset voltage */
|
|
#define ILI9341_NVMWR 0xD0 /* [8.3.20] NV Memory Write */
|
|
#define ILI9341_NVMPKEY 0xD1 /* [8.3.21] NV Memory Protection Key */
|
|
#define ILI9341_RDNVM 0xD2 /* [8.3.22] NV Memory Status Read */
|
|
#define ILI9341_RDID4 0xD3 /* [8.3.23] Read ID4 - IC Device Code */
|
|
#define ILI9341_PGAMCTRL 0xE0 /* [8.3.24] Positive Gamma Control */
|
|
#define ILI9341_NGAMCTRL 0xE1 /* [8.3.25] Negative Gamma Correction */
|
|
#define ILI9341_DGAMCTRL1 0xE2 /* [8.3.26] Digital Gamma Control 1 */
|
|
#define ILI9341_DGAMCTRL2 0xE3 /* [8.3.27] Digital Gamma Control 2 */
|
|
#define ILI9341_IFCTL 0xF6 /* [8.3.28] 16bits Data Format Selection */
|
|
|
|
/* Extended Commands --------------- [section] Description*/
|
|
|
|
#define ILI9341_PWCTRLA 0xCB /* [8.4.1] Power control A */
|
|
#define ILI9341_PWCTRLB 0xCF /* [8.4.2] Power control B */
|
|
#define ILI9341_TIMECTRLA_INT 0xE8 /* [8.4.3] Internal Clock Driver timing control A */
|
|
#define ILI9341_TIMECTRLA_EXT 0xE9 /* [8.4.4] External Clock Driver timing control A */
|
|
#define ILI9341_TIMECTRLB 0xEA /* [8.4.5] Driver timing control B (gate driver timing control) */
|
|
#define ILI9341_PWSEQCTRL 0xED /* [8.4.6] Power on sequence control */
|
|
#define ILI9341_GAM3CTRL 0xF2 /* [8.4.7] Enable 3 gamma control */
|
|
#define ILI9341_PUMPRATIO 0xF7 /* [8.4.8] Pump ratio control */
|
|
|
|
/**********************
|
|
* TYPEDEFS
|
|
**********************/
|
|
|
|
/**********************
|
|
* STATIC PROTOTYPES
|
|
**********************/
|
|
static inline void ili9341_write(int mode, uint8_t data);
|
|
static inline void ili9341_write_array(int mode, uint8_t *data, uint16_t len);
|
|
|
|
/**********************
|
|
* STATIC VARIABLES
|
|
**********************/
|
|
|
|
/**********************
|
|
* MACROS
|
|
**********************/
|
|
|
|
/**********************
|
|
* GLOBAL FUNCTIONS
|
|
**********************/
|
|
|
|
/**
|
|
* Initialize the ILI9341 display controller
|
|
*/
|
|
void ili9341_init(void)
|
|
{
|
|
uint8_t data[15];
|
|
|
|
/* hardware reset */
|
|
LV_DRV_DISP_SPI_CS(1);
|
|
LV_DRV_DISP_CMD_DATA(ILI9341_DATA_MODE);
|
|
LV_DRV_DISP_RST(0);
|
|
LV_DRV_DELAY_US(50);
|
|
LV_DRV_DISP_RST(1);
|
|
LV_DRV_DELAY_MS(5);
|
|
|
|
/* software reset */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_SWRESET);
|
|
LV_DRV_DELAY_MS(5);
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_DISPOFF);
|
|
|
|
/* startup sequence */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PWCTRLB);
|
|
data[0] = 0x00;
|
|
data[1] = 0x83;
|
|
data[2] = 0x30;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 3);
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PWSEQCTRL);
|
|
data[0] = 0x64;
|
|
data[1] = 0x03;
|
|
data[2] = 0x12;
|
|
data[3] = 0x81;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 4);
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_TIMECTRLA_INT);
|
|
data[0] = 0x85;
|
|
data[1] = 0x01;
|
|
data[2] = 0x79;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 3);
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PWCTRLA);
|
|
data[0] = 0x39;
|
|
data[1] = 0x2c;
|
|
data[2] = 0x00;
|
|
data[3] = 0x34;
|
|
data[4] = 0x02;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 5);
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PUMPRATIO);
|
|
ili9341_write(ILI9341_DATA_MODE, 0x20);
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_TIMECTRLB);
|
|
data[0] = 0x00;
|
|
data[1] = 0x00;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 2);
|
|
|
|
/* power control */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PWCTRL1);
|
|
ili9341_write(ILI9341_DATA_MODE, 0x26);
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PWCTRL2);
|
|
ili9341_write(ILI9341_DATA_MODE, 0x11);
|
|
|
|
/* VCOM */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_VMCTRL1);
|
|
data[0] = 0x35;
|
|
data[1] = 0x3e;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 2);
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_VMCTRL2);
|
|
ili9341_write(ILI9341_DATA_MODE, 0xbe);
|
|
|
|
/* set orientation */
|
|
ili9341_rotate(0, ILI9341_BGR);
|
|
|
|
/* 16 bit pixel */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PIXSET);
|
|
ili9341_write(ILI9341_DATA_MODE, 0x55);
|
|
|
|
/* frame rate */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_FRMCTR1);
|
|
data[0] = 0x00;
|
|
data[1] = 0x1b;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 2);
|
|
|
|
#if ILI9341_GAMMA
|
|
/* gamma curve set */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_GAMSET);
|
|
ili9341_write(ILI9341_DATA_MODE, 0x01);
|
|
|
|
/* positive gamma correction */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PGAMCTRL);
|
|
data[0] = 0x1f;
|
|
data[1] = 0x1a;
|
|
data[2] = 0x18;
|
|
data[3] = 0x0a;
|
|
data[4] = 0x0f;
|
|
data[5] = 0x06;
|
|
data[6] = 0x45;
|
|
data[7] = 0x87;
|
|
data[8] = 0x32;
|
|
data[9] = 0x0a;
|
|
data[10] = 0x07;
|
|
data[11] = 0x02;
|
|
data[12] = 0x07;
|
|
data[13] = 0x05;
|
|
data[14] = 0x00;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 15);
|
|
|
|
/* negative gamma correction */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_NGAMCTRL);
|
|
data[0] = 0x00;
|
|
data[1] = 0x25;
|
|
data[2] = 0x27;
|
|
data[3] = 0x05;
|
|
data[4] = 0x10;
|
|
data[5] = 0x09;
|
|
data[6] = 0x3a;
|
|
data[7] = 0x78;
|
|
data[8] = 0x4d;
|
|
data[9] = 0x05;
|
|
data[10] = 0x18;
|
|
data[11] = 0x0d;
|
|
data[12] = 0x38;
|
|
data[13] = 0x3a;
|
|
data[14] = 0x1f;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 15);
|
|
#endif
|
|
|
|
/* window horizontal */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_CASET);
|
|
data[0] = 0;
|
|
data[1] = 0;
|
|
data[2] = (ILI9341_HOR_RES - 1) >> 8;
|
|
data[3] = (ILI9341_HOR_RES - 1);
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 4);
|
|
|
|
/* window vertical */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PASET);
|
|
data[0] = 0;
|
|
data[1] = 0;
|
|
data[2] = (ILI9341_VER_RES - 1) >> 8;
|
|
data[3] = (ILI9341_VER_RES - 1);
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 4);
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_RAMWR);
|
|
|
|
#if ILI9341_TEARING
|
|
/* tearing effect off */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_TEOFF);
|
|
|
|
/* tearing effect on */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_TEON);
|
|
#endif
|
|
|
|
/* entry mode set */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_ETMOD);
|
|
ili9341_write(ILI9341_DATA_MODE, 0x07);
|
|
|
|
/* display function control */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_DISCTRL);
|
|
data[0] = 0x0a;
|
|
data[1] = 0x82;
|
|
data[2] = 0x27;
|
|
data[3] = 0x00;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 4);
|
|
|
|
/* exit sleep mode */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_SLPOUT);
|
|
|
|
LV_DRV_DELAY_MS(100);
|
|
|
|
/* display on */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_DISPON);
|
|
|
|
LV_DRV_DELAY_MS(20);
|
|
}
|
|
|
|
void ili9341_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p)
|
|
{
|
|
if(area->x2 < 0 || area->y2 < 0 || area->x1 > (ILI9341_HOR_RES - 1) || area->y1 > (ILI9341_VER_RES - 1)) {
|
|
lv_disp_flush_ready(drv);
|
|
return;
|
|
}
|
|
|
|
/* Truncate the area to the screen */
|
|
int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
|
|
int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
|
|
int32_t act_x2 = area->x2 > ILI9341_HOR_RES - 1 ? ILI9341_HOR_RES - 1 : area->x2;
|
|
int32_t act_y2 = area->y2 > ILI9341_VER_RES - 1 ? ILI9341_VER_RES - 1 : area->y2;
|
|
|
|
int32_t y;
|
|
uint8_t data[4];
|
|
int32_t len = len = (act_x2 - act_x1 + 1) * 2;
|
|
lv_coord_t w = (area->x2 - area->x1) + 1;
|
|
|
|
/* window horizontal */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_CASET);
|
|
data[0] = act_x1 >> 8;
|
|
data[1] = act_x1;
|
|
data[2] = act_x2 >> 8;
|
|
data[3] = act_x2;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 4);
|
|
|
|
/* window vertical */
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_PASET);
|
|
data[0] = act_y1 >> 8;
|
|
data[1] = act_y1;
|
|
data[2] = act_y2 >> 8;
|
|
data[3] = act_y2;
|
|
ili9341_write_array(ILI9341_DATA_MODE, data, 4);
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_RAMWR);
|
|
|
|
for(y = act_y1; y <= act_y2; y++) {
|
|
ili9341_write_array(ILI9341_DATA_MODE, (uint8_t *)color_p, len);
|
|
color_p += w;
|
|
}
|
|
|
|
lv_disp_flush_ready(drv);
|
|
}
|
|
|
|
void ili9341_rotate(int degrees, bool bgr)
|
|
{
|
|
uint8_t color_order = MADCTL_RGB;
|
|
|
|
if(bgr)
|
|
color_order = MADCTL_BGR;
|
|
|
|
ili9341_write(ILI9341_CMD_MODE, ILI9341_MADCTL);
|
|
|
|
switch(degrees) {
|
|
case 270:
|
|
ili9341_write(ILI9341_DATA_MODE, MADCTL_MV | color_order);
|
|
break;
|
|
case 180:
|
|
ili9341_write(ILI9341_DATA_MODE, MADCTL_MY | color_order);
|
|
break;
|
|
case 90:
|
|
ili9341_write(ILI9341_DATA_MODE, MADCTL_MX | MADCTL_MY | MADCTL_MV | color_order);
|
|
break;
|
|
case 0:
|
|
/* fall-through */
|
|
default:
|
|
ili9341_write(ILI9341_DATA_MODE, MADCTL_MX | color_order);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**********************
|
|
* STATIC FUNCTIONS
|
|
**********************/
|
|
|
|
/**
|
|
* Write byte
|
|
* @param mode sets command or data mode for write
|
|
* @param byte the byte to write
|
|
*/
|
|
static inline void ili9341_write(int mode, uint8_t data)
|
|
{
|
|
LV_DRV_DISP_CMD_DATA(mode);
|
|
LV_DRV_DISP_SPI_WR_BYTE(data);
|
|
}
|
|
|
|
/**
|
|
* Write byte array
|
|
* @param mode sets command or data mode for write
|
|
* @param data the byte array to write
|
|
* @param len the length of the byte array
|
|
*/
|
|
static inline void ili9341_write_array(int mode, uint8_t *data, uint16_t len)
|
|
{
|
|
LV_DRV_DISP_CMD_DATA(mode);
|
|
LV_DRV_DISP_SPI_WR_ARRAY(data, len);
|
|
}
|
|
|
|
#endif
|