Add support for 8 bit color sprites (needs less RAM)

Added setColorDepth(d) where "d" is 8 or 16.
Default is 16 bit if not specified.
This commit is contained in:
Bodmer
2017-11-21 22:57:11 +00:00
parent 85698be07f
commit 3e3d638bba
5 changed files with 472 additions and 80 deletions

View File

@@ -91,6 +91,7 @@ justReleased KEYWORD2
TFT_eSprite KEYWORD1
createSprite KEYWORD2
setColorDepth KEYWORD2
deleteSprite KEYWORD2
fillSprite KEYWORD2
setWindow KEYWORD2

View File

@@ -552,11 +552,6 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
if (dw < 0 || dh < 0) return;
//Serial.print("dx="); Serial.println(dx);
//Serial.print("dy="); Serial.println(dy);
//Serial.print("dw="); Serial.println(dw);
//Serial.print("dh="); Serial.println(dh);
spi_begin();
setAddrWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR
@@ -574,6 +569,7 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
*/
uint32_t len = dw * 2;
uint8_t* ptr = (uint8_t*)data;
// Push pixels into window rectangle, data is a 16 bit pointer thus increment is halved
while ( len>32) { SPI.writePattern(ptr, 32, 1); len -= 32; ptr += 32; }
if (len) SPI.writePattern((uint8_t*)ptr, len, 1);
@@ -585,6 +581,65 @@ uint16_t TFT_eSPI::readPixel(int32_t x0, int32_t y0)
spi_end();
}
void TFT_eSPI::pushSprite(int32_t x, int32_t y, uint32_t w, uint32_t h, uint8_t *data)
{
if ((x >= (int32_t)_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 + w) >= _width ) dw = _width - x;
if ((y + h) >= _height) dh = _height - y;
if (dw < 0 || dh < 0) return;
spi_begin();
setAddrWindow(x, y, x + dw - 1, y + dh - 1); // Sets CS low and sent RAMWR
data += dx + dy * w;
#ifdef ESP8266
uint32_t spimask = ~((SPIMMOSI << SPILMOSI) | (SPIMMISO << SPILMISO));
SPI1U1 = (SPI1U1 & spimask) | (15 << SPILMOSI) | (15 << SPILMISO);
#endif
while (dh--)
{
uint32_t len = dw;
uint8_t* ptr = data;
while(len--)
{
uint16_t color = *ptr++;
color = (color & 0xE0)<<8 | (color & 0xC0)<<5
| (color & 0x1C)<<6 | (color & 0x1C)<<3
| (color & 0x03)<<3 | (color & 0x03)<<1 | (color & 0x03)>>1;
#ifdef ESP32
SPI.write16(color);
#else
color = (color<<8) | (color>>8);
SPI1W0 = color;
SPI1CMD |= SPIBUSY;
while(SPI1CMD & SPIBUSY) {}
#endif
}
data += w;
}
CS_H;
spi_end();
}
/***************************************************************************************
** Function name: read rectangle (for SPI Interface II i.e. IM [3:0] = "1101")
@@ -4132,6 +4187,9 @@ TFT_eSprite::TFT_eSprite(TFT_eSPI *tft)
_iwidth = 0; // Initialise width and height to 0 (it does not exist yet)
_iheight = 0;
_bpp16 = true;
_created = false;
_xs = 0; // window bounds for pushColor
_ys = 0;
@@ -4149,13 +4207,30 @@ TFT_eSprite::TFT_eSprite(TFT_eSPI *tft)
** Function name: createSprite
** Description: Create a sprite (bitmap) of defined width and height
*************************************************************************************x*/
uint16_t* TFT_eSprite::createSprite(int16_t w, int16_t h)
void TFT_eSprite::createSprite(int16_t w, int16_t h)
{
if ( w < 1 || h < 1) return 0;
if ( w < 1 || h < 1) return;
_iwidth = w;
_iheight = h;
_img = (uint16_t*) malloc(w * h * sizeof(uint16_t));
return _img;
if(_bpp16) _img = (uint16_t*) malloc(w * h * 2);
else _img8 = ( uint8_t*) malloc(w * h);
_created = true;
}
/***************************************************************************************
** Function name: setDepth
** Description: Set bits per pixel for colour (8 or 16)
*************************************************************************************x*/
void TFT_eSprite::setColorDepth(int8_t b)
{
if (_created) deleteSprite();
if ( b > 8 ) _bpp16 = true; // Bytes per pixel
else _bpp16 = false;
}
@@ -4165,7 +4240,10 @@ uint16_t* TFT_eSprite::createSprite(int16_t w, int16_t h)
*************************************************************************************x*/
void TFT_eSprite::deleteSprite(void)
{
free(_img);
if (!_created ) return;
if (_bpp16) free(_img);
else free(_img8);
_created = false;
}
@@ -4175,20 +4253,32 @@ void TFT_eSprite::deleteSprite(void)
*************************************************************************************x*/
void TFT_eSprite::pushSprite(int32_t x, int32_t y)
{
_tft->pushSprite(x, y, _iwidth, _iheight, _img);
if (_bpp16) _tft->pushSprite(x, y, _iwidth, _iheight, _img );
else _tft->pushSprite(x, y, _iwidth, _iheight, _img8);
}
/***************************************************************************************
** Function name: readPixel
** Description: Read 565 colour of a pixel at deined coordinates
** Description: Read 565 colour of a pixel at defined coordinates
*************************************************************************************x*/
uint16_t TFT_eSprite::readPixel(int32_t x, int32_t y)
{
if (_bpp16)
{
uint16_t color = _img[x + y * _iwidth];
return (color >> 8) | (color << 8);
}
uint16_t color = _img8[x + y * _iwidth];
if (color != 0)
color = (color & 0xE0)<<8 | (color & 0xC0)<<5
| (color & 0x1C)<<6 | (color & 0x1C)<<3
| (color & 0x03)<<3 | (color & 0x03)<<1 | (color & 0x03)>>1;
return color;
}
/***************************************************************************************
** Function name: pushRect (same as pushBitmap)
@@ -4198,6 +4288,8 @@ void TFT_eSprite::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint
{
if ((x > _iwidth) || (y > _iheight) || (w == 0) || (h == 0)) return;
if (_bpp16)
{
for (uint32_t yp = y; yp < y + h; yp++)
{
for (uint32_t xp = x; xp < x + w; xp++)
@@ -4206,6 +4298,18 @@ void TFT_eSprite::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint
}
}
}
else
{
for (uint32_t yp = y; yp < y + h; yp++)
{
for (uint32_t xp = x; xp < x + w; xp++)
{
uint16_t color = *data++;
_img8[xp + yp * _iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3);
}
}
}
}
/***************************************************************************************
@@ -4214,28 +4318,29 @@ void TFT_eSprite::pushRect(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint
***************************************************************************************/
void TFT_eSprite::pushBitmap(uint32_t x, uint32_t y, uint32_t w, uint32_t h, uint16_t *data)
{
if ((x > _iwidth) || (y > _iheight) || (w == 0) || (h == 0)) return;
for (uint32_t yp = y; yp < y + h; yp++)
{
for (uint32_t xp = x; xp < x + w; xp++)
{
_img[xp + yp * _iwidth] = *data++;
}
}
pushRect(x, y, w, h, data);
}
/***************************************************************************************
** Function name: spriteWindow
** Description: Set the bounds of a window for pushColor
** Function name: setWindow
** Description: Set the bounds of a window for pushColor and writeColor
*************************************************************************************x*/
void TFT_eSprite::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
{
// Bounds will be checked by drawPixel
if (x0 > x1) swap_coord(x0, x1);
if (y0 > y1) swap_coord(y0, y1);
if (x0 < 0) x0 = 0;
if (x0 >= _iwidth) x0 = _iwidth;
if (x1 < 0) x1 = 0;
if (x1 >= _iwidth) x1 = _iwidth;
if (y0 < 0) y0 = 0;
if (y0 >= _iheight) y0 = _iheight;
if (y1 < 0) y1 = 0;
if (y1 >= _iheight) y1 = _iheight;
_xs = x0;
_ys = y0;
_xe = x1;
@@ -4248,20 +4353,69 @@ void TFT_eSprite::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1)
/***************************************************************************************
** Function name: pushColor
** Description: Send a new pixel to the sprite window
** Description: Send a new pixel to the set window
*************************************************************************************x*/
void TFT_eSprite::pushColor(uint32_t color)
{
drawPixel(_xptr++, _yptr, color);
if (_xptr > _xe) { _xptr = _xs; _yptr++; }
if (_yptr > _ye) { _yptr = _ys; }
// Write the colour to RAM in set window
if (_bpp16)
_img [_xptr + _yptr * _iwidth] = (uint16_t) (color >> 8) | (color << 8);
else
_img8[_xptr + _yptr * _iwidth] = (uint8_t )((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3);
// Increment x
_xptr++;
// Wrap on x and y to start, increment y if needed
if (_xptr > _xe)
{
_xptr = _xs;
_yptr++;
if (_yptr > _ye) _yptr = _ys;
}
}
/***************************************************************************************
** Function name: pushColor
** Description: Send a "len" new pixels to the set window
*************************************************************************************x*/
void TFT_eSprite::pushColor(uint32_t color, uint16_t len)
{
drawPixel(_xptr++, _yptr, color);
if (_xptr > _xe) { _xptr = _xs; _yptr++; }
if (_yptr > _ye) { _yptr = _ys; }
uint16_t pixelColor;
if (_bpp16)
pixelColor = (uint16_t) (color >> 8) | (color << 8);
else
pixelColor = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3;
while(len--) writeColor(pixelColor);
}
/***************************************************************************************
** Function name: writeColor
** Description: Write a pixel with pre-formatted colour to the set window
*************************************************************************************x*/
void TFT_eSprite::writeColor(uint16_t color)
{
// Write 16 bit RGB 565 encoded colour to RAM
if (_bpp16) _img [_xptr + _yptr * _iwidth] = color;
// Write 8 bit RGB 332 encoded colour to RAM
else _img8[_xptr + _yptr * _iwidth] = (uint8_t) color;
// Increment x
_xptr++;
// Wrap on x and y to start, increment y if needed
if (_xptr > _xe)
{
_xptr = _xs;
_yptr++;
if (_yptr > _ye) _yptr = _ys;
}
}
@@ -4272,7 +4426,10 @@ void TFT_eSprite::pushColor(uint32_t color, uint16_t len)
void TFT_eSprite::fillSprite(uint32_t color)
{
// Use memset if possible as it is super fast
if((uint8_t)color == (color>>8)) memset(_img, (uint8_t)color, _iwidth * _iheight * 2);
if(( (uint8_t)color == (uint8_t)(color>>8) ) && _bpp16)
memset(_img, (uint8_t)color, _iwidth * _iheight * 2);
else if (!_bpp16) memset(_img8, (uint8_t)color, _iwidth * _iheight);
else fillRect(0, 0, _iwidth, _iheight, color);
}
@@ -4289,7 +4446,7 @@ void TFT_eSprite::setCursor(int16_t x, int16_t y)
/***************************************************************************************
** Function name: width or spriteWidth
** Function name: width
** Description: Return the width of sprite
*************************************************************************************x*/
// Return the size of the display
@@ -4298,16 +4455,9 @@ int16_t TFT_eSprite::width(void)
return _iwidth;
}
/*
// Return the size of the display
int16_t TFT_eSprite::spriteWidth(void)
{
return _iwidth;
}
*/
/***************************************************************************************
** Function name: height or spriteHeight
** Function name: height
** Description: Return the height of sprite
*************************************************************************************x*/
int16_t TFT_eSprite::height(void)
@@ -4315,12 +4465,6 @@ int16_t TFT_eSprite::height(void)
return _iheight;
}
/*
int16_t TFT_eSprite::spriteHeight(void)
{
return _iheight;
}
*/
/***************************************************************************************
** Function name: drawChar
@@ -4471,9 +4615,17 @@ void TFT_eSprite::drawPixel(uint32_t x, uint32_t y, uint32_t color)
// x and y are unsigned so that -ve coordinates turn into large positive ones
// this make bounds checking a bit faster
if ((x >= _iwidth) || (y >= _iheight)) return;
if (_bpp16)
{
color = (color >> 8) | (color << 8);
_img[x+y*_iwidth] = (uint16_t) color;
}
else
{
_img8[x+y*_iwidth] = (uint8_t)((color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3);
}
}
/***************************************************************************************
@@ -4541,9 +4693,18 @@ void TFT_eSprite::drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color)
if ((y + h) > _iheight) h = _iheight - y;
if (h < 1) return;
if (_bpp16)
{
color = (color >> 8) | (color << 8);
while (h--) _img[x + _iwidth * y++] = (uint16_t) color;
}
else
{
color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3;
while (h--) _img8[x + _iwidth * y++] = (uint8_t) color;
}
}
/***************************************************************************************
@@ -4557,9 +4718,19 @@ void TFT_eSprite::drawFastHLine(int32_t x, int32_t y, int32_t w, uint32_t color)
if ((x + w) > _iwidth) w = _iwidth - x;
if (w < 1) return;
if (_bpp16)
{
color = (color >> 8) | (color << 8);
while (w--) _img[_iwidth * y + x++] = (uint16_t) color;
}
else
{
color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3;
//while (w--) _img8[_iwidth * y + x++] = (uint8_t) color;
memset(_img8+_iwidth * y + x, (uint8_t)color, w);
}
}
/***************************************************************************************
@@ -4574,14 +4745,29 @@ void TFT_eSprite::fillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t
if ((x + w) > _iwidth) w = _iwidth - x;
if ((y + h) > _iheight) h = _iheight - y;
if ((w < 1) || (h < 1)) return;
color = (color >> 8) | (color << 8);
while (h--) {
if (_bpp16)
{
color = (color >> 8) | (color << 8);
while (h--)
{
int32_t ix = x, iw = w;
while (iw--) _img[_iwidth * y + ix++] = (uint16_t) color;
y++;
}
}
else
{
color = (color & 0xE000)>>8 | (color & 0x0700)>>6 | (color & 0x0018)>>3;
while (h--)
{
//int32_t ix = x, iw = w;
//while (iw--) _img8[_iwidth * y + ix++] = (uint8_t) color;
memset(_img8 + _iwidth * y + x, (uint8_t)color, w);
y++;
}
}
}
/***************************************************************************************
@@ -4842,11 +5028,13 @@ int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y, int font)
w *= height; // Now w is total number of pixels in the character
if (textcolor != textbgcolor) fillRect(x, pY, width * textsize, textsize * height, textbgcolor);
int16_t color;
if (_bpp16) color = (textcolor >> 8) | (textcolor << 8);
else color = ((textcolor & 0xE000)>>8 | (textcolor & 0x0700)>>6 | (textcolor & 0x0018)>>3);
int px = 0, py = pY; // To hold character block start and end column and row values
int pc = 0; // Pixel count
byte np = textsize * textsize; // Number of pixels in a drawn pixel
byte tnp = 0; // Temporary copy of np for while loop
byte ts = textsize - 1; // Temporary copy of textsize
// 16 bit pixel count so maximum font size is equivalent to 180x180 pixels in area
// w is total number of pixels to plot to fill character block
@@ -4869,15 +5057,9 @@ int16_t TFT_eSprite::drawChar(unsigned int uniCode, int x, int y, int font)
pc++;
setWindow(px, py, px + ts, py + ts);
if (ts) {
tnp = np;
while (tnp--) {
pushColor(textcolor);
}
}
else {
pushColor(textcolor);
}
if (ts) while (np--) writeColor(color);
else writeColor(color);
px += textsize;
if (px >= (x + width * textsize))

View File

@@ -344,9 +344,6 @@ class TFT_eSPI : public Print {
height(void),
width(void);
virtual size_t write(uint8_t);
// The TFT_eSprite class inherits the following functions
void pushColors(uint16_t *data, uint8_t len),
pushColors(uint8_t *data, uint32_t len),
@@ -408,7 +405,7 @@ class TFT_eSPI : public Print {
// Write a block of pixels to the screen
void pushRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint16_t *data);
void pushSprite(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint16_t *data);
void pushSprite(int32_t x0, int32_t y0, uint32_t w, uint32_t h, uint8_t *data);
// This next function has been used successfully to dump the TFT screen to a PC for documentation purposes
// It reads a screen area and returns the RGB 8 bit colour values of each pixel
// Set w and h to 1 to read 1 pixel's colour. The data buffer must be at least w * h * 3 bytes
@@ -453,6 +450,7 @@ class TFT_eSPI : public Print {
void calibrateTouch(uint16_t *data, uint32_t color_fg, uint32_t color_bg, uint8_t size);
void setTouch(uint16_t *data);
size_t write(uint8_t);
private:
@@ -556,9 +554,12 @@ class TFT_eSprite : public TFT_eSPI {
TFT_eSprite(TFT_eSPI *tft);
uint16_t* createSprite(int16_t w, int16_t y); // 16 bpp
void createSprite(int16_t w, int16_t y); // 2 bytes per pixel
void deleteSprite(void);
void setColorDepth(int8_t b);
void drawPixel(uint32_t x, uint32_t y, uint32_t color);
void drawChar(int32_t x, int32_t y, unsigned char c, uint32_t color, uint32_t bg, uint8_t size),
@@ -568,6 +569,7 @@ class TFT_eSprite : public TFT_eSPI {
setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1),
pushColor(uint32_t color),
pushColor(uint32_t color, uint16_t len),
writeColor(uint16_t color),
drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t color),
drawFastVLine(int32_t x, int32_t y, int32_t h, uint32_t color),
@@ -601,10 +603,12 @@ class TFT_eSprite : public TFT_eSPI {
protected:
uint16_t *_img;
uint8_t *_img8;
bool _created;
int32_t _icursor_x, _icursor_y, _xs, _ys, _xe, _ye, _xptr, _yptr;
int32_t _iwidth, _iheight; // Display w/h as modified by current rotation
uint32_t _iwidth, _iheight, _bpp16;
};

View File

@@ -0,0 +1,205 @@
/*
Display "flicker free" scrolling text and updating number
This sketch uses 8 bit colour sprites to save RAM.
Example for library:
https://github.com/Bodmer/TFT_eSPI
The sketch has been tested on a 320x240 ILI9341 based TFT, it
coule be adapted for other screen sizes.
A Sprite is notionally an invisible graphics screen that is
kept in the processors RAM. Graphics can be drawn into the
Sprite just as it can be drawn directly to the screen. Once
the Sprite is completed it can be plotted onto the screen in
any position. If there is sufficient RAM then the Sprite can
be the same size as the screen and used as a frame buffer.
A 16 bit colour Sprite occupies (2 * width * height) bytes.
An 8 bit colour Sprite occupies (width * height) bytes.
On a ESP8266, 16 bit Sprite sizes up to 128 x 160 can be accomodated,
this size requires 128*160*2 bytes (40kBytes) of RAM.
This sketch sets the colour depth to 8 bits so larger sprites can be
created. 8 bit colour sprites use half amount of RAM. If the colour
depth is not specified then 16 bits is assumed.
You need to make the sprite small enough to fit, with RAM spare for
any "local variables" that may be needed by your sketch and libraries.
Created by Bodmer 21/11/17
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
#########################################################################
*/
// Size of sprite image for the scrolling text, this requires ~14 Kbytes of RAM
#define IWIDTH 240
#define IHEIGHT 30
// Pause in milliseconds to set scroll speed
#define WAIT 0
#include <TFT_eSPI.h> // Include the graphics library (this includes the sprite functions)
TFT_eSPI tft = TFT_eSPI(); // Create object "tft"
TFT_eSprite img = TFT_eSprite(&tft); // Create Sprite object "img" with pointer to "tft" object
// // the pointer is used by pushSprite() to push it onto the TFT
// -------------------------------------------------------------------------
// Setup
// -------------------------------------------------------------------------
void setup(void) {
tft.init();
tft.setRotation(0);
tft.fillScreen(TFT_BLUE);
}
// -------------------------------------------------------------------------
// Main loop
// -------------------------------------------------------------------------
void loop() {
while (1)
{
// Set colour depth of Sprite to 8 (or 16) bits
img.setColorDepth(8);
// Create the sprite and clear background to black
img.createSprite(IWIDTH, IHEIGHT);
//img.fillSprite(TFT_BLACK); // Optional here as we fill the sprite later anyway
for (int pos = IWIDTH; pos > 0; pos--)
{
build_banner("Hello World", pos);
img.pushSprite(0, 0);
build_banner("TFT_eSPI sprite" , pos);
img.pushSprite(0, 50);
delay(WAIT);
}
// Delete sprite to free up the memory
img.deleteSprite();
// Create a sprite of a different size
numberBox(random(100), 60, 100);
}
}
// #########################################################################
// Build the scrolling sprite image from scratch, draw text at x = xpos
// #########################################################################
void build_banner(String msg, int xpos)
{
int h = IHEIGHT;
// We could just use fillSprite(color) but lets be a bit more creative...
// Fill with rainbow stripes
while (h--) img.drawFastHLine(0, h, IWIDTH, rainbow(h * 4));
// Draw some graphics, the text will apear to scroll over these
img.fillRect (IWIDTH / 2 - 20, IHEIGHT / 2 - 10, 40, 20, TFT_YELLOW);
img.fillCircle(IWIDTH / 2, IHEIGHT / 2, 10, TFT_ORANGE);
// Now print text on top of the graphics
img.setTextSize(1); // Font size scaling is x1
img.setTextFont(4); // Font 4 selected
img.setTextColor(TFT_BLACK); // Black text, no background colour
img.setTextWrap(false); // Turn of wrap so we can print past end of sprite
// Need to print twice so text appears to wrap around at left and right edges
img.setCursor(xpos, 2); // Print text at xpos
img.print(msg);
img.setCursor(xpos - IWIDTH, 2); // Print text at xpos - sprite width
img.print(msg);
}
// #########################################################################
// Create sprite, plot graphics in it, plot to screen, then delete sprite
// #########################################################################
void numberBox(int num, int x, int y)
{
// Create a sprite 80 pixels wide, 50 high (8kbytes of RAM needed)
img.createSprite(80, 50);
// Fill it with black
img.fillSprite(TFT_BLACK);
// Draw a backgorund of 2 filled triangles
img.fillTriangle( 0, 0, 0, 49, 40, 25, TFT_RED);
img.fillTriangle( 79, 0, 79, 49, 40, 25, TFT_DARKGREEN);
// Set the font parameters
img.setTextSize(1); // Font size scaling is x1
img.setFreeFont(&FreeSerifBoldItalic24pt7b); // Select free font
img.setTextColor(TFT_WHITE); // White text, no background colour
// Set text coordinate datum to middle centre
img.setTextDatum(MC_DATUM);
// Draw the number in middle of 80 x 50 sprite
img.drawNumber(num, 40, 25);
// Push sprite to TFT screen CGRAM at coordinate x,y (top left corner)
img.pushSprite(x, y);
// Delete sprite to free up the RAM
img.deleteSprite();
}
// #########################################################################
// Return a 16 bit rainbow colour
// #########################################################################
unsigned int rainbow(byte value)
{
// Value is expected to be in range 0-127
// The value is converted to a spectrum colour from 0 = red through to 127 = blue
byte red = 0; // Red is the top 5 bits of a 16 bit colour value
byte green = 0;// Green is the middle 6 bits
byte blue = 0; // Blue is the bottom 5 bits
byte sector = value >> 5;
byte amplit = value & 0x1F;
switch (sector)
{
case 0:
red = 0x1F;
green = amplit;
blue = 0;
break;
case 1:
red = 0x1F - amplit;
green = 0x1F;
blue = 0;
break;
case 2:
red = 0;
green = 0x1F;
blue = amplit;
break;
case 3:
red = 0;
green = 0x1F - amplit;
blue = 0x1F;
break;
}
return red << 11 | green << 6 | blue;
}