Files
ESP8266lib/ext/lcd/ILI9486.h

302 lines
7.3 KiB
C++

#ifndef LCD_ILI9341
#define LCD_ILI9341
#include "../../Debug.h"
#include <initializer_list>
// https://www.displayfuture.com/Display/datasheet/controller/ILI9486L.pdf
// https://www.waveshare.com/3.5inch-tft-touch-shield.htm
// https://www.waveshare.com/wiki/File:3.5inch_TFT_Touch_Shield_Code.7z
// https://github.com/ZinggJM/ILI9486_SPI/blob/master/src/ILI9486_SPI.cpp
static constexpr const uint8_t ili9486_init[] = {
};
//template <int PIN_CS, int PIN_MISO, int PIN_MOSI, int PIN_CLK, int PIN_DATA_COMMAND> class ILI9341 {
template <typename SPI, int PIN_CS, int PIN_DATA_COMMAND> class ILI9486 {
private:
int w = 320;
int h = 240;
static constexpr const char* MOD = "ILI9486";
static constexpr const uint8_t REG_SWRESET = 0x01; // Software Reset
static constexpr const uint8_t REG_RDDID = 0x04; // Read display identification information
static constexpr const uint8_t REG_RDDST = 0x09; // Read Display Status
static constexpr const uint8_t REG_CASET = 0x2A; // Column Address Set
static constexpr const uint8_t REG_PASET = 0x2B; // Page Address Set
static constexpr const uint8_t REG_RAMWR = 0x2C; // Memory Write
static constexpr const uint8_t REG_RAMRD = 0x2E; // Memory Read
SPI& spi;
public:
ILI9486(SPI& spi) : spi(spi) {
MyGPIO::setOutput(PIN_DATA_COMMAND);
MyGPIO::setOutput(PIN_CS);
}
/** perform display software reset and initialization */
void init() {
// send reset command
wait();
sendCommand(REG_SWRESET);
wait();
getStatus();
//sendCommandAndData(0xb0, {0x00}); // Interface Mode Control
sendCommandAndData(0x11, {}); // disable sleep
wait();
sendCommandAndData(0x3A, {0x55}); // Interface Pixel Format, 16 bits / pixel
sendCommandAndData(0x36, {0x28}); // Memory Access Control
sendCommandAndData(0xC2, {0x44}); // Power Control 3 (For Normal Mode)
sendCommandAndData(0xC5, {0x00, 0x00, 0x00, 0x00}); // VCOM Control
sendCommandAndData(0xE0, {0x0F, 0x1F, 0x1C, 0x0C, 0x0F, 0x08, 0x48, 0x98, 0x37, 0x0A, 0x13, 0x04, 0x11, 0x0D, 0x00}); // PGAMCTRL(Positive Gamma Control)
sendCommandAndData(0xE1, {0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00}); // NGAMCTRL (Negative Gamma Correction)
sendCommandAndData(0xE2, {0x0F, 0x32, 0x2E, 0x0B, 0x0D, 0x05, 0x47, 0x75, 0x37, 0x06, 0x10, 0x03, 0x24, 0x20, 0x00}); // Digital Gamma Control 1
sendCommandAndData(0x36, {0x28}); // Memory Access Control, BGR
sendCommandAndData(0x11, {}), // # Sleep OUT
sendCommandAndData(0x29, {}), // Display ON
wait();
/*
sendCommand(0x3A);
sendData(0x55); // use 16 bits per pixel color
sendCommand(0x36);
sendData(0x48); // MX, BGR == rotation 0
// PGAMCTRL(Positive Gamma Control)
sendCommand(0xE0);
sendData(0x0F);
sendData(0x1F);
sendData(0x1C);
sendData(0x0C);
sendData(0x0F);
sendData(0x08);
sendData(0x48);
sendData(0x98);
sendData(0x37);
sendData(0x0A);
sendData(0x13);
sendData(0x04);
sendData(0x11);
sendData(0x0D);
sendData(0x00);
// NGAMCTRL(Negative Gamma Control)
sendCommand(0xE1);
sendData(0x0F);
sendData(0x32);
sendData(0x2E);
sendData(0x0B);
sendData(0x0D);
sendData(0x05);
sendData(0x47);
sendData(0x75);
sendData(0x37);
sendData(0x06);
sendData(0x10);
sendData(0x03);
sendData(0x24);
sendData(0x20);
sendData(0x00);
// Digital Gamma Control 1
sendCommand(0xE2);
sendData(0x0F);
sendData(0x32);
sendData(0x2E);
sendData(0x0B);
sendData(0x0D);
sendData(0x05);
sendData(0x47);
sendData(0x75);
sendData(0x37);
sendData(0x06);
sendData(0x10);
sendData(0x03);
sendData(0x24);
sendData(0x20);
sendData(0x00);
sendCommand(0x11); // Sleep OUT
wait();
sendCommand(0x29); // Display ON
wait();
*/
}
void sendCommandAndData(uint8_t cmd, std::initializer_list<uint8_t> data) {
sendCommand(cmd);
for (uint8_t b : data) {sendData(b);}
}
uint32_t getID() {
sendCommand(REG_RDDID);
uint32_t res = 0xFFFFFFFF;
spi.read(reinterpret_cast<uint8_t*>(&res), 4); // dummy-byte + 3 data bytes
return res;
}
void getStatus() {
uint8_t buf[5];
sendCommand(REG_RDDST);
uint32_t res = 0xFFFFFFFF;
spi.read(buf, 5); // dummy-byte + 4 data bytes
printf("Status: %02x %02x %02x %02x \n", buf[1],buf[2],buf[3],buf[4]);
}
/*
void read() {
chipSelect();
setAddrWindow(0,0,100,100);
sendCommand(REG_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) {
setAddrWindow(x,y,w,h);
modeDATA();
chipSelect();
spi.write((const uint8_t*)data, w*h*2);
chipDeselect();
}
void fillRand() {
setAddrWindow(0,0,w,h);
modeDATA();
chipSelect();
for (int y = 0; y < h; ++y) {
uint16_t buf[w];
for (int x = 0; x < w; ++x) {buf[x] = rand();}
spi.write(reinterpret_cast<uint8_t*>(buf), w*2);
}
chipDeselect();
}
void fillColor(uint16_t color) {
setAddrWindow(0,0,w,h);
modeDATA();
chipSelect();
for (uint32_t i = 0; i < w*h; ++i) {
spi.writeWord(color);
}
chipDeselect();
}
private:
void wait() {
vTaskDelay(250 / portTICK_PERIOD_MS);
}
void setAddrWindow(const uint16_t x1, const uint16_t y1, const uint16_t w, const uint16_t h) {
// end (x,y)
uint16_t x2 = x1 + w - 1;
uint16_t y2 = y1 + h - 1;
sendCommand(REG_CASET); // Column addr set
sendData(x1 >> 8); //Set the horizontal starting point to the high octet
sendData(x1 & 0xff); //Set the horizontal starting point to the low octet
sendData(x2 >> 8); //Set the horizontal end to the high octet
sendData(x2 & 0xff); //Set the horizontal end to the low octet
sendCommand(REG_PASET); // Row addr set
sendData(y1 >> 8);
sendData(y1 & 0xff );
sendData(y2 >> 8);
sendData(y2 & 0xff);
sendCommand(REG_RAMWR); // write to RAM
// transmit data now
}
/** send the given command to the display */
void sendCommand(const uint8_t cmd) {
modeCMD();
chipSelect();
spi.writeByte(0x00); // 16 bit transfer!
spi.writeByte(cmd);
chipDeselect();
}
/** send the given data to the display */
void sendData(const uint8_t data) {
modeDATA();
chipSelect();
spi.writeByte(0x00); // 16 bit transfer!
spi.writeByte(data);
chipDeselect();
}
// /** 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);
// }
/** select the display (CS=0) */
inline void chipSelect() {
//asm("nop");asm("nop");asm("nop");asm("nop");
MyGPIO::clear(PIN_CS);
//asm("nop");asm("nop");asm("nop");asm("nop");
}
/** unselect the display (CS=1) */
inline void chipDeselect() {
//asm("nop");asm("nop");asm("nop");asm("nop");
MyGPIO::set(PIN_CS);
//asm("nop");asm("nop");asm("nop");asm("nop");
}
/** switch to command-mode */
inline void modeCMD() {
//asm("nop");asm("nop");asm("nop");asm("nop");
MyGPIO::clear(PIN_DATA_COMMAND);
//asm("nop");asm("nop");asm("nop");asm("nop");
}
/** switch to data-mode */
inline void modeDATA() {
//asm("nop");asm("nop");asm("nop");asm("nop");
MyGPIO::set(PIN_DATA_COMMAND);
//asm("nop");asm("nop");asm("nop");asm("nop");
}
};
#endif