Commit b5826586 authored by Bodmer's avatar Bodmer

Allow 4bpp Sprites to be rotated

4bpp Sprites can now be pushed to the TFT with a rotation
parent 960ff6c7
...@@ -59,8 +59,6 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) ...@@ -59,8 +59,6 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames)
_iwidth = _dwidth = _bitwidth = w; _iwidth = _dwidth = _bitwidth = w;
_iheight = _dheight = h; _iheight = _dheight = h;
_colorMap = nullptr;
this->cursor_x = 0; this->cursor_x = 0;
this->cursor_y = 0; this->cursor_y = 0;
...@@ -94,6 +92,8 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames) ...@@ -94,6 +92,8 @@ void* TFT_eSprite::createSprite(int16_t w, int16_t h, uint8_t frames)
_img8_2 = _img8 + (w * h + 1); _img8_2 = _img8 + (w * h + 1);
} }
if ( (_bpp == 4) && (_colorMap == nullptr)) createPalette(default_4bit_palette);
// This is to make it clear what pointer size is expected to be used // This is to make it clear what pointer size is expected to be used
// but casting in the user sketch is needed due to the use of void* // but casting in the user sketch is needed due to the use of void*
if ( (_bpp == 1) && (frames > 1) ) if ( (_bpp == 1) && (frames > 1) )
...@@ -195,7 +195,7 @@ void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames) ...@@ -195,7 +195,7 @@ void* TFT_eSprite::callocSprite(int16_t w, int16_t h, uint8_t frames)
** Description: Set a palette for a 4-bit per pixel sprite ** Description: Set a palette for a 4-bit per pixel sprite
*************************************************************************************x*/ *************************************************************************************x*/
void TFT_eSprite::createPalette(uint16_t colorMap[], int colors) void TFT_eSprite::createPalette(uint16_t colorMap[], uint8_t colors)
{ {
if (_colorMap != nullptr) if (_colorMap != nullptr)
{ {
...@@ -204,14 +204,18 @@ void TFT_eSprite::createPalette(uint16_t colorMap[], int colors) ...@@ -204,14 +204,18 @@ void TFT_eSprite::createPalette(uint16_t colorMap[], int colors)
if (colorMap == nullptr) if (colorMap == nullptr)
{ {
return; // do nothing other than clear the existing map // Create a color map using the default FLASH map
createPalette(default_4bit_palette);
return;
} }
// allocate color map // Allocate and clear memory for 16 color map
_colorMap = (uint16_t *)calloc(16, sizeof(uint16_t)); _colorMap = (uint16_t *)calloc(16, sizeof(uint16_t));
if (colors > 16)
colors = 16; if (colors > 16) colors = 16;
for (auto i = 0; i < colors; i++)
// Copy map colors
for (uint8_t i = 0; i < colors; i++)
{ {
_colorMap[i] = colorMap[i]; _colorMap[i] = colorMap[i];
} }
...@@ -222,7 +226,7 @@ void TFT_eSprite::createPalette(uint16_t colorMap[], int colors) ...@@ -222,7 +226,7 @@ void TFT_eSprite::createPalette(uint16_t colorMap[], int colors)
** Description: Set a palette for a 4-bit per pixel sprite ** Description: Set a palette for a 4-bit per pixel sprite
*************************************************************************************x*/ *************************************************************************************x*/
void TFT_eSprite::createPalette(const uint16_t colorMap[], int colors) void TFT_eSprite::createPalette(const uint16_t colorMap[], uint8_t colors)
{ {
if (_colorMap != nullptr) if (_colorMap != nullptr)
{ {
...@@ -231,14 +235,17 @@ void TFT_eSprite::createPalette(const uint16_t colorMap[], int colors) ...@@ -231,14 +235,17 @@ void TFT_eSprite::createPalette(const uint16_t colorMap[], int colors)
if (colorMap == nullptr) if (colorMap == nullptr)
{ {
return; // do nothing other than clear the existing map // Create a color map using the default FLASH map
colorMap = default_4bit_palette;
} }
// allocate color map // Allocate and clear memory for 16 color map
_colorMap = (uint16_t *)calloc(16, sizeof(uint16_t)); _colorMap = (uint16_t *)calloc(16, sizeof(uint16_t));
if (colors > 16)
colors = 16; if (colors > 16) colors = 16;
for (auto i = 0; i < colors; i++)
// Copy map colors
for (uint8_t i = 0; i < colors; i++)
{ {
_colorMap[i] = pgm_read_word(colorMap++); _colorMap[i] = pgm_read_word(colorMap++);
} }
...@@ -306,7 +313,7 @@ int8_t TFT_eSprite::getColorDepth(void) ...@@ -306,7 +313,7 @@ int8_t TFT_eSprite::getColorDepth(void)
/*************************************************************************************** /***************************************************************************************
** Function name: setBitmapColor ** Function name: setBitmapColor
** Description: Set the foreground foreground and background colour ** Description: Set the 1bpp foreground foreground and background colour
***************************************************************************************/ ***************************************************************************************/
void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b) void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b)
{ {
...@@ -317,23 +324,22 @@ void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b) ...@@ -317,23 +324,22 @@ void TFT_eSprite::setBitmapColor(uint16_t c, uint16_t b)
/*************************************************************************************** /***************************************************************************************
** Function name: setPaletteColor ** Function name: setPaletteColor
** Description: Set the palette color at the given index ** Description: Set the 4bpp palette color at the given index
***************************************************************************************/ ***************************************************************************************/
void TFT_eSprite::setPaletteColor(uint8_t index, uint16_t color) void TFT_eSprite::setPaletteColor(uint8_t index, uint16_t color)
{ {
if (_colorMap == nullptr || index > 15) if (_colorMap == nullptr || index > 15) return; // out of bounds
return; // out of bounds
_colorMap[index] = color; _colorMap[index] = color;
} }
/*************************************************************************************** /***************************************************************************************
** Function name: getPaletteColor ** Function name: getPaletteColor
** Description: Return the palette color at index, or 0 (black) on error. ** Description: Return the palette color at 4bpp index, or 0 on error.
***************************************************************************************/ ***************************************************************************************/
uint16_t TFT_eSprite::getPaletteColor(uint8_t index) uint16_t TFT_eSprite::getPaletteColor(uint8_t index)
{ {
if (_colorMap == nullptr || index > 15) if (_colorMap == nullptr || index > 15) return 0; // out of bounds
return 0;
return _colorMap[index]; return _colorMap[index];
} }
...@@ -395,7 +401,7 @@ int16_t TFT_eSprite::getPivotY(void) ...@@ -395,7 +401,7 @@ int16_t TFT_eSprite::getPivotY(void)
#define FP_SCALE 10 #define FP_SCALE 10
bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp)
{ {
if ( !_created || _bpp == 4) return false; if ( !_created) return false;
// Bounding box parameters // Bounding box parameters
int16_t min_x; int16_t min_x;
...@@ -413,6 +419,7 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) ...@@ -413,6 +419,7 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp)
uint32_t xe = _iwidth << FP_SCALE; uint32_t xe = _iwidth << FP_SCALE;
uint32_t ye = _iheight << FP_SCALE; uint32_t ye = _iheight << FP_SCALE;
uint32_t tpcolor = transp; // convert to unsigned uint32_t tpcolor = transp; // convert to unsigned
if (_bpp == 4) tpcolor = _colorMap[transp & 0x0F];
_tft->startWrite(); // Avoid transaction overhead for every tft pixel _tft->startWrite(); // Avoid transaction overhead for every tft pixel
...@@ -461,6 +468,7 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp) ...@@ -461,6 +468,7 @@ bool TFT_eSprite::pushRotated(int16_t angle, int32_t transp)
** Function name: pushRotated - Fast fixed point integer maths version ** Function name: pushRotated - Fast fixed point integer maths version
** Description: Push a rotated copy of the Sprite to another Sprite ** Description: Push a rotated copy of the Sprite to another Sprite
*************************************************************************************x*/ *************************************************************************************x*/
// Not compatible with 4bpp
bool TFT_eSprite::pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp) bool TFT_eSprite::pushRotated(TFT_eSprite *spr, int16_t angle, int32_t transp)
{ {
if ( !_created || _bpp == 4) return false; // Check this Sprite is created if ( !_created || _bpp == 4) return false; // Check this Sprite is created
...@@ -658,12 +666,8 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y) ...@@ -658,12 +666,8 @@ void TFT_eSprite::pushSprite(int32_t x, int32_t y)
} }
else if (_bpp == 4) else if (_bpp == 4)
{ {
if (_colorMap == nullptr) {
return;
}
_tft->pushImage(x, y, _dwidth, _dheight, _img4, false, _colorMap); _tft->pushImage(x, y, _dwidth, _dheight, _img4, false, _colorMap);
} }
else _tft->pushImage(x, y, _dwidth, _dheight, _img8, (bool)(_bpp == 8)); else _tft->pushImage(x, y, _dwidth, _dheight, _img8, (bool)(_bpp == 8));
} }
......
...@@ -15,6 +15,7 @@ class TFT_eSprite : public TFT_eSPI { ...@@ -15,6 +15,7 @@ class TFT_eSprite : public TFT_eSPI {
// Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed // Sketch can cast returned value to (uint16_t*) for 16 bit depth if needed
// RAM required is: // RAM required is:
// - 1 bit per pixel for 1 bit colour depth // - 1 bit per pixel for 1 bit colour depth
// - 1 nibble per pixel for 4 bit colour
// - 1 byte per pixel for 8 bit colour // - 1 byte per pixel for 8 bit colour
// - 2 bytes per pixel for 16 bit color depth // - 2 bytes per pixel for 16 bit color depth
~TFT_eSprite(void); ~TFT_eSprite(void);
...@@ -34,8 +35,8 @@ class TFT_eSprite : public TFT_eSPI { ...@@ -34,8 +35,8 @@ class TFT_eSprite : public TFT_eSPI {
int8_t getColorDepth(void); int8_t getColorDepth(void);
// Set the palette for a 4 bit depth sprite. Only the first 16 colours in the map are used. // Set the palette for a 4 bit depth sprite. Only the first 16 colours in the map are used.
void createPalette(uint16_t *palette, int colors = 16); // Palette in RAM void createPalette(uint16_t *palette = nullptr, uint8_t colors = 16); // Palette in RAM
void createPalette(const uint16_t *palette, int colors = 16); // Palette in FLASH void createPalette(const uint16_t *palette = nullptr, uint8_t colors = 16); // Palette in FLASH
// Set a single palette index to the given color // Set a single palette index to the given color
void setPaletteColor(uint8_t index, uint16_t color); void setPaletteColor(uint8_t index, uint16_t color);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
// screen very simple. The rotation is clockwise with increasing angle. The angle is in // screen very simple. The rotation is clockwise with increasing angle. The angle is in
// degrees, an angle of 0 means no Sprite rotation. // degrees, an angle of 0 means no Sprite rotation.
// The pushRotated() function works with 1, 8 and 16 bit per pixel (bpp) Sprites. // The pushRotated() function works with 1, 4, 8 and 16 bit per pixel (bpp) Sprites.
// The original Sprite is unchanged so can be plotted again at a different angle. // The original Sprite is unchanged so can be plotted again at a different angle.
...@@ -20,6 +20,10 @@ ...@@ -20,6 +20,10 @@
// For 1 bpp Sprites the foreground and background colours are defined with the // For 1 bpp Sprites the foreground and background colours are defined with the
// function spr.setBitmapColor(foregroundColor, backgroundColor). // function spr.setBitmapColor(foregroundColor, backgroundColor).
// For 4 bpp Sprites the colour map index is used instead of the 16 bit colour
// e.g. spr.setTextColor(5); // Green text in default colour map
// See "Transparent_Sprite_Demo_4bit" example for default colour map details
// Created by Bodmer 6/1/19 as an example to the TFT_eSPI library: // Created by Bodmer 6/1/19 as an example to the TFT_eSPI library:
// https://github.com/Bodmer/TFT_eSPI // https://github.com/Bodmer/TFT_eSPI
...@@ -46,7 +50,7 @@ void setup() { ...@@ -46,7 +50,7 @@ void setup() {
void loop() { void loop() {
int xw = tft.width()/2; // xw, yh is midle of screen int xw = tft.width()/2; // xw, yh is middle of screen
int yh = tft.height()/2; int yh = tft.height()/2;
......
...@@ -88,7 +88,7 @@ void loop(void) ...@@ -88,7 +88,7 @@ void loop(void)
// Pass the palette to the Sprite class // Pass the palette to the Sprite class
spr.createPalette(cmap); spr.createPalette(cmap);
// Push Sprite parially off-screen to test cropping // Push Sprite partially off-screen to test cropping
spr.pushSprite(-40, -40); spr.pushSprite(-40, -40);
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2, 10); spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2, 10);
spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40); spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
......
{ {
"name": "TFT_eSPI", "name": "TFT_eSPI",
"version": "2.2.8", "version": "2.2.9",
"keywords": "Arduino, tft, ePaper, display, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9486, ST7789, RM68140", "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", "description": "A TFT and ePaper SPI graphics library with optimisation for ESP8266, ESP32 and STM32",
"repository": "repository":
......
name=TFT_eSPI name=TFT_eSPI
version=2.2.8 version=2.2.9
author=Bodmer author=Bodmer
maintainer=Bodmer maintainer=Bodmer
sentence=TFT graphics library for Arduino processors with performance optimisation for STM32, ESP8266 and ESP32 sentence=TFT graphics library for Arduino processors with performance optimisation for STM32, ESP8266 and ESP32
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment