#ifndef LCD_ILI9341 #define LCD_ILI9341 #include "../../Debug.h" // https://github.com/adafruit/Adafruit_ILI9341/blob/master/Adafruit_ILI9341.cpp // https://github.com/adafruit/Adafruit_ILI9341/blob/master/Adafruit_ILI9341.h // http://datasheets.gpio.dk/dl/ILI9341.pdf // e.g. // TJCTM24024-SPI // http://play.fallows.ca/wp/projects/electronics-projects/tjctm24024-mystery-modules-china/ // http://datasheets.gpio.dk/dl/2.4inch-tft-touch/2.4%25e4%25b8%25b2%25e5%258f%25a3_TJC-024-9341/Module_SCH.pdf // http://datasheets.gpio.dk/dl/ILI9341.pdf #define ILI9341_TFTWIDTH 240 ///< ILI9341 max TFT width #define ILI9341_TFTHEIGHT 320 ///< ILI9341 max TFT height #define ILI9341_NOP 0x00 ///< No-op register #define ILI9341_SWRESET 0x01 ///< Software reset register #define ILI9341_RDDID 0x04 ///< Read display identification information #define ILI9341_RDDST 0x09 ///< Read Display Status #define ILI9341_SLPIN 0x10 ///< Enter Sleep Mode #define ILI9341_SLPOUT 0x11 ///< Sleep Out #define ILI9341_PTLON 0x12 ///< Partial Mode ON #define ILI9341_NORON 0x13 ///< Normal Display Mode ON #define ILI9341_RDMODE 0x0A ///< Read Display Power Mode #define ILI9341_RDMADCTL 0x0B ///< Read Display MADCTL #define ILI9341_RDPIXFMT 0x0C ///< Read Display Pixel Format #define ILI9341_RDIMGFMT 0x0D ///< Read Display Image Format #define ILI9341_RDSELFDIAG 0x0F ///< Read Display Self-Diagnostic Result #define ILI9341_INVOFF 0x20 ///< Display Inversion OFF #define ILI9341_INVON 0x21 ///< Display Inversion ON #define ILI9341_GAMMASET 0x26 ///< Gamma Set #define ILI9341_DISPOFF 0x28 ///< Display OFF #define ILI9341_DISPON 0x29 ///< Display ON #define ILI9341_CASET 0x2A ///< Column Address Set #define ILI9341_PASET 0x2B ///< Page Address Set #define ILI9341_RAMWR 0x2C ///< Memory Write #define ILI9341_RAMRD 0x2E ///< Memory Read #define ILI9341_PTLAR 0x30 ///< Partial Area #define ILI9341_MADCTL 0x36 ///< Memory Access Control #define ILI9341_VSCRSADD 0x37 ///< Vertical Scrolling Start Address #define ILI9341_PIXFMT 0x3A ///< COLMOD: Pixel Format Set #define ILI9341_FRMCTR1 0xB1 ///< Frame Rate Control (In Normal Mode/Full Colors) #define ILI9341_FRMCTR2 0xB2 ///< Frame Rate Control (In Idle Mode/8 colors) #define ILI9341_FRMCTR3 0xB3 ///< Frame Rate control (In Partial Mode/Full Colors) #define ILI9341_INVCTR 0xB4 ///< Display Inversion Control #define ILI9341_DFUNCTR 0xB6 ///< Display Function Control #define ILI9341_PWCTR1 0xC0 ///< Power Control 1 #define ILI9341_PWCTR2 0xC1 ///< Power Control 2 #define ILI9341_PWCTR3 0xC2 ///< Power Control 3 #define ILI9341_PWCTR4 0xC3 ///< Power Control 4 #define ILI9341_PWCTR5 0xC4 ///< Power Control 5 #define ILI9341_VMCTR1 0xC5 ///< VCOM Control 1 #define ILI9341_VMCTR2 0xC7 ///< VCOM Control 2 #define ILI9341_RDID1 0xDA ///< Read ID 1 #define ILI9341_RDID2 0xDB ///< Read ID 2 #define ILI9341_RDID3 0xDC ///< Read ID 3 #define ILI9341_RDID4 0xDD ///< Read ID 4 #define ILI9341_GMCTRP1 0xE0 ///< Positive Gamma Correction #define ILI9341_GMCTRN1 0xE1 ///< Negative Gamma Correction //#define ILI9341_PWCTR6 0xFC //#include "../../io/SoftSPI.h" //#include "../../io/HardSPI.h" static constexpr const uint8_t initcmd[] = { 0xEF, 3, 0x03, 0x80, 0x02, 0xCF, 3, 0x00, 0xC1, 0x30, 0xED, 4, 0x64, 0x03, 0x12, 0x81, 0xE8, 3, 0x85, 0x00, 0x78, 0xCB, 5, 0x39, 0x2C, 0x00, 0x34, 0x02, 0xF7, 1, 0x20, 0xEA, 2, 0x00, 0x00, ILI9341_PWCTR1, 1, 0x23, // Power control VRH[5:0] ILI9341_PWCTR2, 1, 0x10, // Power control SAP[2:0];BT[3:0] ILI9341_VMCTR1, 2, 0x3e, 0x28, // VCM control ILI9341_VMCTR2, 1, 0x86, // VCM control2 ILI9341_MADCTL, 1, 0x48, // Memory Access Control ILI9341_VSCRSADD, 1, 0x00, // Vertical scroll zero ILI9341_PIXFMT, 1, 0x55, ILI9341_FRMCTR1, 2, 0x00, 0x18, ILI9341_DFUNCTR, 3, 0x08, 0x82, 0x27, // Display Function Control 0xF2, 1, 0x00, // 3Gamma Function Disable ILI9341_GAMMASET, 1, 0x01, // Gamma curve selected ILI9341_GMCTRP1, 15, 0x0F, 0x31, 0x2B, 0x0C, 0x0E, 0x08, 0x4E, 0xF1, 0x37, 0x07, 0x10, 0x03, 0x0E, 0x09, 0x00, ILI9341_GMCTRN1, 15, 0x00, 0x0E, 0x14, 0x03, 0x11, 0x07, 0x31, 0xC1, 0x48, 0x08, 0x0F, 0x0C, 0x31, 0x36, 0x0F, // Set Gamma //ILI9341_SLPOUT, 0x80, // Exit Sleep //ILI9341_DISPON, 0x80, // Display on 0x00 // End of list }; //template class ILI9341 { template class ILI9341 { private: int w = 240; int h = 320; static constexpr const char* MOD = "ILI9341"; //HardSPI spi; //SoftSPI spi; SPI& spi; public: ILI9341(SPI& spi) : spi(spi) { MyGPIO::setOutput(PIN_DATA_COMMAND); MyGPIO::setOutput(PIN_CS); //spi.init(); } void setPixel(const uint16_t x, const uint16_t y, const uint16_t color) { chipSelect(); setAddrWindow(x,y,1,1); sendWord(color); chipDeselect(); } void setPixel(const uint16_t x, const uint16_t y, const uint8_t w, const uint16_t color) { chipSelect(); setAddrWindow(x-w/2,y-w/2,w,w); for (int i = 0; i < w*w; ++i) { sendWord(color); } chipDeselect(); } /** perform display software reset and initialization */ void init() { chipSelect(); // send reset command wait(); sendCommand(ILI9341_SWRESET); wait(); // send init sequence const uint8_t* bytes = initcmd; while(*bytes) { const uint8_t cmd = *bytes; ++bytes; uint8_t numArgs = *bytes; ++bytes; debugMod2(MOD, "send command %d (%d bytes)", cmd, numArgs); sendCommand(cmd); while(numArgs--) { sendByte(*bytes); ++bytes; } } // finalize init sequence sendCommand(ILI9341_SLPOUT); wait(); sendCommand(ILI9341_DISPON); wait(); // done chipDeselect(); } uint32_t getID() { chipSelect(); sendCommand16(ILI9341_RDDID); uint32_t res = 0xFFFFFFFF; readBytes(reinterpret_cast(&res), 4); // dummy-byte + 3 data bytes chipDeselect(); return res; } void getStatus() { chipSelect(); uint8_t buf[5]; sendCommand16(ILI9341_RDDID); uint32_t res = 0xFFFFFFFF; readBytes(buf, 5); // dummy-byte + 4 data bytes chipDeselect(); //ESP_LOGI(MOD, "%d %d %d %d", buf[1],buf[2],buf[3],buf[4]); read(); } void read() { chipSelect(); setAddrWindow(0,0,100,100); sendCommand(ILI9341_RAMRD); uint8_t buf[32]; readBytes(buf, 32); for (int i = 0; i < 32; ++i) { printf("%d ", buf[i]); } printf("\n"); chipDeselect(); } void draw(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t* data) { chipSelect(); setAddrWindow(x,y,w,h); // const int len = w*h; // for (int i = 0; i < len; ++i) { // spi::writeWord(data[i]); // } spi.write((const uint8_t*)data, w*h*2); chipDeselect(); } void fillRand() { // chipSelect(); // setAddrWindow(0,0,w,h); // for (int i = 0; i < w*h/2; ++i) { // sendQuad(rand()); // } // chipDeselect(); chipSelect(); setAddrWindow(0,0,w,h); for (int y = 0; y < h; ++y) { uint16_t buf[w]; for (int x = 0; x < w; ++x) {buf[x] = rand();} sendBytes(reinterpret_cast(buf), w*2); } chipDeselect(); } void fill(const uint16_t color) { chipSelect(); setAddrWindow(0,0,w,h); for (int y = 0; y < h; ++y) { uint16_t buf[w]; for (int x = 0; x < w; ++x) {buf[x] = color;} sendBytes(reinterpret_cast(buf), w*2); } chipDeselect(); } void fillRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint16_t color) { chipSelect(); setAddrWindow(x,y,w,h); for (int i = 0; i < w*h; ++i) { sendWord(color); } chipDeselect(); } private: void setAddrWindow(const uint16_t x, const uint16_t y, const uint16_t w, const uint16_t h) { const uint32_t xa = ((uint32_t)x << 16) | (x+w-1); const uint32_t ya = ((uint32_t)y << 16) | (y+h-1); sendCommand(ILI9341_CASET); // Column addr set sendQuad(xa); sendCommand(ILI9341_PASET); // Row addr set sendQuad(ya); sendCommand(ILI9341_RAMWR); // write to RAM // transmit data now } void wait() { //vTaskDelay(100 / portTICK_PERIOD_MS); DELAY_MS(100); } /** select the display (CS=0) */ inline void chipSelect() { //spi::chipSelect(); MyGPIO::clear(PIN_CS); } /** send the given command to the display */ void sendCommand(const uint8_t cmd) { modeCMD(); spi.writeByte(cmd); modeDATA(); } /** send the given command to the display */ void sendCommand16(const uint8_t cmd) { modeCMD(); spi.writeByte(cmd); spi.writeByte(0x00); modeDATA(); } /** send the given data byte to the display */ void sendByte(const uint8_t data) { spi.writeByte(data); } /** send the given data word to the display */ void sendWord(const uint16_t data) { spi.writeWord(data); } /** send the given data quad to the display */ void sendQuad(const uint32_t data) { spi.writeQuad(data); } /** send the given data to the display */ void sendBytes(const uint8_t* data, const size_t len) { spi.write(data, len); } /** read the given data from the display */ void readBytes(uint8_t* data, const size_t len) { spi.read(data, len); } /** unselect the display (CS=1) */ inline void chipDeselect() { //spi::chipDeselect(); MyGPIO::set(PIN_CS); } /** switch to command-mode */ inline void modeCMD() { //gpio_set_level((gpio_num_t)PIN_DATA_COMMAND, 0); MyGPIO::clear(PIN_DATA_COMMAND); } /** switch to data-mode */ inline void modeDATA() { //gpio_set_level((gpio_num_t)PIN_DATA_COMMAND, 1); MyGPIO::set(PIN_DATA_COMMAND); } }; #endif