diff --git a/Extensions/Sprite.cpp b/Extensions/Sprite.cpp index fb054bb..dc5af38 100644 --- a/Extensions/Sprite.cpp +++ b/Extensions/Sprite.cpp @@ -171,7 +171,7 @@ void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames) } /*************************************************************************************** -** Function name: createPalette +** Function name: createPalette (from RAM array) ** Description: Set a palette for a 4-bit per pixel sprite *************************************************************************************x*/ @@ -197,6 +197,33 @@ void TFT_eSprite::createPalette(uint16_t colorMap[], int colors) } } +/*************************************************************************************** +** Function name: createPalette (from FLASH array) +** Description: Set a palette for a 4-bit per pixel sprite +*************************************************************************************x*/ + +void TFT_eSprite::createPalette(const uint16_t colorMap[], int colors) +{ + if (_colorMap != nullptr) + { + free(_colorMap); + } + + if (colorMap == nullptr) + { + return; // do nothing other than clear the existing map + } + + // allocate color map + _colorMap = (uint16_t *)calloc(16, sizeof(uint16_t)); + if (colors > 16) + colors = 16; + for (auto i = 0; i < colors; i++) + { + _colorMap[i] = pgm_read_word(colorMap++); + } +} + /*************************************************************************************** ** Function name: frameBuffer ** Description: For 1 bpp Sprites, select the frame used for graphics @@ -487,6 +514,8 @@ bool TFT_eSprite::pushRotatedHP(int16_t angle, int32_t transp) if (max_x > _tft->width()) max_x = _tft->width(); if (max_y > _tft->height()) max_y = _tft->height(); + uint16_t sline_buffer[max_y - min_y + 1]; + _tft->startWrite(); // ESP32: avoid transaction overhead for every tft pixel // Scan destination bounding box and fetch transformed pixels from source Sprite @@ -495,6 +524,8 @@ bool TFT_eSprite::pushRotatedHP(int16_t angle, int32_t transp) float cxt = cosra * xt + _xpivot; float sxt = sinra * xt + _ypivot; bool column_drawn = false; + uint32_t pixel_count = 0; + int32_t y_start = 0; for (int32_t y = min_y; y <= max_y; y++) { int32_t yt = y - _tft->_ypivot; int32_t xs = (int32_t)round(cxt - sinra * yt); @@ -505,12 +536,19 @@ bool TFT_eSprite::pushRotatedHP(int16_t angle, int32_t transp) // Check if ys is in bounds if (ys >= 0 && ys < height()) { int32_t rp = readPixel(xs, ys); - if (rp != transp) _tft->drawPixel(x, y, rp); + if (transp >= 0 ) { + if (rp != transp) _tft->drawPixel(x, y, rp); + } + else { + if (!column_drawn) y_start = y; + sline_buffer[pixel_count++] = rp>>8 | rp<<8; + } column_drawn = true; } } else if (column_drawn) y = max_y; // Skip remaining column pixels } + if (pixel_count) _tft->pushImage(x, y_start, 1, pixel_count, sline_buffer); } _tft->endWrite(); // ESP32: end transaction @@ -665,7 +703,10 @@ bool TFT_eSprite::pushRotatedHP(TFT_eSprite *spr, int16_t angle, int32_t transp) // Check if ys is in bounds if (ys >= 0 && ys < height()) { - int32_t rp = readPixel(xs, ys); + uint32_t rp; + // Can avoid bounds check overhead for reading 16bpp + if (_bpp == 16) {rp = _img[xs + ys * _iwidth]; rp = rp>>8 | rp<<8; } + else rp = readPixel(xs, ys); if (rp != transp) spr->drawPixel(x, y, rp); column_drawn = true; } diff --git a/Extensions/Sprite.h b/Extensions/Sprite.h index ba2fa67..8c9d1dd 100644 --- a/Extensions/Sprite.h +++ b/Extensions/Sprite.h @@ -38,12 +38,13 @@ class TFT_eSprite : public TFT_eSPI { int8_t getColorDepth(void); // Set the palette for a 4 bit depth sprite. Only the first 16 colours in the map are used. - void createPalette(uint16_t *palette, int colors = 16); + void createPalette(uint16_t *palette, int colors = 16); // Palette in RAM + void createPalette(const uint16_t *palette, int colors = 16); // Palette in FLASH - // Set a single palette index to the given color + // Set a single palette index to the given color void setPaletteColor(uint8_t index, uint16_t color); - // Get the color at the given palette index + // Get the color at the given palette index uint16_t getPaletteColor(uint8_t index); // Set foreground and background colours for 1 bit per pixel Sprite diff --git a/Extensions/Touch.cpp b/Extensions/Touch.cpp index cb253be..43694ec 100644 --- a/Extensions/Touch.cpp +++ b/Extensions/Touch.cpp @@ -17,7 +17,7 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ uint16_t tmp; - spi_begin_touch(); + begin_touch_read_write(); // Start YP sample request for x position, read 4 times and keep last sample spi.transfer(0xd0); // Start new YP conversion @@ -48,7 +48,7 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ *y = tmp; - spi_end_touch(); + end_touch_read_write(); return true; } @@ -59,7 +59,7 @@ uint8_t TFT_eSPI::getTouchRaw(uint16_t *x, uint16_t *y){ ***************************************************************************************/ uint16_t TFT_eSPI::getTouchRawZ(void){ - spi_begin_touch(); + begin_touch_read_write(); // Z sample request int16_t tz = 0xFFF; @@ -67,7 +67,7 @@ uint16_t TFT_eSPI::getTouchRawZ(void){ tz += spi.transfer16(0xc0) >> 3; // Read Z1 and start Z2 conversion tz -= spi.transfer16(0x00) >> 3; // Read Z2 - spi_end_touch(); + end_touch_read_write(); return (uint16_t)tz; } diff --git a/Extensions/Touch.h b/Extensions/Touch.h index de4ade7..e568457 100644 --- a/Extensions/Touch.h +++ b/Extensions/Touch.h @@ -18,9 +18,13 @@ void setTouch(uint16_t *data); private: - // Handlers for the SPI settings and clock speed change - inline void spi_begin_touch() __attribute__((always_inline)); - inline void spi_end_touch() __attribute__((always_inline)); + // Legacy support only - deprecated + void spi_begin_touch() {begin_touch_read_write();} + void spi_end_touch() { end_touch_read_write();} + + // Handlers for the touch controller bus settings + inline void begin_touch_read_write() __attribute__((always_inline)); + inline void end_touch_read_write() __attribute__((always_inline)); // Private function to validate a touch, allow settle time and reduce spurious coordinates uint8_t validTouch(uint16_t *x, uint16_t *y, uint16_t threshold = 600); diff --git a/Processors/TFT_eSPI_ESP32.h b/Processors/TFT_eSPI_ESP32.h index 5626c12..fa3b2f4 100644 --- a/Processors/TFT_eSPI_ESP32.h +++ b/Processors/TFT_eSPI_ESP32.h @@ -12,8 +12,8 @@ #include "soc/spi_reg.h" // Processor specific code used by SPI bus transaction startWrite and endWrite functions -#define SET_SPI_WRITE_MODE // Not used -#define SET_SPI_READ_MODE // Not used +#define SET_BUS_WRITE_MODE // Not used +#define SET_BUS_READ_MODE // Not used // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions #define DMA_BUSY_CHECK // DMA not implemented for this processor (yet) @@ -30,15 +30,7 @@ #define SPI_PORT VSPI #endif -// If it is a 16bit serial display we must transfer 16 bits every time -// Set commands bits to 16 or 8 -#ifdef RPI_ILI9486_DRIVER - #ifndef RPI_DRIVER - #define RPI_DRIVER - #endif -#endif - -#ifdef RPI_DRIVER +#ifdef RPI_DISPLAY_TYPE #define CMD_BITS (16-1) #else #define CMD_BITS (8-1) @@ -73,7 +65,7 @@ #define DC_D GPIO.out_w1ts = (1 << TFT_DC) #else #if TFT_DC >= 32 - #ifdef RPI_DRIVER // RPi displays need a slower DC change + #ifdef RPI_DISPLAY_TYPE // RPi displays need a slower DC change #define DC_C GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)); \ GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)) #define DC_D GPIO.out1_w1tc.val = (1 << (TFT_DC - 32)); \ @@ -83,12 +75,12 @@ #define DC_D GPIO.out1_w1ts.val = (1 << (TFT_DC - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_DC - 32)) #endif #elif TFT_DC >= 0 - #ifdef RPI_ILI9486_DRIVER // RPi ILI9486 display needs a slower DC change + #ifdef RPI_DISPLAY_TYPE // RPi ILI9486 display needs a slower DC change #define DC_C GPIO.out_w1tc = (1 << TFT_DC); \ GPIO.out_w1tc = (1 << TFT_DC) #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ GPIO.out_w1ts = (1 << TFT_DC) - #elif defined (RPI_DRIVER) // Other RPi displays need a slower C->D change + #elif defined (RPI_DISPLAY_TYPE) // Other RPi displays need a slower C->D change #define DC_C GPIO.out_w1tc = (1 << TFT_DC) #define DC_D GPIO.out_w1tc = (1 << TFT_DC); \ GPIO.out_w1ts = (1 << TFT_DC) @@ -123,7 +115,7 @@ #endif #else #if TFT_CS >= 32 - #ifdef RPI_ILI9486_DRIVER // RPi ILI9486 display needs a slower CS change + #ifdef RPI_DISPLAY_TYPE // RPi ILI9486 display needs a slower CS change #define CS_L GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)); \ GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)) #define CS_H GPIO.out1_w1tc.val = (1 << (TFT_CS - 32)); \ @@ -133,7 +125,7 @@ #define CS_H GPIO.out1_w1ts.val = (1 << (TFT_CS - 32))//;GPIO.out1_w1ts.val = (1 << (TFT_CS - 32)) #endif #elif TFT_CS >= 0 - #ifdef RPI_ILI9486_DRIVER // RPi ILI9486 display needs a slower CS change + #ifdef RPI_DISPLAY_TYPE // RPi ILI9486 display needs a slower CS change #define CS_L GPIO.out_w1ts = (1 << TFT_CS); GPIO.out_w1tc = (1 << TFT_CS) #define CS_H GPIO.out_w1tc = (1 << TFT_CS); GPIO.out_w1ts = (1 << TFT_CS) #else @@ -277,7 +269,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to an Raspberry Pi TFT //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (RPI_DRIVER) +#elif defined (RPI_DISPLAY_TYPE) // ESP32 low level SPI writes for 8, 16 and 32 bit values // to avoid the function call overhead diff --git a/Processors/TFT_eSPI_ESP8266.h b/Processors/TFT_eSPI_ESP8266.h index a4bfcf5..9f1ea5e 100644 --- a/Processors/TFT_eSPI_ESP8266.h +++ b/Processors/TFT_eSPI_ESP8266.h @@ -12,8 +12,8 @@ // None // Processor specific code used by SPI bus transaction startWrite and endWrite functions -#define SET_SPI_WRITE_MODE SPI1U=SPI1U_WRITE -#define SET_SPI_READ_MODE SPI1U=SPI1U_READ +#define SET_BUS_WRITE_MODE SPI1U=SPI1U_WRITE +#define SET_BUS_READ_MODE SPI1U=SPI1U_READ // Code to check if DMA is busy, used by SPI bus transaction transaction and endWrite functions #define DMA_BUSY_CHECK // DMA not available, leave blank @@ -43,14 +43,6 @@ #undef TFT_PARALLEL_8_BIT #endif -// If it is a 16bit serial display we must transfer 16 bits every time -// Set commands bits to 16 or 8 -#ifdef RPI_ILI9486_DRIVER - #ifndef RPI_DRIVER - #define RPI_DRIVER - #endif -#endif - //////////////////////////////////////////////////////////////////////////////////////// // Define the DC (TFT Data/Command or Register Select (RS))pin drive code //////////////////////////////////////////////////////////////////////////////////////// @@ -151,7 +143,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to an Raspberry Pi TFT //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (RPI_DRIVER) +#elif defined (RPI_DISPLAY_TYPE) // Command is 16 bits #define CMD_BITS 16 diff --git a/Processors/TFT_eSPI_Generic.h b/Processors/TFT_eSPI_Generic.h index fd76a11..a7aae20 100644 --- a/Processors/TFT_eSPI_Generic.h +++ b/Processors/TFT_eSPI_Generic.h @@ -12,8 +12,8 @@ // None // Processor specific code used by SPI bus transaction startWrite and endWrite functions -#define SET_SPI_WRITE_MODE // Not used -#define SET_SPI_READ_MODE // Not used +#define SET_BUS_WRITE_MODE // Not used +#define SET_BUS_READ_MODE // Not used // Code to check if DMA is busy, used by SPI bus transaction startWrite and endWrite functions #define DMA_BUSY_CHECK // Not used so leave blank @@ -111,7 +111,7 @@ // Macros to write commands/pixel colour data to other displays //////////////////////////////////////////////////////////////////////////////////////// #else - #if defined (RPI_ILI9486_DRIVER) // RPi TFT always needs 16 bit transfers + #if defined (RPI_DISPLAY_TYPE) // RPi TFT type always needs 16 bit transfers #define tft_Write_8(C) spi.transfer(0); spi.transfer(C) #else #ifdef __AVR__ // AVR processors do not have 16 bit transfer @@ -123,7 +123,7 @@ #define tft_Write_16(C) spi.transfer16(C) #define tft_Write_16S(C) spi.transfer16(((C)>>8) | ((C)<<8)) #endif // AVR - #endif // RPI_ILI9486_DRIVER + #endif // RPI_DISPLAY_TYPE #define tft_Write_32(C) \ tft_Write_16((uint16_t) ((C)>>16)); \ diff --git a/Processors/TFT_eSPI_STM32.c b/Processors/TFT_eSPI_STM32.c index 8841109..3923f93 100644 --- a/Processors/TFT_eSPI_STM32.c +++ b/Processors/TFT_eSPI_STM32.c @@ -353,7 +353,7 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) if (len == 0) return; // Wait for any current DMA transaction to end - while (dmaHal.State == HAL_DMA_STATE_BUSY); + while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy if(_swapBytes) { for (uint32_t i = 0; i < len; i++) (image[i] = image[i] << 8 | image[i] >> 8); @@ -389,8 +389,7 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t uint32_t len = dw*dh; - // Wait for any current DMA transaction to end - while (dmaHal.State == HAL_DMA_STATE_BUSY); + while (spiHal.State == HAL_SPI_STATE_BUSY_TX); // Check if SPI Tx is busy // If image is clipped, copy pixels into a contiguous block if ( (dw != w) || (dh != h) ) { @@ -418,9 +417,6 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t } } - // Wait for any current SPI transaction to end - while (spiHal.State == HAL_SPI_STATE_BUSY_TX); - setWindow(x, y, x + dw - 1, y + dh - 1); // DMA byte count for transmit is only 16 bits maximum, so to avoid this constraint @@ -446,7 +442,7 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t ** Description: Override the default HAL stream 3 interrupt handler ***************************************************************************************/ extern "C" void DMA2_Stream3_IRQHandler(); -void DMA2_Stream3_IRQHandler() +void DMA2_Stream3_IRQHandler(void) { // Call the default end of buffer handler HAL_DMA_IRQHandler(&dmaHal); @@ -490,7 +486,7 @@ bool TFT_eSPI::initDMA(void) ***************************************************************************************/ extern "C" void DMA1_Channel3_IRQHandler(); -void DMA1_Channel3_IRQHandler() +void DMA1_Channel3_IRQHandler(void) { // Call the default end of buffer handler HAL_DMA_IRQHandler(&dmaHal); diff --git a/Processors/TFT_eSPI_STM32.h b/Processors/TFT_eSPI_STM32.h index 6b50e4c..7001290 100644 --- a/Processors/TFT_eSPI_STM32.h +++ b/Processors/TFT_eSPI_STM32.h @@ -11,9 +11,11 @@ // Include processor specific header // None +// RPi support not tested - Fast RPi not supported + // Processor specific code used by SPI bus transaction startWrite and endWrite functions -#define SET_SPI_WRITE_MODE // Not used -#define SET_SPI_READ_MODE // Not used +#define SET_BUS_WRITE_MODE // Not used +#define SET_BUS_READ_MODE // Not used // SUPPORT_TRANSACTIONS is mandatory for STM32 #if !defined (SUPPORT_TRANSACTIONS) @@ -43,7 +45,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // Write strobe timing setup //////////////////////////////////////////////////////////////////////////////////////// - #if defined (ILI9341_DRIVER) // WRX twc spec is 66ns = 15.15MHz + #if defined (ILI9341_DRIVER) || defined (ST7796_DRIVER) // WRX twc spec is 66ns = 15.15MHz // Extra write pulse low time (delay for data setup) #if defined (STM32F2xx) || defined (STM32F4xx) @@ -731,7 +733,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // Macros to write commands/pixel colour data to a SPI Raspberry Pi TFT //////////////////////////////////////////////////////////////////////////////////////// -#elif defined (RPI_ILI9486_DRIVER) +#elif defined (RPI_DISPLAY_TYPE) #define tft_Write_8(C) \ { spiBuffer[0] = 0; spiBuffer[1] = C; \ diff --git a/README.md b/README.md index 08be565..e8de185 100644 --- a/README.md +++ b/README.md @@ -12,11 +12,13 @@ You can take this one step further and have your own setup select file and then To select a new setup you then edit your own my_setup_select.h file (which will not get over-written during an upgrade). # News -1. The library has been upgraded to support STM32 processors when used with SPI or 8 bit parallel displays. DMA capability for SPI displays has been added for STM32F103 (e.g. "Blue Pill") and STM32F2xx/4xx/7xx (e.g. 32/64/144 Nucleo boards). New DMA demo examples have been added (for STM32 only). Smooth (anti-aliased) fonts are not yet supported for STM32 processors due to the lack of SPIFFS, support for smooth fonts using SD cards will be added at a future date. +1. The Sprite class now supports 4 bits per pixel with a 16 color palette. Three new examples have been added. -2. The ST7796 display controller has been added. The ST7796 RPi MHS-4.0 inch Display-B type display is supported (this is fast for a SPI display as an ESP32 can clock it at 80MHz (ESP8266 at 40MHz)), see setups 27 and 28. +2. The library has been upgraded to support STM32 processors when used with SPI or 8 bit parallel displays. DMA capability for SPI displays has been added for STM32F103 (e.g. "Blue Pill") and STM32F2xx/4xx/7xx (e.g. 32/64/144 Nucleo boards). New DMA demo examples have been added (for STM32 only). Smooth (anti-aliased) fonts are not yet supported for STM32 processors due to the lack of SPIFFS, support for smooth fonts using SD cards will be added at a future date. -3. A callback function has been added, this allows antialiased fonts to be rendered over colour gradients or images. Two new examples have been added to illustrate this new capability: +3. The ST7796 display controller has been added. The ST7796 RPi MHS-4.0 inch Display-B type display is supported (this is fast for a SPI display as an ESP32 can clock it at 80MHz (ESP8266 at 40MHz)), see setups 27 and 28. + +4. A callback function has been added, this allows antialiased fonts to be rendered over colour gradients or images. Two new examples have been added to illustrate this new capability: "Smooth_font_reading_TFT" @@ -24,9 +26,9 @@ To select a new setup you then edit your own my_setup_select.h file (which will ![AA_gradien](https://i.imgur.com/YMBcPHp.png) -4. Sprites can now by pushed to the screen (or another Sprite) with a rotation angle. The new function is pushRotated(). Three new examples (Rotate_Sprite_1/2/3) have been added to show how the functions can be used to rotate text, images and to draw animated dials with moving needles. +5. Sprites can now by pushed to the screen (or another Sprite) with a rotation angle. The new function is pushRotated(). Three new examples (Rotate_Sprite_1/2/3) have been added to show how the functions can be used to rotate text, images and to draw animated dials with moving needles. -5. A new TFT_eFEX support library has been created which includes extra functions such as drawing a BMP or Jpeg to the screen. This library will simplify the examples. It will be expanded at a future date to include meters, dials and GUI elements like progress bars, graphs and animated buttons: +6. A new TFT_eFEX support library has been created which includes extra functions such as drawing a BMP or Jpeg to the screen. This library will simplify the examples. It will be expanded at a future date to include meters, dials and GUI elements like progress bars, graphs and animated buttons: https://github.com/Bodmer/TFT_eFEX diff --git a/README.txt b/README.txt index 03ec449..11a4d56 100644 --- a/README.txt +++ b/README.txt @@ -1,18 +1,7 @@ This is a standalone library that contains both graphics functions -and the TFT chip driver library. - -This library has been derived from the Adafruit_GFX and driver library with -further code from other authors. - -It is not compatible with legacy versions of the IDE (e.g. 1.0.6 and -older. Use the latest version. - -New functions have been added in particular it contains proportional fonts -in addition to the original Adafruit font. - -A sprite class has been added to aid the generation of flicker free complex -graphics. - -Note: This version of the library might not be fully compatible with the -original. - +and the TFT chip driver library. It supports the ESP8266, ESP32 and +STM32 processors with performance optimised code. Other Arduino IDE +compatible boards are also supported but the library then uses +generic functions which will be slower. The library uses 32 bit +variables extensively so this will affect performance on 8 and 16 +bit processors. diff --git a/TFT_Drivers/ILI9341_Init.h b/TFT_Drivers/ILI9341_Init.h index 7c763e0..5c439b7 100644 --- a/TFT_Drivers/ILI9341_Init.h +++ b/TFT_Drivers/ILI9341_Init.h @@ -115,9 +115,9 @@ writecommand(ILI9341_SLPOUT); //Exit Sleep - spi_end(); + end_tft_write(); delay(120); - spi_begin(); + begin_tft_write(); writecommand(ILI9341_DISPON); //Display on diff --git a/TFT_Drivers/ST7789_Init.h b/TFT_Drivers/ST7789_Init.h index d6b0b11..f2683e4 100644 --- a/TFT_Drivers/ST7789_Init.h +++ b/TFT_Drivers/ST7789_Init.h @@ -109,9 +109,9 @@ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - spi_end(); + end_tft_write(); delay(120); - spi_begin(); + begin_tft_write(); writecommand(ST7789_DISPON); //Display on delay(120); diff --git a/TFT_Drivers/ST7796_Init.h b/TFT_Drivers/ST7796_Init.h index afc89f9..9908264 100644 --- a/TFT_Drivers/ST7796_Init.h +++ b/TFT_Drivers/ST7796_Init.h @@ -102,9 +102,9 @@ writecommand(0xF0); //Command Set control writedata(0x69); //Disable extension command 2 partII - spi_end(); + end_tft_write(); delay(120); - spi_begin(); + begin_tft_write(); writecommand(0x29); //Display on } \ No newline at end of file diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 2e3217d..7535a43 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -28,10 +28,10 @@ /*************************************************************************************** -** Function name: spi_begin +** Function name: begin_tft_write (was called spi_begin) ** Description: Start SPI transaction for writes and select TFT ***************************************************************************************/ -inline void TFT_eSPI::spi_begin(void){ +inline void TFT_eSPI::begin_tft_write(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT) if (locked) { locked = false; @@ -41,14 +41,14 @@ inline void TFT_eSPI::spi_begin(void){ #else CS_L; #endif - SET_SPI_WRITE_MODE; + SET_BUS_WRITE_MODE; } /*************************************************************************************** -** Function name: spi_end +** Function name: end_tft_write (was called spi_end) ** Description: End transaction for write and deselect TFT ***************************************************************************************/ -inline void TFT_eSPI::spi_end(void){ +inline void TFT_eSPI::end_tft_write(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT) if(!inTransaction) { if (!locked) { @@ -57,18 +57,18 @@ inline void TFT_eSPI::spi_end(void){ spi.endTransaction(); } } - SET_SPI_READ_MODE; + SET_BUS_READ_MODE; #else if(!inTransaction) {CS_H;} #endif } /*************************************************************************************** -** Function name: spi_begin_read -** Description: Start SPI transaction for reads and select TFT +** Function name: begin_tft_read (was called spi_begin_read) +** Description: Start transaction for reads and select TFT ***************************************************************************************/ -// Reads require a lower SPI clock rate that writes -inline void TFT_eSPI::spi_begin_read(void){ +// Reads require a lower SPI clock rate than writes +inline void TFT_eSPI::begin_tft_read(void){ DMA_BUSY_CHECK; // Wait for any DMA transfer to complete before changing SPI settings #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT) if (locked) { @@ -82,14 +82,14 @@ inline void TFT_eSPI::spi_begin_read(void){ #endif CS_L; #endif - SET_SPI_READ_MODE; + SET_BUS_READ_MODE; } /*************************************************************************************** -** Function name: spi_end_read -** Description: End SPI transaction for reads and deselect TFT +** Function name: end_tft_read (was called spi_end_read) +** Description: End transaction for reads and deselect TFT ***************************************************************************************/ -inline void TFT_eSPI::spi_end_read(void){ +inline void TFT_eSPI::end_tft_read(void){ #if defined (SPI_HAS_TRANSACTION) && defined (SUPPORT_TRANSACTIONS) && !defined(TFT_PARALLEL_8_BIT) if(!inTransaction) { if (!locked) { @@ -104,17 +104,17 @@ inline void TFT_eSPI::spi_end_read(void){ #endif if(!inTransaction) {CS_H;} #endif - SET_SPI_WRITE_MODE; + SET_BUS_WRITE_MODE; } -#if defined (TOUCH_CS) && defined (SPI_TOUCH_FREQUENCY) // && !defined(TFT_PARALLEL_8_BIT) +#if defined (TOUCH_CS) && defined (SPI_TOUCH_FREQUENCY) /*************************************************************************************** -** Function name: spi_begin_touch -** Description: Start SPI transaction and select touch controller +** 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::spi_begin_touch(void){ +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) @@ -122,22 +122,22 @@ inline void TFT_eSPI::spi_begin_touch(void){ #else spi.setFrequency(SPI_TOUCH_FREQUENCY); #endif - SET_SPI_READ_MODE; + SET_BUS_READ_MODE; T_CS_L; } /*************************************************************************************** -** Function name: spi_end_touch -** Description: End SPI transaction and deselect touch controller +** Function name: end_touch_read_write - was spi_end_touch +** Description: End transaction and deselect touch controller ***************************************************************************************/ - inline void TFT_eSPI::spi_end_touch(void){ + 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_SPI_WRITE_MODE; + SET_BUS_WRITE_MODE; } #endif @@ -348,11 +348,11 @@ void TFT_eSPI::init(uint8_t tc) #endif _booted = false; - spi_end(); + end_tft_write(); } // end of: if just _booted // Toggle RST low to reset - spi_begin(); + begin_tft_write(); #ifdef TFT_RST if (TFT_RST >= 0) { @@ -367,11 +367,11 @@ void TFT_eSPI::init(uint8_t tc) writecommand(TFT_SWRST); // Software reset #endif - spi_end(); + end_tft_write(); delay(150); // Wait for reset to complete - spi_begin(); + begin_tft_write(); tc = tc; // Supress warning @@ -392,9 +392,6 @@ void TFT_eSPI::init(uint8_t tc) #elif defined (ST7796_DRIVER) #include "TFT_Drivers/ST7796_Init.h" -#elif defined (RPI_ILI9486_DRIVER) - #include "TFT_Drivers/ILI9486_Init.h" - #elif defined (ILI9486_DRIVER) #include "TFT_Drivers/ILI9486_Init.h" @@ -429,7 +426,7 @@ void TFT_eSPI::init(uint8_t tc) writecommand(TFT_INVOFF); #endif - spi_end(); + end_tft_write(); setRotation(rotation); @@ -453,7 +450,7 @@ void TFT_eSPI::init(uint8_t tc) void TFT_eSPI::setRotation(uint8_t m) { - spi_begin(); + begin_tft_write(); // This loads the driver specific rotation code <<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVERS TO THE LIST HERE <<<<<<<<<<<<<<<<<<<<<<< #if defined (ILI9341_DRIVER) @@ -471,9 +468,6 @@ void TFT_eSPI::setRotation(uint8_t m) #elif defined (ST7796_DRIVER) #include "TFT_Drivers/ST7796_Rotation.h" -#elif defined (RPI_ILI9486_DRIVER) - #include "TFT_Drivers/ILI9486_Rotation.h" - #elif defined (ILI9486_DRIVER) #include "TFT_Drivers/ILI9486_Rotation.h" @@ -502,7 +496,7 @@ void TFT_eSPI::setRotation(uint8_t m) delayMicroseconds(10); - spi_end(); + end_tft_write(); addr_row = 0xFFFF; addr_col = 0xFFFF; @@ -559,7 +553,7 @@ void TFT_eSPI::spiwrite(uint8_t c) ***************************************************************************************/ void TFT_eSPI::writecommand(uint8_t c) { - spi_begin(); // CS_L; + begin_tft_write(); DC_C; @@ -567,7 +561,7 @@ void TFT_eSPI::writecommand(uint8_t c) DC_D; - spi_end(); // CS_H; + end_tft_write(); } @@ -578,7 +572,7 @@ void TFT_eSPI::writecommand(uint8_t c) ***************************************************************************************/ void TFT_eSPI::writedata(uint8_t d) { - spi_begin(); // CS_L; + begin_tft_write(); DC_D; // Play safe, but should already be in data mode @@ -586,7 +580,7 @@ void TFT_eSPI::writedata(uint8_t d) CS_L; // Allow more hold time for low VDI rail - spi_end(); // CS_H; + end_tft_write(); } @@ -614,7 +608,7 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) #else // SPI interface // Tested with ILI9341 set to Interface II i.e. IM [3:0] = "1101" - spi_begin_read(); + begin_tft_read(); index = 0x10 + (index & 0x0F); DC_C; tft_Write_8(0xD9); @@ -627,7 +621,7 @@ uint8_t TFT_eSPI::readcommand8(uint8_t cmd_function, uint8_t index) DC_D; reg = tft_Read_8(); - spi_end_read(); + end_tft_read(); #endif return reg; } @@ -715,9 +709,9 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) // This function can get called during antialiased font rendering // so a transaction may be in progress bool wasInTransaction = inTransaction; - if (inTransaction) { inTransaction= false; spi_end();} + if (inTransaction) { inTransaction= false; end_tft_write();} - spi_begin_read(); + begin_tft_read(); readAddrWindow(x0, y0, 1, 1); // Sets CS low @@ -752,10 +746,10 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0) end_SDA_Read(); #endif - spi_end_read(); + end_tft_read(); // Reinstate the transaction if one was in progress - if(wasInTransaction) { spi_begin(); inTransaction = true; } + if(wasInTransaction) { begin_tft_write(); inTransaction = true; } return color565(r, g, b); @@ -819,7 +813,7 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da #else // SPI interface - spi_begin_read(); + begin_tft_read(); readAddrWindow(x, y, w, h); // Sets CS low @@ -862,7 +856,7 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da end_SDA_Read(); #endif - spi_end_read(); + end_tft_read(); #endif } @@ -902,7 +896,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d if (dw < 1 || dh < 1) return; - spi_begin(); + begin_tft_write(); inTransaction = true; setWindow(x, y, x + dw - 1, y + dh - 1); @@ -921,7 +915,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d } inTransaction = false; - spi_end(); + end_tft_write(); } /*************************************************************************************** @@ -946,7 +940,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d if (dw < 1 || dh < 1) return; - spi_begin(); + begin_tft_write(); inTransaction = true; data += dx + dy * w; @@ -992,7 +986,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d } inTransaction = false; - spi_end(); + end_tft_write(); } @@ -1019,7 +1013,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 if (dw < 1 || dh < 1) return; - spi_begin(); + begin_tft_write(); inTransaction = true; data += dx + dy * w; @@ -1053,7 +1047,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 } inTransaction = false; - spi_end(); + end_tft_write(); } @@ -1079,7 +1073,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 if (dw < 1 || dh < 1) return; - spi_begin(); + begin_tft_write(); inTransaction = true; data += dx + dy * w; @@ -1122,7 +1116,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1 } inTransaction = false; - spi_end(); + end_tft_write(); } @@ -1148,7 +1142,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da if (dw < 1 || dh < 1) return; - spi_begin(); + begin_tft_write(); inTransaction = true; setWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR @@ -1275,7 +1269,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da } inTransaction = false; - spi_end(); + end_tft_write(); } @@ -1300,7 +1294,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da if (dw < 1 || dh < 1) return; - spi_begin(); + begin_tft_write(); inTransaction = true; int32_t xe = x + dw - 1, ye = y + dh - 1; @@ -1498,9 +1492,10 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da } inTransaction = false; - spi_end(); + end_tft_write(); } + /*************************************************************************************** ** Function name: setSwapBytes ** Description: Used by 16 bit pushImage() to swap byte order in colours @@ -1520,6 +1515,7 @@ bool TFT_eSPI::getSwapBytes(void) return _swapBytes; } + /*************************************************************************************** ** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101") ** Description: Read RGB pixel colours from a defined area @@ -1533,7 +1529,7 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_ #else // Not TFT_PARALLEL_8_BIT - spi_begin_read(); + begin_tft_read(); readAddrWindow(x0, y0, w, h); // Sets CS low @@ -1574,7 +1570,7 @@ void TFT_eSPI::readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_ end_SDA_Read(); #endif - spi_end_read(); + end_tft_read(); #endif } @@ -1592,7 +1588,7 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) int32_t dy = r+r; int32_t p = -(r>>1); - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; // These are ordered to minimise coordinate changes in x or y @@ -1629,7 +1625,7 @@ void TFT_eSPI::drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -1685,7 +1681,7 @@ void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) int32_t dy = r+r; int32_t p = -(r>>1); - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; drawFastHLine(x0 - r, y0, dy+1, color); @@ -1710,7 +1706,7 @@ void TFT_eSPI::fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color) } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -1766,7 +1762,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 int32_t fy2 = 4 * ry2; int32_t s; - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) { @@ -1799,7 +1795,7 @@ void TFT_eSPI::drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -1818,7 +1814,7 @@ void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 int32_t fy2 = 4 * ry2; int32_t s; - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; for (x = 0, y = ry, s = 2*ry2+rx2*(1-2*ry); ry2*x <= rx2*y; x++) { @@ -1844,7 +1840,7 @@ void TFT_eSPI::fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint1 } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -1865,7 +1861,7 @@ void TFT_eSPI::fillScreen(uint32_t color) // Draw a rectangle void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; drawFastHLine(x, y, w, color); @@ -1875,7 +1871,7 @@ void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col drawFastVLine(x + w - 1, y+1, h-2, color); inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -1886,7 +1882,7 @@ void TFT_eSPI::drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col // Draw a rounded rectangle void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; // smarter version @@ -1901,7 +1897,7 @@ void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t drawCircleHelper(x + r , y + h - r - 1, r, 8, color); inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -1912,7 +1908,7 @@ void TFT_eSPI::drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t // Fill a rounded rectangle, changed to horizontal lines (faster in sprites) void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; // smarter version @@ -1923,7 +1919,7 @@ void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t fillCircleHelper(x + r , y + r, r, 2, w - r - r - 1, color); inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -1934,7 +1930,7 @@ void TFT_eSPI::fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t // Draw a triangle void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; drawLine(x0, y0, x1, y1, color); @@ -1942,7 +1938,7 @@ void TFT_eSPI::drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int3 drawLine(x2, y2, x0, y0, color); inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -1976,7 +1972,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in return; } - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; int32_t @@ -2023,7 +2019,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -2033,7 +2029,7 @@ void TFT_eSPI::fillTriangle ( int32_t x0, int32_t y0, int32_t x1, int32_t y1, in ***************************************************************************************/ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; int32_t i, j, byteWidth = (w + 7) / 8; @@ -2047,7 +2043,7 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -2057,7 +2053,7 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w ***************************************************************************************/ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; int32_t i, j, byteWidth = (w + 7) / 8; @@ -2071,7 +2067,7 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } /*************************************************************************************** @@ -2080,7 +2076,7 @@ void TFT_eSPI::drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w ***************************************************************************************/ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; int32_t i, j, byteWidth = (w + 7) / 8; @@ -2094,7 +2090,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -2104,7 +2100,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t ***************************************************************************************/ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t color, uint16_t bgcolor) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; int32_t i, j, byteWidth = (w + 7) / 8; @@ -2118,7 +2114,7 @@ void TFT_eSPI::drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } @@ -2467,7 +2463,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 if ((size==1) && fillbg) { uint8_t column[6]; uint8_t mask = 0x1; - spi_begin(); + begin_tft_write(); setWindow(x, y, x+5, y+8); @@ -2483,10 +2479,10 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 tft_Write_16(bg); } - spi_end(); + end_tft_write(); } else { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; for (int8_t i = 0; i < 6; i++ ) { uint8_t line; @@ -2510,7 +2506,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 } } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } //>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -2523,7 +2519,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 #ifdef LOAD_GFXFF // Filter out bad characters not present in font if ((c >= pgm_read_word(&gfxFont->first)) && (c <= pgm_read_word(&gfxFont->last ))) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; //>>>>>>>>>>>>>>>>>>>>>>>>>>> @@ -2572,7 +2568,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 } inTransaction = false; - spi_end(); // Does nothing if Sprite class uses this function + end_tft_write(); // Does nothing if Sprite class uses this function } #endif @@ -2592,11 +2588,11 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32 // Chip select is high at the end of this function void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t w, int32_t h) { - spi_begin(); + begin_tft_write(); setWindow(x0, y0, x0 + w - 1, y0 + h - 1); - spi_end(); + end_tft_write(); } @@ -2604,10 +2600,10 @@ void TFT_eSPI::setAddrWindow(int32_t x0, int32_t y0, int32_t w, int32_t h) ** Function name: setWindow ** Description: define an area to receive a stream of pixels ***************************************************************************************/ -// Chip select stays low, call spi_begin first. Use setAddrWindow() from sketches +// Chip select stays low, call begin_tft_write first. Use setAddrWindow() from sketches void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) { - //spi_begin(); // Must be called before setWindow + //begin_tft_write(); // Must be called before setWindow addr_col = 0xFFFF; addr_row = 0xFFFF; @@ -2631,7 +2627,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) DC_D; - //spi_end(); // Must be called after setWindow + //end_tft_write(); // Must be called after setWindow } @@ -2684,7 +2680,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) y+=rowstart; #endif - spi_begin(); + begin_tft_write(); // No need to send x if it has not changed (speeds things up) if (addr_col != x) { @@ -2703,7 +2699,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_C; tft_Write_8(TFT_RAMWR); DC_D; tft_Write_16(color); - spi_end(); + end_tft_write(); } /*************************************************************************************** @@ -2712,11 +2708,11 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) ***************************************************************************************/ void TFT_eSPI::pushColor(uint16_t color) { - spi_begin(); + begin_tft_write(); tft_Write_16(color); - spi_end(); + end_tft_write(); } @@ -2726,11 +2722,11 @@ void TFT_eSPI::pushColor(uint16_t color) ***************************************************************************************/ void TFT_eSPI::pushColor(uint16_t color, uint32_t len) { - spi_begin(); + begin_tft_write(); pushBlock(color, len); - spi_end(); + end_tft_write(); } /*************************************************************************************** @@ -2739,7 +2735,7 @@ void TFT_eSPI::pushColor(uint16_t color, uint32_t len) ***************************************************************************************/ void TFT_eSPI::startWrite(void) { - spi_begin(); + begin_tft_write(); inTransaction = true; } @@ -2751,7 +2747,7 @@ void TFT_eSPI::endWrite(void) { inTransaction = false; DMA_BUSY_CHECK; // Safety check - user code should have checked this! - spi_end(); + end_tft_write(); } /*************************************************************************************** @@ -2771,11 +2767,11 @@ void TFT_eSPI::writeColor(uint16_t color, uint32_t len) // len is number of bytes, not pixels void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) { - spi_begin(); + begin_tft_write(); pushPixels(data, len>>1); - spi_end(); + end_tft_write(); } @@ -2785,13 +2781,13 @@ void TFT_eSPI::pushColors(uint8_t *data, uint32_t len) ***************************************************************************************/ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) { - spi_begin(); + begin_tft_write(); if (swap) {swap = _swapBytes; _swapBytes = true; } pushPixels(data, len); _swapBytes = swap; // Restore old value - spi_end(); + end_tft_write(); } @@ -2803,7 +2799,7 @@ void TFT_eSPI::pushColors(uint16_t *data, uint32_t len, bool swap) // an efficient FastH/V Line draw routine for line segments of 2 pixels or more void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; bool steep = abs(y1 - y0) > abs(x1 - x0); @@ -2855,7 +2851,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t } inTransaction = false; - spi_end(); + end_tft_write(); } @@ -2874,13 +2870,13 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color) if (h < 1) return; - spi_begin(); + begin_tft_write(); setWindow(x, y, x, y + h - 1); pushBlock(color, h); - spi_end(); + end_tft_write(); } @@ -2899,13 +2895,13 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color) if (w < 1) return; - spi_begin(); + begin_tft_write(); setWindow(x, y, x + w - 1, y); pushBlock(color, w); - spi_end(); + end_tft_write(); } @@ -2926,13 +2922,13 @@ void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t col if ((w < 1) || (h < 1)) return; - spi_begin(); + begin_tft_write(); setWindow(x, y, x + w - 1, y + h - 1); pushBlock(color, w * h); - spi_end(); + end_tft_write(); } @@ -2980,11 +2976,11 @@ uint16_t TFT_eSPI::color8to16(uint8_t color) ***************************************************************************************/ void TFT_eSPI::invertDisplay(bool i) { - spi_begin(); + begin_tft_write(); // Send the command twice as otherwise it does not always work! writecommand(i ? TFT_INVON : TFT_INVOFF); writecommand(i ? TFT_INVON : TFT_INVOFF); - spi_end(); + end_tft_write(); } @@ -3366,7 +3362,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) if (x + width * textsize >= (int16_t)_width) return width * textsize ; if (textcolor == textbgcolor || textsize != 1) { - //spi_begin(); // Sprite class can use this function, avoiding spi_begin() + //begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write() inTransaction = true; for (int32_t i = 0; i < height; i++) { @@ -3403,10 +3399,10 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) } inTransaction = false; - spi_end(); + end_tft_write(); } else { // Faster drawing of characters and background using block write - spi_begin(); + begin_tft_write(); setWindow(x, y, x + width - 1, y + height - 1); @@ -3426,7 +3422,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) if (pX) {tft_Write_16(textbgcolor);} } - spi_end(); + end_tft_write(); } } @@ -3438,7 +3434,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) #ifdef LOAD_RLE //674 bytes of code // Font is not 2 and hence is RLE encoded { - spi_begin(); + begin_tft_write(); inTransaction = true; w *= height; // Now w is total number of pixels in the character @@ -3508,7 +3504,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font) } } inTransaction = false; - spi_end(); + end_tft_write(); } // End of RLE font rendering #endif diff --git a/TFT_eSPI.h b/TFT_eSPI.h index 2ecca75..956ca38 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -6,17 +6,21 @@ hardware driver, the graphics functions and the proportional fonts. - The larger fonts are Run Length Encoded to reduce - their FLASH footprint. + The built-in fonts 4, 6, 7 and 8 are Run Length + Encoded (RLE) to reduce the FLASH footprint. + Last review/edit by Bodmer: 26/01/20 ****************************************************/ // Stop fonts etc being loaded multiple times #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "1.5.0" +#define TFT_ESPI_VERSION "2.0.0" +/*************************************************************************************** +** Section 1: Load required header files +***************************************************************************************/ // Include header file that defines the fonts loaded, the TFT drivers // available and the pins to be used, etc, etc #include @@ -26,6 +30,9 @@ #include #include +/*************************************************************************************** +** Section 2: Load processor specific header files +***************************************************************************************/ #ifdef __AVR__ #include #elif defined(ESP8266) || defined(ESP32) @@ -45,31 +52,38 @@ #include "Processors/TFT_eSPI_Generic.h" #endif +/*************************************************************************************** +** Section 3: Interface setup +***************************************************************************************/ #ifndef TAB_COLOUR #define TAB_COLOUR 0 #endif -// If the frequency is not defined, set a default +// If the SPI frequency is not defined, set a default #ifndef SPI_FREQUENCY #define SPI_FREQUENCY 20000000 #endif -// If the frequency is not defined, set a default +// If the SPI read frequency is not defined, set a default #ifndef SPI_READ_FREQUENCY - #define SPI_READ_FREQUENCY SPI_FREQUENCY + #define SPI_READ_FREQUENCY 10000000 #endif +// Some ST7789 boards do not work with Mode 0 #if defined(ST7789_DRIVER) || defined(ST7789_2_DRIVER) #define TFT_SPI_MODE SPI_MODE3 #else #define TFT_SPI_MODE SPI_MODE0 #endif -// If the frequency is not defined, set a default +// If the XPT2046 SPI frequency is not defined, set a default #ifndef SPI_TOUCH_FREQUENCY #define SPI_TOUCH_FREQUENCY 2500000 #endif +/*************************************************************************************** +** Section 4: Setup fonts +***************************************************************************************/ // Use GLCD font in error case where user requests a smooth font file // that does not exist (this is a temporary fix to stop ESP32 reboot) #ifdef SMOOTH_FONT @@ -112,7 +126,7 @@ #ifndef LOAD_RLE #define LOAD_RLE #endif -#elif defined LOAD_FONT8N +#elif defined LOAD_FONT8N // Optional narrower version #define LOAD_FONT8 #include #ifndef LOAD_RLE @@ -128,124 +142,13 @@ #include #endif // #ifdef LOAD_GFXFF -//These enumerate the text plotting alignment (reference datum point) -#define TL_DATUM 0 // Top left (default) -#define TC_DATUM 1 // Top centre -#define TR_DATUM 2 // Top right -#define ML_DATUM 3 // Middle left -#define CL_DATUM 3 // Centre left, same as above -#define MC_DATUM 4 // Middle centre -#define CC_DATUM 4 // Centre centre, same as above -#define MR_DATUM 5 // Middle right -#define CR_DATUM 5 // Centre right, same as above -#define BL_DATUM 6 // Bottom left -#define BC_DATUM 7 // Bottom centre -#define BR_DATUM 8 // Bottom right -#define L_BASELINE 9 // Left character baseline (Line the 'A' character would sit on) -#define C_BASELINE 10 // Centre character baseline -#define R_BASELINE 11 // Right character baseline - - -// New color definitions use for all my libraries -#define TFT_BLACK 0x0000 /* 0, 0, 0 */ -#define TFT_NAVY 0x000F /* 0, 0, 128 */ -#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */ -#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */ -#define TFT_MAROON 0x7800 /* 128, 0, 0 */ -#define TFT_PURPLE 0x780F /* 128, 0, 128 */ -#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */ -#define TFT_LIGHTGREY 0xC618 /* 192, 192, 192 */ -#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */ -#define TFT_BLUE 0x001F /* 0, 0, 255 */ -#define TFT_GREEN 0x07E0 /* 0, 255, 0 */ -#define TFT_CYAN 0x07FF /* 0, 255, 255 */ -#define TFT_RED 0xF800 /* 255, 0, 0 */ -#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */ -#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */ -#define TFT_WHITE 0xFFFF /* 255, 255, 255 */ -#define TFT_ORANGE 0xFDA0 /* 255, 180, 0 */ -#define TFT_GREENYELLOW 0xB7E0 /* 180, 255, 0 */ -#define TFT_PINK 0xFC9F - -// 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. -#define TFT_TRANSPARENT 0x0120 - -// Swap any type -template static inline void -swap_coord(T& a, T& b) { T t = a; a = b; b = t; } - -#ifndef min - // Return minimum of two numbers, may already be defined - // #define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -// This structure allows sketches to retrieve the user setup parameters at runtime -// by calling getSetup(), zero impact on code size unless used, mainly for diagnostics -typedef struct -{ -String version = TFT_ESPI_VERSION; -int32_t esp; -uint8_t trans; -uint8_t serial; -uint8_t overlap; - -#if defined (ESP32) - #if defined (USE_HSPI_PORT) - uint8_t port = HSPI; - #else - uint8_t port = VSPI; - #endif -#endif - -uint16_t tft_driver; // Hexadecimal code -uint16_t tft_width; // Rotation 0 width and height -uint16_t tft_height; - -uint8_t r0_x_offset; // Offsets, not all used yet -uint8_t r0_y_offset; -uint8_t r1_x_offset; -uint8_t r1_y_offset; -uint8_t r2_x_offset; -uint8_t r2_y_offset; -uint8_t r3_x_offset; -uint8_t r3_y_offset; - -int8_t pin_tft_mosi; -int8_t pin_tft_miso; -int8_t pin_tft_clk; -int8_t pin_tft_cs; - -int8_t pin_tft_dc; -int8_t pin_tft_rd; -int8_t pin_tft_wr; -int8_t pin_tft_rst; - -int8_t pin_tft_d0; -int8_t pin_tft_d1; -int8_t pin_tft_d2; -int8_t pin_tft_d3; -int8_t pin_tft_d4; -int8_t pin_tft_d5; -int8_t pin_tft_d6; -int8_t pin_tft_d7; - -int8_t pin_tch_cs; - -int16_t tft_spi_freq; -int16_t tft_rd_freq; -int16_t tch_spi_freq; -} setup_t; - -// This is a structure to conveniently hold information on the default fonts -// Stores pointer to font character image address table, width table and height - -// Create a null set in case some fonts not used (to prevent crash) +// Create a null default font in case some fonts not used (to prevent crash) const uint8_t widtbl_null[1] = {0}; PROGMEM const uint8_t chr_null[1] = {0}; PROGMEM const uint8_t* const chrtbl_null[1] = {chr_null}; +// This is a structure to conveniently hold information on the default fonts +// Stores pointer to font character image address table, width table and height typedef struct { const uint8_t *chartbl; const uint8_t *widthtbl; @@ -300,21 +203,169 @@ const PROGMEM fontinfo fontdata [] = { #endif }; +/*************************************************************************************** +** Section 5: Font datum enumeration +***************************************************************************************/ +//These enumerate the text plotting alignment (reference datum point) +#define TL_DATUM 0 // Top left (default) +#define TC_DATUM 1 // Top centre +#define TR_DATUM 2 // Top right +#define ML_DATUM 3 // Middle left +#define CL_DATUM 3 // Centre left, same as above +#define MC_DATUM 4 // Middle centre +#define CC_DATUM 4 // Centre centre, same as above +#define MR_DATUM 5 // Middle right +#define CR_DATUM 5 // Centre right, same as above +#define BL_DATUM 6 // Bottom left +#define BC_DATUM 7 // Bottom centre +#define BR_DATUM 8 // Bottom right +#define L_BASELINE 9 // Left character baseline (Line the 'A' character would sit on) +#define C_BASELINE 10 // Centre character baseline +#define R_BASELINE 11 // Right character baseline + +/*************************************************************************************** +** Section 6: Colour enumeration +***************************************************************************************/ +// Default color definitions +#define TFT_BLACK 0x0000 /* 0, 0, 0 */ +#define TFT_NAVY 0x000F /* 0, 0, 128 */ +#define TFT_DARKGREEN 0x03E0 /* 0, 128, 0 */ +#define TFT_DARKCYAN 0x03EF /* 0, 128, 128 */ +#define TFT_MAROON 0x7800 /* 128, 0, 0 */ +#define TFT_PURPLE 0x780F /* 128, 0, 128 */ +#define TFT_OLIVE 0x7BE0 /* 128, 128, 0 */ +#define TFT_LIGHTGREY 0xD69A /* 211, 211, 211 */ +#define TFT_DARKGREY 0x7BEF /* 128, 128, 128 */ +#define TFT_BLUE 0x001F /* 0, 0, 255 */ +#define TFT_GREEN 0x07E0 /* 0, 255, 0 */ +#define TFT_CYAN 0x07FF /* 0, 255, 255 */ +#define TFT_RED 0xF800 /* 255, 0, 0 */ +#define TFT_MAGENTA 0xF81F /* 255, 0, 255 */ +#define TFT_YELLOW 0xFFE0 /* 255, 255, 0 */ +#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_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 */ + +// 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. +#define TFT_TRANSPARENT 0x0120 // This is actually a dark green + +// Default palette for 4 bit colour sprites +static const uint16_t default_4bit_palette[] PROGMEM = { + TFT_BLACK, // 0 ^ + TFT_BROWN, // 1 | + TFT_RED, // 2 | + TFT_ORANGE, // 3 | + TFT_YELLOW, // 4 Colours 0-9 follow the resistor colour code! + TFT_GREEN, // 5 | + TFT_BLUE, // 6 | + TFT_PURPLE, // 7 | + TFT_DARKGREY, // 8 | + TFT_WHITE, // 9 v + TFT_CYAN, // 10 Blue+green mix + TFT_MAGENTA, // 11 Blue+red mix + TFT_MAROON, // 12 Darker red colour + TFT_DARKGREEN,// 13 Darker green colour + TFT_NAVY, // 14 Darker blue colour + TFT_PINK // 15 +}; + +/*************************************************************************************** +** Section 7: Diagnostic support +***************************************************************************************/ +// #define TFT_eSPI_DEBUG // Switch on debug support serial messages (not used yet) +// #define TFT_eSPI_FNx_DEBUG // Switch on debug support for function "x" (not used yet) + +// This structure allows sketches to retrieve the user setup parameters at runtime +// by calling getSetup(), zero impact on code size unless used, mainly for diagnostics +typedef struct +{ +String version = TFT_ESPI_VERSION; +int32_t esp; // Processor code +uint8_t trans; // SPI transaction supoort +uint8_t serial; // Serial (SPI) or parallel +uint8_t overlap; // ESP8266 overlap mode + +#if defined (ESP32) // TODO: make generic for other processors + #if defined (USE_HSPI_PORT) + uint8_t port = HSPI; + #else + uint8_t port = VSPI; + #endif +#endif + +uint16_t tft_driver; // Hexadecimal code +uint16_t tft_width; // Rotation 0 width and height +uint16_t tft_height; + +uint8_t r0_x_offset; // Display offsets, not all used yet +uint8_t r0_y_offset; +uint8_t r1_x_offset; +uint8_t r1_y_offset; +uint8_t r2_x_offset; +uint8_t r2_y_offset; +uint8_t r3_x_offset; +uint8_t r3_y_offset; + +int8_t pin_tft_mosi; // SPI pins +int8_t pin_tft_miso; +int8_t pin_tft_clk; +int8_t pin_tft_cs; + +int8_t pin_tft_dc; // Control pins +int8_t pin_tft_rd; +int8_t pin_tft_wr; +int8_t pin_tft_rst; + +int8_t pin_tft_d0; // Parallel port pins +int8_t pin_tft_d1; +int8_t pin_tft_d2; +int8_t pin_tft_d3; +int8_t pin_tft_d4; +int8_t pin_tft_d5; +int8_t pin_tft_d6; +int8_t pin_tft_d7; + +int8_t pin_tch_cs; // Touch chip select pin + +int16_t tft_spi_freq;// TFT write SPI frequency +int16_t tft_rd_freq; // TFT read SPI frequency +int16_t tch_spi_freq;// Touch controller read/write SPI frequency +} setup_t; + +/*************************************************************************************** +** Section 8: Class member and support functions +***************************************************************************************/ +// Swap any type +template static inline void +swap_coord(T& a, T& b) { T t = a; a = b; b = t; } + +// Callback prototype for smooth font pixel colour read typedef uint16_t (*getColorCallback)(uint16_t x, uint16_t y); // Class functions and variables class TFT_eSPI : public Print { + //--------------------------------------- public ------------------------------------// public: TFT_eSPI(int16_t _W = TFT_WIDTH, int16_t _H = TFT_HEIGHT); - void init(uint8_t tc = TAB_COLOUR), begin(uint8_t tc = TAB_COLOUR); // Same - begin included for backwards compatibility + // init() and begin() are equivalent, begin() included for backwards compatibility + // Sketch defined tab colour option is for ST7735 displays only + void init(uint8_t tc = TAB_COLOUR), begin(uint8_t tc = TAB_COLOUR); // These are virtual so the TFT_eSprite class can override them with sprite specific functions virtual void drawPixel(int32_t x, int32_t y, uint32_t color), drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size), - drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color), + drawLine(int32_t xs, int32_t ys, int32_t xe, int32_t ye, uint32_t color), drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color), drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color), fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color); @@ -324,89 +375,21 @@ class TFT_eSPI : public Print { height(void), width(void); - // The TFT_eSprite class inherits the following functions - void setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye), - pushColor(uint16_t color), - pushColor(uint16_t color, uint32_t len), + void setRotation(uint8_t r); // Set the display image orientation to 0, 1, 2 or 3 + uint8_t getRotation(void); // Read the current rotation + + void invertDisplay(bool i); // Tell TFT to invert all displayed colours + + + // The TFT_eSprite class inherits the following functions (not all are useful to Sprite class + void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h), // Note: start coordinates + width and height + setWindow(int32_t xs, int32_t ys, int32_t xe, int32_t ye); // Note: start + end coordinates + + // Push (aka write pixel) colours to the TFT (use setAddrWindow() first) + void pushColor(uint16_t color), + pushColor(uint16_t color, uint32_t len), // Deprecated, use pushBlock() pushColors(uint16_t *data, uint32_t len, bool swap = true), // With byte swap option - pushColors(uint8_t *data, uint32_t len), - - fillScreen(uint32_t color); - - void drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color), - drawRoundRect(int32_t x0, int32_t y0, int32_t w, int32_t h, int32_t radius, uint32_t color), - fillRoundRect(int32_t x0, int32_t y0, int32_t w, int32_t h, int32_t radius, uint32_t color), - - setRotation(uint8_t r), - invertDisplay(bool i), - - drawCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color), - drawCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t cornername, uint32_t color), - fillCircle(int32_t x0, int32_t y0, int32_t r, uint32_t color), - fillCircleHelper(int32_t x0, int32_t y0, int32_t r, uint8_t cornername, int32_t delta, uint32_t color), - - drawEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color), - fillEllipse(int16_t x0, int16_t y0, int32_t rx, int32_t ry, uint16_t color), - - drawTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color), - fillTriangle(int32_t x0, int32_t y0, int32_t x1, int32_t y1, int32_t x2, int32_t y2, uint32_t color), - - drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), - drawBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), - drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), - drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), - setBitmapColor(uint16_t fgcolor, uint16_t bgcolor), // For 1bpp sprites - - setPivot(int16_t x, int16_t y), - setCursor(int16_t x, int16_t y), - setCursor(int16_t x, int16_t y, uint8_t font), - setTextColor(uint16_t color), - setTextColor(uint16_t fgcolor, uint16_t bgcolor), - setTextSize(uint8_t size), - - setTextWrap(bool wrapX, bool wrapY = false), - setTextDatum(uint8_t datum), - setTextPadding(uint16_t x_width), - -#ifdef LOAD_GFXFF - setFreeFont(const GFXfont *f = NULL), - setTextFont(uint8_t font), -#else - setFreeFont(uint8_t font), - setTextFont(uint8_t font), -#endif - spiwrite(uint8_t), - writecommand(uint8_t c), - writedata(uint8_t d), - - commandList(const uint8_t *addr); - - uint8_t readcommand8(uint8_t cmd_function, uint8_t index = 0); - uint16_t readcommand16(uint8_t cmd_function, uint8_t index = 0); - uint32_t readcommand32(uint8_t cmd_function, uint8_t index = 0); - - // Read the colour of a pixel at x,y and return value in 565 format - uint16_t readPixel(int32_t x0, int32_t y0); - void setCallback(getColorCallback getCol); - - // The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location - // Read a block of pixels to a data buffer, buffer is 16 bit and the array size must be at least w * h - void readRect(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); - // Write a block of pixels to the screen - void pushRect(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); - - // These are used to render images or sprites stored in RAM arrays - void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data); - void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint16_t *data, uint16_t transparent); - - - // These are used to render images stored in FLASH (PROGMEM) - void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent); - void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, const uint16_t *data); - - // These are used by pushSprite for 1, 4 and 8 bit colours (color map needed for 4 bit) - void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data, bool bpp8 = true, uint16_t *cmap = nullptr); - void pushImage(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true, uint16_t *cmap = nullptr); + pushColors(uint8_t *data, uint32_t len); // Deprecated, use pushPixels() // Write a solid block of a single colour void pushBlock(uint16_t color, uint32_t len); @@ -414,163 +397,333 @@ class TFT_eSPI : public Print { // 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 + 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 + #ifdef TFT_SDA_READ + #if defined (TFT_eSPI_ENABLE_8_BIT_READ) + uint8_t tft_Read_8(void); // Read 8 bit value from TFT command register + #endif + void begin_SDA_Read(void); // Begin a read on a half duplex (bi-directional SDA) SPI bus - sets MOSI to input + void end_SDA_Read(void); // Restore MOSI to output + #endif + + // Graphics drawing + void fillScreen(uint32_t color), + drawRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color), + drawRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color), + fillRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t radius, uint32_t color); + + + void drawCircle(int32_t x, int32_t y, int32_t r, uint32_t color), + drawCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, uint32_t color), + fillCircle(int32_t x, int32_t y, int32_t r, uint32_t color), + fillCircleHelper(int32_t x, int32_t y, int32_t r, uint8_t cornername, int32_t delta, uint32_t color), + + drawEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color), + fillEllipse(int16_t x, int16_t y, int32_t rx, int32_t ry, uint16_t color), + + // Corner 1 Corner 2 Corner 3 + drawTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color), + fillTriangle(int32_t x1,int32_t y1, int32_t x2,int32_t y2, int32_t x3,int32_t y3, uint32_t color); + + // Image rendering // Swap the byte order for pushImage() and pushPixels() - corrects endianness void setSwapBytes(bool swap); bool getSwapBytes(void); + // Draw bitmap + void drawBitmap( int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), + drawBitmap( int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), + drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor), + drawXBitmap(int16_t x, int16_t y, const uint8_t *bitmap, int16_t w, int16_t h, uint16_t fgcolor, uint16_t bgcolor), + setBitmapColor(uint16_t fgcolor, uint16_t bgcolor); // Define the 2 colours for 1bpp sprites + + // Set TFT pivot point (use when rendering rotated sprites) + void setPivot(int16_t x, int16_t y); + int16_t getPivotX(void), // Get pivot x + getPivotY(void); // Get pivot y + + // The next functions can be used as a pair to copy screen blocks (or horizontal/vertical lines) to another location + // Read a block of pixels to a data buffer, buffer is 16 bit and the size must be at least w * h + void readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); + // Write a block of pixels to the screen - this is a deprecated alternative to pushImage() + void pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); + + // These are used to render images or sprites stored in RAM arrays (used by Sprite class for 16bpp Sprites) + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data); + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transparent); + + // These are used to render images stored in FLASH (PROGMEM) + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transparent); + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data); + + // These are used by Sprite class pushSprite() member function for 1, 4 and 8 bits per pixel (bpp) colours + // They are not intended to be used with user sketches (but could be) + // Set bpp8 true for 8bpp sprites, false otherwise. The cmap pointer must be specified for 4bpp + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8 = true, uint16_t *cmap = nullptr); + void pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transparent, bool bpp8 = true, uint16_t *cmap = nullptr); + // This next function has been used successfully to dump the TFT screen to a PC for documentation purposes - // It reads a screen area and returns the RGB 8 bit colour values of each pixel + // It reads a screen area and returns the 3 RGB 8 bit colour values of each pixel in the buffer // Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes - void readRectRGB(int32_t x0, int32_t y0, int32_t w, int32_t h, uint8_t *data); + void readRectRGB(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data); - uint8_t getRotation(void), - getTextDatum(void), - color16to8(uint16_t color565); // Convert 16 bit colour to 8 bits - - int16_t getCursorX(void), - getCursorY(void); - - int16_t getPivotX(void), - getPivotY(void); - - uint16_t fontsLoaded(void), - color565(uint8_t red, uint8_t green, uint8_t blue), // Convert 8 bit red, green and blue to 16 bits - color8to16(uint8_t color332); // Convert 8 bit colour to 16 bits - - int16_t drawNumber(long long_num, int32_t poX, int32_t poY, uint8_t font), - drawNumber(long long_num, int32_t poX, int32_t poY), - drawFloat(float floatNumber, uint8_t decimal, int32_t poX, int32_t poY, uint8_t font), - drawFloat(float floatNumber, uint8_t decimal, int32_t poX, int32_t poY), + // 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 + drawFloat(float floatNumber, uint8_t decimal, int32_t x, int32_t y), // Draw float using current font // Handle char arrays - drawString(const char *string, int32_t poX, int32_t poY, uint8_t font), - drawString(const char *string, int32_t poX, int32_t poY), - drawCentreString(const char *string, int32_t dX, int32_t poY, uint8_t font), // Deprecated, use setTextDatum() and drawString() - drawRightString(const char *string, int32_t dX, int32_t poY, uint8_t font), // Deprecated, use setTextDatum() and drawString() + // Use with setTextDatum() to position string on TFT, and setTextPadding() to blank old displayed strings + drawString(const char *string, int32_t x, int32_t y, uint8_t font), // Draw string using specifed font number + drawString(const char *string, int32_t x, int32_t y), // Draw string using current font + drawString(const String& string, int32_t x, int32_t y, uint8_t font),// Draw string using specifed font number + drawString(const String& string, int32_t x, int32_t y), // Draw string using current font - // Handle String type - drawString(const String& string, int32_t poX, int32_t poY, uint8_t font), - drawString(const String& string, int32_t poX, int32_t poY), - drawCentreString(const String& string, int32_t dX, int32_t poY, uint8_t font), // Deprecated, use setTextDatum() and drawString() - drawRightString(const String& string, int32_t dX, int32_t poY, uint8_t font); // Deprecated, use setTextDatum() and drawString() + drawCentreString(const char *string, int32_t x, int32_t y, uint8_t font), // Deprecated, use setTextDatum() and drawString() + drawRightString(const char *string, int32_t x, int32_t y, uint8_t font), // Deprecated, use setTextDatum() and drawString() + drawCentreString(const String& string, int32_t x, int32_t y, uint8_t font),// Deprecated, use setTextDatum() and drawString() + drawRightString(const String& string, int32_t x, int32_t y, uint8_t font); // Deprecated, use setTextDatum() and drawString() - int16_t textWidth(const char *string, uint8_t font), - textWidth(const char *string), - textWidth(const String& string, uint8_t font), - textWidth(const String& string), - fontHeight(int16_t font), - fontHeight(void); + // Text rendering and font handling support funtions + void setCursor(int16_t x, int16_t y), // Set cursor for tft.print() + setCursor(int16_t x, int16_t y, uint8_t font); // Set cursor and font number for tft.print() - void setAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); + 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) - // Compatibility additions - void startWrite(void); // Begin SPI transaction - void writeColor(uint16_t color, uint32_t len); // Write colours without transaction overhead Deprecated, use pushBlock() - void endWrite(void); // End SPI transaction + void setTextWrap(bool wrapX, bool wrapY = false); // Turn on/off wrapping of text in TFT width and/or height - uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining); - uint16_t decodeUTF8(uint8_t c); - uint16_t alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc); + void setTextDatum(uint8_t datum); // Set text datum position (default is top left), see Section 6 above + uint8_t getTextDatum(void); - size_t write(uint8_t); + void setTextPadding(uint16_t x_width); // Set text padding (background blanking/over-write) width in pixels -#ifdef TFT_SDA_READ - #if defined (TFT_eSPI_ENABLE_8_BIT_READ) - uint8_t tft_Read_8(void); - #endif - void begin_SDA_Read(void); - void end_SDA_Read(void); +#ifdef LOAD_GFXFF + void setFreeFont(const GFXfont *f = NULL), // Select the GFX Free Font + setTextFont(uint8_t font); // Set the font number to use in future +#else + void setFreeFont(uint8_t font), // Not used, historical fix to prevent an error + setTextFont(uint8_t font); // Set the font number to use in future #endif - // Set or get an arbitrary library attribute or configuration option - void setAttribute(uint8_t id = 0, uint8_t a = 0); - uint8_t getAttribute(uint8_t id = 0); + int16_t textWidth(const char *string, uint8_t font), // Returns pixel width of string in specified font + textWidth(const char *string), // Returns pixel width of string in current font + textWidth(const String& string, uint8_t font), // As above for String types + textWidth(const String& string), + fontHeight(int16_t font), // Returns pixel height of string in specified font + fontHeight(void); // Returns pixel width of string in current font + // Used by library and Smooth font class to extract Unicode point codes from a UTF8 encoded string + uint16_t decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining), + decodeUTF8(uint8_t c); + + // 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); + + uint16_t fontsLoaded(void); // Each bit in returned value represents a font type that is loaded - used for debug/error handling only + + // Low level read/write + void spiwrite(uint8_t); // legacy support only + + void writecommand(uint8_t c), // Send a command, function resets DC/RS high ready for data + writedata(uint8_t d); // Send data with DC/RS set high + + void commandList(const uint8_t *addr); // Send a initialisation sequence to TFT stored in FLASH + + uint8_t readcommand8( uint8_t cmd_function, uint8_t index = 0); // read 8 bits from TFT + uint16_t readcommand16(uint8_t cmd_function, uint8_t index = 0); // read 16 bits from TFT + uint32_t readcommand32(uint8_t cmd_function, uint8_t index = 0); // read 32 bits from TFT + + + // Colour conversion + // Convert 8 bit red, green and blue to 16 bits + uint16_t color565(uint8_t red, uint8_t green, uint8_t blue); + + // Convert 8 bit colour to 16 bits + uint16_t color8to16(uint8_t color332); + // Convert 16 bit colour to 8 bits + uint8_t color16to8(uint16_t color565); + + // 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); + + + // DMA support functions - these are currently just for SPI writes whe using the STM32 processors + // Bear in mind DMA will only be of benefit in particular circumstances and can be tricky + // to manage by noobs. The functions have however been designed to be noob friendly and + // avoid a few DMA behaviour "gotchas". + // + // At best you will get a 2x TFT rendering performance improvement when using DMA because + // this library handles the SPI bus so efficiently during normal (non DMA) transfers. The best + // performance improvement scenario is the DMA transfer time is exactly the same as the time it + // takes for the processor to prepare the next image buffer and initiate another DMA transfer. + // + // DMA transfer to the TFT is done while the processor moves on to handle other tasks. Bear + // this in mind and watch out for "gotchas" like the image buffer going out of scope as the + // processor leaves a function or its content being changed while the DMA engine is reading it. + // + // The compiler MAY change the implied scope of a buffer which has been set aside by creating + // and an array. For example a buffer defined before a "for-next" loop may get de-allocated when + // the loop ends. To avoid this use, for example, malloc() and free() to take control of when + // the buffer space is available and ensure it is not released until DMA is complete. + // + // Clearly you should not modify a buffer that is being DMA'ed to the TFT until the DMA is over. + // Use the dmaBusy() function to check this. Use tft.startWrite() before invoking DMA so the + // TFT chip select stays low. If you use tft.endWrite() before DMA is complete then the endWrite + // function will wait for the DMA to complete, so this may defeat any DMA performance benefit. + // + + bool initDMA(void); // Initialise the DMA engine and attach to SPI bus - typically used in setup() + 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 + // in the original data image will be swapped by the function before DMA is initiated. + // The function will wait for the last DMA to complete if it is called while a previous DMA is still + // in progress, this simplifies the sketch and helps avoid "gotchas". + void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* data, uint16_t* buffer = nullptr); + + // Push a block of pixels into a window set up using setAddrWindow() + void pushPixelsDMA(uint16_t* image, uint32_t len); + + // Check if the DMA is complete - use while(tft.dmaBusy); for a blocking wait + bool dmaBusy(void); + + bool DMA_Enabled = false; // Flag for DMA enabled state + + + // Bare metal functions + void startWrite(void); // Begin SPI transaction + void writeColor(uint16_t color, uint32_t len); // Deprecated, use pushBlock() + void endWrite(void); // End SPI transaction + + // Set/get an arbitrary library configuration attribute or option + // Use to switch ON/OFF capabilities such as UTF8 decoding - each attribute has a unique ID + // id = 0: reserved - may be used in fuuture to reset all attributes to a default state + // id = 1: Turn on (a=true) or off (a=false) GLCD cp437 font character error correction + // id = 2: Turn on (a=true) or off (a=false) UTF8 decoding + #define CP437_SWITCH 1 + #define UTF8_SWITCH 2 + void setAttribute(uint8_t id = 0, uint8_t a = 0); // Set attribute value + uint8_t getAttribute(uint8_t id = 0); // Get attribute value + + // Used for diagnostic sketch to see library setup adopted by compiler, see Section 7 above void getSetup(setup_t& tft_settings); // Sketch provides the instance to populate - // DMA support functions - bool initDMA(void); - void deInitDMA(void); - void pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* data, uint16_t* buffer = nullptr); - //void pushBlockDMA(uint16_t color, uint32_t len); - void pushPixelsDMA(uint16_t* image, uint32_t len); - bool dmaBusy(void); - bool DMA_Enabled = false; + // Global variables + static SPIClass& getSPIinstance(void); // Get SPI class handle - static SPIClass& getSPIinstance(void); + int32_t cursor_x, cursor_y, padX; // Text cursor x,y and padding setting + uint32_t textcolor, textbgcolor; // Text foreground and background colours - int32_t cursor_x, cursor_y, padX; - uint32_t textcolor, textbgcolor; + uint32_t bitmap_fg, bitmap_bg; // Bitmap foreground (bit=1) and background (bit=0) colours - uint32_t bitmap_fg, bitmap_bg; - - uint8_t textfont, // Current selected font + uint8_t textfont, // Current selected font number textsize, // Current font size multiplier textdatum, // Text reference datum rotation; // Display rotation (0-3) - int16_t _xpivot; // x pivot point coordinate - int16_t _ypivot; // x pivot point coordinate + 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 - uint16_t decoderBuffer; // Unicode code-point buffer + 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();} - inline void spi_begin() __attribute__((always_inline)); - inline void spi_end() __attribute__((always_inline)); + void spi_begin_read() {begin_tft_read(); } + void spi_end_read() { end_tft_read(); } - inline void spi_begin_read() __attribute__((always_inline)); - inline void spi_end_read() __attribute__((always_inline)); + // New begin and end prototypes + // begin/end a TFT write transaction + // For SPI bus the transmit clock rate is set + inline void begin_tft_write() __attribute__((always_inline)); + inline void end_tft_write() __attribute__((always_inline)); - // Private function, sketches must use pushPixels() with setSwapBytes(true) + // begin/end a TFT read transaction + // For SPI bus begin lowers SPI clock rate, end reinstates transmit clock rate + inline void begin_tft_read() __attribute__((always_inline)); + inline void end_tft_read() __attribute__((always_inline)); + + // Temporary library development function TODO: remove need for this void pushSwapBytePixels(const void* data_in, uint32_t len); + // Same as setAddrWindow but exits with CGRAM in read mode void readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h); - // Byte read prototype + // Byte read prototype uint8_t readByte(void); - // GPIO parallel input/output control + // GPIO parallel bus input/output direction control void busDir(uint32_t mask, uint8_t mode); - // Single GPIO input/output direction control + // Single GPIO input/output direction control void gpioMode(uint8_t gpio, uint8_t mode); - uint8_t tabcolor, - colstart = 0, rowstart = 0; // some ST7735 displays need this changed + // Display variant settings + uint8_t tabcolor, // ST7735 screen protector "tab" colour (now invalid) + colstart = 0, rowstart = 0; // Screen display area to CGRAM area coordinate offsets + // Port and pin masks for control signals (ESP826 only) - TODO: remove need for this volatile uint32_t *dcport, *csport; - uint32_t cspinmask, dcpinmask, wrpinmask, sclkpinmask; -#if defined(ESP32_PARALLEL) - uint32_t xclr_mask, xdir_mask, xset_mask[256]; -#endif + #if defined(ESP32_PARALLEL) + // Bit masks for ESP32 parallel bus interface + uint32_t xclr_mask, xdir_mask; // Port set/clear and direction control masks - uint32_t lastColor = 0xFFFF; + // Lookup table for ESP32 parallel bus interface uses 1kbyte RAM, + uint32_t xset_mask[256]; // Makes Sprite rendering test 33% faster, for slower macro equivalent + // see commented out #define set_mask(C) within TFT_eSPI_ESP32.h + #endif - getColorCallback getColor = nullptr; + //uint32_t lastColor = 0xFFFF; // Last colour - used to minimise bit shifting overhead + getColorCallback getColor = nullptr; // Smooth font callback function pointer + + //-------------------------------------- protected ----------------------------------// protected: - int32_t win_xe, win_ye; + //int32_t win_xe, win_ye; // Window end coords - not needed int32_t _init_width, _init_height; // Display w/h as input, used by setRotation() int32_t _width, _height; // Display w/h as modified by current rotation - int32_t addr_row, addr_col; + int32_t addr_row, addr_col; // Window position - used to minimise window commands - uint32_t fontsloaded; + uint32_t fontsloaded; // Bit field of fonts loaded - uint8_t glyph_ab, // glyph delta Y (height) above baseline - glyph_bb; // glyph delta Y (height) below baseline + uint8_t glyph_ab, // Smooth font glyph delta Y (height) above baseline + glyph_bb; // Smooth font glyph delta Y (height) below baseline bool isDigits; // adjust bounding box for numbers to reduce visual jiggling - bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display + bool textwrapX, textwrapY; // If set, 'wrap' text at right and optionally bottom edge of display bool _swapBytes; // Swap the byte order for TFT pushImage() - bool locked, inTransaction; // Transaction and mutex lock flags + bool locked, inTransaction; // 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) @@ -580,22 +733,28 @@ class TFT_eSPI : public Print { GFXfont *gfxFont; #endif +/*************************************************************************************** +** Section 9: TFT_eSPI class conditional extensions +***************************************************************************************/ // Load the Touch extension #ifdef TOUCH_CS - #include "Extensions/Touch.h" + #include "Extensions/Touch.h" // Loaded if TOUCH_CS is defined by user #endif // Load the Anti-aliased font extension #ifdef SMOOTH_FONT - #include "Extensions/Smooth_font.h" + #include "Extensions/Smooth_font.h" // Loaded if SMOOTH_FONT is defined by user #endif }; // End of class TFT_eSPI +/*************************************************************************************** +** Section 10: Additional extension classes +***************************************************************************************/ // Load the Button Class #include "Extensions/Button.h" // Load the Sprite Class #include "Extensions/Sprite.h" -#endif +#endif // ends #ifndef _TFT_eSPIH_ diff --git a/User_Setup_Select.h b/User_Setup_Select.h index ca0dc37..80adf83 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -55,6 +55,11 @@ //#include // ESP32 RPi MHS-4.0 inch Display-B //#include // ESP8266 RPi MHS-4.0 inch Display-B +//#include // Setup for Nucleo board +//#include // Setup for Nucleo board and parallel display +//#include // Setup for Nucleo board and parallel display +//#include // Setup for "Blue Pill" + //#include // Setup file configured for my ST7735S 80x160 //#include // Setup file for ESP8266 and ST7789 135 x 240 TFT @@ -69,7 +74,7 @@ ///////////////////////////////////////////////////////////////////////////////////// // // // DON'T TINKER WITH ANY OF THE FOLLOWING LINES, THESE ADD THE TFT DRIVERS // -// AND ESP8266 PIN DEFINITONS THEY ARE HERE FOR BODMER'S CONVENIENCE! // +// AND ESP8266 PIN DEFINITONS, THEY ARE HERE FOR BODMER'S CONVENIENCE! // // // ///////////////////////////////////////////////////////////////////////////////////// @@ -78,6 +83,23 @@ #define TFT_BGR 0 // Colour order Blue-Green-Red #define TFT_RGB 1 // Colour order Red-Green-Blue +// Legacy setup support, RPI_DISPLAY_TYPE replaces RPI_DRIVER +#if defined (RPI_DRIVER) + #if !defined (RPI_DISPLAY_TYPE) + #define RPI_DISPLAY_TYPE + #endif +#endif + +// Legacy setup support, RPI_ILI9486_DRIVER form is deprecated +// Instead define RPI_DISPLAY_TYPE and also define driver (e.g. ILI9486_DRIVER) +#if defined (RPI_ILI9486_DRIVER) + #if !defined (ILI9486_DRIVER) + #define ILI9486_DRIVER + #endif + #if !defined (RPI_DISPLAY_TYPE) + #define RPI_DISPLAY_TYPE + #endif +#endif // Load the right driver definition - do not tinker here ! #if defined (ILI9341_DRIVER) @@ -93,11 +115,8 @@ #include #define TFT_DRIVER 0x6D02 #elif defined (ST7796_DRIVER) - #include "TFT_Drivers/ST7796_Defines.h" - #define TFT_DRIVER 0x7796 -#elif defined (RPI_ILI9486_DRIVER) - #include - #define TFT_DRIVER 0x9486 + #include "TFT_Drivers/ST7796_Defines.h" + #define TFT_DRIVER 0x7796 #elif defined (ILI9486_DRIVER) #include #define TFT_DRIVER 0x9486 @@ -125,7 +144,9 @@ #elif defined (RM68140_DRIVER) #include "TFT_Drivers/RM68140_Defines.h" #define TFT_DRIVER 0x6814 -#elif defined (XYZZY_DRIVER) // <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE + // <<<<<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVER HERE + // XYZZY_init.h and XYZZY_rotation.h must also be added in TFT_eSPI.c +#elif defined (XYZZY_DRIVER) #include "TFT_Drivers/XYZZY_Defines.h" #define TFT_DRIVER 0x0000 #else diff --git a/User_Setups/Setup10_RPi_touch_ILI9486.h b/User_Setups/Setup10_RPi_touch_ILI9486.h index ffe2f71..045c21c 100644 --- a/User_Setups/Setup10_RPi_touch_ILI9486.h +++ b/User_Setups/Setup10_RPi_touch_ILI9486.h @@ -2,9 +2,8 @@ #define RPI_ILI9486_DRIVER // 20MHz maximum SPI - // For NodeMCU - use pin numbers in the form PIN_Dx where Dx is the NodeMCU pin designation -#define TFT_CS PIN_D8 // Chip select control pin D8 +#define TFT_CS PIN_D2 // Chip select control pin D2 #define TFT_DC PIN_D3 // Data Command control pin #define TFT_RST PIN_D4 // Reset pin (could connect to NodeMCU RST, see next line) //#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to NodeMCU RST or 3.3V diff --git a/User_Setups/Setup31_ST7796_Parallel_STM32.h b/User_Setups/Setup31_ST7796_Parallel_STM32.h new file mode 100644 index 0000000..cd0cd42 --- /dev/null +++ b/User_Setups/Setup31_ST7796_Parallel_STM32.h @@ -0,0 +1,52 @@ + /////////////////////////////////////////////////// + // Setup for Nucleo-F446/767 and ILI9341 display // + /////////////////////////////////////////////////// + +// See SetupX_Template.h for all options available + +// Define STM32 to invoke optimised processor support +#define STM32 + +// Defining the board allows the library to optimise the performance +// for UNO compatible "MCUfriend" style shields +#define NUCLEO_64_TFT +//#define NUCLEO_144_TFT + +// Tell the library to use 8 bit parallel mode(otherwise SPI is assumed) +#define TFT_PARALLEL_8_BIT + +// Define the display driver chip type +#define ST7796_DRIVER +//#define ILI9481_DRIVER + +// Define the Nucleo 64/144 pins used for the parallel interface TFT +// The pins can be changed here but these are the ones used by the +// common "MCUfriend" shields +#define TFT_CS A3 // Chip select control pin +#define TFT_DC A2 // Data Command control pin +#define TFT_RST A4 // Reset pin + +#define TFT_WR A1 // Write strobe control pin +#define TFT_RD A0 // Read pin + +#define TFT_D0 D8 // 8 bit parallel bus to TFT +#define TFT_D1 D9 +#define TFT_D2 D2 +#define TFT_D3 D3 +#define TFT_D4 D4 +#define TFT_D5 D5 +#define TFT_D6 D6 +#define TFT_D7 D7 + +// Fonts to be available +#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_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +// At the moment SMOOTH fonts must be disabled for STM32 processors (due to lack of SPIFFS) +// Support for smooth fonts via SD cards is planned. +//#define SMOOTH_FONT diff --git a/User_Setups/Setup32_ILI9341_STM32F103.h b/User_Setups/Setup32_ILI9341_STM32F103.h new file mode 100644 index 0000000..265903a --- /dev/null +++ b/User_Setups/Setup32_ILI9341_STM32F103.h @@ -0,0 +1,62 @@ + /////////////////////////////////////////////////// + // Setup for Nucleo-F446/767 and ILI9341 display // + /////////////////////////////////////////////////// + +// Last update by Bodmer: 14/1/20 + +// Define STM32 to invoke STM32 optimised driver (optimised fns only tested on STM32F767 so far) +// so you may need to comment this out +#define STM32 + +// Define the TFT display driver +#define ILI9341_DRIVER +//#define ILI9481_DRIVER + +// MOSI and SCK do not need to be defined, connect: +// - Arduino SCK (Blue Pill pin A5) to TFT SCK +// - Arduino MOSI (Blue Pill pin A7) to TFT SDI (may be marked SDA or MOSI) +// - Optional to read TFT: Arduino MISO (Blue Pill pin A6) to TFT SDO (may be marked MISO or may not exist on TFT) +// Note: not all TFT's support reads + +// reminder: Blue Pill SPI pins are SCK=A5, MISO = A6, MOSI=A7 + +// Can use Ardiuno pin references, arbitrary allocation, TFT_eSPI controls chip select +#define TFT_CS A0 // Chip select control pin to TFT CS +#define TFT_DC A1 // Data Command control pin to TFT DC (may be labelled RS = Register Select) +#define TFT_RST A2 // Reset pin to TFT RST (or RESET) + +//#define TFT_RST -1 // Set TFT_RST to -1 if the display RESET is connected to processor reset + // Use an Arduino pin for initial testing as connecting to processor reset + // may not work (due to variations in display design) + +#define TOUCH_CS A4 // Connect to T_CS (Touch controller chip select) if XPT2046 is connected to SPI bus + // You may need to wire the touch controller to the processor in addition to the TFT + // For example on some boards the pins are labelled: + // T_IRQ - no connection to processor + // T_DO - connect to processor MISO + // T_DIN - connect to processor MOSI + // T_CS - connect to processor pin specified by TOUCH_CS above + // T_SCK - connect to processor SCK +//* +#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_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts +//*/ +// At the moment SMOOTH fonts MUST be disabled for STM32 processors (due to lack of SPIFFS) +// Support for smooth fonts via SD cards is planned. +//#define SMOOTH_FONT // Must be commented out for STM32 + +// Assuming the processor clock is 72MHz: +#define SPI_FREQUENCY 36000000 // 36MHz SPI clock +//#define SPI_FREQUENCY 18000000 // 18MHz SPI clock + +#define SPI_READ_FREQUENCY 12000000 // Reads need a slower SPI clock + +#define SPI_TOUCH_FREQUENCY 2500000 // Must be very slow + +// This has no effect, transactions are automatically enabled for STM32 +//#define SUPPORT_TRANSACTIONS diff --git a/examples/Generic/alphaBlend_Test/alphaBlend_Test.ino b/examples/Generic/alphaBlend_Test/alphaBlend_Test.ino new file mode 100644 index 0000000..f3f4cdf --- /dev/null +++ b/examples/Generic/alphaBlend_Test/alphaBlend_Test.ino @@ -0,0 +1,194 @@ +/* + 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/examples/Sprite/Sprite_drawPixel/Sprite_drawPixel.ino b/examples/Sprite/Sprite_draw/Sprite_draw.ino similarity index 100% rename from examples/Sprite/Sprite_drawPixel/Sprite_drawPixel.ino rename to examples/Sprite/Sprite_draw/Sprite_draw.ino diff --git a/examples/Sprite/Sprite_colorMap/Sprite_colorMap.ino b/examples/Sprite/Sprite_draw_4bit/Sprite_draw_4bit.ino similarity index 59% rename from examples/Sprite/Sprite_colorMap/Sprite_colorMap.ino rename to examples/Sprite/Sprite_draw_4bit/Sprite_draw_4bit.ino index fc7b9e8..40d9fc1 100644 --- a/examples/Sprite/Sprite_colorMap/Sprite_colorMap.ino +++ b/examples/Sprite/Sprite_draw_4bit/Sprite_draw_4bit.ino @@ -1,9 +1,16 @@ /* - - Sketch to show how a Sprite is created, how to draw pixels + Sketch to show how a 4 bit Sprite is created, how to draw pixels and text within the Sprite and then push the Sprite onto the display screen. + The advantage of 4 bit sprites is: + 1. Small memory footprint + 2. Any set of 16 colours can be specified + 3. Colours can be changed without redrawing in Sprite + 4. Simple animations like flashing text can be achieved + by colour palette cycling and pushing sprite to TFT: + https://en.wikipedia.org/wiki/Color_cycling + Example for library: https://github.com/Bodmer/TFT_eSPI @@ -14,14 +21,7 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 16 bit Sprite occupies (2 * width * height) bytes in RAM. - - On a ESP8266 Sprite sizes up to 126 x 160 can be accomodated, - this size requires 40kBytes of RAM for a 16 bit color depth. - - When 8 bit color depth sprites are created they occupy - (width * height) bytes in RAM, so larger sprites can be - created, or the RAM required is halved. + A 4 bit Sprite occupies (width * height)/2 bytes in RAM. */ @@ -41,14 +41,15 @@ TFT_eSprite spr = TFT_eSprite(&tft); // Declare Sprite object "spr" with pointe void setup() { - Serial.begin(250000); + Serial.begin(115200); Serial.println(); delay(500); // Initialise the TFT registers tft.init(); - + + // Set the sprite colour depth to 4 spr.setColorDepth(4); // Create a sprite of defined size @@ -60,89 +61,72 @@ void setup() void loop(void) { - // Fill the whole sprite with color 5 (Sprite is in memory so not visible yet) - spr.fillSprite(10); + // Fill the whole sprite with color 0 (Sprite is in memory so not visible yet) + spr.fillSprite(0); - // create a color map with known colors + // create a color map with known colors (16 maximum for 4 bit Sprite uint16_t cmap[16]; - cmap[0] = TFT_BLACK; - cmap[1] = TFT_NAVY; - cmap[2] = TFT_DARKGREEN; - cmap[3] = TFT_DARKCYAN; - cmap[4] = TFT_MAROON; - cmap[5] = TFT_PURPLE; - cmap[6] = TFT_OLIVE; - cmap[7] = TFT_LIGHTGREY; - cmap[8] = TFT_DARKGREY; - cmap[9] = TFT_BLUE; + cmap[0] = TFT_BLACK; // We will keep this as black + cmap[1] = TFT_NAVY; + cmap[2] = TFT_DARKGREEN; + cmap[3] = TFT_DARKCYAN; + cmap[4] = TFT_MAROON; + cmap[5] = TFT_PURPLE; + cmap[6] = TFT_PINK; + cmap[7] = TFT_LIGHTGREY; + cmap[8] = TFT_YELLOW; + cmap[9] = TFT_BLUE; cmap[10] = TFT_GREEN; cmap[11] = TFT_CYAN; cmap[12] = TFT_RED; cmap[13] = TFT_MAGENTA; - cmap[14] = TFT_YELLOW; - cmap[15] = TFT_WHITE; + cmap[14] = TFT_WHITE; // Keep as white for text + cmap[15] = TFT_BLUE; // Keep as blue for sprite border - spr.createPalette(cmap, 16); - + // Pass the palette to the Sprite class + spr.createPalette(cmap); + + // Push Sprite parially off-screen to test cropping spr.pushSprite(-40, -40); spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2, 10); spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40); // Number of pixels to draw uint16_t n = 100; + // Draw 100 random color pixels at random positions in sprite while (n--) { - uint16_t color = random(0x10); // Returns color 0 - 0x0F - int16_t x = random(WIDTH); // Random x coordinate - int16_t y = random(HEIGHT); // Random y coordinate - spr.drawPixel( x, y, color); // Draw pixel in sprite + uint16_t color = random(0x10); // Returns color 0 - 0x0F (i.e. 0-15) + int16_t x = random(WIDTH); // Random x coordinate + int16_t y = random(HEIGHT); // Random y coordinate + spr.drawPixel(x, y, color); // Draw pixel in sprite } - spr.pushSprite(-40, -40); - spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2); - spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40); - - delay(DELAY); - // Draw some lines - spr.drawLine(1, 0, WIDTH, HEIGHT-1, 6); - spr.drawLine(0, 0, WIDTH, HEIGHT, 6); - spr.drawLine(0, 1, WIDTH-1, HEIGHT, 2); - spr.drawLine(0, HEIGHT-1, WIDTH-1, 0, 2); - spr.drawLine(0, HEIGHT, WIDTH, 0, 3); - spr.drawLine(1, HEIGHT, WIDTH, 1, 3); - spr.drawLine(4, 0, 4, HEIGHT-1, 11); - spr.drawLine(0, 16, WIDTH-1, 16, 13); - - // draw some circles with random colors. - spr.drawCircle(20, 60, 10, 6); - spr.drawCircle(80, 60, 15, 7); - spr.drawCircle(50, 108, 5, 9); - spr.drawCircle(45, 86, 3, 8); - spr.fillCircle(102, 56, 4, 11); - - spr.fillRect(28, 32, 40, 4, 5); - //spr.fillRect(27, 42, 40, 14, 6); - //spr.fillRect(33, 55, 3, 4, 7); - //spr.fillRect(34, 32, 7, 4, 8); + spr.drawLine(1, 0, WIDTH, HEIGHT-1, 10); + spr.drawLine(0, 0, WIDTH, HEIGHT, 10); + spr.drawLine(0, 1, WIDTH-1, HEIGHT, 10); + spr.drawLine(0, HEIGHT-1, WIDTH-1, 0, 12); + spr.drawLine(0, HEIGHT, WIDTH, 0, 12); + spr.drawLine(1, HEIGHT, WIDTH, 1, 12); // Draw some text with Middle Centre datum spr.setTextDatum(MC_DATUM); - spr.drawString("Sprite", WIDTH / 2, HEIGHT / 2, 1); + spr.setTextColor(14); // White text + spr.drawString("Sprite", WIDTH / 2, HEIGHT / 2, 4); - // Now push the sprite to the TFT at position 0,0 on screen + // Now push the sprite to the TFT at 3 positions on screen spr.pushSprite(-40, -40); spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2); spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40); delay(DELAY * 4); - // create a new color map and use it instead - - for (auto i = 0; i < 16; i++) + // create a new color map for colours 1-13 and use it instead + for (auto i = 1; i <= 13; i++) { cmap[i] = random(0x10000); } @@ -161,10 +145,9 @@ void loop(void) // Draw a blue rectangle in sprite so when we move it 1 pixel it does not leave a trail // on the blue screen background - cmap[14] = TFT_BLUE; - spr.createPalette(cmap, 16); + spr.createPalette(cmap); - spr.drawRect(0, 0, WIDTH, HEIGHT, 14); + spr.drawRect(0, 0, WIDTH, HEIGHT, 15); // Blue rectangle int x = tft.width() / 2 - WIDTH / 2; int y = tft.height() / 2 - HEIGHT / 2; @@ -183,7 +166,15 @@ void loop(void) if (y < -HEIGHT/2) dy = 1; if (y >= tft.height()-HEIGHT/2) dy = -1; - // Draw it 50 time, moving in random direct or staying still + // Randomise the palette to change colours without redrawing + // the sprite + for (auto i = 1; i <= 13; i++) + { + cmap[i] = random(0x10000); + } + spr.createPalette(cmap); // Update sprite class palette + + // Draw it 50 times, moving in random direct or staying still n = 50; int wait = random (50); while (n) @@ -205,4 +196,3 @@ void loop(void) } } // Infinite while, will not exit! } - diff --git a/examples/Sprite/Sprite_scroll_cmap/Sprite_scroll_cmap.ino b/examples/Sprite/Sprite_scroll_4bit/Sprite_scroll_4bit.ino similarity index 74% rename from examples/Sprite/Sprite_scroll_cmap/Sprite_scroll_cmap.ino rename to examples/Sprite/Sprite_scroll_4bit/Sprite_scroll_4bit.ino index 3c32813..eb063ca 100644 --- a/examples/Sprite/Sprite_scroll_cmap/Sprite_scroll_cmap.ino +++ b/examples/Sprite/Sprite_scroll_4bit/Sprite_scroll_4bit.ino @@ -1,7 +1,7 @@ /* - Sketch to show scrolling of the graphics in sprites. + Sketch to show scrolling of the graphics in 4 bit sprites. Scrolling in this way moves the pixels in a defined rectangle - within the Sprite. By defalt the whole sprite is scrolled. + within the Sprite. By default the whole sprite is scrolled. The gap left by scrolling is filled with a defined colour. Example for library: @@ -14,10 +14,7 @@ any position. If there is sufficient RAM then the Sprite can be the same size as the screen and used as a frame buffer. - A 16 bit Sprite occupies (2 * width * height) bytes in RAM. - - An 8 bit Sprite occupies (width * height) bytes in RAM. - + A 4 bit Sprite occupies (width * height)/2 bytes in RAM. */ #include @@ -35,7 +32,8 @@ int delta = 1; int grid = 0; int tcount = 0; -uint16_t cmap[16]; +// Palette colour table +uint16_t palette[16]; //========================================================================================== void setup() { @@ -43,47 +41,49 @@ void setup() { tft.init(); tft.fillScreen(TFT_BLACK); - cmap[0] = TFT_BLACK; - cmap[1] = TFT_ORANGE; - cmap[2] = TFT_DARKGREEN; - cmap[3] = TFT_DARKCYAN; - cmap[4] = TFT_MAROON; - cmap[5] = TFT_PURPLE; - cmap[6] = TFT_OLIVE; - cmap[7] = TFT_DARKGREY; - cmap[8] = TFT_ORANGE; - cmap[9] = TFT_BLUE; - cmap[10] = TFT_GREEN; - cmap[11] = TFT_CYAN; - cmap[12] = TFT_RED; - cmap[13] = TFT_NAVY; - cmap[14] = TFT_YELLOW; - cmap[15] = TFT_WHITE; + // Populate the palette table, table must have 16 entires + palette[0] = TFT_BLACK; + palette[1] = TFT_ORANGE; + palette[2] = TFT_DARKGREEN; + palette[3] = TFT_DARKCYAN; + palette[4] = TFT_MAROON; + palette[5] = TFT_PURPLE; + palette[6] = TFT_OLIVE; + palette[7] = TFT_DARKGREY; + palette[8] = TFT_ORANGE; + palette[9] = TFT_BLUE; + palette[10] = TFT_GREEN; + palette[11] = TFT_CYAN; + palette[12] = TFT_RED; + palette[13] = TFT_NAVY; + palette[14] = TFT_YELLOW; + palette[15] = TFT_WHITE; // Create a sprite for the graph graph1.setColorDepth(4); graph1.createSprite(128, 61); - graph1.createPalette(cmap, 16); - graph1.fillSprite(9); // Note: Sprite is filled with black when created + graph1.createPalette(palette); + graph1.fillSprite(9); // Note: Sprite is filled with palette[0] colour when created // The scroll area is set to the full sprite size upon creation of the sprite // but we can change that by defining a smaller area using "setScrollRect()"if needed // parameters are x,y,w,h,color as in drawRect(), the color fills the gap left by scrolling + //graph1.setScrollRect(64, 0, 64, 61, TFT_DARKGREY); // Try this line to change the graph scroll area // Create a sprite for the scrolling numbers stext1.setColorDepth(4); stext1.createSprite(32, 64); - stext1.createPalette(cmap, 16); - stext1.fillSprite(9); // Fill sprite with blue - stext1.setScrollRect(0, 0, 32, 64, 9); // here we set scroll gap fill color to blue - stext1.setTextColor(15); // White text, no background + stext1.createPalette(palette); + stext1.fillSprite(9); // Fill sprite with palette colour 9 (blue in this example) + stext1.setScrollRect(0, 0, 32, 64, 9); // here we set scroll gap fill color to blue + stext1.setTextColor(15); // Palette colour 15 (white) text, no background stext1.setTextDatum(BR_DATUM); // Bottom right coordinate datum // Create a sprite for Hello World stext2.setColorDepth(4); stext2.createSprite(80, 16); - stext2.createPalette(cmap, 16); + stext2.createPalette(palette); stext2.fillSprite(7); stext2.setScrollRect(0, 0, 40, 16, 7); // Scroll the "Hello" in the first 40 pixels stext2.setTextColor(15); // White text, no background @@ -97,7 +97,7 @@ void loop() { // Draw number in stext1 sprite at 31,63 (bottom right datum set) stext1.drawNumber(graphVal, 31, 63, 2); // plot value in font 2 - // Push the sprites onto the TFT at specied coordinates + // Push the sprites onto the TFT at specified coordinates graph1.pushSprite(0, 0); stext1.pushSprite(0, 64); stext2.pushSprite(40, 70); @@ -132,7 +132,7 @@ void loop() { tcount--; if (tcount <=0) - { // If we have scrolled 40 pixels the redraw text + { // If we have scrolled 40 pixels then redraw text tcount = 40; stext2.drawString("Hello World", 6, 0, 2); // draw at 6,0 in sprite, font 2 } diff --git a/examples/Sprite/Transparent_Sprite_Demo_4bit/Transparent_Sprite_Demo_4bit.ino b/examples/Sprite/Transparent_Sprite_Demo_4bit/Transparent_Sprite_Demo_4bit.ino new file mode 100644 index 0000000..c116ed4 --- /dev/null +++ b/examples/Sprite/Transparent_Sprite_Demo_4bit/Transparent_Sprite_Demo_4bit.ino @@ -0,0 +1,146 @@ +/* + Sketch to show creation of a 4 bit sprite with a transparent + background, then plot it on the TFT. The palette setup and + palette update functions are also shown in this example. + + Example for library: + https://github.com/Bodmer/TFT_eSPI + + A Sprite is notionally an invisible graphics screen that is + kept in the processors RAM. Graphics can be drawn into the + Sprite just as it can be drawn directly to the screen. Once + the Sprite is completed it can be plotted onto the screen in + any position. If there is sufficient RAM then the Sprite can + be the same size as the screen and used as a frame buffer. + + A 4 bit Sprite occupies (width * height)/2 bytes in RAM. + For example the "star" 70x80 Sprite uses 2800 bytes. +*/ + +// This is the default palette for 4 bit colour sprites +// which is built into the library. You can create your +// own palette (use a different array name!). The palette +// is captured and stored in RAM by the Sprite class so a +// copy does not need to be kept in the sketch. + +// The default library palette is stored in FLASH and is called: +// default_4bit_palette +// To edit colours change the default_4bit_palette array name +// at line 32, then edit line 77 to match new name. +// To setup you own palette edit the next line to //* + /* + static const uint16_t default_4bit_palette[] PROGMEM = { + TFT_BLACK, // 0 ^ + TFT_BROWN, // 1 | + TFT_RED, // 2 | + TFT_ORANGE, // 3 | + TFT_YELLOW, // 4 Colours 0-9 follow the resistor colour code! + TFT_GREEN, // 5 | + TFT_BLUE, // 6 | + TFT_PURPLE, // 7 | + TFT_DARKGREY, // 8 | + TFT_WHITE, // 9 v + TFT_CYAN, // 10 Blue+green mix + TFT_MAGENTA, // 11 Blue+red mix + TFT_MAROON, // 12 Darker red colour + TFT_DARKGREEN,// 13 Darker green colour + TFT_NAVY, // 14 Darker blue colour + TFT_PINK // 15 + }; + //*/ + +#include // Include the graphics library (this includes the sprite functions) + +TFT_eSPI tft = TFT_eSPI(); // Create object "tft" + +TFT_eSprite spr = TFT_eSprite(&tft); // Create Sprite object "spr" with pointer to "tft" object +// the pointer is used by pushSprite() to push it onto the TFT + +void setup(void) { + Serial.begin(115200); + + tft.init(); + + tft.setRotation(0); +} + +void loop() { + + tft.fillScreen(TFT_DARKGREY); + + // Set color depth to 4 bits + spr.setColorDepth(4); + spr.createSprite(70, 80); // The Sprite MUST be created before setting the palette! + + // Pass the default library palette to the Sprite class + // Edit palette array name if you use your own palette + spr.createPalette(default_4bit_palette); // <<<<<<<<<<<<<<<<<<<<<<<<< palette array name + + // If <16 colours are defined then specify how many + // spr.createPalette(default_4bit_palette, 12); + + // After rendering a Sprite you can change the palette to increase the range of colours + // plotted to the screen to the full 16 bit set. + + // Change palette colour 11 to violet + spr.setPaletteColor(11, TFT_VIOLET); + + uint16_t color15 = spr.getPaletteColor(15); // The 16 bit colour in a palette can be read back + + // Draw 50 sprites containing a "transparent" colour + for (int i = 0; i < 50; i++) + { + int x = random(tft.width() - 70); + int y = random(tft.height() - 80); + int c = random(15); // Random colour 0-14 (4 bit index into color map). Leave 15 for transparent. + drawStar(x, y, c); + } + + delay(2000); + + // Change the palette to a 16 bit grey scale colour + for (uint8_t i = 0; i < 16; i++) { + // (i*16+i) produces a value in range 0-255 for the RGB colours + // Red Green Blue + spr.setPaletteColor(i, tft.color565(i*16+i, i*16+i, i*16+i)); + } + + // Now go bananas and draw 500 more + for (int i = 0; i < 500; i++) + { + int x = random(tft.width() - 70); + int y = random(tft.height() - 80); + int c = random(0x10); // Random colour + drawStar(x, y, c); + yield(); // Stop watchdog reset + } + + // Delete it to free memory, the Sprite copy of the palette is also deleted + spr.deleteSprite(); + + delay(2000); +} + +// ######################################################################### +// Plot graphics to sprite using defined color and plot to screen +// ######################################################################### +void drawStar(int x, int y, int star_color) +{ + // star_color will be in the range 0-14 so that 15 is reserved for the + // transparent colour + + // Fill Sprite with the chosen "transparent" colour + spr.fillSprite(15); // Fill with color 15 + + // Draw 2 triangles to create a filled in star + spr.fillTriangle(35, 0, 0, 59, 69, 59, star_color); + spr.fillTriangle(35, 79, 0, 20, 69, 20, star_color); + + // Punch a star shaped hole in the middle with a smaller transparent star + spr.fillTriangle(35, 7, 6, 56, 63, 56, 15); + spr.fillTriangle(35, 73, 6, 24, 63, 24, 15); + + // Push sprite to TFT screen at coordinate x,y (top left corner) + // Specify what colour from the palette is treated as transparent. + spr.pushSprite(x, y, 15); +} diff --git a/examples/Sprite/Transparent_Sprite_Demo_Colormap/Transparent_Sprite_Demo_Colormap.ino b/examples/Sprite/Transparent_Sprite_Demo_Colormap/Transparent_Sprite_Demo_Colormap.ino deleted file mode 100644 index 61e9d7d..0000000 --- a/examples/Sprite/Transparent_Sprite_Demo_Colormap/Transparent_Sprite_Demo_Colormap.ino +++ /dev/null @@ -1,168 +0,0 @@ -/* - Sketch to show creation of a sprite with a transparent - background, then plot it on the TFT. - - Example for library: - https://github.com/Bodmer/TFT_eSPI - - A Sprite is notionally an invisible graphics screen that is - kept in the processors RAM. Graphics can be drawn into the - Sprite just as it can be drawn directly to the screen. Once - the Sprite is completed it can be plotted onto the screen in - any position. If there is sufficient RAM then the Sprite can - be the same size as the screen and used as a frame buffer. - - A 16 bit Sprite occupies (2 * width * height) bytes in RAM. - - On a ESP8266 Sprite sizes up to 126 x 160 can be accomodated, - this size requires 40kBytes of RAM for a 16 bit colour depth. - - When 8 bit colour depth sprites are created they occupy - (width * height) bytes in RAM, so larger sprites can be - created, or the RAM required is halved. -*/ - -#include // Include the graphics library (this includes the sprite functions) - -TFT_eSPI tft = TFT_eSPI(); // Create object "tft" - -TFT_eSprite img = TFT_eSprite(&tft); // Create Sprite object "img" with pointer to "tft" object - // the pointer is used by pushSprite() to push it onto the TFT - -TFT_eSprite img2 = TFT_eSprite(&tft); - -void setup(void) { - Serial.begin(250000); - - tft.init(); - - tft.setRotation(0); -} - -void loop() { - - tft.fillScreen(TFT_NAVY); - - img.setColorDepth(4); - - // Draw 10 sprites containing a "transparent" colour - for (int i = 0; i < 10; i++) - { - int x = random(240-70); - int y = random(320-80); - int c = random(0x0F); // Random colour (4 bit index into color map). Leave 15 for transparent. - drawStar(x, y, c); // note: not random; should be c - } - - delay(2000); - - uint32_t dt = millis(); - - // Now go bananas and draw 500 nore - for (int i = 0; i < 500; i++) - { - int x = random(240-70); - int y = random(320-80); - int c = random(0x10); // Random colour - drawStar(x, y, c); - yield(); // Stop watchdog reset - } - - // Show time in milliseconds to draw and then push 1 sprite to TFT screen - numberBox( 10, 10, (millis()-dt)/500.0 ); - delay(2000); - -} - -// ######################################################################### -// Create sprite, plot graphics in it, plot to screen, then delete sprite -// ######################################################################### -void drawStar(int x, int y, int star_color) -{ - // Create an 8 bit sprite 70x 80 pixels (uses 5600 bytes of RAM) - img.setColorDepth(4); - img.createSprite(70, 80); - - uint16_t cmap[16]; - - cmap[0] = TFT_BLACK; - cmap[1] = TFT_ORANGE; - cmap[2] = TFT_DARKGREEN; - cmap[3] = TFT_DARKCYAN; - cmap[4] = TFT_MAROON; - cmap[5] = TFT_PURPLE; - cmap[6] = TFT_OLIVE; - cmap[7] = TFT_LIGHTGREY; - cmap[8] = TFT_DARKGREY; - cmap[9] = TFT_BLUE; - cmap[10] = TFT_GREEN; - cmap[11] = TFT_CYAN; - cmap[12] = TFT_RED; - cmap[13] = TFT_MAGENTA; - cmap[14] = TFT_YELLOW; - cmap[15] = TFT_WHITE; // this one will be transparent. - - img.createPalette(cmap, 16); - - // Fill Sprite with a "transparent" colour - // TFT_TRANSPARENT is already defined for convenience - // We could also fill with any colour as "transparent" and later specify that - // same colour when we push the Sprite onto the screen. - img.fillSprite(15); - - // Draw 2 triangles to create a filled in star - img.fillTriangle(35, 0, 0,59, 69,59, star_color); - img.fillTriangle(35,79, 0,20, 69,20, star_color); - - // Punch a star shaped hole in the middle with a smaller transparent star - // this one damages on pixel in the second triangle - img.fillTriangle(35, 7, 6,56, 63,56, 15); - img.fillTriangle(35,73, 6,24, 63,24, 15); - - // Push sprite to TFT screen at coordinate x,y (top left corner) - // Specify what colour from the map is to be treated as transparent. - img.pushSprite(x, y, 15); - - // Delete it to free memory - img.deleteSprite(); -} - -// ######################################################################### -// Draw a number in a rounded rectangle with some transparent pixels -// ######################################################################### -void numberBox(int x, int y, float num ) -{ - - // Size of sprite - #define IWIDTH 80 - #define IHEIGHT 35 - - // Create a 8 bit sprite 80 pixels wide, 35 high (2800 bytes of RAM needed) - img.setColorDepth(8); - img.createSprite(IWIDTH, IHEIGHT); - - // Fill it with black (this will be the transparent colour this time) - img.fillSprite(TFT_BLACK); - - // Draw a background for the numbers - img.fillRoundRect( 0, 0, 80, 35, 15, TFT_RED); - img.drawRoundRect( 0, 0, 80, 35, 15, TFT_WHITE); - - // Set the font parameters - img.setTextSize(1); // Font size scaling is x1 - img.setTextColor(TFT_WHITE); // White text, no background colour - - // Set text coordinate datum to middle right - img.setTextDatum(MR_DATUM); - - // Draw the number to 3 decimal places at 70,20 in font 4 - img.drawFloat(num, 3, 70, 20, 4); - - // Push sprite to TFT screen CGRAM at coordinate x,y (top left corner) - // All black pixels will not be drawn hence will show as "transparent" - img.pushSprite(x, y, TFT_BLACK); - - // Delete sprite to free up the RAM - img.deleteSprite(); -} - diff --git a/library.json b/library.json index c8fa582..7559741 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "1.5.0", + "version": "2.0.0", "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 7045552..4baea5e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=1.5.0 +version=2.0.0 author=Bodmer maintainer=Bodmer sentence=TFT graphics library for Arduino processors with performance optimisation for STM32, ESP8266 and ESP32 diff --git a/license.txt b/license.txt index ba20042..32d1df9 100644 --- a/license.txt +++ b/license.txt @@ -105,7 +105,7 @@ and is compatible with the GNU GPL. vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvStartvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv Software License Agreement (FreeBSD License) -Copyright (c) 2017 Bodmer (https://github.com/Bodmer) +Copyright (c) 2020 Bodmer (https://github.com/Bodmer) All rights reserved.