mirror of
https://github.com/Bodmer/TFT_eSPI.git
synced 2025-08-09 23:54:43 +02:00
@@ -359,9 +359,13 @@ bool TFT_eSPI::getUnicodeIndex(uint16_t unicode, uint16_t *index)
|
||||
// Expects file to be open
|
||||
void TFT_eSPI::drawGlyph(uint16_t code)
|
||||
{
|
||||
uint16_t fg = textcolor;
|
||||
uint16_t bg = textbgcolor;
|
||||
|
||||
if (code < 0x21)
|
||||
{
|
||||
if (code == 0x20) {
|
||||
//if (fg!=bg) fillRect(cursor_x, cursor_y, gFont.spaceWidth, gFont.yAdvance, bg);
|
||||
cursor_x += gFont.spaceWidth;
|
||||
return;
|
||||
}
|
||||
@@ -377,18 +381,15 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
||||
uint16_t gNum = 0;
|
||||
bool found = getUnicodeIndex(code, &gNum);
|
||||
|
||||
uint16_t fg = textcolor;
|
||||
uint16_t bg = textbgcolor;
|
||||
|
||||
if (found)
|
||||
{
|
||||
|
||||
if (textwrapX && (cursor_x + gWidth[gNum] + gdX[gNum] > _width))
|
||||
if (textwrapX && (cursor_x + gWidth[gNum] + gdX[gNum] > width()))
|
||||
{
|
||||
cursor_y += gFont.yAdvance;
|
||||
cursor_x = 0;
|
||||
}
|
||||
if (textwrapY && ((cursor_y + gFont.yAdvance) >= _height)) cursor_y = 0;
|
||||
if (textwrapY && ((cursor_y + gFont.yAdvance) >= height())) cursor_y = 0;
|
||||
if (cursor_x == 0) cursor_x -= gdX[gNum];
|
||||
|
||||
uint8_t* pbuffer = nullptr;
|
||||
@@ -402,15 +403,17 @@ void TFT_eSPI::drawGlyph(uint16_t code)
|
||||
}
|
||||
#endif
|
||||
|
||||
int16_t xs = 0;
|
||||
uint32_t dl = 0;
|
||||
uint8_t pixel;
|
||||
|
||||
int16_t cy = cursor_y + gFont.maxAscent - gdY[gNum];
|
||||
int16_t cx = cursor_x + gdX[gNum];
|
||||
|
||||
int16_t xs = cx;
|
||||
uint32_t dl = 0;
|
||||
uint8_t pixel;
|
||||
|
||||
startWrite(); // Avoid slow ESP32 transaction overhead for every pixel
|
||||
|
||||
//if (fg!=bg) fillRect(cursor_x, cursor_y, gxAdvance[gNum], gFont.yAdvance, bg);
|
||||
|
||||
for (int y = 0; y < gHeight[gNum]; y++)
|
||||
{
|
||||
#ifdef FONT_FS_AVAILABLE
|
||||
|
@@ -843,9 +843,9 @@ bool TFT_eSprite::pushSprite(int32_t tx, int32_t ty, int32_t sx, int32_t sy, int
|
||||
_tft->pushImage(tx, ty, sw, sh, _img4 + (_iwidth>>1) * _ys, false, _colorMap );
|
||||
else // Render line by line
|
||||
{
|
||||
uint32_t ds = _xs&1; // Odd x start pixel
|
||||
int32_t ds = _xs&1; // Odd x start pixel
|
||||
|
||||
uint32_t de = 0; // Odd x end pixel
|
||||
int32_t de = 0; // Odd x end pixel
|
||||
if ((sw > ds) && (_xe&1)) de = 1;
|
||||
|
||||
uint32_t dm = 0; // Midsection pixel count
|
||||
@@ -877,7 +877,7 @@ bool TFT_eSprite::pushSprite(int32_t tx, int32_t ty, int32_t sx, int32_t sy, int
|
||||
_tft->setWindow(tx, ty, tx+sw-1, ty+sh-1);
|
||||
while (sh--)
|
||||
{
|
||||
for (uint32_t dx = _xs; dx < _xs + sw; dx++) _tft->pushColor(readPixel(dx, _ys));
|
||||
for (int32_t dx = _xs; dx < _xs + sw; dx++) _tft->pushColor(readPixel(dx, _ys));
|
||||
ty++;
|
||||
_ys++;
|
||||
}
|
||||
|
@@ -575,18 +575,18 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
|
||||
// This will clip and also swap bytes if setSwapBytes(true) was called by sketch
|
||||
void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer)
|
||||
{
|
||||
if ((x >= _width) || (y >= _height) || (!DMA_Enabled)) return;
|
||||
if ((x >= _vpW) || (y >= _vpH) || (!DMA_Enabled)) return;
|
||||
|
||||
int32_t dx = 0;
|
||||
int32_t dy = 0;
|
||||
int32_t dw = w;
|
||||
int32_t dh = h;
|
||||
|
||||
if (x < 0) { dw += x; dx = -x; x = 0; }
|
||||
if (y < 0) { dh += y; dy = -y; y = 0; }
|
||||
if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; }
|
||||
if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; }
|
||||
|
||||
if ((x + dw) > _width ) dw = _width - x;
|
||||
if ((y + dh) > _height) dh = _height - y;
|
||||
if ((x + dw) > _vpW ) dw = _vpW - x;
|
||||
if ((y + dh) > _vpH ) dh = _vpH - y;
|
||||
|
||||
if (dw < 1 || dh < 1) return;
|
||||
|
||||
|
@@ -437,18 +437,18 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len)
|
||||
// This will clip and also swap bytes if setSwapBytes(true) was called by sketch
|
||||
void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image, uint16_t* buffer)
|
||||
{
|
||||
if ((x >= _width) || (y >= _height)) return;
|
||||
if ((x >= _vpW) || (y >= _vpH)) return;
|
||||
|
||||
int32_t dx = 0;
|
||||
int32_t dy = 0;
|
||||
int32_t dw = w;
|
||||
int32_t dh = h;
|
||||
|
||||
if (x < 0) { dw += x; dx = -x; x = 0; }
|
||||
if (y < 0) { dh += y; dy = -y; y = 0; }
|
||||
if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; }
|
||||
if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; }
|
||||
|
||||
if ((x + dw) > _width ) dw = _width - x;
|
||||
if ((y + dh) > _height) dh = _height - y;
|
||||
if ((x + dw) > _vpW ) dw = _vpW - x;
|
||||
if ((y + dh) > _vpH ) dh = _vpH - y;
|
||||
|
||||
if (dw < 1 || dh < 1) return;
|
||||
|
||||
|
19
README.md
19
README.md
@@ -2,23 +2,24 @@
|
||||
The Sprite class has been updated to remove an inconsistency for the setSwapBytes() function. Although all the examples are unchanged, user sketches may be affected. If the colors of the sprite change when loading this new version 2.2.16 then it may be necessary to change the swap bytes setting, e.g. for a sprite instance "spr" use either: spr.setSwapBytes(true) or spr.setSwapBytes(false) to correct the colour.
|
||||
|
||||
# News
|
||||
1. A companion library [U8g2_for_TFT_eSPI](https://github.com/Bodmer/U8g2_for_TFT_eSPI) has been created to allow U8g2 library fonts to be used with TFT_eSPI.
|
||||
1. The library now provides a "viewport" capability. See "Viewport_Demo" and "Viewport_graphicstest" examples. When a viewport is defined grpahics will only appear within that window. The coordinate datum by default moves to the top left corner of the viewport, but can optionally remain at top left corner of TFT. The GUIslice library will make use of this feature to spped up the rendering of GUI objects (see #769).
|
||||
|
||||
2. The library now supports SPI DMA transfers for both ESP32 and STM32 processors. The DMA Test examples now work on the ESP32 for SPI displays (excluding RPi type and ILI9488).
|
||||
2. The library now supports SSD1963 based screen, this has been tested on a [480x800 screen](https://www.buydisplay.com/7-tft-screen-touch-lcd-display-module-w-ssd1963-controller-board-mcu) with an ESP32. The interface is 8 bit parallel only as that controller does not support a SPI interface.
|
||||
|
||||
3. A new option has been added for STM32 processors to optimise performance where Port A (or B) pins 0-7 are used for the 8 bit parallel interface data pins 0-7 to the TFT. This gives a dramatic 8 times better rendering performance for the lower clock rate STM32 processors such as the STM32F103 "Blue Pill" or STM411 "Black Pill" since no time consuming data bit manipulation is required. See setup file "User_Setups/Setup35_ILI9341_STM32_Port_Bus.h".
|
||||
3. A companion library [U8g2_for_TFT_eSPI](https://github.com/Bodmer/U8g2_for_TFT_eSPI) has been created to allow U8g2 library fonts to be used with TFT_eSPI.
|
||||
|
||||
4. A new "Animated_dial" example has been added to show how dials can be created using a rotated Sprite for the needle. To run this example the TFT must support reading from the screen RAM. The dial rim and scale is a jpeg image, created using a paint program.
|
||||
4. The library now supports SPI DMA transfers for both ESP32 and STM32 processors. The DMA Test examples now work on the ESP32 for SPI displays (excluding RPi type and ILI9488).
|
||||
|
||||
5. A new option has been added for STM32 processors to optimise performance where Port A (or B) pins 0-7 are used for the 8 bit parallel interface data pins 0-7 to the TFT. This gives a dramatic 8 times better rendering performance for the lower clock rate STM32 processors such as the STM32F103 "Blue Pill" or STM411 "Black Pill" since no time consuming data bit manipulation is required. See setup file "User_Setups/Setup35_ILI9341_STM32_Port_Bus.h".
|
||||
|
||||
6. A new "Animated_dial" example has been added to show how dials can be created using a rotated Sprite for the needle. To run this example the TFT must support reading from the screen RAM. The dial rim and scale is a jpeg image, created using a paint program.
|
||||
|
||||

|
||||
|
||||
5. Anti-aliased (smooth) fonts can now be stored as arrays in FLASH (program) memory. This means that processors such as STM32 that do not have SPIFFS support can use the fonts. The processor must have sufficient FLASH memory to store the fonts used.
|
||||
7. Anti-aliased (smooth) fonts can now be stored as arrays in FLASH (program) memory. This means that processors such as STM32 that do not have SPIFFS support can use the fonts. The processor must have sufficient FLASH memory to store the fonts used.
|
||||
|
||||
6. The Sprite class now supports 4 bits per pixel with a 16 color palette. Three new examples have been added.
|
||||
8. The Sprite class now supports 4 bits per pixel with a 16 color palette. Three new examples have been added.
|
||||
|
||||
7. 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).
|
||||
|
||||
8. 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.
|
||||
|
||||
# TFT_eSPI
|
||||
|
||||
|
535
TFT_eSPI.cpp
535
TFT_eSPI.cpp
@@ -26,6 +26,26 @@
|
||||
#include "Processors/TFT_eSPI_Generic.c"
|
||||
#endif
|
||||
|
||||
// Clipping macro for pushImage
|
||||
#define PI_CLIP \
|
||||
if (_vpOoB) return; \
|
||||
x+= _xDatum; \
|
||||
y+= _yDatum; \
|
||||
\
|
||||
if ((x >= _vpW) || (y >= _vpH)) return; \
|
||||
\
|
||||
int32_t dx = 0; \
|
||||
int32_t dy = 0; \
|
||||
int32_t dw = w; \
|
||||
int32_t dh = h; \
|
||||
\
|
||||
if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; } \
|
||||
if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; } \
|
||||
\
|
||||
if ((x + dw) > _vpW ) dw = _vpW - x; \
|
||||
if ((y + dh) > _vpH ) dh = _vpH - y; \
|
||||
\
|
||||
if (dw < 1 || dh < 1) return;
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: begin_tft_write (was called spi_begin)
|
||||
@@ -85,6 +105,204 @@ inline void TFT_eSPI::begin_tft_read(void){
|
||||
SET_BUS_READ_MODE;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: setViewport
|
||||
** Description: Set the clipping region for the TFT screen
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum)
|
||||
{
|
||||
// Viewport
|
||||
_xDatum = x; // Datum x position in screen coordinates
|
||||
_yDatum = y; // Datum y position in screen coordinates
|
||||
_xWidth = w; // Viewport width
|
||||
_yHeight = h; // Viewport height
|
||||
|
||||
// Clipped viewport
|
||||
_vpX = 0; // Viewport top left corner x coordinate
|
||||
_vpY = 0; // Viewport top left corner y coordinate
|
||||
_vpW = _width; // Equivalent of TFT width (Nb: viewport right edge coord + 1)
|
||||
_vpH = _height; // Equivalent of TFT height (Nb: viewport bottom edge coord + 1)
|
||||
|
||||
_vpDatum = false; // Datum is at top left corner of screen (true = top left of viewport)
|
||||
_vpOoB = false; // Out of Bounds flag (true is all of viewport is off screen)
|
||||
|
||||
// Clip viewport to screen area
|
||||
if (x<0) { w += x; x = 0; }
|
||||
if (y<0) { h += y; y = 0; }
|
||||
if ((x + w) > _width ) { w = _width - x; }
|
||||
if ((y + h) > _height) { h = _height - y; }
|
||||
|
||||
//Serial.print(" x=");Serial.print( x);Serial.print(", y=");Serial.print( y);
|
||||
//Serial.print(", w=");Serial.print(w);Serial.print(", h=");Serial.println(h);
|
||||
|
||||
// Check if viewport is entirely out of bounds
|
||||
if (w < 1 || h < 1)
|
||||
{
|
||||
// Set default values and Out of Bounds flag in case of error
|
||||
_xDatum = 0;
|
||||
_yDatum = 0;
|
||||
_xWidth = _width;
|
||||
_yHeight = _height;
|
||||
_vpOoB = true; // Set Out of Bounds flag to inhibit all drawing
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vpDatum)
|
||||
{
|
||||
_xDatum = 0; // Reset to top left of screen if not useing a viewport datum
|
||||
_yDatum = 0;
|
||||
_xWidth = _width;
|
||||
_yHeight = _height;
|
||||
}
|
||||
|
||||
// Store the on screen viewport metrics and datum position
|
||||
_vpX = x;
|
||||
_vpY = y;
|
||||
_vpW = x + w;
|
||||
_vpH = y + h;
|
||||
_vpDatum = vpDatum;
|
||||
|
||||
//Serial.print(" _xDatum=");Serial.print( _xDatum);Serial.print(", _yDatum=");Serial.print( _yDatum);
|
||||
//Serial.print(", _xWidth=");Serial.print(_xWidth);Serial.print(", _yHeight=");Serial.println(_yHeight);
|
||||
|
||||
//Serial.print(" _vpX=");Serial.print( _vpX);Serial.print(", _vpY=");Serial.print( _vpY);
|
||||
//Serial.print(", _vpW=");Serial.print(_vpW);Serial.print(", _vpH=");Serial.println(_vpH);
|
||||
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: checkViewport
|
||||
** Description: Check if any part of specified area is visible in viewport
|
||||
***************************************************************************************/
|
||||
// Note: Setting w and h to 1 will check if coordinate x,y is in area
|
||||
bool TFT_eSPI::checkViewport(int32_t x, int32_t y, int32_t w, int32_t h)
|
||||
{
|
||||
if (_vpOoB) return false;
|
||||
x+= _xDatum;
|
||||
y+= _yDatum;
|
||||
|
||||
if ((x >= _vpW) || (y >= _vpH)) return false;
|
||||
|
||||
int32_t dx = 0;
|
||||
int32_t dy = 0;
|
||||
int32_t dw = w;
|
||||
int32_t dh = h;
|
||||
|
||||
if (x < _vpX) { dx = _vpX - x; dw -= dx; x = _vpX; }
|
||||
if (y < _vpY) { dy = _vpY - y; dh -= dy; y = _vpY; }
|
||||
|
||||
if ((x + dw) > _vpW ) dw = _vpW - x;
|
||||
if ((y + dh) > _vpH ) dh = _vpH - y;
|
||||
|
||||
if (dw < 1 || dh < 1) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: resetViewport
|
||||
** Description: Reset viewport to whle TFT screen, datum at 0,0
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::resetViewport(void)
|
||||
{
|
||||
// Reset viewport to the whole screen
|
||||
_xDatum = 0;
|
||||
_yDatum = 0;
|
||||
_vpX = 0;
|
||||
_vpY = 0;
|
||||
_vpW = _width;
|
||||
_vpH = _height;
|
||||
_xWidth = _width;
|
||||
_yHeight = _height;
|
||||
|
||||
_vpDatum = false;
|
||||
_vpOoB = false;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: getViewportX
|
||||
** Description: Get x position of the viewport
|
||||
***************************************************************************************/
|
||||
int32_t TFT_eSPI::getViewportX(void)
|
||||
{
|
||||
return _xDatum;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: getViewportY
|
||||
** Description: Get y position of the viewport
|
||||
***************************************************************************************/
|
||||
int32_t TFT_eSPI::getViewportY(void)
|
||||
{
|
||||
return _yDatum;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: getViewportWidth
|
||||
** Description: Get width of the viewport
|
||||
***************************************************************************************/
|
||||
int32_t TFT_eSPI::getViewportWidth(void)
|
||||
{
|
||||
return _vpW - _vpX;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: getViewportHeight
|
||||
** Description: Get height of the viewport
|
||||
***************************************************************************************/
|
||||
int32_t TFT_eSPI::getViewportHeight(void)
|
||||
{
|
||||
return _vpH - _vpY;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: getViewportDatum
|
||||
** Description: Get datum of the viewport (true = viewport corner)
|
||||
***************************************************************************************/
|
||||
bool TFT_eSPI::getViewportDatum(void)
|
||||
{
|
||||
return _vpDatum;
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: frameViewport
|
||||
** Description: Draw a frame inside or outside the viewport of width w
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::frameViewport(uint16_t color, int32_t w)
|
||||
{
|
||||
// If w is positive the frame is drawn inside the viewport
|
||||
// a large positive width will clear the screen inside the viewport
|
||||
if (w>0)
|
||||
{
|
||||
fillRect(_vpX, _vpY, _vpW - _vpX, w, color);
|
||||
fillRect(_vpX, _vpY + w, w, _vpH - _vpY - w - w, color);
|
||||
fillRect(_vpW - w, _vpY + w, w, _vpH - _vpY - w - w, color);
|
||||
fillRect(_vpX, _vpH - w, _vpW - _vpX, w, color);
|
||||
}
|
||||
else
|
||||
// If w is negative the frame is drawn outside the viewport
|
||||
// a large negative width will clear the screen outside the viewport
|
||||
{
|
||||
w = -w;
|
||||
int32_t _xTemp = _vpX; _vpX = 0;
|
||||
int32_t _yTemp = _vpY; _vpY = 0;
|
||||
int32_t _wTemp = _vpW; _vpW = _width;
|
||||
int32_t _hTemp = _vpH; _vpH = _height;
|
||||
bool _dTemp = _vpDatum; _vpDatum = false;
|
||||
|
||||
fillRect(_xTemp - _xDatum, _yTemp - w - _yDatum, _wTemp - _xTemp + w + w, w, color);
|
||||
fillRect(_xTemp - w - _xDatum, _yTemp - _yDatum, w, _hTemp - _yTemp, color);
|
||||
fillRect(_wTemp - _xDatum, _yTemp - _yDatum, w, _hTemp - _yTemp, color);
|
||||
fillRect(_xTemp - w - _xDatum, _hTemp - _yDatum, _wTemp - _xTemp + w + w, w, color);
|
||||
|
||||
_vpX = _xTemp;
|
||||
_vpY = _yTemp;
|
||||
_vpW = _wTemp;
|
||||
_vpH = _hTemp;
|
||||
_vpDatum = _dTemp;
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: end_tft_read (was called spi_end_read)
|
||||
** Description: End transaction for reads and deselect TFT
|
||||
@@ -181,6 +399,10 @@ TFT_eSPI::TFT_eSPI(int16_t w, int16_t h)
|
||||
|
||||
_init_width = _width = w; // Set by specific xxxxx_Defines.h file or by users sketch
|
||||
_init_height = _height = h; // Set by specific xxxxx_Defines.h file or by users sketch
|
||||
|
||||
// Reset the viewport to the whole screen
|
||||
resetViewport();
|
||||
|
||||
rotation = 0;
|
||||
cursor_y = cursor_x = 0;
|
||||
textfont = 1;
|
||||
@@ -490,6 +712,9 @@ void TFT_eSPI::setRotation(uint8_t m)
|
||||
|
||||
addr_row = 0xFFFF;
|
||||
addr_col = 0xFFFF;
|
||||
|
||||
// Reset the viewport to the whole screen
|
||||
resetViewport();
|
||||
}
|
||||
|
||||
|
||||
@@ -657,6 +882,19 @@ uint32_t TFT_eSPI::readcommand32(uint8_t cmd_function, uint8_t index)
|
||||
***************************************************************************************/
|
||||
uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
|
||||
{
|
||||
if (_vpOoB) return 0;
|
||||
|
||||
x0+= _xDatum;
|
||||
y0+= _yDatum;
|
||||
|
||||
// Range checking
|
||||
if ((x0 < _vpX) || (y0 < _vpY) ||(x0 >= _vpW) || (y0 >= _vpH)) return 0;
|
||||
|
||||
#ifdef CGRAM_OFFSET
|
||||
x0+=colstart;
|
||||
y0+=rowstart;
|
||||
#endif
|
||||
|
||||
#if defined(TFT_PARALLEL_8_BIT)
|
||||
|
||||
CS_L;
|
||||
@@ -666,13 +904,15 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
|
||||
// Set masked pins D0- D7 to input
|
||||
busDir(dir_mask, INPUT);
|
||||
|
||||
#if !defined (SSD1963_DRIVER)
|
||||
// Dummy read to throw away don't care value
|
||||
readByte();
|
||||
#endif
|
||||
|
||||
// Fetch the 16 bit BRG pixel
|
||||
//uint16_t rgb = (readByte() << 8) | readByte();
|
||||
|
||||
#if defined (ILI9341_DRIVER) | defined (ILI9488_DRIVER) // Read 3 bytes
|
||||
#if defined (ILI9341_DRIVER) | defined (ILI9488_DRIVER) | defined (SSD1963_DRIVER)// Read 3 bytes
|
||||
|
||||
// Read window pixel 24 bit RGB values and fill in LS bits
|
||||
uint16_t rgb = ((readByte() & 0xF8) << 8) | ((readByte() & 0xFC) << 3) | (readByte() >> 3);
|
||||
@@ -777,7 +1017,21 @@ void TFT_eSPI::setCallback(getColorCallback getCol)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
|
||||
{
|
||||
if ((x > _width) || (y > _height) || (w == 0) || (h == 0)) return;
|
||||
if (_vpOoB) return;
|
||||
|
||||
x+= _xDatum;
|
||||
y+= _yDatum;
|
||||
|
||||
// Clipping
|
||||
if ((x >= _vpW) || (y >= _vpH)) return;
|
||||
|
||||
if (x < _vpX) { w += x - _vpX; x = _vpX; }
|
||||
if (y < _vpY) { h += y - _vpY; y = _vpY; }
|
||||
|
||||
if ((x + w) > _vpW) w = _vpW - x;
|
||||
if ((y + h) > _vpH) h = _vpH - y;
|
||||
|
||||
if ((w < 1) || (h < 1)) return;
|
||||
|
||||
#if defined(TFT_PARALLEL_8_BIT)
|
||||
|
||||
@@ -788,13 +1042,13 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
|
||||
// Set masked pins D0- D7 to input
|
||||
busDir(dir_mask, INPUT);
|
||||
|
||||
// Dummy read to throw away don't care value
|
||||
readByte();
|
||||
|
||||
// Total pixel count
|
||||
uint32_t len = w * h;
|
||||
|
||||
#if defined (ILI9341_DRIVER) | defined (ILI9488_DRIVER) // Read 3 bytes
|
||||
// Dummy read to throw away don't care value
|
||||
readByte();
|
||||
|
||||
// Fetch the 24 bit RGB value
|
||||
while (len--) {
|
||||
// Assemble the RGB 16 bit colour
|
||||
@@ -803,7 +1057,23 @@ void TFT_eSPI::readRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
|
||||
// Swapped byte order for compatibility with pushRect()
|
||||
*data++ = (rgb<<8) | (rgb>>8);
|
||||
}
|
||||
|
||||
#elif defined (SSD1963_DRIVER)
|
||||
// Fetch the 18 bit BRG pixels
|
||||
while (len--) {
|
||||
uint16_t bgr = ((readByte() & 0xF8) >> 3);; // CS_L adds a small delay
|
||||
bgr |= ((readByte() & 0xFC) << 3);
|
||||
bgr |= (readByte() << 8);
|
||||
// Swap Red and Blue (could check MADCTL setting to see if this is needed)
|
||||
uint16_t rgb = (bgr>>11) | (bgr<<11) | (bgr & 0x7E0);
|
||||
// Swapped byte order for compatibility with pushRect()
|
||||
*data++ = (rgb<<8) | (rgb>>8);
|
||||
}
|
||||
|
||||
#else // ILI9481 reads as 16 bits
|
||||
// Dummy read to throw away don't care value
|
||||
readByte();
|
||||
|
||||
// Fetch the 16 bit BRG pixels
|
||||
while (len--) {
|
||||
#ifdef ILI9486_DRIVER
|
||||
@@ -902,21 +1172,7 @@ void TFT_eSPI::pushRect(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *da
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data)
|
||||
{
|
||||
|
||||
if ((x >= _width) || (y >= _height)) return;
|
||||
|
||||
int32_t dx = 0;
|
||||
int32_t dy = 0;
|
||||
int32_t dw = w;
|
||||
int32_t dh = h;
|
||||
|
||||
if (x < 0) { dw += x; dx = -x; x = 0; }
|
||||
if (y < 0) { dh += y; dy = -y; y = 0; }
|
||||
|
||||
if ((x + dw) > _width ) dw = _width - x;
|
||||
if ((y + dh) > _height) dh = _height - y;
|
||||
|
||||
if (dw < 1 || dh < 1) return;
|
||||
PI_CLIP;
|
||||
|
||||
begin_tft_write();
|
||||
inTransaction = true;
|
||||
@@ -946,21 +1202,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *data, uint16_t transp)
|
||||
{
|
||||
|
||||
if ((x >= _width) || (y >= _height)) return;
|
||||
|
||||
int32_t dx = 0;
|
||||
int32_t dy = 0;
|
||||
int32_t dw = w;
|
||||
int32_t dh = h;
|
||||
|
||||
if (x < 0) { dw += x; dx = -x; x = 0; }
|
||||
if (y < 0) { dh += y; dy = -y; y = 0; }
|
||||
|
||||
if ((x + dw) > _width ) dw = _width - x;
|
||||
if ((y + dh) > _height) dh = _height - y;
|
||||
|
||||
if (dw < 1 || dh < 1) return;
|
||||
PI_CLIP;
|
||||
|
||||
begin_tft_write();
|
||||
inTransaction = true;
|
||||
@@ -1020,20 +1262,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t *d
|
||||
void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data)
|
||||
{
|
||||
// Requires 32 bit aligned access, so use PROGMEM 16 bit word functions
|
||||
if ((x >= _width) || (y >= _height)) return;
|
||||
|
||||
int32_t dx = 0;
|
||||
int32_t dy = 0;
|
||||
int32_t dw = w;
|
||||
int32_t dh = h;
|
||||
|
||||
if (x < 0) { dw += x; dx = -x; x = 0; }
|
||||
if (y < 0) { dh += y; dy = -y; y = 0; }
|
||||
|
||||
if ((x + dw) > _width ) dw = _width - x;
|
||||
if ((y + dh) > _height) dh = _height - y;
|
||||
|
||||
if (dw < 1 || dh < 1) return;
|
||||
PI_CLIP;
|
||||
|
||||
begin_tft_write();
|
||||
inTransaction = true;
|
||||
@@ -1056,7 +1285,6 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1
|
||||
end_tft_write();
|
||||
}
|
||||
|
||||
|
||||
/***************************************************************************************
|
||||
** Function name: pushImage - for FLASH (PROGMEM) stored images
|
||||
** Description: plot 16 bit image with 1 colour being transparent
|
||||
@@ -1064,20 +1292,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1
|
||||
void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *data, uint16_t transp)
|
||||
{
|
||||
// Requires 32 bit aligned access, so use PROGMEM 16 bit word functions
|
||||
if ((x >= _width) || (y >= (int32_t)_height)) return;
|
||||
|
||||
int32_t dx = 0;
|
||||
int32_t dy = 0;
|
||||
int32_t dw = w;
|
||||
int32_t dh = h;
|
||||
|
||||
if (x < 0) { dw += x; dx = -x; x = 0; }
|
||||
if (y < 0) { dh += y; dy = -y; y = 0; }
|
||||
|
||||
if ((x + dw) > _width ) dw = _width - x;
|
||||
if ((y + dh) > _height) dh = _height - y;
|
||||
|
||||
if (dw < 1 || dh < 1) return;
|
||||
PI_CLIP;
|
||||
|
||||
begin_tft_write();
|
||||
inTransaction = true;
|
||||
@@ -1133,21 +1348,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, const uint1
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, bool bpp8, uint16_t *cmap)
|
||||
{
|
||||
|
||||
if ((x >= _width) || (y >= (int32_t)_height)) return;
|
||||
|
||||
int32_t dx = 0;
|
||||
int32_t dy = 0;
|
||||
int32_t dw = w;
|
||||
int32_t dh = h;
|
||||
|
||||
if (x < 0) { dw += x; dx = -x; x = 0; }
|
||||
if (y < 0) { dh += y; dy = -y; y = 0; }
|
||||
|
||||
if ((x + dw) > _width ) dw = _width - x;
|
||||
if ((y + dh) > _height) dh = _height - y;
|
||||
|
||||
if (dw < 1 || dh < 1) return;
|
||||
PI_CLIP;
|
||||
|
||||
begin_tft_write();
|
||||
inTransaction = true;
|
||||
@@ -1290,20 +1491,7 @@ void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *da
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::pushImage(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t *data, uint8_t transp, bool bpp8, uint16_t *cmap)
|
||||
{
|
||||
if ((x >= _width) || (y >= _height)) return;
|
||||
|
||||
int32_t dx = 0;
|
||||
int32_t dy = 0;
|
||||
int32_t dw = w;
|
||||
int32_t dh = h;
|
||||
|
||||
if (x < 0) { dw += x; dx = -x; x = 0; }
|
||||
if (y < 0) { dh += y; dy = -y; y = 0; }
|
||||
|
||||
if ((x + dw) > _width ) dw = _width - x;
|
||||
if ((y + dh) > _height) dh = _height - y;
|
||||
|
||||
if (dw < 1 || dh < 1) return;
|
||||
PI_CLIP;
|
||||
|
||||
begin_tft_write();
|
||||
inTransaction = true;
|
||||
@@ -2329,7 +2517,7 @@ uint8_t TFT_eSPI::getTextDatum(void)
|
||||
// Return the size of the display (per current rotation)
|
||||
int16_t TFT_eSPI::width(void)
|
||||
{
|
||||
return _width;
|
||||
return _xWidth;
|
||||
}
|
||||
|
||||
|
||||
@@ -2339,7 +2527,7 @@ int16_t TFT_eSPI::width(void)
|
||||
***************************************************************************************/
|
||||
int16_t TFT_eSPI::height(void)
|
||||
{
|
||||
return _height;
|
||||
return _yHeight;
|
||||
}
|
||||
|
||||
|
||||
@@ -2479,28 +2667,34 @@ int16_t TFT_eSPI::fontHeight(void)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32_t bg, uint8_t size)
|
||||
{
|
||||
if ((x >= _width) || // Clip right
|
||||
(y >= _height) || // Clip bottom
|
||||
((x + 6 * size - 1) < 0) || // Clip left
|
||||
((y + 8 * size - 1) < 0)) // Clip top
|
||||
return;
|
||||
if (_vpOoB) return;
|
||||
|
||||
int32_t xd = x + _xDatum;
|
||||
int32_t yd = y + _yDatum;
|
||||
|
||||
if (c < 32) return;
|
||||
#ifdef LOAD_GLCD
|
||||
//>>>>>>>>>>>>>>>>>>
|
||||
#ifdef LOAD_GFXFF
|
||||
#ifdef LOAD_GFXFF
|
||||
if(!gfxFont) { // 'Classic' built-in font
|
||||
#endif
|
||||
#endif
|
||||
//>>>>>>>>>>>>>>>>>>
|
||||
|
||||
bool fillbg = (bg != color);
|
||||
if ((xd >= _vpW) || // Clip right
|
||||
( yd >= _vpH) || // Clip bottom
|
||||
((xd + 6 * size - 1) < _vpX) || // Clip left
|
||||
((yd + 8 * size - 1) < _vpY)) // Clip top
|
||||
return;
|
||||
|
||||
if ((size==1) && fillbg) {
|
||||
bool fillbg = (bg != color);
|
||||
bool clip = xd < _vpX || xd + 6 * textsize >= _vpW || yd < _vpY || yd + 8 * textsize >= _vpH;
|
||||
|
||||
if ((size==1) && fillbg && !clip) {
|
||||
uint8_t column[6];
|
||||
uint8_t mask = 0x1;
|
||||
begin_tft_write();
|
||||
|
||||
setWindow(x, y, x+5, y+8);
|
||||
setWindow(xd, yd, xd+5, yd+8);
|
||||
|
||||
for (int8_t i = 0; i < 5; i++ ) column[i] = pgm_read_byte(font + (c * 5) + i);
|
||||
column[5] = 0;
|
||||
@@ -2519,6 +2713,7 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32
|
||||
else {
|
||||
//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;
|
||||
if (i == 5)
|
||||
@@ -2526,13 +2721,13 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32
|
||||
else
|
||||
line = pgm_read_byte(font + (c * 5) + i);
|
||||
|
||||
if (size == 1) { // default size
|
||||
if (size == 1 && !fillbg) { // default size
|
||||
for (int8_t j = 0; j < 8; j++) {
|
||||
if (line & 0x1) drawPixel(x + i, y + j, color);
|
||||
line >>= 1;
|
||||
}
|
||||
}
|
||||
else { // big size
|
||||
else { // big size or clipped
|
||||
for (int8_t j = 0; j < 8; j++) {
|
||||
if (line & 0x1) fillRect(x + (i * size), y + (j * size), size, size, color);
|
||||
else if (fillbg) fillRect(x + i * size, y + j * size, size, size, bg);
|
||||
@@ -2545,9 +2740,9 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32
|
||||
}
|
||||
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
#ifdef LOAD_GFXFF
|
||||
#ifdef LOAD_GFXFF
|
||||
} else { // Custom font
|
||||
#endif
|
||||
#endif
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
||||
#endif // LOAD_GLCD
|
||||
|
||||
@@ -2713,8 +2908,13 @@ void TFT_eSPI::readAddrWindow(int32_t xs, int32_t ys, int32_t w, int32_t h)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
|
||||
{
|
||||
if (_vpOoB) return;
|
||||
|
||||
x+= _xDatum;
|
||||
y+= _yDatum;
|
||||
|
||||
// Range checking
|
||||
if ((x < 0) || (y < 0) ||(x >= _width) || (y >= _height)) return;
|
||||
if ((x < _vpX) || (y < _vpY) ||(x >= _vpW) || (y >= _vpH)) return;
|
||||
|
||||
#ifdef CGRAM_OFFSET
|
||||
x+=colstart;
|
||||
@@ -2914,12 +3114,17 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
|
||||
{
|
||||
if (_vpOoB) return;
|
||||
|
||||
x+= _xDatum;
|
||||
y+= _yDatum;
|
||||
|
||||
// Clipping
|
||||
if ((x < 0) || (x >= _width) || (y >= _height)) return;
|
||||
if ((x < _vpX) || (x >= _vpW) || (y >= _vpH)) return;
|
||||
|
||||
if (y < 0) { h += y; y = 0; }
|
||||
if (y < _vpY) { h += y - _vpY; y = _vpY; }
|
||||
|
||||
if ((y + h) > _height) h = _height - y;
|
||||
if ((y + h) > _vpH) h = _vpH - y;
|
||||
|
||||
if (h < 1) return;
|
||||
|
||||
@@ -2939,12 +3144,17 @@ void TFT_eSPI::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color)
|
||||
{
|
||||
if (_vpOoB) return;
|
||||
|
||||
x+= _xDatum;
|
||||
y+= _yDatum;
|
||||
|
||||
// Clipping
|
||||
if ((y < 0) || (x >= _width) || (y >= _height)) return;
|
||||
if ((y < _vpY) || (x >= _vpW) || (y >= _vpH)) return;
|
||||
|
||||
if (x < 0) { w += x; x = 0; }
|
||||
if (x < _vpX) { w += x - _vpX; x = _vpX; }
|
||||
|
||||
if ((x + w) > _width) w = _width - x;
|
||||
if ((x + w) > _vpW) w = _vpW - x;
|
||||
|
||||
if (w < 1) return;
|
||||
|
||||
@@ -2964,17 +3174,31 @@ void TFT_eSPI::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color)
|
||||
***************************************************************************************/
|
||||
void TFT_eSPI::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color)
|
||||
{
|
||||
if (_vpOoB) return;
|
||||
|
||||
x+= _xDatum;
|
||||
y+= _yDatum;
|
||||
|
||||
// Clipping
|
||||
if ((x >= _width) || (y >= _height)) return;
|
||||
if ((x >= _vpW) || (y >= _vpH)) return;
|
||||
|
||||
if (x < 0) { w += x; x = 0; }
|
||||
if (y < 0) { h += y; y = 0; }
|
||||
if (x < _vpX) { w += x - _vpX; x = _vpX; }
|
||||
if (y < _vpY) { h += y - _vpY; y = _vpY; }
|
||||
|
||||
if ((x + w) > _width) w = _width - x;
|
||||
if ((y + h) > _height) h = _height - y;
|
||||
if ((x + w) > _vpW) w = _vpW - x;
|
||||
if ((y + h) > _vpH) h = _vpH - y;
|
||||
|
||||
if ((w < 1) || (h < 1)) return;
|
||||
|
||||
//Serial.print(" _xDatum=");Serial.print( _xDatum);Serial.print(", _yDatum=");Serial.print( _yDatum);
|
||||
//Serial.print(", _xWidth=");Serial.print(_xWidth);Serial.print(", _yHeight=");Serial.println(_yHeight);
|
||||
|
||||
//Serial.print(" _vpX=");Serial.print( _vpX);Serial.print(", _vpY=");Serial.print( _vpY);
|
||||
//Serial.print(", _vpW=");Serial.print(_vpW);Serial.print(", _vpH=");Serial.println(_vpH);
|
||||
|
||||
//Serial.print(" x=");Serial.print( y);Serial.print(", y=");Serial.print( y);
|
||||
//Serial.print(", w=");Serial.print(w);Serial.print(", h=");Serial.println(h);
|
||||
|
||||
begin_tft_write();
|
||||
|
||||
setWindow(x, y, x + w - 1, y + h - 1);
|
||||
@@ -3359,11 +3583,11 @@ size_t TFT_eSPI::write(uint8_t utf8)
|
||||
cursor_x = 0;
|
||||
}
|
||||
else {
|
||||
if (textwrapX && (cursor_x + width * textsize > _width)) {
|
||||
if (textwrapX && (cursor_x + width * textsize > this->width())) {
|
||||
cursor_y += height;
|
||||
cursor_x = 0;
|
||||
}
|
||||
if (textwrapY && (cursor_y >= (int32_t)_height)) cursor_y = 0;
|
||||
if (textwrapY && (cursor_y >= (int32_t)this->height())) cursor_y = 0;
|
||||
cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont);
|
||||
}
|
||||
|
||||
@@ -3386,13 +3610,13 @@ size_t TFT_eSPI::write(uint8_t utf8)
|
||||
h = pgm_read_byte(&glyph->height);
|
||||
if((w > 0) && (h > 0)) { // Is there an associated bitmap?
|
||||
int16_t xo = (int8_t)pgm_read_byte(&glyph->xOffset);
|
||||
if(textwrapX && ((cursor_x + textsize * (xo + w)) > _width)) {
|
||||
if(textwrapX && ((cursor_x + textsize * (xo + w)) > this->width())) {
|
||||
// Drawing character would go off right edge; wrap to new line
|
||||
cursor_x = 0;
|
||||
cursor_y += (int16_t)textsize *
|
||||
(uint8_t)pgm_read_byte(&gfxFont->yAdvance);
|
||||
}
|
||||
if (textwrapY && (cursor_y >= (int32_t)_height)) cursor_y = 0;
|
||||
if (textwrapY && (cursor_y >= (int32_t)this->height())) cursor_y = 0;
|
||||
drawChar(cursor_x, cursor_y, uniCode, textcolor, textbgcolor, textsize);
|
||||
}
|
||||
cursor_x += pgm_read_byte(&glyph->xAdvance) * (int16_t)textsize;
|
||||
@@ -3418,7 +3642,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y)
|
||||
// Any UTF-8 decoding must be done before calling drawChar()
|
||||
int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
{
|
||||
if (!uniCode) return 0;
|
||||
if (_vpOoB || !uniCode) return 0;
|
||||
|
||||
if (font==1) {
|
||||
#ifdef LOAD_GLCD
|
||||
@@ -3482,18 +3706,23 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
}
|
||||
#endif
|
||||
|
||||
int32_t xd = x + _xDatum;
|
||||
int32_t yd = y + _yDatum;
|
||||
|
||||
if ((xd + width * textsize < _vpX || xd >= _vpW) && (yd + height * textsize < _vpY || yd >= _vpH)) return width * textsize ;
|
||||
|
||||
int32_t w = width;
|
||||
int32_t pX = 0;
|
||||
int32_t pY = y;
|
||||
uint8_t line = 0;
|
||||
bool clip = xd < _vpX || xd + width * textsize >= _vpW || yd < _vpY || yd + height * textsize >= _vpH;
|
||||
|
||||
#ifdef LOAD_FONT2 // chop out code if we do not need it
|
||||
if (font == 2) {
|
||||
w = w + 6; // Should be + 7 but we need to compensate for width increment
|
||||
w = w / 8;
|
||||
if (x + width * textsize >= (int16_t)_width) return width * textsize ;
|
||||
|
||||
if (textcolor == textbgcolor || textsize != 1) {
|
||||
if (textcolor == textbgcolor || textsize != 1 || clip) {
|
||||
//begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
|
||||
inTransaction = true;
|
||||
|
||||
@@ -3534,9 +3763,10 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
end_tft_write();
|
||||
}
|
||||
else { // Faster drawing of characters and background using block write
|
||||
|
||||
begin_tft_write();
|
||||
|
||||
setWindow(x, y, x + width - 1, y + height - 1);
|
||||
setWindow(xd, yd, xd + width - 1, yd + height - 1);
|
||||
|
||||
uint8_t mask;
|
||||
for (int32_t i = 0; i < height; i++) {
|
||||
@@ -3570,7 +3800,8 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
inTransaction = true;
|
||||
|
||||
w *= height; // Now w is total number of pixels in the character
|
||||
if (textcolor == textbgcolor) {
|
||||
if (textcolor == textbgcolor && !clip) {
|
||||
|
||||
int32_t px = 0, py = pY; // To hold character block start and end column and row values
|
||||
int32_t pc = 0; // Pixel count
|
||||
uint8_t np = textsize * textsize; // Number of pixels in a drawn pixel
|
||||
@@ -3586,12 +3817,12 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
line &= 0x7F;
|
||||
line++;
|
||||
if (ts) {
|
||||
px = x + textsize * (pc % width); // Keep these px and py calculations outside the loop as they are slow
|
||||
py = y + textsize * (pc / width);
|
||||
px = xd + textsize * (pc % width); // Keep these px and py calculations outside the loop as they are slow
|
||||
py = yd + textsize * (pc / width);
|
||||
}
|
||||
else {
|
||||
px = x + pc % width; // Keep these px and py calculations outside the loop as they are slow
|
||||
py = y + pc / width;
|
||||
px = xd + pc % width; // Keep these px and py calculations outside the loop as they are slow
|
||||
py = yd + pc / width;
|
||||
}
|
||||
while (line--) { // In this case the while(line--) is faster
|
||||
pc++; // This is faster than putting pc+=line before while()?
|
||||
@@ -3604,8 +3835,8 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
else {tft_Write_16(textcolor);}
|
||||
px += textsize;
|
||||
|
||||
if (px >= (x + width * textsize)) {
|
||||
px = x;
|
||||
if (px >= (xd + width * textsize)) {
|
||||
px = xd;
|
||||
py += textsize;
|
||||
}
|
||||
}
|
||||
@@ -3617,11 +3848,11 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Text colour != background and textsize = 1 and character is within screen area
|
||||
// Text colour != background and textsize = 1 and character is within viewport area
|
||||
// so use faster drawing of characters and background using block write
|
||||
if ((textsize == 1) && (x >= 0) && (x + width <= _width) && (y >= 0) && (y + height <= _height))
|
||||
if (textcolor != textbgcolor && textsize == 1 && !clip)
|
||||
{
|
||||
setWindow(x, y, x + width - 1, y + height - 1);
|
||||
setWindow(xd, yd, xd + width - 1, yd + height - 1);
|
||||
|
||||
// Maximum font size is equivalent to 180x180 pixels in area
|
||||
while (w > 0) {
|
||||
@@ -3644,12 +3875,12 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
int32_t pc = 0; // Pixel count
|
||||
int32_t pl = 0; // Pixel line length
|
||||
uint16_t pcol = 0; // Pixel color
|
||||
|
||||
bool pf = true; // Flag for plotting
|
||||
while (pc < w) {
|
||||
line = pgm_read_byte((uint8_t *)flash_address);
|
||||
flash_address++;
|
||||
if (line & 0x80) { pcol = textcolor; line &= 0x7F; }
|
||||
else pcol = textbgcolor;
|
||||
if (line & 0x80) { pcol = textcolor; line &= 0x7F; pf = true;}
|
||||
else { pcol = textbgcolor; if (textcolor == textbgcolor) pf = false;}
|
||||
line++;
|
||||
px = pc % width;
|
||||
tx = x + textsize * px;
|
||||
@@ -3661,7 +3892,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
while (line--) {
|
||||
pl++;
|
||||
if ((px+pl) >= width) {
|
||||
fillRect(tx, ty, pl * textsize, textsize, pcol);
|
||||
if (pf) fillRect(tx, ty, pl * textsize, textsize, pcol);
|
||||
pl = 0;
|
||||
px = 0;
|
||||
tx = x;
|
||||
@@ -3669,7 +3900,7 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
||||
ty += textsize;
|
||||
}
|
||||
}
|
||||
if (pl) fillRect(tx, ty, pl * textsize, textsize, pcol);
|
||||
if (pl && pf) fillRect(tx, ty, pl * textsize, textsize, pcol);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3805,11 +4036,6 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
|
||||
padding += 2;
|
||||
break;
|
||||
}
|
||||
/* // Check coordinates are OK, adjust if not
|
||||
if (poX < 0) poX = 0;
|
||||
if (poX+cwidth > width()) poX = width() - cwidth;
|
||||
if (poY < 0) poY = 0;
|
||||
if (poY+cheight-baseline> height()) poY = height() - cheight; //*/
|
||||
}
|
||||
|
||||
|
||||
@@ -3846,7 +4072,16 @@ int16_t TFT_eSPI::drawString(const char *string, int32_t poX, int32_t poY, uint8
|
||||
#ifdef SMOOTH_FONT
|
||||
if(fontLoaded) {
|
||||
if (textcolor!=textbgcolor) fillRect(poX, poY, cwidth, cheight, textbgcolor);
|
||||
|
||||
/*
|
||||
// The above only works for a single text line, not if the text is going to wrap...
|
||||
// So need to use code like this in a while loop to fix it:
|
||||
if (textwrapX && (cursor_x + width * textsize > this->width())) {
|
||||
cursor_y += height;
|
||||
cursor_x = 0;
|
||||
}
|
||||
if (textwrapY && (cursor_y >= (int32_t)this->height())) cursor_y = 0;
|
||||
cursor_x += drawChar(uniCode, cursor_x, cursor_y, textfont);
|
||||
*/
|
||||
setCursor(poX, poY);
|
||||
|
||||
while (n < len) {
|
||||
|
26
TFT_eSPI.h
26
TFT_eSPI.h
@@ -16,7 +16,11 @@
|
||||
#ifndef _TFT_eSPIH_
|
||||
#define _TFT_eSPIH_
|
||||
|
||||
#define TFT_ESPI_VERSION "2.2.23"
|
||||
#define TFT_ESPI_VERSION "2.3.2"
|
||||
|
||||
// Bit level feature flags
|
||||
// Bit 0 set: viewport capability
|
||||
#define TFT_ESPI_FEATURES 1
|
||||
|
||||
/***************************************************************************************
|
||||
** Section 1: Load required header files
|
||||
@@ -390,6 +394,17 @@ class TFT_eSPI : public Print {
|
||||
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
|
||||
|
||||
// Viewport commands, see "Viewport_Demo" sketch
|
||||
void setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum = true);
|
||||
bool checkViewport(int32_t x, int32_t y, int32_t w, int32_t h);
|
||||
int32_t getViewportX(void);
|
||||
int32_t getViewportY(void);
|
||||
int32_t getViewportWidth(void);
|
||||
int32_t getViewportHeight(void);
|
||||
bool getViewportDatum(void);
|
||||
void frameViewport(uint16_t color, int32_t w);
|
||||
void resetViewport(void);
|
||||
|
||||
// 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()
|
||||
@@ -728,6 +743,15 @@ class TFT_eSPI : public Print {
|
||||
int32_t _width, _height; // Display w/h as modified by current rotation
|
||||
int32_t addr_row, addr_col; // Window position - used to minimise window commands
|
||||
|
||||
// Viewport variables
|
||||
int32_t _vpX, _vpY, _vpW, _vpH; // Note: x start, y start, x end + 1, y end + 1
|
||||
int32_t _xDatum;
|
||||
int32_t _yDatum;
|
||||
int32_t _xWidth;
|
||||
int32_t _yHeight;
|
||||
bool _vpDatum;
|
||||
bool _vpOoB;
|
||||
|
||||
uint32_t fontsloaded; // Bit field of fonts loaded
|
||||
|
||||
uint8_t glyph_ab, // Smooth font glyph delta Y (height) above baseline
|
||||
|
@@ -20,7 +20,10 @@
|
||||
//#define SSD1963_480_DRIVER // 272 x 480 display
|
||||
//#define SSD1963_800_DRIVER // 480 x 800 display
|
||||
//#define SSD1963_800ALT_DRIVER // Alternative 480 x 800 display
|
||||
#define SSD1963_800BD_DRIVER // 480 x 800 displau sourced from https://www.buydisplay.com/7-tft-screen-touch-lcd-display-module-w-ssd1963-controller-board-mcu
|
||||
#define SSD1963_800BD_DRIVER // 480 x 800 display sourced from https://www.buydisplay.com/7-tft-screen-touch-lcd-display-module-w-ssd1963-controller-board-mcu
|
||||
|
||||
//#define TFT_RGB_ORDER TFT_RGB // Colour order Red-Green-Blue
|
||||
#define TFT_RGB_ORDER TFT_BGR // Colour order Blue-Green-Red
|
||||
|
||||
// ##################################################################################
|
||||
//
|
||||
|
@@ -45,12 +45,11 @@ void loop() {
|
||||
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
tft.drawFloat(drawTime / 2890.0, 3, 0, 80, 4);
|
||||
if (drawTime < 100) tft.drawString("Font 1 not loaded!", 0, 108, 2);
|
||||
|
||||
|
||||
delay(4000);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
drawTime = millis();
|
||||
drawTime = millis();
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
tft.drawNumber(i, 0, 0, 2);
|
||||
@@ -60,12 +59,11 @@ void loop() {
|
||||
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
tft.drawFloat(drawTime / 2890.0, 3, 0, 80, 4);
|
||||
if (drawTime < 200) tft.drawString("Font 2 not loaded!", 0, 108, 2);
|
||||
|
||||
|
||||
delay(4000);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
drawTime = millis();
|
||||
drawTime = millis();
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
tft.drawNumber(i, 0, 0, 4);
|
||||
@@ -75,12 +73,11 @@ void loop() {
|
||||
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
tft.drawFloat(drawTime / 2890.0, 3, 0, 80, 4);
|
||||
if (drawTime < 200) tft.drawString("Font 4 not loaded!", 0, 108, 2);
|
||||
|
||||
|
||||
delay(4000);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
drawTime = millis();
|
||||
drawTime = millis();
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
yield(); tft.drawNumber(i, 0, 0, 6);
|
||||
@@ -90,12 +87,11 @@ void loop() {
|
||||
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
tft.drawFloat(drawTime / 2890.0, 3, 0, 80, 4);
|
||||
if (drawTime < 200) tft.drawString("Font 6 not loaded!", 0, 108, 2);
|
||||
|
||||
|
||||
delay(4000);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
drawTime = millis();
|
||||
drawTime = millis();
|
||||
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
yield(); tft.drawNumber(i, 0, 0, 7);
|
||||
@@ -105,12 +101,11 @@ void loop() {
|
||||
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
tft.drawFloat(drawTime / 2890.0, 3, 0, 80, 4);
|
||||
if (drawTime < 200) tft.drawString("Font 7 not loaded!", 0, 108, 2);
|
||||
|
||||
|
||||
delay(4000);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
drawTime = millis();
|
||||
drawTime = millis();
|
||||
|
||||
for (int i = 0; i < 100; i++) {
|
||||
yield(); tft.drawNumber(i, 0, 0, 8);
|
||||
@@ -120,8 +115,7 @@ void loop() {
|
||||
|
||||
tft.setTextColor(TFT_RED, TFT_BLACK);
|
||||
tft.drawFloat(drawTime / 190.0, 3, 0, 80, 4);
|
||||
if (drawTime < 200) tft.drawString("Font 8 not loaded!", 0, 108, 2);
|
||||
|
||||
|
||||
delay(4000);
|
||||
}
|
||||
|
||||
|
@@ -311,7 +311,7 @@ void loop()
|
||||
// It takes 30ms to calculate the 30,000 random numbers so this is not a true drawPixel speed test
|
||||
for (int i=0; i<10000; i++)
|
||||
{
|
||||
myGLCD.drawPixel(2+random(316), 16+random(209),random(0xFFFF));
|
||||
myGLCD.drawPixel(2+random(TFT_W - 3), 16+random(TFT_H - 31),random(0xFFFF));
|
||||
}
|
||||
#else
|
||||
// Draw 10,000 pixels to fill a 100x100 pixel box, better drawPixel speed test
|
||||
|
@@ -20,7 +20,7 @@ uint8_t __attribute__((always_inline)) rng()
|
||||
zx++;
|
||||
za = (za^zc^zx);
|
||||
zb = (zb+za);
|
||||
zc = (zc+(zb>>1)^za);
|
||||
zc = ((zc+(zb>>1))^za);
|
||||
return zc;
|
||||
}
|
||||
|
||||
|
116
examples/Generic/Viewport_Demo/Viewport_Demo.ino
Normal file
116
examples/Generic/Viewport_Demo/Viewport_Demo.ino
Normal file
@@ -0,0 +1,116 @@
|
||||
// Viewport Demo
|
||||
|
||||
// See viewport_commands tab for details of functions available
|
||||
|
||||
// This example uses the viewport commands to create a "virtual TFT" within the
|
||||
// normal TFT display area. This allows a sketch written for a smaller screen to
|
||||
// be run in a viewport window. By default, the graphics 0,0 datum is set to the
|
||||
// top left corner of the viewport, but optionally the datum can be kept at the
|
||||
// corner of the TFT.
|
||||
|
||||
// Viewports have a number of potential uses:
|
||||
// - create a "virtual" TFT screen smaller than the actual TFT screen
|
||||
// - render GUI items (menus etc) in a viewport, erase GUI item by redrawing whole screen,
|
||||
// this will be fast because only the viewport will be refreshed (e.g. clearing menu)
|
||||
// - limit screen refresh to a particular area, e.g. changing numbers, icons or graph plotting
|
||||
// - showing a small portion of a larger image or sprite, this allows panning and scrolling
|
||||
|
||||
// A viewport can have the coordinate datum (position 0,0) either at the top left corner of
|
||||
// the viewport or at the normal top left corner of the TFT.
|
||||
// Putting the coordinate datum at the viewport corner means that functions that draw graphics
|
||||
// in a fixed position can be relocated anywhere on the screen. (see plotBox() below). This
|
||||
// makes it easier to reposition groups of graphical objects (for example GUI buttons) that have
|
||||
// fixed relative positions.
|
||||
|
||||
// The viewport position x, and y coordinates and viewport bounds must be constrained by the
|
||||
// user sketch to be within the screen boundaries.
|
||||
|
||||
#include <SPI.h>
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
|
||||
tft.init();
|
||||
tft.setRotation(1);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
// Normal Screen
|
||||
drawX();
|
||||
|
||||
delay(2000);
|
||||
|
||||
// Viewport screen
|
||||
tft.setViewport(10, 10, 140, 100);
|
||||
tft.frameViewport(TFT_NAVY, -2);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
drawX();
|
||||
tft.resetViewport();
|
||||
|
||||
delay(2000);
|
||||
|
||||
//Normal screen
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
drawX();
|
||||
|
||||
delay(2000);
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// Viewport as a clipping window (false parameter means coordinate datum stays at TFT top left)
|
||||
tft.setViewport(10, 10, tft.width()/2 - 10, tft.height() - 20, false);
|
||||
//tft.frameViewport(TFT_NAVY, 2); // Add 2 pixel border inside viewport
|
||||
//tft.frameViewport(TFT_NAVY, -2); // Add 2 pixel border outside viewport
|
||||
drawX();
|
||||
|
||||
delay(2000);
|
||||
|
||||
while(1)
|
||||
{
|
||||
tft.resetViewport(); // Reset viewport so width() and height() return TFT size
|
||||
|
||||
uint16_t w = 40;
|
||||
uint16_t h = 40;
|
||||
uint16_t x = random(tft.width() - w);
|
||||
uint16_t y = random(tft.height() - h);
|
||||
|
||||
tft.setViewport(x, y, w, h);
|
||||
|
||||
plotBox();
|
||||
|
||||
delay(0);
|
||||
}
|
||||
}
|
||||
|
||||
void drawX(void)
|
||||
{
|
||||
tft.fillScreen(tft.color565(25,25,25)); // Grey
|
||||
|
||||
// Draw circle
|
||||
tft.drawCircle(tft.width()/2, tft.height()/2, tft.width()/4, TFT_RED);
|
||||
|
||||
// Draw diagonal lines
|
||||
tft.drawLine(0 , 0, tft.width()-1, tft.height()-1, TFT_GREEN);
|
||||
tft.drawLine(0 , tft.height()-1, tft.width()-1, 0, TFT_BLUE);
|
||||
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE, tft.color565(25,25,25));
|
||||
tft.drawString("Hello World!", tft.width()/2, tft.height()/2, 4); // Font 4
|
||||
}
|
||||
|
||||
void plotBox(void)
|
||||
{
|
||||
// These are always plotted at a fixed position but they can
|
||||
// be plotted into a viewport anywhere on the screen because
|
||||
// a viewport can move the screen datum
|
||||
tft.fillScreen(TFT_BLACK); // When a viewport is set, this just fills the viewport
|
||||
tft.drawRect(0,0, 40,40, TFT_BLUE);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.setTextColor(TFT_WHITE);
|
||||
tft.drawNumber( random(100), 20, 23, 4); // Number in font 4
|
||||
}
|
40
examples/Generic/Viewport_Demo/Viewport_commands.ino
Normal file
40
examples/Generic/Viewport_Demo/Viewport_commands.ino
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
// Create a viewport at TFT screen coordinated X,Y of width W and height H
|
||||
tft.setViewport(X, Y, W, H); // By default the 0,0 coordinate datum is moved to top left
|
||||
// corner of viewport
|
||||
// Note: tft.width() and tft.height() now return viewport size!
|
||||
// The above command is identical to:
|
||||
tft.setViewport(VP_X, VP_Y, VP_W, VP_H, true); // true parameter is optional
|
||||
|
||||
// To create a viewport that keeps the coordinate datum at top left of TFT, use false parameter
|
||||
tft.setViewport(VP_X, VP_Y, VP_W, VP_H, false); // Note: tft.width() and tft.height() return TFT size!
|
||||
|
||||
// To get viewport x, y coordinates, width, height and datum position flag
|
||||
int32_t x = tft.getViewportX(); // Always returns viewport x coordinate relative to screen left edge
|
||||
int32_t y = tft.getViewportY(void); // Always returns viewport y coordinate relative to screen top edge
|
||||
int32_t w = tft.getViewportWidth(); // Always returns width of viewport
|
||||
int32_t h = tft.getViewportHeight(); // Always returns height of viewport
|
||||
bool f = tft.getViewportDatum(); // Datum of the viewport (false = TFT corner, true = viewport corner)
|
||||
// To check if all or part of an area is in the viewport
|
||||
checkViewport(x, y, w, h); // Retruns "true" if all or part of area is in viewport
|
||||
|
||||
// To draw a rectangular frame outside viewport of width W (when W is negative)
|
||||
tft.frameViewport(TFT_RED, -W); // Note setting the width to a large negative value will clear the screen
|
||||
// outside the viewport
|
||||
|
||||
// To draw a rectangular frame inside viewport of width W (when W is positive)
|
||||
tft.frameViewport(TFT_RED, W); // Note setting the width to a large positive value will clear the screen
|
||||
// inside the viewport
|
||||
|
||||
// To reset the viewport to the normal TFT full screen
|
||||
tft.resetViewport(); // Note: Graphics will NOT be drawn to the TFT outside a viewport until
|
||||
// this command is used! ( The exception is using the frameViewport command
|
||||
// detailed above with a negative width.)
|
||||
|
||||
// Note:
|
||||
// Using setRotation rotates the whole TFT screen it does not just
|
||||
// rotate the viewport (this is a possible future enhancement).
|
||||
// Redraw all graphics after a rotation since some TFT's do not
|
||||
// re-map the TFT graphics RAM to the screen pixels as expected.
|
||||
*/
|
382
examples/Generic/Viewport_graphicstest/Viewport_graphicstest.ino
Normal file
382
examples/Generic/Viewport_graphicstest/Viewport_graphicstest.ino
Normal file
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
This sketch demonstrates the Adafruit graphicstest sketch running in a
|
||||
viewport (aka window) within the TFT screen area. To do this line 37 has
|
||||
been added. Line 39 draws a frame outside the viewport.
|
||||
|
||||
This sketch uses the GLCD font (font 1) only.
|
||||
|
||||
Make sure all the display driver and pin comnenctions are correct by
|
||||
editting the User_Setup.h file in the TFT_eSPI library folder.
|
||||
|
||||
#########################################################################
|
||||
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
|
||||
#########################################################################
|
||||
*/
|
||||
|
||||
|
||||
#include "SPI.h"
|
||||
#include "TFT_eSPI.h"
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
unsigned long total = 0;
|
||||
unsigned long tn = 0;
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial);
|
||||
|
||||
Serial.println(""); Serial.println("");
|
||||
Serial.println("TFT_eSPI library test!");
|
||||
|
||||
tft.init();
|
||||
|
||||
tn = micros();
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// Create a viewport 220 x 300 pixels
|
||||
tft.setViewport(10,10,220,300);
|
||||
|
||||
tft.frameViewport(TFT_RED, -1); // 1 pixel wide frame around viewport
|
||||
|
||||
yield(); Serial.println(F("Benchmark Time (microseconds)"));
|
||||
|
||||
yield(); Serial.print(F("Screen fill "));
|
||||
yield(); Serial.println(testFillScreen());
|
||||
//total+=testFillScreen();
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.print(F("Text "));
|
||||
yield(); Serial.println(testText());
|
||||
//total+=testText();
|
||||
//delay(3000);
|
||||
|
||||
yield(); Serial.print(F("Lines "));
|
||||
yield(); Serial.println(testLines(TFT_CYAN));
|
||||
//total+=testLines(TFT_CYAN);
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.print(F("Horiz/Vert Lines "));
|
||||
yield(); Serial.println(testFastLines(TFT_RED, TFT_BLUE));
|
||||
//total+=testFastLines(TFT_RED, TFT_BLUE);
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.print(F("Rectangles (outline) "));
|
||||
yield(); Serial.println(testRects(TFT_GREEN));
|
||||
//total+=testRects(TFT_GREEN);
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.print(F("Rectangles (filled) "));
|
||||
yield(); Serial.println(testFilledRects(TFT_YELLOW, TFT_MAGENTA));
|
||||
//total+=testFilledRects(TFT_YELLOW, TFT_MAGENTA);
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.print(F("Circles (filled) "));
|
||||
yield(); Serial.println(testFilledCircles(10, TFT_MAGENTA));
|
||||
//total+= testFilledCircles(10, TFT_MAGENTA);
|
||||
|
||||
yield(); Serial.print(F("Circles (outline) "));
|
||||
yield(); Serial.println(testCircles(10, TFT_WHITE));
|
||||
//total+=testCircles(10, TFT_WHITE);
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.print(F("Triangles (outline) "));
|
||||
yield(); Serial.println(testTriangles());
|
||||
//total+=testTriangles();
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.print(F("Triangles (filled) "));
|
||||
yield(); Serial.println(testFilledTriangles());
|
||||
//total += testFilledTriangles();
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.print(F("Rounded rects (outline) "));
|
||||
yield(); Serial.println(testRoundRects());
|
||||
//total+=testRoundRects();
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.print(F("Rounded rects (filled) "));
|
||||
yield(); Serial.println(testFilledRoundRects());
|
||||
//total+=testFilledRoundRects();
|
||||
//delay(500);
|
||||
|
||||
yield(); Serial.println(F("Done!")); yield();
|
||||
//Serial.print(F("Total = ")); Serial.println(total);
|
||||
|
||||
//yield();Serial.println(millis()-tn);
|
||||
}
|
||||
|
||||
void loop(void) {
|
||||
for (uint8_t rotation = 0; rotation < 4; rotation++) {
|
||||
tft.setRotation(rotation);
|
||||
tft.resetViewport(); // reset viewport to whole screen
|
||||
tft.fillScreen(TFT_BLACK); // so it can be cleared
|
||||
|
||||
// Create a viewport 220 x 300 pixels
|
||||
tft.setViewport(10,10,220,300);
|
||||
tft.frameViewport(TFT_RED, -1); // 1 pixel wide frame around viewport
|
||||
|
||||
testText();
|
||||
delay(2000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned long testFillScreen() {
|
||||
unsigned long start = micros();
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
tft.fillScreen(TFT_RED);
|
||||
tft.fillScreen(TFT_GREEN);
|
||||
tft.fillScreen(TFT_BLUE);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testText() {
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
unsigned long start = micros();
|
||||
tft.setCursor(0, 0);
|
||||
tft.setTextColor(TFT_WHITE); tft.setTextSize(1);
|
||||
tft.println("Hello World!");
|
||||
tft.setTextColor(TFT_YELLOW); tft.setTextSize(2);
|
||||
tft.println(1234.56);
|
||||
tft.setTextColor(TFT_RED); tft.setTextSize(3);
|
||||
tft.println(0xDEADBEEF, HEX);
|
||||
tft.println();
|
||||
tft.setTextColor(TFT_GREEN);
|
||||
tft.setTextSize(5);
|
||||
tft.println("Groop");
|
||||
tft.setTextSize(2);
|
||||
tft.println("I implore thee,");
|
||||
//tft.setTextColor(TFT_GREEN,TFT_BLACK);
|
||||
tft.setTextSize(1);
|
||||
tft.println("my foonting turlingdromes.");
|
||||
tft.println("And hooptiously drangle me");
|
||||
tft.println("with crinkly bindlewurdles,");
|
||||
tft.println("Or I will rend thee");
|
||||
tft.println("in the gobberwarts");
|
||||
tft.println("with my blurglecruncheon,");
|
||||
tft.println("see if I don't!");
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testLines(uint16_t color) {
|
||||
unsigned long start, t;
|
||||
int x1, y1, x2, y2,
|
||||
w = tft.width(),
|
||||
h = tft.height();
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
x1 = y1 = 0;
|
||||
y2 = h - 1;
|
||||
start = micros();
|
||||
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
x2 = w - 1;
|
||||
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
t = micros() - start; // fillScreen doesn't count against timing
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
x1 = w - 1;
|
||||
y1 = 0;
|
||||
y2 = h - 1;
|
||||
start = micros();
|
||||
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
x2 = 0;
|
||||
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
t += micros() - start;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
x1 = 0;
|
||||
y1 = h - 1;
|
||||
y2 = 0;
|
||||
start = micros();
|
||||
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
x2 = w - 1;
|
||||
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
t += micros() - start;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
x1 = w - 1;
|
||||
y1 = h - 1;
|
||||
y2 = 0;
|
||||
start = micros();
|
||||
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
x2 = 0;
|
||||
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testFastLines(uint16_t color1, uint16_t color2) {
|
||||
unsigned long start;
|
||||
int x, y, w = tft.width(), h = tft.height();
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
start = micros();
|
||||
for (y = 0; y < h; y += 5) tft.drawFastHLine(0, y, w, color1);
|
||||
for (x = 0; x < w; x += 5) tft.drawFastVLine(x, 0, h, color2);
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testRects(uint16_t color) {
|
||||
unsigned long start;
|
||||
int n, i, i2,
|
||||
cx = tft.width() / 2,
|
||||
cy = tft.height() / 2;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
n = min(tft.width(), tft.height());
|
||||
start = micros();
|
||||
for (i = 2; i < n; i += 6) {
|
||||
i2 = i / 2;
|
||||
tft.drawRect(cx - i2, cy - i2, i, i, color);
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
|
||||
unsigned long start, t = 0;
|
||||
int n, i, i2,
|
||||
cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
n = min(tft.width(), tft.height());
|
||||
for (i = n - 1; i > 0; i -= 6) {
|
||||
i2 = i / 2;
|
||||
start = micros();
|
||||
tft.fillRect(cx - i2, cy - i2, i, i, color1);
|
||||
t += micros() - start;
|
||||
// Outlines are not included in timing results
|
||||
tft.drawRect(cx - i2, cy - i2, i, i, color2);
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
|
||||
unsigned long start;
|
||||
int x, y, w = tft.width(), h = tft.height(), r2 = radius * 2;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
start = micros();
|
||||
for (x = radius; x < w; x += r2) {
|
||||
for (y = radius; y < h; y += r2) {
|
||||
tft.fillCircle(x, y, radius, color);
|
||||
}
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testCircles(uint8_t radius, uint16_t color) {
|
||||
unsigned long start;
|
||||
int x, y, r2 = radius * 2,
|
||||
w = tft.width() + radius,
|
||||
h = tft.height() + radius;
|
||||
|
||||
// Screen is not cleared for this one -- this is
|
||||
// intentional and does not affect the reported time.
|
||||
start = micros();
|
||||
for (x = 0; x < w; x += r2) {
|
||||
for (y = 0; y < h; y += r2) {
|
||||
tft.drawCircle(x, y, radius, color);
|
||||
}
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testTriangles() {
|
||||
unsigned long start;
|
||||
int n, i, cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
n = min(cx, cy);
|
||||
start = micros();
|
||||
for (i = 0; i < n; i += 5) {
|
||||
tft.drawTriangle(
|
||||
cx , cy - i, // peak
|
||||
cx - i, cy + i, // bottom left
|
||||
cx + i, cy + i, // bottom right
|
||||
tft.color565(0, 0, i));
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testFilledTriangles() {
|
||||
unsigned long start, t = 0;
|
||||
int i, cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
start = micros();
|
||||
for (i = min(cx, cy); i > 10; i -= 5) {
|
||||
start = micros();
|
||||
tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
|
||||
tft.color565(0, i, i));
|
||||
t += micros() - start;
|
||||
tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
|
||||
tft.color565(i, i, 0));
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
unsigned long testRoundRects() {
|
||||
unsigned long start;
|
||||
int w, i, i2,
|
||||
cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
w = min(tft.width(), tft.height());
|
||||
start = micros();
|
||||
for (i = 0; i < w; i += 6) {
|
||||
i2 = i / 2;
|
||||
tft.drawRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(i, 0, 0));
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
unsigned long testFilledRoundRects() {
|
||||
unsigned long start;
|
||||
int i, i2,
|
||||
cx = tft.width() / 2 - 1,
|
||||
cy = tft.height() / 2 - 1;
|
||||
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
start = micros();
|
||||
for (i = min(tft.width(), tft.height()); i > 20; i -= 6) {
|
||||
i2 = i / 2;
|
||||
tft.fillRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(0, i, 0));
|
||||
}
|
||||
|
||||
return micros() - start;
|
||||
}
|
||||
|
||||
/***************************************************
|
||||
Original Adafruit text:
|
||||
|
||||
This is an example sketch for the Adafruit 2.2" SPI display.
|
||||
This library works with the Adafruit 2.2" TFT Breakout w/SD card
|
||||
----> http://www.adafruit.com/products/1480
|
||||
|
||||
Check out the links above for our tutorials and wiring diagrams
|
||||
These displays use SPI to communicate, 4 or 5 pins are required to
|
||||
interface (RST is optional)
|
||||
Adafruit invests time and resources providing this open source code,
|
||||
please support Adafruit and open-source hardware by purchasing
|
||||
products from Adafruit!
|
||||
|
||||
Written by Limor Fried/Ladyada for Adafruit Industries.
|
||||
MIT license, all text above must be included in any redistribution
|
||||
****************************************************/
|
@@ -132,7 +132,7 @@ void loop() {
|
||||
for (int16_t angle = 30; angle <= 360; angle += 30)
|
||||
{
|
||||
spr.fillSprite(TFT_BLACK); // Clear the Sprite
|
||||
spr.drawNumber(num, 20, 15, 4); // Plot number, in Sprite at 15,15 and with font 4
|
||||
spr.drawNumber(num, 20, 15, 4); // Plot number, in Sprite at 20,15 and with font 4
|
||||
spr.pushRotated(angle, TFT_BLACK); // Plot rotated Sprite, black being transparent
|
||||
num++;
|
||||
}
|
||||
@@ -143,7 +143,7 @@ void loop() {
|
||||
for (int16_t angle = -90; angle < 270; angle += 30)
|
||||
{
|
||||
spr.fillSprite(TFT_BLACK); // Clear the Sprite
|
||||
spr.drawNumber(angle+90, 15, 15, 4); // Plot number, in Sprite at 15,15 and with font 4
|
||||
spr.drawNumber(angle+90, 20, 15, 4); // Plot number, in Sprite at 20,15 and with font 4
|
||||
spr.pushRotated(angle, TFT_BLACK); // Plot rotated Sprite, black being transparent
|
||||
num++;
|
||||
}
|
||||
|
10
keywords.txt
10
keywords.txt
@@ -17,6 +17,16 @@ getRotation KEYWORD2
|
||||
invertDisplay KEYWORD2
|
||||
setAddrWindow KEYWORD2
|
||||
setWindow KEYWORD2
|
||||
|
||||
setViewport KEYWORD2
|
||||
resetViewport KEYWORD2
|
||||
getViewportX KEYWORD2
|
||||
getViewportY KEYWORD2
|
||||
getViewportWidth KEYWORD2
|
||||
getViewportHeight KEYWORD2
|
||||
getViewportDatum KEYWORD2
|
||||
frameViewport KEYWORD2
|
||||
|
||||
pushColor KEYWORD2
|
||||
pushColors KEYWORD2
|
||||
pushBlock KEYWORD2
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "TFT_eSPI",
|
||||
"version": "2.2.23",
|
||||
"version": "2.3.2",
|
||||
"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":
|
||||
|
@@ -1,5 +1,5 @@
|
||||
name=TFT_eSPI
|
||||
version=2.2.23
|
||||
version=2.3.2
|
||||
author=Bodmer
|
||||
maintainer=Bodmer
|
||||
sentence=TFT graphics library for Arduino processors with performance optimisation for STM32, ESP8266 and ESP32
|
||||
|
Reference in New Issue
Block a user