diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index dc5af38..092bc4b 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -827,7 +827,7 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y, uint16_t transp) *************************************************************************************x*/ uint8_t TFT_eSprite::readPixelValue(int32_t x, int32_t y) { - if ((x < 0) || (x >= _iwidth) || (y < 0) || (y >= _iheight) || !_created) return 0xFFFF; + if ((x < 0) || (x >= _iwidth) || (y < 0) || (y >= _iheight) || !_created) return 0xFF; if (_bpp == 4) { diff --git a/Extensions/Touch.cpp b/Extensions/Touch.cpp index 43694ec..9aa56f6 100644 --- a/Extensions/Touch.cpp +++ b/Extensions/Touch.cpp @@ -10,6 +10,44 @@ // See license in root directory. +/*************************************************************************************** +** Function name: begin_touch_read_write - was spi_begin_touch +** Description: Start transaction and select touch controller +***************************************************************************************/ +// The touch controller has a low SPI clock rate +inline void TFT_eSPI::begin_touch_read_write(void){ + DMA_BUSY_CHECK; + CS_H; // Just in case it has been left low + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) + if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} + #else + spi.setFrequency(SPI_TOUCH_FREQUENCY); + #endif + SET_BUS_READ_MODE; + T_CS_L; +} + +/*************************************************************************************** +** Function name: end_touch_read_write - was spi_end_touch +** Description: End transaction and deselect touch controller +***************************************************************************************/ +inline void TFT_eSPI::end_touch_read_write(void){ + T_CS_H; + #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) + if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} + #else + spi.setFrequency(SPI_FREQUENCY); + #endif + SET_BUS_WRITE_MODE; +} + +/*************************************************************************************** +** Function name: Legacy - deprecated +** Description: Start/end transaction +***************************************************************************************/ +void TFT_eSPI::spi_begin_touch() {begin_touch_read_write();} +void TFT_eSPI::spi_end_touch() { end_touch_read_write();} + /*************************************************************************************** ** Function name: getTouchRaw ** Description: read raw touch position. Always returns true. diff --git a/Extensions/Touch.h b/Extensions/Touch.h index e568457..4cefab2 100644 --- a/Extensions/Touch.h +++ b/Extensions/Touch.h @@ -18,9 +18,9 @@ void setTouch(uint16_t *data); private: - // Legacy support only - deprecated - void spi_begin_touch() {begin_touch_read_write();} - void spi_end_touch() { end_touch_read_write();} + // Legacy support only - deprecated TODO: delete + void spi_begin_touch(); + void spi_end_touch(); // Handlers for the touch controller bus settings inline void begin_touch_read_write() __attribute__((always_inline)); diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 7535a43..8244980 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -107,41 +107,14 @@ inline void TFT_eSPI::end_tft_read(void){ SET_BUS_WRITE_MODE; } -#if defined (TOUCH_CS) && defined (SPI_TOUCH_FREQUENCY) - /*************************************************************************************** -** Function name: begin_touch_read_write - was spi_begin_touch -** Description: Start transaction and select touch controller +** Function name: Legacy - deprecated +** Description: Start/end transaction ***************************************************************************************/ -// The touch controller has a low SPI clock rate -inline void TFT_eSPI::begin_touch_read_write(void){ - DMA_BUSY_CHECK; - CS_H; // Just in case it has been left low - #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) - if (locked) {locked = false; spi.beginTransaction(SPISettings(SPI_TOUCH_FREQUENCY, MSBFIRST, SPI_MODE0));} - #else - spi.setFrequency(SPI_TOUCH_FREQUENCY); - #endif - SET_BUS_READ_MODE; - T_CS_L; -} - -/*************************************************************************************** -** Function name: end_touch_read_write - was spi_end_touch -** Description: End transaction and deselect touch controller -***************************************************************************************/ - inline void TFT_eSPI::end_touch_read_write(void){ - T_CS_H; - #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) - if(!inTransaction) {if (!locked) {locked = true; spi.endTransaction();}} - #else - spi.setFrequency(SPI_FREQUENCY); - #endif - SET_BUS_WRITE_MODE; - } - -#endif - + void TFT_eSPI::spi_begin() {begin_tft_write();} + void TFT_eSPI::spi_end() { end_tft_write();} + void TFT_eSPI::spi_begin_read() {begin_tft_read(); } + void TFT_eSPI::spi_end_read() { end_tft_read(); } /*************************************************************************************** ** Function name: TFT_eSPI @@ -2969,6 +2942,31 @@ uint16_t TFT_eSPI::color8to16(uint8_t color) return color16; } +/*************************************************************************************** +** Function name: color16to24 +** Description: convert 16 bit colour to a 24 bit 888 colour value +***************************************************************************************/ +uint32_t TFT_eSPI::color16to24(uint16_t color565) +{ + uint8_t r = (color565 >> 8) & 0xF8; r |= (r >> 5); + uint8_t g = (color565 >> 3) & 0xFC; g |= (g >> 6); + uint8_t b = (color565 << 3) & 0xF8; b |= (b >> 5); + + return ((uint32_t)r << 16) | ((uint32_t)g << 8) | ((uint32_t)b << 0); +} + +/*************************************************************************************** +** Function name: color24to16 +** Description: convert 24 bit colour to a 16 bit 565 colour value +***************************************************************************************/ +uint32_t TFT_eSPI::color24to16(uint32_t color888) +{ + uint16_t r = (color888 >> 8) & 0xF800; + uint16_t g = (color888 >> 5) & 0x07E0; + uint16_t b = (color888 >> 3) & 0x001F; + + return (r | g | b); +} /*************************************************************************************** ** Function name: invertDisplay @@ -3108,7 +3106,7 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) /*************************************************************************************** ** Function name: alphaBlend -** Description: Blend foreground and background and return new colour +** Description: Blend 16bit foreground and background *************************************************************************************x*/ uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc) { @@ -3132,6 +3130,53 @@ uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc) return (r << 11) | (g << 5) | (b << 0); } +/*************************************************************************************** +** Function name: alphaBlend +** Description: Blend 16bit foreground and background with dither +*************************************************************************************x*/ +uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither) +{ + if (dither) { + int16_t alphaDither = (int16_t)alpha - dither + random(2*dither+1); // +/-4 randomised + alpha = (uint8_t)alphaDither; + if (alphaDither < 0) alpha = 0; + if (alphaDither >255) alpha = 255; + } + + return alphaBlend(alpha, fgc, bgc); +} + +/*************************************************************************************** +** Function name: alphaBlend +** Description: Blend 24bit foreground and background with optional dither +*************************************************************************************x*/ +uint32_t TFT_eSPI::alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither) +{ + + if (dither) { + int16_t alphaDither = (int16_t)alpha - dither + random(2*dither+1); // +/-dither randomised + alpha = (uint8_t)alphaDither; + if (alphaDither < 0) alpha = 0; + if (alphaDither >255) alpha = 255; + } + + // For speed use fixed point maths and rounding to permit a power of 2 division + uint16_t fgR = ((fgc >> 15) & 0x1FE) + 1; + uint16_t fgG = ((fgc >> 7) & 0x1FE) + 1; + uint16_t fgB = ((fgc << 1) & 0x1FE) + 1; + + uint16_t bgR = ((bgc >> 15) & 0x1FE) + 1; + uint16_t bgG = ((bgc >> 7) & 0x1FE) + 1; + uint16_t bgB = ((bgc << 1) & 0x1FE) + 1; + + // Shift right 1 to drop rounding bit and shift right 8 to divide by 256 + uint16_t r = (((fgR * alpha) + (bgR * (255 - alpha))) >> 9); + uint16_t g = (((fgG * alpha) + (bgG * (255 - alpha))) >> 9); + uint16_t b = (((fgB * alpha) + (bgB * (255 - alpha))) >> 9); + + // Combine RGB colours into 24 bits + return (r << 16) | (g << 8) | (b << 0); +} /*************************************************************************************** ** Function name: write diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 956ca38..ed5db6c 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -16,7 +16,7 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "2.0.0" +#define TFT_ESPI_VERSION "2.0.1" /*************************************************************************************** ** Section 1: Load required header files @@ -558,10 +558,18 @@ class TFT_eSPI : public Print { // Convert 16 bit colour to 8 bits uint8_t color16to8(uint16_t color565); + // Convert 16 bit colour to/from 24 bit, R+G+B concatenated into LS 24 bits + uint32_t color16to24(uint16_t color565); + uint32_t color24to16(uint32_t color888); + // Alpha blend 2 colours, see generic "alphaBlend_Test" example // alpha = 0 = 100% background colour // alpha = 255 = 100% foreground colour uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); + // 16 bit colour alphaBlend with alpha dither (dither reduces colour banding) + uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc, uint8_t dither); + // 24 bit colour alphaBlend with optional alpha dither + uint32_t alphaBlend24(uint8_t alpha, uint32_t fgc, uint32_t bgc, uint8_t dither = 0); // DMA support functions - these are currently just for SPI writes whe using the STM32 processors @@ -640,20 +648,20 @@ class TFT_eSPI : public Print { textdatum, // Text reference datum rotation; // Display rotation (0-3) - int16_t _xpivot; // TFT x pivot point coordinate for rotated Sprites - int16_t _ypivot; // TFT x pivot point coordinate for rotated Sprites + int16_t _xpivot; // TFT x pivot point coordinate for rotated Sprites + int16_t _ypivot; // TFT x pivot point coordinate for rotated Sprites uint8_t decoderState = 0; // UTF8 decoder state - not for user access uint16_t decoderBuffer; // Unicode code-point buffer - not for user access //--------------------------------------- private ------------------------------------// private: - // Legacy begin and end prototypes - deprecated - void spi_begin() {begin_tft_write();} - void spi_end() { end_tft_write();} + // Legacy begin and end prototypes - deprecated TODO: delete + void spi_begin(); + void spi_end(); - void spi_begin_read() {begin_tft_read(); } - void spi_end_read() { end_tft_read(); } + void spi_begin_read(); + void spi_end_read(); // New begin and end prototypes // begin/end a TFT write transaction diff --git a/examples/Smooth Fonts/alphaBlend_Test/alphaBlend_Test.ino b/examples/Smooth Fonts/alphaBlend_Test/alphaBlend_Test.ino deleted file mode 100644 index f3f4cdf..0000000 --- a/examples/Smooth Fonts/alphaBlend_Test/alphaBlend_Test.ino +++ /dev/null @@ -1,194 +0,0 @@ -/* - This tests the alpha blending function that is used with the antialiased - fonts: - - Alpha = 0 = 100% background, alpha = 255 = 100% foreground colour - - blendedColor = tft.alphaBlend(alpha, fg_color, bg_color); - - The alphaBlend() function operates on 16 bit colours only - A test is included where the colours are mapped to 8 bits after blending - - Information on alpha blending is here - https://en.wikipedia.org/wiki/Alpha_compositing - - Example for library: - https://github.com/Bodmer/TFT_eSPI - - The sketch has been tested on a 320x240 ILI9341 based TFT, it - could be adapted for other screen sizes. - - Created by Bodmer 10/2/18 - - ######################################################################### - ###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ###### - ######################################################################### -*/ - -#include // Include the graphics library - -TFT_eSPI tft = TFT_eSPI(); // Create object "tft" - -// ------------------------------------------------------------------------- -// Setup -// ------------------------------------------------------------------------- -void setup(void) { - tft.init(); - tft.setRotation(0); - tft.fillScreen(TFT_DARKGREY); -} - -// ------------------------------------------------------------------------- -// Main loop -// ------------------------------------------------------------------------- -void loop() -{ - // 16 bit colours (5 bits red, 6 bits green, 5 bits blue) - // Blend from white to full spectrum - for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground - { - for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.alphaBlend(a, rainbow(c), TFT_WHITE)); - } - - // Blend from full spectrum to black - for (int a = 255; a > 2; a-=2) - { - for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.alphaBlend(a, rainbow(c), TFT_BLACK)); - } - - // Blend from white to black (32 grey levels) - for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground - { - tft.drawFastHLine(192, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_WHITE)); - tft.drawFastHLine(204, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_RED)); - tft.drawFastHLine(216, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_GREEN)); - tft.drawFastHLine(228, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_BLUE)); - } - - delay(4000); - - // Blend from white to colour (32 grey levels) - for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground - { - //tft.drawFastHLine(192, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_WHITE)); - tft.drawFastHLine(204, a, 12, tft.alphaBlend(a, TFT_RED, TFT_WHITE)); - tft.drawFastHLine(216, a, 12, tft.alphaBlend(a, TFT_GREEN, TFT_WHITE)); - tft.drawFastHLine(228, a, 12, tft.alphaBlend(a, TFT_BLUE, TFT_WHITE)); - } - - delay(4000); - - //* - // Decrease to 8 bit colour (3 bits red, 3 bits green, 2 bits blue) - // Blend from white to full spectrum - for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground - { - // Convert blended 16 bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying - for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.color8to16(tft.color16to8(tft.alphaBlend(a, rainbow(c), 0xFFFF)))); - } - - // Blend from full spectrum to black - for (int a = 255; a > 2; a-=2) - { - // Convert blended 16 bit colour to 8 bits to reduce colour resolution, then map back to 16 bits for displaying - for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.color8to16(tft.color16to8(tft.alphaBlend(a, rainbow(c), 0)))); - } - - // Blend from white to black (4 grey levels - it will draw 4 more with a blue tinge due to lower blue bit count) - // Blend from black to a primary colour - for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground - { - tft.drawFastHLine(192, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_WHITE)))); - tft.drawFastHLine(204, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_RED)))); - tft.drawFastHLine(216, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_GREEN)))); - tft.drawFastHLine(228, a, 12, tft.color8to16(tft.color16to8(tft.alphaBlend(a, TFT_BLACK, TFT_BLUE)))); - } - - delay(4000); - //*/ - - /* - // 16 bit colours (5 bits red, 6 bits green, 5 bits blue) - for (int a = 0; a < 256; a+=2) // Alpha 0 = 100% background, alpha 255 = 100% foreground - { - for (int c = 0; c < 192; c++) tft.drawPixel(c, a/2, tft.alphaBlend(a, rainbow(c), TFT_CYAN)); - } - - // Blend from full spectrum to cyan - for (int a = 255; a > 2; a-=2) - { - for (int c = 0; c < 192; c++) tft.drawPixel(c, 128 + (255-a)/2, tft.alphaBlend(a, rainbow(c), TFT_YELLOW)); - } - //*/ - - /* - // Blend other colour transitions for test purposes - for (uint16_t a = 0; a < 255; a++) // Alpha 0 = 100% background, alpha 255 = 100% foreground - { - tft.drawFastHLine(192, a, 12, tft.alphaBlend(a, TFT_WHITE, TFT_WHITE)); // Should show as solid white - tft.drawFastHLine(204, a, 12, tft.alphaBlend(a, TFT_BLACK, TFT_BLACK)); // Should show as solid black - tft.drawFastHLine(216, a, 12, tft.alphaBlend(a, TFT_YELLOW, TFT_CYAN)); // Brightness should be fairly even - tft.drawFastHLine(228, a, 12, tft.alphaBlend(a, TFT_CYAN, TFT_MAGENTA));// Brightness should be fairly even - } - - delay(4000); - //*/ -} - - -// ######################################################################### -// Return a 16 bit rainbow colour -// ######################################################################### -unsigned int rainbow(byte value) -{ - // If 'value' is in the range 0-159 it is converted to a spectrum colour - // from 0 = red through to 127 = blue to 159 = violet - // Extending the range to 0-191 adds a further violet to red band - - value = value%192; - - byte red = 0; // Red is the top 5 bits of a 16 bit colour value - byte green = 0; // Green is the middle 6 bits, but only top 5 bits used here - byte blue = 0; // Blue is the bottom 5 bits - - byte sector = value >> 5; - byte amplit = value & 0x1F; - - switch (sector) - { - case 0: - red = 0x1F; - green = amplit; // Green ramps up - blue = 0; - break; - case 1: - red = 0x1F - amplit; // Red ramps down - green = 0x1F; - blue = 0; - break; - case 2: - red = 0; - green = 0x1F; - blue = amplit; // Blue ramps up - break; - case 3: - red = 0; - green = 0x1F - amplit; // Green ramps down - blue = 0x1F; - break; - case 4: - red = amplit; // Red ramps up - green = 0; - blue = 0x1F; - break; - case 5: - red = 0x1F; - green = 0; - blue = 0x1F - amplit; // Blue ramps down - break; - } - - return red << 11 | green << 6 | blue; -} - - diff --git a/library.json b/library.json index 7559741..091a89f 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "2.0.0", + "version": "2.0.1", "keywords": "Arduino, tft, ePaper, display, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789, RM68140", "description": "A TFT and ePaper SPI graphics library with optimisation for ESP8266, ESP32 and STM32", "repository": diff --git a/library.properties b/library.properties index 4baea5e..97dd1d7 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=2.0.0 +version=2.0.1 author=Bodmer maintainer=Bodmer sentence=TFT graphics library for Arduino processors with performance optimisation for STM32, ESP8266 and ESP32