/************************************************************************* * Arduino Text & Bitmap Display Library for color LCDs * Distributed under GPL v2.0 * Developed by Stanley Huang * For more information, please visit http://arduinodev.com *************************************************************************/ #include #include #include "MultiLCD.h" /* Pins D4 : RESET D5 : CS D6 : D/C D7 : LED D11 : MOSI D12 : MISO D13 : SCK */ #define PIN_RESET 4 #define PIN_CS 5 #define PIN_DC 6 #define PIN_LED 7 //Basic Colors #define RED 0xf800 #define GREEN 0x07e0 #define BLUE 0x001f #define BLACK 0x0000 #define YELLOW 0xffe0 #define WHITE 0xffff //Other Colors #define CYAN 0x07ff #define BRIGHT_RED 0xf810 #define GRAY1 0x8410 #define GRAY2 0x4208 //TFT resolution 240*320 #define MIN_X 0 #define MIN_Y 0 #define MAX_X 239 #define MAX_Y 319 #define TFT_CS_LOW digitalWrite(PIN_CS, LOW) #define TFT_CS_HIGH digitalWrite(PIN_CS, HIGH) #define TFT_DC_LOW digitalWrite(PIN_DC, LOW) #define TFT_DC_HIGH digitalWrite(PIN_DC, HIGH) #define TFT_RST_OFF digitalWrite(PIN_RESET, HIGH) #define TFT_RST_ON digitalWrite(PIN_RESET, LOW) #define YP A2 // must be an analog pin, use "An" notation! #define XM A1 // must be an analog pin, use "An" notation! #define YM 14 // can be a digital pin, this is A0 #define XP 17 // can be a digital pin, this is A3 #define TS_MINX 116*2 #define TS_MAXX 890*2 #define TS_MINY 83*2 #define TS_MAXY 913*2 void LCD_ILI9341::sendCMD(uint8_t index) { TFT_DC_LOW; TFT_CS_LOW; SPI.transfer(index); TFT_CS_HIGH; } void LCD_ILI9341::WRITE_DATA(uint8_t data) { TFT_DC_HIGH; TFT_CS_LOW; SPI.transfer(data); TFT_CS_HIGH; } void LCD_ILI9341::sendData(uint16_t data) { uint8_t data1 = data>>8; uint8_t data2 = data&0xff; TFT_DC_HIGH; TFT_CS_LOW; SPI.transfer(data1); SPI.transfer(data2); TFT_CS_HIGH; } void LCD_ILI9341::WRITE_Package(uint16_t *data, uint8_t howmany) { uint16_t data1 = 0; uint8_t data2 = 0; TFT_DC_HIGH; TFT_CS_LOW; uint8_t count=0; for(count=0;count>8; data2 = data[count]&0xff; SPI.transfer(data1); SPI.transfer(data2); } TFT_CS_HIGH; } uint8_t LCD_ILI9341::Read_Register(uint8_t Addr, uint8_t xParameter) { uint8_t data=0; sendCMD(0xd9); /* ext command */ WRITE_DATA(0x10+xParameter); /* 0x11 is the first Parameter */ TFT_DC_LOW; TFT_CS_LOW; SPI.transfer(Addr); TFT_DC_HIGH; data = SPI.transfer(0); TFT_CS_HIGH; return data; } void LCD_ILI9341::begin (void) { pinMode(PIN_CS, OUTPUT); pinMode(PIN_DC, OUTPUT); pinMode(PIN_LED, OUTPUT); pinMode(PIN_RESET, OUTPUT); SPI.begin(); TFT_CS_HIGH; TFT_DC_HIGH; uint8_t i=0, TFTDriver=0; TFT_RST_ON; delay(10); TFT_RST_OFF; for(i=0;i<3;i++) { TFTDriver = readID(); } sendCMD(0xCB); WRITE_DATA(0x39); WRITE_DATA(0x2C); WRITE_DATA(0x00); WRITE_DATA(0x34); WRITE_DATA(0x02); sendCMD(0xCF); WRITE_DATA(0x00); WRITE_DATA(0XC1); WRITE_DATA(0X30); sendCMD(0xE8); WRITE_DATA(0x85); WRITE_DATA(0x00); WRITE_DATA(0x78); sendCMD(0xEA); WRITE_DATA(0x00); WRITE_DATA(0x00); sendCMD(0xED); WRITE_DATA(0x64); WRITE_DATA(0x03); WRITE_DATA(0X12); WRITE_DATA(0X81); sendCMD(0xF7); WRITE_DATA(0x20); sendCMD(0xC0); //Power control WRITE_DATA(0x23); //VRH[5:0] sendCMD(0xC1); //Power control WRITE_DATA(0x10); //SAP[2:0];BT[3:0] sendCMD(0xC5); //VCM control WRITE_DATA(0x3e); //Contrast WRITE_DATA(0x28); sendCMD(0xC7); //VCM control2 WRITE_DATA(0x86); //-- sendCMD(0x36); // Memory Access Control WRITE_DATA(0x48); //C8 sendCMD(0x3A); WRITE_DATA(0x55); sendCMD(0xB1); WRITE_DATA(0x00); WRITE_DATA(0x18); sendCMD(0xB6); // Display Function Control WRITE_DATA(0x08); WRITE_DATA(0x82); WRITE_DATA(0x27); sendCMD(0xF2); // 3Gamma Function Disable WRITE_DATA(0x00); sendCMD(0x26); //Gamma curve selected WRITE_DATA(0x01); sendCMD(0xE0); //Set Gamma WRITE_DATA(0x0F); WRITE_DATA(0x31); WRITE_DATA(0x2B); WRITE_DATA(0x0C); WRITE_DATA(0x0E); WRITE_DATA(0x08); WRITE_DATA(0x4E); WRITE_DATA(0xF1); WRITE_DATA(0x37); WRITE_DATA(0x07); WRITE_DATA(0x10); WRITE_DATA(0x03); WRITE_DATA(0x0E); WRITE_DATA(0x09); WRITE_DATA(0x00); sendCMD(0XE1); //Set Gamma WRITE_DATA(0x00); WRITE_DATA(0x0E); WRITE_DATA(0x14); WRITE_DATA(0x03); WRITE_DATA(0x11); WRITE_DATA(0x07); WRITE_DATA(0x31); WRITE_DATA(0xC1); WRITE_DATA(0x48); WRITE_DATA(0x08); WRITE_DATA(0x0F); WRITE_DATA(0x0C); WRITE_DATA(0x31); WRITE_DATA(0x36); WRITE_DATA(0x0F); sendCMD(0x11); //Exit Sleep delay(120); sendCMD(0x29); //Display on sendCMD(0x2c); clear(); setBackLight(255); setColor(0xffff); setBackColor(0); } uint8_t LCD_ILI9341::readID(void) { uint8_t i=0; uint8_t data[3] ; uint8_t ID[3] = {0x00, 0x93, 0x41}; uint8_t ToF=1; for(i=0;i<3;i++) { data[i]=Read_Register(0xd3,i+1); if(data[i] != ID[i]) { ToF=0; } } if(!ToF) /* data!=ID */ { #if 0 Serial.print("Read TFT ID failed, ID should be 0x09341, but read ID = 0x"); for(i=0;i<3;i++) { Serial.print(data[i],HEX); } Serial.println(); #endif } return ToF; } void LCD_ILI9341::setCol(uint16_t StartCol,uint16_t EndCol) { sendCMD(0x2A); /* Column Command address */ sendData(StartCol); sendData(EndCol); } void LCD_ILI9341::setPage(uint16_t StartPage,uint16_t EndPage) { sendCMD(0x2B); /* Column Command address */ sendData(StartPage); sendData(EndPage); } void LCD_ILI9341::fill(uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1, uint16_t color) { uint8_t Hcolor = color>>8; uint8_t Lcolor = color&0xff; setCol(239 - y1, 239 - y0); setPage(x0, x1); sendCMD(0x2c); /* start to write to display ra */ /* m */ TFT_DC_HIGH; TFT_CS_LOW; for(uint16_t n = (x1-x0+1) * (y1-y0+1); n > 0; n--) { SPI.transfer(Hcolor); SPI.transfer(Lcolor); } TFT_CS_HIGH; } void LCD_ILI9341::clear(void) { setCol(0, 239); setPage(0, 319); sendCMD(0x2c); /* start to write to display ra */ /* m */ TFT_DC_HIGH; TFT_CS_LOW; for(uint16_t i=0; i<38400; i++) { SPI.transfer(0); SPI.transfer(0); SPI.transfer(0); SPI.transfer(0); } TFT_CS_HIGH; m_x = 0; m_y = 0; } void LCD_ILI9341::setXY(uint16_t x0, uint16_t x1, uint16_t y0, uint16_t y1) { setCol(239 - x1, 239 - x0); setPage(y0, y1); sendCMD(0x2c); } void LCD_ILI9341::setPixel(uint16_t poX, uint16_t poY,uint16_t color) { setXY(poY, poY, poX, poX); sendData(color); } void LCD_ILI9341::setBackLight(byte brightness) { digitalWrite(PIN_LED, brightness ? HIGH : LOW); } void LCD_ILI9341::clearPixels(uint16_t pixels) { TFT_DC_HIGH; TFT_CS_LOW; for(uint16_t i = 0; i < pixels; i++) { SPI.transfer(0); SPI.transfer(0); } TFT_CS_HIGH; } void LCD_ILI9341::sendPixelData(byte d) { for (byte j = 0; j < 8; j++, d <<= 1) { if (d & 0x80) { SPI.transfer(m_color[1][1]); SPI.transfer(m_color[1][0]); } else { SPI.transfer(m_color[0][1]); SPI.transfer(m_color[0][0]); } } } size_t LCD_ILI9341::write(uint8_t c) { if (c == '\n') { m_y += (m_font + 1) << 3; return 1; } else if (c == '\r') { m_x = 0; return 1; } #ifndef MEMORY_SAVING if (m_font == FONT_SIZE_SMALL) { #endif setXY(m_y, m_y + 7, m_x, m_x + 4); m_x += 6; if (m_x >= 320) { m_y += 8; m_x = 0; if (m_y >= 240) m_y = 0; } if (c > 0x20 && c < 0x7f) { byte pgm_buffer[5]; memcpy_P(pgm_buffer, &font5x8[c - 0x21], 5); TFT_DC_HIGH; TFT_CS_LOW; for (byte i = 0; i < 5; i++) { sendPixelData(pgm_buffer[i]); } TFT_CS_HIGH; } else { clearPixels(5 * 8); } #ifndef MEMORY_SAVING } else { setXY(m_y, m_y + 15, m_x, m_x + 7); m_x += 9; if (m_x >= 320) { m_y += 16; m_x = 0; if (m_y >= 240) m_y = 0; } if (c > 0x20 && c < 0x7f) { byte pgm_buffer[16]; memcpy_P(pgm_buffer, &font8x16_terminal[c - 0x21], 16); TFT_DC_HIGH; TFT_CS_LOW; for (byte i = 0; i < 16; i += 2) { sendPixelData(pgm_buffer[i + 1]); sendPixelData(pgm_buffer[i]); } TFT_CS_HIGH; } else { clearPixels(8 * 16); } } #endif return 1; } void LCD_ILI9341::writeDigit(byte n) { if (m_font == FONT_SIZE_LARGE) { setXY(m_y, m_y + 15, m_x, m_x + 15); m_x += 16; if (n <= 9) { byte pgm_buffer[32]; memcpy_P(pgm_buffer, &digits16x16[n], sizeof(pgm_buffer)); TFT_DC_HIGH; TFT_CS_LOW; for (byte i = 0; i < 16; i++) { sendPixelData(pgm_buffer[16 + i]); sendPixelData(pgm_buffer[i]); } TFT_CS_HIGH; } else { clearPixels(16 * 16); } } else if (m_font == FONT_SIZE_XLARGE) { setXY(m_y, m_y + 23, m_x, m_x + 15); m_x += 17; if (n <= 9) { byte pgm_buffer[48]; memcpy_P(pgm_buffer, &digits16x24[n], sizeof(pgm_buffer)); TFT_DC_HIGH; TFT_CS_LOW; for (int i = 0; i < 48; i += 3) { sendPixelData(pgm_buffer[i + 2]); sendPixelData(pgm_buffer[i + 1]); sendPixelData(pgm_buffer[i]); } TFT_CS_HIGH; } else { clearPixels(16 * 24); } } else { write(n <= 9 ? ('0' + n) : ' '); } } void LCD_ILI9341::draw(const PROGMEM byte* buffer, uint16_t width, uint16_t height) { byte rows = height >> 3; setXY(m_y, m_y + height - 1, m_x, m_x + width - 1); uint16_t i = width - 1; TFT_DC_HIGH; TFT_CS_LOW; for (uint16_t i = 0; i < width; i++) { for (int8_t h = rows - 1; h >= 0; h--) { byte d = pgm_read_byte(buffer + i + width * h); sendPixelData(d); } } TFT_CS_HIGH; m_x += width; } void LCD_ILI9341::draw(const PROGMEM byte* buffer, uint16_t width, uint16_t height, byte scaleX, byte ScaleY) { byte rows = height >> 3; setXY(m_y, m_y + height * 2 - 1, m_x, m_x + width * 2 - 1); uint16_t i = width - 1; uint16_t w = width << 1; TFT_DC_HIGH; TFT_CS_LOW; for (uint16_t i = 0; i < w; i++) { for (int8_t h = rows - 1; h >= 0; h--) { byte d = pgm_read_byte(buffer + (i >> 1) + width * h); for (byte j = 0; j < 8; j++, d <<= 1) { if (d & 0x80) { SPI.transfer(m_color[1][1]); SPI.transfer(m_color[1][0]); SPI.transfer(m_color[1][1]); SPI.transfer(m_color[1][0]); } else { SPI.transfer(m_color[0][1]); SPI.transfer(m_color[0][0]); SPI.transfer(m_color[0][1]); SPI.transfer(m_color[0][0]); } } } }; TFT_CS_HIGH; m_x += (width << 1); }