From f21e66ae15de9fa12621ae866ead4a1aa44d42ae Mon Sep 17 00:00:00 2001 From: Gozi Date: Thu, 12 Aug 2021 00:34:23 +0800 Subject: [PATCH] Add mirror option on setRotation for ST7789 --- TFT_Drivers/ST7789_2_Rotation.h | 47 ++++++++++++++++++++++++++------- TFT_Drivers/ST7789_Rotation.h | 45 ++++++++++++++++++++++++------- TFT_eSPI.cpp | 26 +++++++++++------- TFT_eSPI.h | 22 +++++++++------ 4 files changed, 103 insertions(+), 37 deletions(-) diff --git a/TFT_Drivers/ST7789_2_Rotation.h b/TFT_Drivers/ST7789_2_Rotation.h index 44a363e..8171818 100644 --- a/TFT_Drivers/ST7789_2_Rotation.h +++ b/TFT_Drivers/ST7789_2_Rotation.h @@ -1,5 +1,4 @@ // This is the command sequence that rotates the ST7789 driver coordinate frame - writecommand(TFT_MADCTL); rotation = m % 4; switch (rotation) { @@ -16,7 +15,11 @@ rowstart = 0; } #endif - writedata(TFT_MAD_COLOR_ORDER); + if (mirror) { + writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER); + } else { + writedata(TFT_MAD_COLOR_ORDER); + } _width = _init_width; _height = _init_height; @@ -26,22 +29,32 @@ #ifdef CGRAM_OFFSET if (_init_width == 135) { + // TODO: Fix offset after mirror colstart = 40; rowstart = 53; } else { - colstart = 0; - rowstart = 0; + if (mirror) { + colstart = 80; + rowstart = 0; + } else { + colstart = 0; + rowstart = 0; + } } #endif - writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); + if (mirror) { + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + } else { + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); + } _width = _init_height; _height = _init_width; break; - case 2: // Inverter portrait + case 2: // Inverter portrait #ifdef CGRAM_OFFSET if (_init_width == 135) { @@ -54,7 +67,11 @@ rowstart = 80; } #endif - writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + if (mirror) { + writedata(TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + } else { + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + } _width = _init_width; _height = _init_height; @@ -63,16 +80,26 @@ #ifdef CGRAM_OFFSET if (_init_width == 135) { + // TODO: Fix offset after mirror colstart = 40; rowstart = 52; } else { - colstart = 80; - rowstart = 0; + if (mirror) { + colstart = 0; + rowstart = 0; + } else { + colstart = 80; + rowstart = 0; + } } #endif - writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + if (mirror) { + writedata(TFT_MAD_MV | TFT_MAD_COLOR_ORDER); + } else { + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + } _width = _init_height; _height = _init_width; diff --git a/TFT_Drivers/ST7789_Rotation.h b/TFT_Drivers/ST7789_Rotation.h index 707c775..8171818 100644 --- a/TFT_Drivers/ST7789_Rotation.h +++ b/TFT_Drivers/ST7789_Rotation.h @@ -1,5 +1,4 @@ // This is the command sequence that rotates the ST7789 driver coordinate frame - writecommand(TFT_MADCTL); rotation = m % 4; switch (rotation) { @@ -16,7 +15,11 @@ rowstart = 0; } #endif - writedata(TFT_MAD_COLOR_ORDER); + if (mirror) { + writedata(TFT_MAD_MX | TFT_MAD_COLOR_ORDER); + } else { + writedata(TFT_MAD_COLOR_ORDER); + } _width = _init_width; _height = _init_height; @@ -26,16 +29,26 @@ #ifdef CGRAM_OFFSET if (_init_width == 135) { + // TODO: Fix offset after mirror colstart = 40; rowstart = 53; } else { - colstart = 0; - rowstart = 0; + if (mirror) { + colstart = 80; + rowstart = 0; + } else { + colstart = 0; + rowstart = 0; + } } #endif - writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); + if (mirror) { + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + } else { + writedata(TFT_MAD_MX | TFT_MAD_MV | TFT_MAD_COLOR_ORDER); + } _width = _init_height; _height = _init_width; @@ -54,7 +67,11 @@ rowstart = 80; } #endif - writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + if (mirror) { + writedata(TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + } else { + writedata(TFT_MAD_MX | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + } _width = _init_width; _height = _init_height; @@ -63,16 +80,26 @@ #ifdef CGRAM_OFFSET if (_init_width == 135) { + // TODO: Fix offset after mirror colstart = 40; rowstart = 52; } else { - colstart = 80; - rowstart = 0; + if (mirror) { + colstart = 0; + rowstart = 0; + } else { + colstart = 80; + rowstart = 0; + } } #endif - writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + if (mirror) { + writedata(TFT_MAD_MV | TFT_MAD_COLOR_ORDER); + } else { + writedata(TFT_MAD_MV | TFT_MAD_MY | TFT_MAD_COLOR_ORDER); + } _width = _init_height; _height = _init_width; diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 493d01f..432a6e7 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -189,7 +189,7 @@ bool TFT_eSPI::checkViewport(int32_t x, int32_t y, int32_t w, int32_t h) x+= _xDatum; y+= _yDatum; - if ((x >= _vpW) || (y >= _vpH)) return false; + if ((x >= _vpW) || (y >= _vpH)) return false; int32_t dx = 0; int32_t dy = 0; @@ -296,7 +296,7 @@ void TFT_eSPI::frameViewport(uint16_t color, int32_t w) // a large negative width will clear the screen outside the viewport { w = -w; - + // Save old values int32_t _xT = _vpX; _vpX = 0; int32_t _yT = _vpY; _vpY = 0; @@ -691,7 +691,13 @@ void TFT_eSPI::init(uint8_t tc) ** Function name: setRotation ** Description: rotate the screen orientation m = 0-3 or 4-7 for BMP drawing ***************************************************************************************/ + void TFT_eSPI::setRotation(uint8_t m) +{ + setRotation(m, false); +} + +void TFT_eSPI::setRotation(uint8_t m, bool mirror) { begin_tft_write(); @@ -1894,7 +1900,7 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_ uint8_t* buf565 = data + len; readRect(x0, y0, w, h, (uint16_t*)buf565); - + while (len--) { uint16_t pixel565 = (*buf565++)<<8; pixel565 |= *buf565++; @@ -1973,7 +1979,7 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) int32_t xs = -1; int32_t xe = 0; int32_t len = 0; - + bool first = true; do { while (f < 0) { @@ -3231,7 +3237,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) x+= _xDatum; y+= _yDatum; - // Range checking + // Range checking if ((x < _vpX) || (y < _vpY) ||(x >= _vpW) || (y >= _vpH)) return; #ifdef CGRAM_OFFSET @@ -3254,7 +3260,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_D; tft_Write_16(0); DC_C; tft_Write_8(TFT_CASET2); DC_D; tft_Write_16(175); - + DC_C; tft_Write_8(TFT_PASET1); DC_D; tft_Write_16(0); DC_C; tft_Write_8(TFT_PASET2); @@ -3342,7 +3348,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) #else -#if defined (SSD1351_DRIVER) || defined (SSD1963_DRIVER) +#if defined (SSD1351_DRIVER) || defined (SSD1963_DRIVER) if ((rotation & 0x1) == 0) { swap_coord(x, y); } #endif @@ -3384,7 +3390,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) } #endif DC_C; tft_Write_8(TFT_RAMWR); - + #if defined(TFT_PARALLEL_8_BIT) || !defined(ESP32) DC_D; tft_Write_16(color); #else @@ -3899,7 +3905,7 @@ uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t if (alphaDither < 0) alpha = 0; if (alphaDither >255) alpha = 255; } - + return alphaBlend(alpha, fgc, bgc); } @@ -4235,7 +4241,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) w *= height; // Now w is total number of pixels in the character if (textcolor == textbgcolor && !clip) { - + int32_t px = 0, py = pY; // To hold character block start and end column and row values int32_t pc = 0; // Pixel count uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 78a7f5b..b102df6 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -270,13 +270,18 @@ const PROGMEM fontinfo fontdata [] = { #define TFT_WHITE 0xFFFF /* 255, 255, 255 */ #define TFT_ORANGE 0xFDA0 /* 255, 180, 0 */ #define TFT_GREENYELLOW 0xB7E0 /* 180, 255, 0 */ -#define TFT_PINK 0xFE19 /* 255, 192, 203 */ //Lighter pink, was 0xFC9F +#define TFT_PINK 0xFE19 /* 255, 192, 203 */ //Lighter pink, was 0xFC9F #define TFT_BROWN 0x9A60 /* 150, 75, 0 */ #define TFT_GOLD 0xFEA0 /* 255, 215, 0 */ #define TFT_SILVER 0xC618 /* 192, 192, 192 */ #define TFT_SKYBLUE 0x867D /* 135, 206, 235 */ #define TFT_VIOLET 0x915C /* 180, 46, 226 */ +#define TFT_PORTRAIT 0 +#define TFT_LANDSCAPE 1 +#define TFT_PORTRAIT_INVERT 2 +#define TFT_LANDSCAPE_INVERT 3 + // Next is a special 16 bit colour value that encodes to 8 bits // and will then decode back to the same 16 bit value. // Convenient for 8 bit and 16 bit transparent sprites. @@ -404,6 +409,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac width(void); void setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3 + void setRotation(uint8_t r, bool mirror); // Set the display image orientation with mirro flag uint8_t getRotation(void); // Read the current rotation void invertDisplay(bool i); // Tell TFT to invert all displayed colours @@ -436,7 +442,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // Write a set of pixels stored in memory, use setSwapBytes(true/false) function to correct endianess void pushPixels(const void * data_in, uint32_t len); - // Read the colour of a pixel at x,y and return value in 565 format + // Read the colour of a pixel at x,y and return value in 565 format uint16_t readPixel(int32_t x, int32_t y); // Support for half duplex (bi-directional SDA) SPI bus where MOSI must be switched to input @@ -513,7 +519,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // Text rendering - value returned is the pixel width of the rendered text int16_t drawNumber(long intNumber, int32_t x, int32_t y, uint8_t font), // Draw integer using specified font number drawNumber(long intNumber, int32_t x, int32_t y), // Draw integer using current font - + // Decimal is the number of decimal places to render // Use with setTextDatum() to position values on TFT, and setTextPadding() to blank old displayed values drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y, uint8_t font), // Draw float using specified font number @@ -537,14 +543,14 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac int16_t getCursorX(void), // Read current cursor x position (moves with tft.print()) getCursorY(void); // Read current cursor y position - + void setTextColor(uint16_t color), // Set character (glyph) color only (background not over-written) setTextColor(uint16_t fgcolor, uint16_t bgcolor),// Set character (glyph) foreground and backgorund colour setTextSize(uint8_t size); // Set character size multiplier (this increases pixel size) void setTextWrap(bool wrapX, bool wrapY = false); // Turn on/off wrapping of text in TFT width and/or height - void setTextDatum(uint8_t datum); // Set text datum position (default is top left), see Section 6 above + void setTextDatum(uint8_t datum); // Set text datum position (default is top left), see Section 6 above uint8_t getTextDatum(void); void setTextPadding(uint16_t x_width); // Set text padding (background blanking/over-write) width in pixels @@ -571,7 +577,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // Support function to UTF8 decode and draw characters piped through print stream size_t write(uint8_t); - + // Used by Smooth font class to fetch a pixel colour for the anti-aliasing void setCallback(getColorCallback getCol); @@ -642,7 +648,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // Parameter "true" enables DMA engine control of TFT chip select (ESP32 only) // For ESP32 only, TFT reads will not work if parameter is true void deInitDMA(void); // De-initialise the DMA engine and detach from SPI bus - typically not used - + // Push an image to the TFT using DMA, buffer is optional and grabs (double buffers) a copy of the image // Use the buffer if the image data will get over-written or destroyed while DMA is in progress // If swapping colour bytes is defined, and the double buffer option is NOT used, then the bytes @@ -786,7 +792,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac bool locked, inTransaction, lockTransaction; // SPI transaction and mutex lock flags bool _booted; // init() or begin() has already run once - + // User sketch manages these via set/getAttribute() bool _cp437; // If set, use correct CP437 charset (default is ON) bool _utf8; // If set, use UTF-8 decoder in print stream 'write()' function (default ON)