|
|
|
@@ -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)
|
|
|
|
@@ -91,50 +111,63 @@ inline void TFT_eSPI::begin_tft_read(void){
|
|
|
|
|
***************************************************************************************/
|
|
|
|
|
void TFT_eSPI::setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDatum)
|
|
|
|
|
{
|
|
|
|
|
// Set to whole screen in case of error
|
|
|
|
|
// 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;
|
|
|
|
|
_vpX = 0;
|
|
|
|
|
_vpY = 0;
|
|
|
|
|
_vpW = _width;
|
|
|
|
|
_vpH = _height;
|
|
|
|
|
|
|
|
|
|
_vpDatum = false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if out of bounds
|
|
|
|
|
if ((x >= _width) || (y >= _height)) return;
|
|
|
|
|
|
|
|
|
|
// Clip
|
|
|
|
|
if (x < 0) { x = 0; }
|
|
|
|
|
if (y < 0) { y = 0; }
|
|
|
|
|
|
|
|
|
|
if ((x + w) > _width ) w = _width - x;
|
|
|
|
|
if ((y + h) > _height) h = _height - y;
|
|
|
|
|
|
|
|
|
|
// Check if out of bounds
|
|
|
|
|
if (w < 1 || h < 1) return;
|
|
|
|
|
|
|
|
|
|
if (vpDatum)
|
|
|
|
|
{
|
|
|
|
|
_xDatum = x;
|
|
|
|
|
_yDatum = y;
|
|
|
|
|
_vpX = 0;
|
|
|
|
|
_vpY = 0;
|
|
|
|
|
_vpW = w;
|
|
|
|
|
_vpH = h;
|
|
|
|
|
_xWidth = _width;
|
|
|
|
|
_yHeight = _height;
|
|
|
|
|
_vpOoB = true; // Set Out of Bounds flag to inhibit all drawing
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
|
|
|
|
|
if (!vpDatum)
|
|
|
|
|
{
|
|
|
|
|
_xDatum = 0;
|
|
|
|
|
_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);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************************
|
|
|
|
@@ -143,15 +176,18 @@ void TFT_eSPI::setViewport(int32_t x, int32_t y, int32_t w, int32_t h, bool vpDa
|
|
|
|
|
***************************************************************************************/
|
|
|
|
|
void TFT_eSPI::resetViewport(void)
|
|
|
|
|
{
|
|
|
|
|
// Set to whole screen
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/***************************************************************************************
|
|
|
|
@@ -198,10 +234,10 @@ void TFT_eSPI::frameViewport(uint16_t color, int32_t w)
|
|
|
|
|
int32_t _hTemp = _vpH; _vpH = _height;
|
|
|
|
|
bool _dTemp = _vpDatum; _vpDatum = false;
|
|
|
|
|
|
|
|
|
|
fillRect(_xDatum + _xTemp - w, _yDatum + _yTemp - w, _wTemp - _xTemp + w + w, w, color);
|
|
|
|
|
fillRect(_xDatum + _xTemp - w, _yDatum + _yTemp, w, _hTemp -_yTemp, color);
|
|
|
|
|
fillRect(_xDatum + _wTemp, _yDatum + _yTemp, w, _hTemp - _yTemp, color);
|
|
|
|
|
fillRect(_xDatum + _xTemp - w, _yDatum + _hTemp, _wTemp - _xTemp + w + w, w, color);
|
|
|
|
|
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;
|
|
|
|
@@ -308,13 +344,8 @@ 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
|
|
|
|
|
|
|
|
|
|
// Set display clip window to whole screen
|
|
|
|
|
_xDatum = 0;
|
|
|
|
|
_yDatum = 0;
|
|
|
|
|
_vpX = 0;
|
|
|
|
|
_vpY = 0;
|
|
|
|
|
_vpW = _width;
|
|
|
|
|
_vpH = _height;
|
|
|
|
|
// Reset the viewport to the whole screen
|
|
|
|
|
resetViewport();
|
|
|
|
|
|
|
|
|
|
rotation = 0;
|
|
|
|
|
cursor_y = cursor_x = 0;
|
|
|
|
@@ -626,17 +657,8 @@ void TFT_eSPI::setRotation(uint8_t m)
|
|
|
|
|
addr_row = 0xFFFF;
|
|
|
|
|
addr_col = 0xFFFF;
|
|
|
|
|
|
|
|
|
|
if (!_vpDatum)
|
|
|
|
|
{
|
|
|
|
|
// Reset viewport to whole screen
|
|
|
|
|
_xDatum = 0;
|
|
|
|
|
_yDatum = 0;
|
|
|
|
|
_vpX = 0;
|
|
|
|
|
_vpY = 0;
|
|
|
|
|
_vpW = _width;
|
|
|
|
|
_vpH = _height;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Reset the viewport to the whole screen
|
|
|
|
|
resetViewport();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -804,6 +826,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;
|
|
|
|
@@ -813,13 +848,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);
|
|
|
|
@@ -924,7 +961,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)
|
|
|
|
|
|
|
|
|
@@ -935,13 +986,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
|
|
|
|
@@ -950,7 +1001,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
|
|
|
|
@@ -1049,21 +1116,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 >= _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;
|
|
|
|
|
PI_CLIP;
|
|
|
|
|
|
|
|
|
|
begin_tft_write();
|
|
|
|
|
inTransaction = true;
|
|
|
|
@@ -1093,21 +1146,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 >= _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;
|
|
|
|
|
PI_CLIP;
|
|
|
|
|
|
|
|
|
|
begin_tft_write();
|
|
|
|
|
inTransaction = true;
|
|
|
|
@@ -1167,20 +1206,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 >= _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;
|
|
|
|
|
PI_CLIP;
|
|
|
|
|
|
|
|
|
|
begin_tft_write();
|
|
|
|
|
inTransaction = true;
|
|
|
|
@@ -1203,7 +1229,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
|
|
|
|
@@ -1211,20 +1236,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 >= _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;
|
|
|
|
|
PI_CLIP;
|
|
|
|
|
|
|
|
|
|
begin_tft_write();
|
|
|
|
|
inTransaction = true;
|
|
|
|
@@ -1280,21 +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, uint8_t *data, bool bpp8, uint16_t *cmap)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
PI_CLIP;
|
|
|
|
|
|
|
|
|
|
begin_tft_write();
|
|
|
|
|
inTransaction = true;
|
|
|
|
@@ -1437,20 +1435,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 >= _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;
|
|
|
|
|
PI_CLIP;
|
|
|
|
|
|
|
|
|
|
begin_tft_write();
|
|
|
|
|
inTransaction = true;
|
|
|
|
@@ -2476,8 +2461,7 @@ uint8_t TFT_eSPI::getTextDatum(void)
|
|
|
|
|
// Return the size of the display (per current rotation)
|
|
|
|
|
int16_t TFT_eSPI::width(void)
|
|
|
|
|
{
|
|
|
|
|
if (_vpDatum) return _vpW - _vpX;
|
|
|
|
|
else return _width;
|
|
|
|
|
return _xWidth;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -2487,8 +2471,7 @@ int16_t TFT_eSPI::width(void)
|
|
|
|
|
***************************************************************************************/
|
|
|
|
|
int16_t TFT_eSPI::height(void)
|
|
|
|
|
{
|
|
|
|
|
if (_vpDatum) return _vpH - _vpY;
|
|
|
|
|
else return _height;
|
|
|
|
|
return _yHeight;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -2628,11 +2611,10 @@ 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 >= _vpW) || // Clip right
|
|
|
|
|
(y >= _vpH) || // Clip bottom
|
|
|
|
|
((x + 6 * size - 1) < _vpX) || // Clip left
|
|
|
|
|
((y + 8 * size - 1) < _vpY)) // Clip top
|
|
|
|
|
return;
|
|
|
|
|
if (_vpOoB) return;
|
|
|
|
|
|
|
|
|
|
int32_t xd = x + _xDatum;
|
|
|
|
|
int32_t yd = y + _yDatum;
|
|
|
|
|
|
|
|
|
|
if (c < 32) return;
|
|
|
|
|
#ifdef LOAD_GLCD
|
|
|
|
@@ -2642,14 +2624,21 @@ void TFT_eSPI::drawChar(int32_t x, int32_t y, uint16_t c, uint32_t color, uint32
|
|
|
|
|
#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 && x >= _vpX && (x + 6 * size - 1) < _vpW) {
|
|
|
|
|
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;
|
|
|
|
@@ -2668,6 +2657,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)
|
|
|
|
@@ -2789,14 +2779,6 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
|
|
|
|
|
{
|
|
|
|
|
//begin_tft_write(); // Must be called before setWindow
|
|
|
|
|
|
|
|
|
|
if( _vpDatum)
|
|
|
|
|
{
|
|
|
|
|
x0+= _xDatum;
|
|
|
|
|
x1+= _xDatum;
|
|
|
|
|
y0+= _yDatum;
|
|
|
|
|
y1+= _yDatum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if defined (SSD1963_DRIVER)
|
|
|
|
|
if ((rotation & 0x1) == 0) { swap_coord(x0, y0); swap_coord(x1, y1); }
|
|
|
|
|
#endif
|
|
|
|
@@ -2870,14 +2852,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)
|
|
|
|
|
{
|
|
|
|
|
// Range checking
|
|
|
|
|
if ((x < _vpX) || (y < _vpY) ||(x >= _vpW) || (y >= _vpH)) return;
|
|
|
|
|
if (_vpOoB) return;
|
|
|
|
|
|
|
|
|
|
if( _vpDatum)
|
|
|
|
|
{
|
|
|
|
|
x+= _xDatum;
|
|
|
|
|
y+= _yDatum;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Range checking
|
|
|
|
|
if ((x < _vpX) || (y < _vpY) ||(x >= _vpW) || (y >= _vpH)) return;
|
|
|
|
|
|
|
|
|
|
#ifdef CGRAM_OFFSET
|
|
|
|
|
x+=colstart;
|
|
|
|
@@ -3077,6 +3058,11 @@ 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 < _vpX) || (x >= _vpW) || (y >= _vpH)) return;
|
|
|
|
|
|
|
|
|
@@ -3102,6 +3088,11 @@ 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 < _vpY) || (x >= _vpW) || (y >= _vpH)) return;
|
|
|
|
|
|
|
|
|
@@ -3127,6 +3118,11 @@ 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 >= _vpW) || (y >= _vpH)) return;
|
|
|
|
|
|
|
|
|
@@ -3138,6 +3134,15 @@ 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;
|
|
|
|
|
|
|
|
|
|
//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);
|
|
|
|
@@ -3581,7 +3586,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
|
|
|
|
@@ -3645,19 +3650,23 @@ int16_t TFT_eSPI::drawChar(uint16_t uniCode, int32_t x, int32_t y, uint8_t font)
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
if (x + width * textsize < (int16_t)_vpX || x >= _vpW) return width * textsize ;
|
|
|
|
|
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 (textcolor == textbgcolor || textsize != 1 || x < _vpX || x + width * textsize >= _vpW) {
|
|
|
|
|
if (textcolor == textbgcolor || textsize != 1 || clip) {
|
|
|
|
|
//begin_tft_write(); // Sprite class can use this function, avoiding begin_tft_write()
|
|
|
|
|
inTransaction = true;
|
|
|
|
|
|
|
|
|
@@ -3698,9 +3707,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++) {
|
|
|
|
@@ -3734,7 +3744,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 && x >= _vpX && x + width * textsize <= _vpW) {
|
|
|
|
|
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
|
|
|
|
@@ -3750,12 +3761,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()?
|
|
|
|
@@ -3768,8 +3779,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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -3781,11 +3792,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 >= _vpX && x + width <= _vpW)
|
|
|
|
|
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) {
|
|
|
|
@@ -3969,11 +3980,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; //*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -4010,7 +4016,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) {
|
|
|
|
|