Merge 0a8964696e into 5e7394f485
This commit is contained in:
commit
cd1e8d1f71
|
|
@ -0,0 +1,103 @@
|
||||||
|
// Change the width and height if required (defined in portrait mode)
|
||||||
|
// or use the constructor to over-ride defaults
|
||||||
|
// Based ON: ILI9225_Defines.h for ST7781 / SPFD5408 (MCUFRIEND UNO/Mega Display Shield)
|
||||||
|
// https://www.crystalfontz.com/controllers/Sitronix/ST7781/
|
||||||
|
// https://www.rhydolabz.com/documents/SPFD5408A.pdf
|
||||||
|
|
||||||
|
|
||||||
|
#define WRITE_COMMAND_16 // Change TFT_eSPI::writecommand(); to use tft_Write_16(c);
|
||||||
|
|
||||||
|
#define TFT_WIDTH 240
|
||||||
|
#define TFT_HEIGHT 320
|
||||||
|
|
||||||
|
// Generic commands used by TFT_eSPI.cpp
|
||||||
|
#define TFT_NOP 0x00
|
||||||
|
#define TFT_SWRST 0x00 // NO Software Reset ?
|
||||||
|
|
||||||
|
#define TFT_CASET 0
|
||||||
|
#define TFT_PASET 0
|
||||||
|
|
||||||
|
#define TFT_CASET1 ST7781_HORIZONTAL_WINDOW_ADDR1
|
||||||
|
#define TFT_CASET2 ST7781_HORIZONTAL_WINDOW_ADDR2
|
||||||
|
|
||||||
|
#define TFT_PASET1 ST7781_VERTICAL_WINDOW_ADDR1
|
||||||
|
#define TFT_PASET2 ST7781_VERTICAL_WINDOW_ADDR2
|
||||||
|
|
||||||
|
#define TFT_RAM_ADDR1 ST7781_RAM_ADDR_SET1
|
||||||
|
#define TFT_RAM_ADDR2 ST7781_RAM_ADDR_SET2
|
||||||
|
|
||||||
|
#define TFT_RAMWR ST7781_RAM_DATA_REG
|
||||||
|
|
||||||
|
#define TFT_MAD_BGR 0x10
|
||||||
|
#define TFT_MAD_RGB 0x00
|
||||||
|
|
||||||
|
#ifdef TFT_RGB_ORDER
|
||||||
|
#if (TFT_RGB_ORDER == 1)
|
||||||
|
#define TFT_MAD_COLOR_ORDER TFT_MAD_RGB
|
||||||
|
#else
|
||||||
|
#define TFT_MAD_COLOR_ORDER TFT_MAD_BGR
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#define TFT_MAD_COLOR_ORDER TFT_MAD_BGR
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Not used
|
||||||
|
#define TFT_INVOFF 0x00
|
||||||
|
#define TFT_INVON 0x00
|
||||||
|
#define TFT_RAMRD 0x00
|
||||||
|
#define TFT_IDXRD 0x00
|
||||||
|
|
||||||
|
/* ST7781 Registers */
|
||||||
|
#define ST7781_DRIVER_OUTPUT_CTRL 0x01 // Driver Output Control
|
||||||
|
#define ST7781_LCD_AC_DRIVING_CTRL 0x02 // LCD AC Driving Control
|
||||||
|
#define ST7781_ENTRY_MODE 0x03 // Entry Mode
|
||||||
|
#define ST7781_RESIZE_CTRL 0x04 // Resize Control
|
||||||
|
#define ST7781_DISP_CTRL1 0x07 // Display Control 1
|
||||||
|
#define ST7781_DISP_CTRL2 0x08 // Display Control 2
|
||||||
|
#define ST7781_DISP_CTRL3 0x09 // Display Control 3
|
||||||
|
#define ST7781_DISP_CTRL4 0x0A // Display Control 4
|
||||||
|
#define ST7781_FRAME_MAKER_POS 0x0D // Frame Maker Position
|
||||||
|
#define ST7781_POWER_CTRL1 0x10 // Power Control 1
|
||||||
|
#define ST7781_POWER_CTRL2 0x11 // Power Control 2
|
||||||
|
#define ST7781_POWER_CTRL3 0x12 // Power Control 3
|
||||||
|
#define ST7781_POWER_CTRL4 0x13 // Power Control 4
|
||||||
|
#define ST7781_RAM_ADDR_SET1 0x20 // Horizontal GRAM Address Set
|
||||||
|
#define ST7781_RAM_ADDR_SET2 0x21 // Vertical GRAM Address Set
|
||||||
|
#define ST7781_RAM_DATA_REG 0x22 // Read/Write to RAM Data Register
|
||||||
|
#define ST7781_VCOMH_CTRL 0x29 // VCOMH Control
|
||||||
|
#define ST7781_FRAME_COLOR_CTRL 0x2B // Frame Rate and Color Control
|
||||||
|
#define ST7781_GAMMA_CTRL1 0x30 // Gamma Control 1
|
||||||
|
#define ST7781_GAMMA_CTRL2 0x31 // Gamma Control 2
|
||||||
|
#define ST7781_GAMMA_CTRL3 0x32 // Gamma Control 3
|
||||||
|
#define ST7781_GAMMA_CTRL4 0x35 // Gamma Control 4
|
||||||
|
#define ST7781_GAMMA_CTRL5 0x36 // Gamma Control 5
|
||||||
|
#define ST7781_GAMMA_CTRL6 0x37 // Gamma Control 6
|
||||||
|
#define ST7781_GAMMA_CTRL7 0x38 // Gamma Control 7
|
||||||
|
#define ST7781_GAMMA_CTRL8 0x39 // Gamma Control 8
|
||||||
|
#define ST7781_GAMMA_CTRL9 0x3C // Gamma Control 9
|
||||||
|
#define ST7781_GAMMA_CTRL10 0x3D // Gamma Control 10
|
||||||
|
#define ST7781_HORIZONTAL_WINDOW_ADDR1 0x50 // Horizontal Address Start Position
|
||||||
|
#define ST7781_HORIZONTAL_WINDOW_ADDR2 0x51 // Horizontal Address End Position
|
||||||
|
#define ST7781_VERTICAL_WINDOW_ADDR1 0x52 // Vertical Address Start Position
|
||||||
|
#define ST7781_VERTICAL_WINDOW_ADDR2 0x53 // Vertical Address End Position
|
||||||
|
#define ST7781_GATE_SCAN_CTRL1 0x60 // Gate Scan Control 1
|
||||||
|
#define ST7781_GATE_SCAN_CTRL2 0x61 // Gate Scan Control 2
|
||||||
|
#define ST7781_PARTIAL_POS_IMG1 0x80 // Partial Image 1 Display Position
|
||||||
|
#define ST7781_PARTIAL_START_ADDR_IMG1 0x81 // Partial Image 1 Start Address
|
||||||
|
#define ST7781_PARTIAL_END_ADDR_IMG1 0x82 // Partial Image 1 End Address
|
||||||
|
#define ST7781_PARTIAL_POS_IMG2 0x83 // Partial Image 2 Display Position
|
||||||
|
#define ST7781_PARTIAL_START_ADDR_IMG2 0x84 // Partial Image 2 Start Address
|
||||||
|
#define ST7781_PARTIAL_END_ADDR_IMG2 0x85 // Partial Image 2 End Address
|
||||||
|
#define ST7781_PANEL_IFACE_CTRL1 0x90 // Panel Interface Control 1
|
||||||
|
#define ST7781_PANEL_IFACE_CTRL2 0x92 // Panel Interface Control 2
|
||||||
|
#define ST7781_EEPROM_ID_CODE 0xD2 // EEPROM ID Code
|
||||||
|
#define ST7781_EEPROM_CTRL_STATUS 0xD9 // EEPROM Control Status
|
||||||
|
#define ST7781_EEPROM_WRITE_COMMAND 0xDF // EEPROM Wite Command
|
||||||
|
#define ST7781_EEPROM_ENABLE 0xFA // EEPROM Enable
|
||||||
|
#define ST7781_EEPROM_VCOM_OFFSET 0xFE // EEPROM VCOM Offset
|
||||||
|
#define ST7781_FA_FE_ENABLE 0xFF // FAh/FEh Enable
|
||||||
|
|
||||||
|
|
||||||
|
// Delay between some initialisation commands
|
||||||
|
//#define TFT_INIT_DELAY 0x00 // Not used unless commandlist invoked
|
||||||
|
#define TFT_INIT_DELAY 0x00
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
//
|
||||||
|
// This is the command sequence that initialises the ST7781 / SPFD5408 driver
|
||||||
|
// References:
|
||||||
|
// - https://github.com/compihu/SWIFT-Shield
|
||||||
|
// - https://github.com/prenticedavid/MCUFRIEND_kbv
|
||||||
|
// SUPPORT_7781 / ST7781_regValues_CPT24
|
||||||
|
//
|
||||||
|
// This want full 16 bit command, so writecommand() is changed with define WRITE_COMMAND_16
|
||||||
|
{
|
||||||
|
writecommand(ST7781_DRIVER_OUTPUT_CTRL); writedata(0x01);writedata(0x00); // Driver Output Control Register (R01h)
|
||||||
|
writecommand(ST7781_LCD_AC_DRIVING_CTRL); writedata(0x07);writedata(0x00); // LCD Driving Waveform Control (R02h)
|
||||||
|
writecommand(ST7781_ENTRY_MODE); writedata(0x10);writedata(0x30); // Entry Mode (R03h)
|
||||||
|
writecommand(ST7781_DISP_CTRL2); writedata(0x03);writedata(0x02); // Porch
|
||||||
|
writecommand(ST7781_DISP_CTRL3); writedata(0x00);writedata(0x00); // Scan
|
||||||
|
writecommand(ST7781_DISP_CTRL4); writedata(0x00);writedata(0x08); // Fmark Off
|
||||||
|
writecommand(ST7781_POWER_CTRL1); writedata(0x00);writedata(0x08); // Power Control 1 (R10h)
|
||||||
|
writecommand(ST7781_POWER_CTRL2); writedata(0x00);writedata(0x05); // Power Control 2 (R11h)
|
||||||
|
writecommand(ST7781_POWER_CTRL3); writedata(0x00);writedata(0x00); // Power Control 3 (R12h)
|
||||||
|
writecommand(ST7781_POWER_CTRL4); writedata(0x00);writedata(0x00); // Power Control 4 (R13h)
|
||||||
|
delay(100);
|
||||||
|
writecommand(ST7781_POWER_CTRL1); writedata(0x12);writedata(0xB0); // Power Control 1 SAP=1, BT=2, APE=1, AP=3
|
||||||
|
delay(50);
|
||||||
|
writecommand(ST7781_POWER_CTRL2); writedata(0x00);writedata(0x07); // Power Control 2 VC=7
|
||||||
|
delay(50);
|
||||||
|
writecommand(ST7781_POWER_CTRL3); writedata(0x00);writedata(0x8C); // Power Control 3 VCIRE=1, VRH=12
|
||||||
|
writecommand(ST7781_POWER_CTRL4); writedata(0x17);writedata(0x00); // Power Control 4 VDV=23
|
||||||
|
writecommand(ST7781_VCOMH_CTRL); writedata(0x00);writedata(0x20); // NVM read data 2 VCM=32
|
||||||
|
delay(50);
|
||||||
|
writecommand(ST7781_GAMMA_CTRL1); writedata(0x00);writedata(0x00); // Gamma Control 1 App Note CPT 2.4
|
||||||
|
writecommand(ST7781_GAMMA_CTRL2); writedata(0x01);writedata(0x06); // Gamma Control 2
|
||||||
|
writecommand(ST7781_GAMMA_CTRL3); writedata(0x01);writedata(0x01); // Gamma Control 3
|
||||||
|
writecommand(ST7781_GAMMA_CTRL4); writedata(0x01);writedata(0x06); // Gamma Control 4
|
||||||
|
writecommand(ST7781_GAMMA_CTRL5); writedata(0x02);writedata(0x03); // Gamma Control 5
|
||||||
|
writecommand(ST7781_GAMMA_CTRL6); writedata(0x00);writedata(0x00); // Gamma Control 6
|
||||||
|
writecommand(ST7781_GAMMA_CTRL7); writedata(0x07);writedata(0x07); // Gamma Control 7
|
||||||
|
writecommand(ST7781_GAMMA_CTRL8); writedata(0x02);writedata(0x04); // Gamma Control 8
|
||||||
|
writecommand(ST7781_GAMMA_CTRL9); writedata(0x01);writedata(0x06); // Gamma Control 9
|
||||||
|
writecommand(ST7781_GAMMA_CTRL10); writedata(0x01);writedata(0x03); // Gamma Control 10
|
||||||
|
writecommand(ST7781_GATE_SCAN_CTRL1); writedata(0xA7);writedata(0x00); // Driver Output Control (R60h) .kbv was 0xa700
|
||||||
|
writecommand(ST7781_GATE_SCAN_CTRL2); writedata(0x00);writedata(0x01); // Driver Output Control (R61h)
|
||||||
|
writecommand(ST7781_PANEL_IFACE_CTRL1); writedata(0x00);writedata(0x30); // Panel Interface Control 1 (R90h)
|
||||||
|
// Display On
|
||||||
|
writecommand(ST7781_DISP_CTRL1); writedata(0x01);writedata(0x33); // Display Control (R07h)
|
||||||
|
delay(50);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
// This is the command sequence that rotates the ST7781 driver coordinate frame
|
||||||
|
// Based on ILI9225_Rotation.h and MCUFRIEND_kbv = MCUFRIEND_kbv::setRotation()
|
||||||
|
|
||||||
|
rotation = m % 4; // Limit the range of values to 0-3
|
||||||
|
|
||||||
|
switch (rotation) {
|
||||||
|
case 0:
|
||||||
|
writecommand(ST7781_GATE_SCAN_CTRL1);
|
||||||
|
writedata(0xA7);writedata(0x00);
|
||||||
|
writecommand(ST7781_DRIVER_OUTPUT_CTRL);
|
||||||
|
writedata(0x01);writedata(0x00);
|
||||||
|
writecommand(ST7781_ENTRY_MODE);
|
||||||
|
writedata(TFT_MAD_COLOR_ORDER);writedata(0x30);
|
||||||
|
_width = _init_width;
|
||||||
|
_height = _init_height;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
writecommand(ST7781_GATE_SCAN_CTRL1);
|
||||||
|
writedata(0xA7);writedata(0x00);
|
||||||
|
writecommand(ST7781_DRIVER_OUTPUT_CTRL);
|
||||||
|
writedata(0x00);writedata(0x00);
|
||||||
|
writecommand(ST7781_ENTRY_MODE);
|
||||||
|
writedata(TFT_MAD_COLOR_ORDER);writedata(0x38);
|
||||||
|
_width = _init_height;
|
||||||
|
_height = _init_width;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
writecommand(ST7781_GATE_SCAN_CTRL1);
|
||||||
|
writedata(0x27);writedata(0x00);
|
||||||
|
writecommand(ST7781_DRIVER_OUTPUT_CTRL);
|
||||||
|
writedata(0x00);writedata(0x00);
|
||||||
|
writecommand(ST7781_ENTRY_MODE);
|
||||||
|
writedata(TFT_MAD_COLOR_ORDER);writedata(0x30);
|
||||||
|
_width = _init_width;
|
||||||
|
_height = _init_height;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
writecommand(ST7781_GATE_SCAN_CTRL1);
|
||||||
|
writedata(0x27);writedata(0x00);
|
||||||
|
writecommand(ST7781_DRIVER_OUTPUT_CTRL);
|
||||||
|
writedata(0x01);writedata(0x00);
|
||||||
|
writecommand(ST7781_ENTRY_MODE);
|
||||||
|
writedata(TFT_MAD_COLOR_ORDER);writedata(0x38);
|
||||||
|
_width = _init_height;
|
||||||
|
_height = _init_width;
|
||||||
|
break;
|
||||||
|
}
|
||||||
102
TFT_eSPI.cpp
102
TFT_eSPI.cpp
|
|
@ -658,6 +658,9 @@ void TFT_eSPI::init(uint8_t tc)
|
||||||
#elif defined (ILI9225_DRIVER)
|
#elif defined (ILI9225_DRIVER)
|
||||||
#include "TFT_Drivers/ILI9225_Init.h"
|
#include "TFT_Drivers/ILI9225_Init.h"
|
||||||
|
|
||||||
|
#elif defined (ST7781_DRIVER)
|
||||||
|
#include "TFT_Drivers/ST7781_Init.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef TFT_INVERSION_ON
|
#ifdef TFT_INVERSION_ON
|
||||||
|
|
@ -746,6 +749,9 @@ void TFT_eSPI::setRotation(uint8_t m)
|
||||||
#elif defined (ILI9225_DRIVER)
|
#elif defined (ILI9225_DRIVER)
|
||||||
#include "TFT_Drivers/ILI9225_Rotation.h"
|
#include "TFT_Drivers/ILI9225_Rotation.h"
|
||||||
|
|
||||||
|
#elif defined (ST7781_DRIVER)
|
||||||
|
#include "TFT_Drivers/ST7781_Rotation.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
delayMicroseconds(10);
|
delayMicroseconds(10);
|
||||||
|
|
@ -816,7 +822,11 @@ void TFT_eSPI::writecommand(uint8_t c)
|
||||||
|
|
||||||
DC_C;
|
DC_C;
|
||||||
|
|
||||||
|
#if defined(WRITE_COMMAND_16)
|
||||||
|
tft_Write_16(c);
|
||||||
|
#else
|
||||||
tft_Write_8(c);
|
tft_Write_8(c);
|
||||||
|
#endif
|
||||||
|
|
||||||
DC_D;
|
DC_D;
|
||||||
|
|
||||||
|
|
@ -945,6 +955,10 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
|
||||||
// Dummy read to throw away don't care value
|
// Dummy read to throw away don't care value
|
||||||
readByte();
|
readByte();
|
||||||
#endif
|
#endif
|
||||||
|
// Some drives need throw 16 bits
|
||||||
|
#if defined (ST7781_DRIVER)
|
||||||
|
readByte();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Fetch the 16 bit BRG pixel
|
// Fetch the 16 bit BRG pixel
|
||||||
//uint16_t rgb = (readByte() << 8) | readByte();
|
//uint16_t rgb = (readByte() << 8) | readByte();
|
||||||
|
|
@ -971,7 +985,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
|
||||||
// Set masked pins D0- D7 to output
|
// Set masked pins D0- D7 to output
|
||||||
busDir(dir_mask, OUTPUT);
|
busDir(dir_mask, OUTPUT);
|
||||||
|
|
||||||
#ifdef ILI9486_DRIVER
|
#if defined(ILI9486_DRIVER) | defined(ST7781_DRIVER)
|
||||||
return bgr;
|
return bgr;
|
||||||
#else
|
#else
|
||||||
// Swap Red and Blue (could check MADCTL setting to see if this is needed)
|
// Swap Red and Blue (could check MADCTL setting to see if this is needed)
|
||||||
|
|
@ -1105,13 +1119,17 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
|
||||||
#else // ILI9481 reads as 16 bits
|
#else // ILI9481 reads as 16 bits
|
||||||
// Dummy read to throw away don't care value
|
// Dummy read to throw away don't care value
|
||||||
readByte();
|
readByte();
|
||||||
|
// Some drives need throw 16 bits
|
||||||
|
#if defined (ST7781_DRIVER)
|
||||||
|
readByte();
|
||||||
|
#endif
|
||||||
|
|
||||||
// Fetch the 16 bit BRG pixels
|
// Fetch the 16 bit BRG pixels
|
||||||
while (dh--) {
|
while (dh--) {
|
||||||
int32_t lw = dw;
|
int32_t lw = dw;
|
||||||
uint16_t* line = data;
|
uint16_t* line = data;
|
||||||
while (lw--) {
|
while (lw--) {
|
||||||
#ifdef ILI9486_DRIVER
|
#if defined (ILI9486_DRIVER) | defined (ST7781_DRIVER)
|
||||||
// Read the RGB 16 bit colour
|
// Read the RGB 16 bit colour
|
||||||
*line++ = readByte() | (readByte() << 8);
|
*line++ = readByte() | (readByte() << 8);
|
||||||
#else
|
#else
|
||||||
|
|
@ -3066,6 +3084,32 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
||||||
// write to RAM
|
// write to RAM
|
||||||
DC_C; tft_Write_8(TFT_RAMWR);
|
DC_C; tft_Write_8(TFT_RAMWR);
|
||||||
DC_D;
|
DC_D;
|
||||||
|
|
||||||
|
#elif defined (ST7781_DRIVER) // Like ILI9225_DRIVER, but 16 bits
|
||||||
|
if (rotation & 0x01) { swap_coord(x0, y0); swap_coord(x1, y1); }
|
||||||
|
|
||||||
|
addr_row = 0xFFFF;
|
||||||
|
addr_col = 0xFFFF;
|
||||||
|
|
||||||
|
DC_C; tft_Write_16(TFT_CASET1);
|
||||||
|
DC_D; tft_Write_16(x0);
|
||||||
|
DC_C; tft_Write_16(TFT_CASET2);
|
||||||
|
DC_D; tft_Write_16(x1);
|
||||||
|
|
||||||
|
DC_C; tft_Write_16(TFT_PASET1);
|
||||||
|
DC_D; tft_Write_16(y0);
|
||||||
|
DC_C; tft_Write_16(TFT_PASET2);
|
||||||
|
DC_D; tft_Write_16(y1);
|
||||||
|
|
||||||
|
DC_C; tft_Write_16(TFT_RAM_ADDR1);
|
||||||
|
DC_D; tft_Write_16(x0);
|
||||||
|
DC_C; tft_Write_16(TFT_RAM_ADDR2);
|
||||||
|
DC_D; tft_Write_16(y0);
|
||||||
|
|
||||||
|
// write to RAM
|
||||||
|
DC_C; tft_Write_16(TFT_RAMWR);
|
||||||
|
DC_D;
|
||||||
|
|
||||||
#elif defined (SSD1351_DRIVER)
|
#elif defined (SSD1351_DRIVER)
|
||||||
if (rotation & 1) {
|
if (rotation & 1) {
|
||||||
swap_coord(x0, y0);
|
swap_coord(x0, y0);
|
||||||
|
|
@ -3207,6 +3251,32 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
|
||||||
while (spi_is_readable(SPI_X)) (void)spi_get_hw(SPI_X)->dr;
|
while (spi_is_readable(SPI_X)) (void)spi_get_hw(SPI_X)->dr;
|
||||||
spi_get_hw(SPI_X)->icr = SPI_SSPICR_RORIC_BITS;
|
spi_get_hw(SPI_X)->icr = SPI_SSPICR_RORIC_BITS;
|
||||||
|
|
||||||
|
#elif defined (ST7781_DRIVER)
|
||||||
|
// Is Like setWindow()
|
||||||
|
if (rotation & 0x01) { swap_coord(xs, ys); swap_coord(xe, ye); }
|
||||||
|
|
||||||
|
// Horizontal Range
|
||||||
|
DC_C; tft_Write_16(TFT_CASET1);
|
||||||
|
DC_D; tft_Write_16(xs);
|
||||||
|
DC_C; tft_Write_16(TFT_CASET2);
|
||||||
|
DC_D; tft_Write_16(xe);
|
||||||
|
|
||||||
|
// Vertical Range
|
||||||
|
DC_C; tft_Write_16(TFT_PASET1);
|
||||||
|
DC_D; tft_Write_16(ys);
|
||||||
|
DC_C; tft_Write_16(TFT_PASET2);
|
||||||
|
DC_D; tft_Write_16(ye);
|
||||||
|
|
||||||
|
// Start Address Pointer
|
||||||
|
DC_C; tft_Write_16(TFT_RAM_ADDR1);
|
||||||
|
DC_D; tft_Write_16(xs);
|
||||||
|
DC_C; tft_Write_16(TFT_RAM_ADDR2);
|
||||||
|
DC_D; tft_Write_16(ys);
|
||||||
|
|
||||||
|
// write to RAM
|
||||||
|
DC_C; tft_Write_16(TFT_RAMWR);
|
||||||
|
DC_D;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
// Column addr set
|
// Column addr set
|
||||||
DC_C; tft_Write_8(TFT_CASET);
|
DC_C; tft_Write_8(TFT_CASET);
|
||||||
|
|
@ -3281,6 +3351,34 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
|
||||||
DC_D; tft_Write_16N(color);
|
DC_D; tft_Write_16N(color);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#elif defined (ST7781_DRIVER) // Like ILI9225_DRIVER, but commands 16 Bits
|
||||||
|
|
||||||
|
if (rotation & 0x01) { swap_coord(x, y); }
|
||||||
|
|
||||||
|
// Set window to full screen to optimise sequential pixel rendering
|
||||||
|
if (addr_row != TFT_DRIVER) {
|
||||||
|
addr_row = TFT_DRIVER; // addr_row used for flag
|
||||||
|
DC_C; tft_Write_16(TFT_CASET1);
|
||||||
|
DC_D; tft_Write_16(0);
|
||||||
|
DC_C; tft_Write_16(TFT_CASET2);
|
||||||
|
DC_D; tft_Write_16(TFT_WIDTH - 1);
|
||||||
|
|
||||||
|
DC_C; tft_Write_16(TFT_PASET1);
|
||||||
|
DC_D; tft_Write_16(0);
|
||||||
|
DC_C; tft_Write_16(TFT_PASET2);
|
||||||
|
DC_D; tft_Write_16(TFT_HEIGHT - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define pixel coordinate
|
||||||
|
DC_C; tft_Write_16(TFT_RAM_ADDR1);
|
||||||
|
DC_D; tft_Write_16(x);
|
||||||
|
DC_C; tft_Write_16(TFT_RAM_ADDR2);
|
||||||
|
DC_D; tft_Write_16(y);
|
||||||
|
|
||||||
|
// write to RAM
|
||||||
|
DC_C; tft_Write_16(TFT_RAMWR);
|
||||||
|
DC_D; tft_Write_16(color);
|
||||||
|
|
||||||
// Temporary solution is to include the RP2040 optimised code here
|
// Temporary solution is to include the RP2040 optimised code here
|
||||||
#elif (defined (ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)) && !defined(TFT_PARALLEL_8_BIT)
|
#elif (defined (ARDUINO_ARCH_RP2040) || defined (ARDUINO_ARCH_MBED)) && !defined(TFT_PARALLEL_8_BIT)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@
|
||||||
//#include <User_Setups/Setup35_ILI9341_STM32_Port_Bus.h> // Setup for STM32 port A parallel display
|
//#include <User_Setups/Setup35_ILI9341_STM32_Port_Bus.h> // Setup for STM32 port A parallel display
|
||||||
|
|
||||||
//#include <User_Setups/Setup36_RPi_touch_ST7796.h> // Setup file configured for ESP32 and RPi ST7796 TFT with touch
|
//#include <User_Setups/Setup36_RPi_touch_ST7796.h> // Setup file configured for ESP32 and RPi ST7796 TFT with touch
|
||||||
|
//#include <User_Setups/Setup37_ST7781.h> // Setup for ST7781 parallel display
|
||||||
|
|
||||||
//#include <User_Setups/Setup43_ST7735.h> // Setup file configured for my ST7735S 80x160
|
//#include <User_Setups/Setup43_ST7735.h> // Setup file configured for my ST7735S 80x160
|
||||||
//#include <User_Setups/Setup44_TTGO_CameraPlus.h> // Setup file for ESP32 and TTGO T-CameraPlus ST7789 SPI bus TFT 240x240
|
//#include <User_Setups/Setup44_TTGO_CameraPlus.h> // Setup file for ESP32 and TTGO T-CameraPlus ST7789 SPI bus TFT 240x240
|
||||||
|
|
@ -209,6 +210,9 @@
|
||||||
#elif defined (ILI9225_DRIVER)
|
#elif defined (ILI9225_DRIVER)
|
||||||
#include "TFT_Drivers/ILI9225_Defines.h"
|
#include "TFT_Drivers/ILI9225_Defines.h"
|
||||||
#define TFT_DRIVER 0x9225
|
#define TFT_DRIVER 0x9225
|
||||||
|
#elif defined (ST7781_DRIVER)
|
||||||
|
#include "TFT_Drivers/ST7781_Defines.h"
|
||||||
|
#define TFT_DRIVER 0x7781
|
||||||
// <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE
|
// <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE
|
||||||
// XYZZY_init.h and XYZZY_rotation.h must also be added in TFT_eSPI.cpp
|
// XYZZY_init.h and XYZZY_rotation.h must also be added in TFT_eSPI.cpp
|
||||||
#elif defined (XYZZY_DRIVER)
|
#elif defined (XYZZY_DRIVER)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
// Setup for ESP32 and ST7781/SPFD5408 240 x 320 TFT
|
||||||
|
|
||||||
|
// See SetupX_Template.h for all options available
|
||||||
|
#define ST7781_DRIVER
|
||||||
|
#define TFT_PARALLEL_8_BIT // MCUFRIEND Shields is Parallel
|
||||||
|
|
||||||
|
// ESP32 pins used for the parallel interface TFT
|
||||||
|
#define TFT_CS 27 // Chip select control pin
|
||||||
|
#define TFT_DC 14 // Data Command control pin - must use a pin in the range 0-31
|
||||||
|
#define TFT_RST 26 // Reset pin
|
||||||
|
|
||||||
|
#define TFT_WR 12 // Write strobe control pin - must use a pin in the range 0-31
|
||||||
|
#define TFT_RD 13
|
||||||
|
|
||||||
|
#define TFT_D0 16 // Must use pins in the range 0-31 for the data bus
|
||||||
|
#define TFT_D1 4 // so a single register write sets/clears all bits
|
||||||
|
#define TFT_D2 23
|
||||||
|
#define TFT_D3 22
|
||||||
|
#define TFT_D4 21
|
||||||
|
#define TFT_D5 19
|
||||||
|
#define TFT_D6 18
|
||||||
|
#define TFT_D7 17
|
||||||
|
|
||||||
|
#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH
|
||||||
|
#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters
|
||||||
|
#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters
|
||||||
|
#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm
|
||||||
|
#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:.
|
||||||
|
#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-.
|
||||||
|
//#define LOAD_FONT8N // Font 8. Alternative to Font 8 above, slightly narrower, so 3 digits fit a 160 pixel TFT
|
||||||
|
#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts
|
||||||
|
|
||||||
|
#define SMOOTH_FONT
|
||||||
|
|
||||||
|
|
||||||
|
//#define SPI_FREQUENCY 20000000
|
||||||
|
#define SPI_FREQUENCY 27000000 // Actually sets it to 26.67MHz = 80/3
|
||||||
|
|
@ -0,0 +1,229 @@
|
||||||
|
/*
|
||||||
|
Common Paint Example
|
||||||
|
Is adapted to work with Resistive touch from TFT 2.4" MCUFRIEND Shield
|
||||||
|
with chipset ST7781 / SPFD5408. This uses shared pins to touch analogic
|
||||||
|
values.
|
||||||
|
Tested with ESP32-Dev Board.
|
||||||
|
|
||||||
|
Need connect pin SD_SCK and set in PIN_SD_SCK
|
||||||
|
Need download Adafruit Resistive Touch Library: Adafruit_TouchScreen
|
||||||
|
On different boards maybe need adjust isValidPressure()
|
||||||
|
|
||||||
|
Make sure all the display driver and pin connections are correct by
|
||||||
|
editing the User_Setup.h file in the TFT_eSPI library folder.
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
|
||||||
|
#########################################################################
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <TFT_eSPI.h> // Hardware-specific library
|
||||||
|
#include <SPI.h>
|
||||||
|
#include <TouchScreen.h> // Adafruit_TouchScreen
|
||||||
|
|
||||||
|
// If User_Setup.h is OK, just need setup this option.
|
||||||
|
// On Display, Touch Screen shares PIN with SD Card
|
||||||
|
// Just select one free pin, this example use GPIO 32 on ESP32
|
||||||
|
#define PIN_SD_SCK 32
|
||||||
|
|
||||||
|
|
||||||
|
#define YP TFT_WR // On Uno is pin A1, just use User_Setup.h
|
||||||
|
#define XM TFT_DC // On Uno is pin A2, just use User_Setup.h
|
||||||
|
#define YM TFT_D7 // On Uno is pin D7, just use User_Setup.h
|
||||||
|
#define XP TFT_D6 // On Uno is pin D6, just use User_Setup.h
|
||||||
|
|
||||||
|
// For better pressure precision, we need to know the resistance
|
||||||
|
// between X+ and X- Use any multimeter to read it
|
||||||
|
// For the one we're using, its 300 ohms across the X plate
|
||||||
|
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
|
||||||
|
TSPoint p;
|
||||||
|
|
||||||
|
TFT_eSPI tft = TFT_eSPI();
|
||||||
|
|
||||||
|
#define BOXSIZE 40
|
||||||
|
#define PENRADIUS 3
|
||||||
|
int oldcolor, currentcolor;
|
||||||
|
int calibration = 0;
|
||||||
|
|
||||||
|
int16_t calibMinX = 0;
|
||||||
|
int16_t calibMinY = 0;
|
||||||
|
int16_t calibMaxX = 0;
|
||||||
|
int16_t calibMaxY = 0;
|
||||||
|
int16_t userX = 0;
|
||||||
|
int16_t userY = 0;
|
||||||
|
|
||||||
|
void setup(void) {
|
||||||
|
Serial.begin(115200);
|
||||||
|
Serial.println(F("Paint Time!"));
|
||||||
|
//
|
||||||
|
uint16_t identifier = tft.readcommand16(0x00, 2); // 16 Bits
|
||||||
|
Serial.print(F("LCD driver chip: "));
|
||||||
|
Serial.println(identifier, HEX);
|
||||||
|
//
|
||||||
|
Serial.print("Screen Width: "); Serial.println(tft.width());
|
||||||
|
Serial.print("Screen Height: "); Serial.println(tft.height());
|
||||||
|
//
|
||||||
|
pinMode(PIN_SD_SCK, OUTPUT);
|
||||||
|
|
||||||
|
tft.begin();
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (calibration < 30) {
|
||||||
|
doCalibration();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if (isValidPressure()) {
|
||||||
|
// Serial.print("X = "); Serial.print(p.x);
|
||||||
|
// Serial.print("\tY = "); Serial.print(p.y);
|
||||||
|
// Serial.print("\tPressure = "); Serial.println(p.z);
|
||||||
|
|
||||||
|
// Calculate correct user touch
|
||||||
|
userX = map(p.x, calibMinX, calibMaxX, 0, tft.width());
|
||||||
|
userY = map(p.y, calibMinY, calibMaxY, 0, tft.height());
|
||||||
|
// Fix limits
|
||||||
|
if (userX < 0) userX = 0;
|
||||||
|
if (userY < 0) userY = 0;
|
||||||
|
if (userX > tft.width()) userX = tft.width();
|
||||||
|
if (userY > tft.height()) userY = tft.height();
|
||||||
|
// Serial.print("User X: "); Serial.print(userX);
|
||||||
|
// Serial.print("\tUser Y: "); Serial.println(userY);
|
||||||
|
|
||||||
|
if (userY > (tft.height()-5)) {
|
||||||
|
// Serial.println("Erase");
|
||||||
|
// press the bottom of the screen to erase
|
||||||
|
tft.fillRect(0, BOXSIZE, tft.width(), tft.height()-BOXSIZE, TFT_BLACK);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select colors
|
||||||
|
if (userY < BOXSIZE) {
|
||||||
|
oldcolor = currentcolor;
|
||||||
|
|
||||||
|
if (userX < BOXSIZE) {
|
||||||
|
currentcolor = TFT_RED;
|
||||||
|
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
|
||||||
|
} else if (userX < BOXSIZE*2) {
|
||||||
|
currentcolor = TFT_YELLOW;
|
||||||
|
tft.drawRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
|
||||||
|
} else if (userX < BOXSIZE*3) {
|
||||||
|
currentcolor = TFT_GREEN;
|
||||||
|
tft.drawRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
|
||||||
|
} else if (userX < BOXSIZE*4) {
|
||||||
|
currentcolor = TFT_CYAN;
|
||||||
|
tft.drawRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
|
||||||
|
} else if (userX < BOXSIZE*5) {
|
||||||
|
currentcolor = TFT_BLUE;
|
||||||
|
tft.drawRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
|
||||||
|
} else if (userX < BOXSIZE*6) {
|
||||||
|
currentcolor = TFT_MAGENTA;
|
||||||
|
tft.drawRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
|
||||||
|
}
|
||||||
|
if (oldcolor != currentcolor) {
|
||||||
|
if (oldcolor == TFT_RED) tft.fillRect(0, 0, BOXSIZE, BOXSIZE, TFT_RED);
|
||||||
|
if (oldcolor == TFT_YELLOW) tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE, TFT_YELLOW);
|
||||||
|
if (oldcolor == TFT_GREEN) tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, TFT_GREEN);
|
||||||
|
if (oldcolor == TFT_CYAN) tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, TFT_CYAN);
|
||||||
|
if (oldcolor == TFT_BLUE) tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, TFT_BLUE);
|
||||||
|
if (oldcolor == TFT_MAGENTA) tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, TFT_MAGENTA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (((userY-PENRADIUS) > BOXSIZE) && ((userY+PENRADIUS) < tft.height())) {
|
||||||
|
tft.fillCircle(userX, userY, PENRADIUS, currentcolor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawnPalette() {
|
||||||
|
|
||||||
|
tft.fillRect(0 , 0, BOXSIZE, BOXSIZE, TFT_RED);
|
||||||
|
tft.fillRect(BOXSIZE , 0, BOXSIZE, BOXSIZE, TFT_YELLOW);
|
||||||
|
tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE, TFT_GREEN);
|
||||||
|
tft.fillRect(BOXSIZE*3, 0, BOXSIZE, BOXSIZE, TFT_CYAN);
|
||||||
|
tft.fillRect(BOXSIZE*4, 0, BOXSIZE, BOXSIZE, TFT_BLUE);
|
||||||
|
tft.fillRect(BOXSIZE*5, 0, BOXSIZE, BOXSIZE, TFT_MAGENTA);
|
||||||
|
tft.drawRect(0, 0, BOXSIZE, BOXSIZE, TFT_WHITE);
|
||||||
|
currentcolor = TFT_RED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void readTouchPoint() {
|
||||||
|
// Switch SD CLK to read touch data
|
||||||
|
digitalWrite(PIN_SD_SCK, HIGH);
|
||||||
|
p = ts.getPoint(); // read to global
|
||||||
|
digitalWrite(PIN_SD_SCK, LOW);
|
||||||
|
|
||||||
|
// if sharing pins, you'll need to fix the directions of the touchscreen pins
|
||||||
|
//pinMode(XP, OUTPUT);
|
||||||
|
pinMode(XM, OUTPUT);
|
||||||
|
pinMode(YP, OUTPUT);
|
||||||
|
//pinMode(YM, OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValidPressure()
|
||||||
|
{
|
||||||
|
readTouchPoint();
|
||||||
|
// I using ESP 32, and reading on Z is 0 (zero) no touch (normally),
|
||||||
|
// and Adafruit library return negative values or positive..
|
||||||
|
//if (p.z > 10 && p.z < 1000) { // Original
|
||||||
|
if (p.z > 1 || p.z < -1) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simple calibration steps
|
||||||
|
void doCalibration() {
|
||||||
|
|
||||||
|
if (calibration == 0) {
|
||||||
|
// Draw 0,0 circle
|
||||||
|
tft.fillCircle(10, 10, 10, TFT_WHITE);
|
||||||
|
tft.setCursor(5, 30);
|
||||||
|
tft.setTextColor(TFT_WHITE);
|
||||||
|
tft.println("1: TOUCH ON CIRCLE TO CALIBRATE");
|
||||||
|
calibration = 1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (calibration == 1) {
|
||||||
|
if (isValidPressure()) {
|
||||||
|
calibMinX = p.x;
|
||||||
|
calibMinY = p.y;
|
||||||
|
//Serial.print("Z:"); Serial.print(p.z);
|
||||||
|
Serial.print("[minX:");
|
||||||
|
Serial.print(calibMinX);
|
||||||
|
Serial.print("][minY:");
|
||||||
|
Serial.print(calibMinY);
|
||||||
|
Serial.println("]");
|
||||||
|
calibration = 2;
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (calibration == 2) {
|
||||||
|
// Draw 0,0 circle
|
||||||
|
tft.fillCircle(tft.width() - 10, tft.height() - 10, 10, TFT_WHITE);
|
||||||
|
tft.setCursor(5, 30);
|
||||||
|
tft.setTextColor(TFT_WHITE);
|
||||||
|
tft.println("2: TOUCH ON CIRCLE TO CALIBRATE");
|
||||||
|
calibration = 3;
|
||||||
|
delay(3000);// Wait to not get multiple touch on last location, users will press a lot the second point ;P
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (calibration == 3) {
|
||||||
|
if (isValidPressure()) {
|
||||||
|
calibMaxX = p.x;
|
||||||
|
calibMaxY = p.y;
|
||||||
|
Serial.print("[maxX:");
|
||||||
|
Serial.print(calibMaxX);
|
||||||
|
Serial.print("][maxY:");
|
||||||
|
Serial.print(calibMaxY);
|
||||||
|
Serial.println("]");
|
||||||
|
Serial.println("Calibration Ended.");
|
||||||
|
calibration = 33; // end
|
||||||
|
tft.fillScreen(TFT_BLACK);
|
||||||
|
drawnPalette();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue