Files
ESP8266lib/ext/lcd/ILI9341.h
kazu 5cb02880b3 many updates..
new sensors.. display.. led.. drawing.. stuff..
2019-01-17 23:12:01 +01:00

366 lines
9.8 KiB
C++

#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 <int PIN_CS, int PIN_MISO, int PIN_MOSI, int PIN_CLK, int PIN_DATA_COMMAND> class ILI9341 {
template <int PIN_CS, int PIN_DATA_COMMAND, typename SPI> class ILI9341 {
private:
int w = 240;
int h = 320;
static constexpr const char* MOD = "ILI9341";
//HardSPI<PIN_MISO, PIN_MOSI, PIN_CLK> spi;
//SoftSPI<PIN_MISO, PIN_MOSI, PIN_CLK, true> spi;
SPI& spi;
public:
ILI9341(SPI& spi) : spi(spi) {
GPIO::setOutput(PIN_DATA_COMMAND);
GPIO::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<uint8_t*>(&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<uint8_t*>(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<uint8_t*>(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);
}
/** select the display (CS=0) */
inline void chipSelect() {
//spi::chipSelect();
GPIO::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();
GPIO::set(PIN_CS);
}
/** switch to command-mode */
inline void modeCMD() {
//gpio_set_level((gpio_num_t)PIN_DATA_COMMAND, 0);
GPIO::clear(PIN_DATA_COMMAND);
}
/** switch to data-mode */
inline void modeDATA() {
//gpio_set_level((gpio_num_t)PIN_DATA_COMMAND, 1);
GPIO::set(PIN_DATA_COMMAND);
}
};
#endif