Add libraries, picocalc notes.
This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
// This example draws an animated dial with a rotating needle.
|
||||
|
||||
// The dial is a jpeg image, the needle is created using a rotated
|
||||
// Sprite. The example operates by reading blocks of pixels from the
|
||||
// TFT, thus the TFT setup must support reading from the TFT CGRAM.
|
||||
|
||||
// The sketch operates by creating a copy of the screen block where
|
||||
// the needle will be drawn, the needle is then drawn on the screen.
|
||||
// When the needle moves, the original copy of the screen area is
|
||||
// pushed to the screen to over-write the needle graphic. A copy
|
||||
// of the screen where the new position will be drawn is then made
|
||||
// before drawing the needle in the new position. This technique
|
||||
// allows the needle to move over other screen graphics.
|
||||
|
||||
// The sketch calculates the size of the buffer memory required and
|
||||
// reserves the memory for the TFT block copy.
|
||||
|
||||
// Created by Bodmer 17/3/20 as an example to the TFT_eSPI library:
|
||||
// https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
#define NEEDLE_LENGTH 35 // Visible length
|
||||
#define NEEDLE_WIDTH 5 // Width of needle - make it an odd number
|
||||
#define NEEDLE_RADIUS 90 // Radius at tip
|
||||
#define NEEDLE_COLOR1 TFT_MAROON // Needle periphery colour
|
||||
#define NEEDLE_COLOR2 TFT_RED // Needle centre colour
|
||||
#define DIAL_CENTRE_X 120
|
||||
#define DIAL_CENTRE_Y 120
|
||||
|
||||
// Font attached to this sketch
|
||||
#include "NotoSansBold36.h"
|
||||
#define AA_FONT_LARGE NotoSansBold36
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
TFT_eSprite needle = TFT_eSprite(&tft); // Sprite object for needle
|
||||
TFT_eSprite spr = TFT_eSprite(&tft); // Sprite for meter reading
|
||||
|
||||
// Jpeg image array attached to this sketch
|
||||
#include "dial.h"
|
||||
|
||||
// Include the jpeg decoder library
|
||||
#include <TJpg_Decoder.h>
|
||||
|
||||
uint16_t* tft_buffer;
|
||||
bool buffer_loaded = false;
|
||||
uint16_t spr_width = 0;
|
||||
uint16_t bg_color =0;
|
||||
// =======================================================================================
|
||||
// This function will be called during decoding of the jpeg file
|
||||
// =======================================================================================
|
||||
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
|
||||
{
|
||||
// Stop further decoding as image is running off bottom of screen
|
||||
if ( y >= tft.height() ) return 0;
|
||||
|
||||
// This function will clip the image block rendering automatically at the TFT boundaries
|
||||
tft.pushImage(x, y, w, h, bitmap);
|
||||
|
||||
// Return 1 to decode next block
|
||||
return 1;
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Setup
|
||||
// =======================================================================================
|
||||
void setup() {
|
||||
Serial.begin(115200); // Debug only
|
||||
|
||||
// The byte order can be swapped (set true for TFT_eSPI)
|
||||
TJpgDec.setSwapBytes(true);
|
||||
|
||||
// The jpeg decoder must be given the exact name of the rendering function above
|
||||
TJpgDec.setCallback(tft_output);
|
||||
|
||||
tft.begin();
|
||||
tft.setRotation(0);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// Draw the dial
|
||||
TJpgDec.drawJpg(0, 0, dial, sizeof(dial));
|
||||
tft.drawCircle(DIAL_CENTRE_X, DIAL_CENTRE_Y, NEEDLE_RADIUS-NEEDLE_LENGTH, TFT_DARKGREY);
|
||||
|
||||
// Load the font and create the Sprite for reporting the value
|
||||
spr.loadFont(AA_FONT_LARGE);
|
||||
spr_width = spr.textWidth("777"); // 7 is widest numeral in this font
|
||||
spr.createSprite(spr_width, spr.fontHeight());
|
||||
bg_color = tft.readPixel(120, 120); // Get colour from dial centre
|
||||
spr.fillSprite(bg_color);
|
||||
spr.setTextColor(TFT_WHITE, bg_color, true);
|
||||
spr.setTextDatum(MC_DATUM);
|
||||
spr.setTextPadding(spr_width);
|
||||
spr.drawNumber(0, spr_width/2, spr.fontHeight()/2);
|
||||
spr.pushSprite(DIAL_CENTRE_X - spr_width / 2, DIAL_CENTRE_Y - spr.fontHeight() / 2);
|
||||
|
||||
// Plot the label text
|
||||
tft.setTextColor(TFT_WHITE, bg_color);
|
||||
tft.setTextDatum(MC_DATUM);
|
||||
tft.drawString("(degrees)", DIAL_CENTRE_X, DIAL_CENTRE_Y + 48, 2);
|
||||
|
||||
// Define where the needle pivot point is on the TFT before
|
||||
// creating the needle so boundary calculation is correct
|
||||
tft.setPivot(DIAL_CENTRE_X, DIAL_CENTRE_Y);
|
||||
|
||||
// Create the needle Sprite
|
||||
createNeedle();
|
||||
|
||||
// Reset needle position to 0
|
||||
plotNeedle(0, 0);
|
||||
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Loop
|
||||
// =======================================================================================
|
||||
void loop() {
|
||||
uint16_t angle = random(241); // random speed in range 0 to 240
|
||||
|
||||
// Plot needle at random angle in range 0 to 240, speed 40ms per increment
|
||||
plotNeedle(angle, 30);
|
||||
|
||||
// Pause at new position
|
||||
delay(2500);
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Create the needle Sprite
|
||||
// =======================================================================================
|
||||
void createNeedle(void)
|
||||
{
|
||||
needle.setColorDepth(16);
|
||||
needle.createSprite(NEEDLE_WIDTH, NEEDLE_LENGTH); // create the needle Sprite
|
||||
|
||||
needle.fillSprite(TFT_BLACK); // Fill with black
|
||||
|
||||
// Define needle pivot point relative to top left corner of Sprite
|
||||
uint16_t piv_x = NEEDLE_WIDTH / 2; // pivot x in Sprite (middle)
|
||||
uint16_t piv_y = NEEDLE_RADIUS; // pivot y in Sprite
|
||||
needle.setPivot(piv_x, piv_y); // Set pivot point in this Sprite
|
||||
|
||||
// Draw the red needle in the Sprite
|
||||
needle.fillRect(0, 0, NEEDLE_WIDTH, NEEDLE_LENGTH, TFT_MAROON);
|
||||
needle.fillRect(1, 1, NEEDLE_WIDTH-2, NEEDLE_LENGTH-2, TFT_RED);
|
||||
|
||||
// Bounding box parameters to be populated
|
||||
int16_t min_x;
|
||||
int16_t min_y;
|
||||
int16_t max_x;
|
||||
int16_t max_y;
|
||||
|
||||
// Work out the worst case area that must be grabbed from the TFT,
|
||||
// this is at a 45 degree rotation
|
||||
needle.getRotatedBounds(45, &min_x, &min_y, &max_x, &max_y);
|
||||
|
||||
// Calculate the size and allocate the buffer for the grabbed TFT area
|
||||
tft_buffer = (uint16_t*) malloc( ((max_x - min_x) + 2) * ((max_y - min_y) + 2) * 2 );
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Move the needle to a new position
|
||||
// =======================================================================================
|
||||
void plotNeedle(int16_t angle, uint16_t ms_delay)
|
||||
{
|
||||
static int16_t old_angle = -120; // Starts at -120 degrees
|
||||
|
||||
// Bounding box parameters
|
||||
static int16_t min_x;
|
||||
static int16_t min_y;
|
||||
static int16_t max_x;
|
||||
static int16_t max_y;
|
||||
|
||||
if (angle < 0) angle = 0; // Limit angle to emulate needle end stops
|
||||
if (angle > 240) angle = 240;
|
||||
|
||||
angle -= 120; // Starts at -120 degrees
|
||||
|
||||
// Move the needle until new angle reached
|
||||
while (angle != old_angle || !buffer_loaded) {
|
||||
|
||||
if (old_angle < angle) old_angle++;
|
||||
else old_angle--;
|
||||
|
||||
// Only plot needle at even values to improve plotting performance
|
||||
if ( (old_angle & 1) == 0)
|
||||
{
|
||||
if (buffer_loaded) {
|
||||
// Paste back the original needle free image area
|
||||
tft.pushRect(min_x, min_y, 1 + max_x - min_x, 1 + max_y - min_y, tft_buffer);
|
||||
}
|
||||
|
||||
if ( needle.getRotatedBounds(old_angle, &min_x, &min_y, &max_x, &max_y) )
|
||||
{
|
||||
// Grab a copy of the area before needle is drawn
|
||||
tft.readRect(min_x, min_y, 1 + max_x - min_x, 1 + max_y - min_y, tft_buffer);
|
||||
buffer_loaded = true;
|
||||
}
|
||||
|
||||
// Draw the needle in the new position, black in needle image is transparent
|
||||
needle.pushRotated(old_angle, TFT_BLACK);
|
||||
|
||||
// Wait before next update
|
||||
delay(ms_delay);
|
||||
}
|
||||
|
||||
// Update the number at the centre of the dial
|
||||
spr.setTextColor(TFT_WHITE, bg_color, true);
|
||||
spr.drawNumber(old_angle+120, spr_width/2, spr.fontHeight()/2);
|
||||
spr.pushSprite(120 - spr_width / 2, 120 - spr.fontHeight() / 2);
|
||||
|
||||
// Slow needle down slightly as it approaches the new position
|
||||
if (abs(old_angle - angle) < 10) ms_delay += ms_delay / 5;
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
@@ -0,0 +1,380 @@
|
||||
/* The font vlw file can be converted to a byte array using:
|
||||
|
||||
https://tomeko.net/online_tools/file_to_hex.php?lang=en
|
||||
|
||||
Paste the byte array into a sketch tab and add two lines
|
||||
at the start with a unique font name:
|
||||
|
||||
const uint8_t fontName[] PROGMEM = {
|
||||
|
||||
At the end add:
|
||||
|
||||
};
|
||||
|
||||
See example below. Include the tab in the main sketch, e.g.:
|
||||
|
||||
#include "NotoSansBold36.h"
|
||||
*/
|
||||
|
||||
// Digits 0-9 and .
|
||||
const uint8_t NotoSansBold36[] PROGMEM = {
|
||||
0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x07,
|
||||
0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x13,
|
||||
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x31, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x14,
|
||||
0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32,
|
||||
0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1B,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x1C,
|
||||
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x15,
|
||||
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1A, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x35, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14,
|
||||
0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36,
|
||||
0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1B,
|
||||
0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x1A,
|
||||
0x00, 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x01,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x13,
|
||||
0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x39, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x14,
|
||||
0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x7B,
|
||||
0x72, 0x28, 0x00, 0x00, 0xA3, 0xFF, 0xFF, 0xFF, 0xF8, 0x30, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x9B, 0x85, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0x7B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x57, 0x1B,
|
||||
0xEE, 0xFF, 0xFF, 0xFF, 0xA3, 0x00, 0x00, 0x19, 0x5B, 0x61, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x92, 0xDD, 0xFF, 0xFF, 0xFC, 0xDA, 0x88, 0x17,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xEE, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x70,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x5B, 0x59, 0xDA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x06, 0x00,
|
||||
0x00, 0x19, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xD4, 0x0C, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x4A, 0x00, 0x00, 0x8E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x2A, 0x00, 0x00, 0x00, 0x00, 0xF2,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0x00, 0x0A, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x39,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0xB2, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xDD, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x63, 0x02, 0xFA,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x5F, 0x37, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x55, 0x5B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x44, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x55, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0xA7, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x00, 0xB2, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x00,
|
||||
0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x77, 0x00, 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x2A, 0x00, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x00, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00,
|
||||
0x00, 0x00, 0x00, 0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x9F, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xCC, 0x00, 0x00, 0x00, 0x13, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x08, 0x00, 0x00, 0x57,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6E, 0x02, 0x2C, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x68, 0x00,
|
||||
0x00, 0x00, 0x0C, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xB4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xCE, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xB6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x7B, 0xE9,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC9, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x2E, 0x4E, 0x50, 0x48, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xAE, 0xAE, 0xAE, 0xAE, 0x48,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x06, 0x00, 0x00,
|
||||
0x00, 0x00, 0x35, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD6, 0x00, 0x00, 0x00, 0x0E,
|
||||
0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA3, 0x00, 0x00, 0x5B, 0xE7, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x68, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xDA, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0x37, 0x00, 0x24, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xAA, 0x26, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x02, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xE5, 0x4E, 0x00,
|
||||
0x57, 0xFF, 0xFF, 0xFF, 0xFF, 0xC5, 0x00, 0x00, 0x00, 0x06, 0xD6, 0x92, 0x0C, 0x00, 0x00, 0xA5,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xF6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0x85, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x4E, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE5, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xA3, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x06, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x4C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7D,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAE, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x5F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x26, 0x88, 0xC9, 0xF8, 0xFF, 0xFF, 0xF8, 0xC5, 0x77, 0x0C, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xA3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xE5, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xF4, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7B,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x22, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x85, 0x70, 0xBD, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFC, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xFF, 0xFF, 0xD0, 0x30, 0x00,
|
||||
0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x48, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xA5, 0x90, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x44, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xF6, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x17, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xFC, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xD8, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7B,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC5, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8A, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xF6, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xDD,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x35, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA3, 0x9B, 0x9B,
|
||||
0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x9B, 0x92, 0x00, 0x00, 0x00, 0x22, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x00, 0x55,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x92, 0x00, 0x00, 0x00, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x00, 0x00, 0x00, 0xB6, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x50, 0xA1, 0xDA, 0xF8, 0xFF, 0xFF, 0xFC,
|
||||
0xDA, 0x94, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x72, 0xE3, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xD4, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5F, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xE7, 0x02, 0x00, 0x00, 0x00, 0x00, 0x06, 0xDD, 0xFF, 0xFF, 0xCE, 0x7F, 0x55, 0x52, 0x83, 0xF6,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0xCE, 0x3F, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x57, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x4E, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x5B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x04, 0x06, 0x0A, 0x41, 0x6A, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xAC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x66, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE,
|
||||
0x59, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFC, 0xB2, 0x2E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37,
|
||||
0xB4, 0xB4, 0xBB, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x2A,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x6A, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xAC,
|
||||
0x00, 0x00, 0x59, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x6E, 0x00, 0x00, 0xB4, 0xFA, 0xB0, 0x5F, 0x2C, 0x02, 0x00, 0x00, 0x0A, 0x50,
|
||||
0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0x15, 0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xF8, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x70, 0x00, 0x00, 0x00, 0xB4, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x00, 0x00,
|
||||
0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF2,
|
||||
0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x7D, 0xC9, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xCE, 0x7B, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x2E, 0x4C,
|
||||
0x50, 0x50, 0x4C, 0x3D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xAE, 0xAE, 0xAE,
|
||||
0xAE, 0xAE, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1D, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0C, 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xFA, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0x0E,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xE9, 0xFF, 0xFF, 0xFF, 0x9F, 0xF2,
|
||||
0xFF, 0xFF, 0xFF, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xD4, 0xFF,
|
||||
0xFF, 0xFF, 0xDD, 0x4E, 0xFF, 0xFF, 0xFF, 0xFF, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF, 0xF8, 0x30, 0x85, 0xFF, 0xFF, 0xFF, 0xFF, 0x6E, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0x5B, 0x00, 0xC1, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0x83,
|
||||
0x00, 0x02, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3B, 0xFA,
|
||||
0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x1D, 0xE9, 0xFF, 0xFF, 0xFF, 0xC9, 0x08, 0x00, 0x00, 0x74, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xD4, 0xFF, 0xFF, 0xFF, 0xE5, 0x17, 0x00, 0x00, 0x00,
|
||||
0xAC, 0xFF, 0xFF, 0xFF, 0xFF, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF, 0xF4,
|
||||
0x30, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x7D,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x94, 0x94, 0x94, 0x94, 0x96, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x94,
|
||||
0x94, 0x8C, 0x00, 0x00, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x00, 0x02, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0x00, 0x30, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x50, 0x00, 0x37, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xA7, 0xAA, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xA7, 0xA7, 0xA7, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6A, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xDA, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
|
||||
0xAE, 0xAE, 0xAE, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xFC, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x55, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x57, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x24,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
|
||||
0xF2, 0xF2, 0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE7, 0xFF, 0xFF, 0xFF, 0xFC, 0x11, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x74, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFC, 0xFF, 0xFF, 0xFF, 0xDD, 0x06, 0x35, 0x35,
|
||||
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x6E, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x15, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x9B, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55, 0x24, 0x02,
|
||||
0x00, 0x02, 0x3F, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xEB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x9D, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x00, 0x00,
|
||||
0x63, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x30, 0x00, 0x00, 0x94, 0xFF, 0xDA, 0x83, 0x4A, 0x15, 0x06, 0x08, 0x3B, 0x7D, 0xEE, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0x2A, 0x00, 0x00, 0x00, 0x94, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x4E, 0x00, 0x00, 0x00, 0x00,
|
||||
0x90, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x37, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x04, 0x5F, 0xB0, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xBF,
|
||||
0x66, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x4A, 0x50, 0x50,
|
||||
0x4C, 0x37, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x06, 0x02, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x63, 0xA7, 0xE1, 0xFC, 0xFF, 0xFF,
|
||||
0xFF, 0xF6, 0xC1, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x81, 0xF6, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0xDA,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x39, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x24, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x8A, 0x57, 0x4A, 0x4A,
|
||||
0x55, 0x7B, 0x41, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x5F, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x79, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xEB, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xF2,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x7B, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE1, 0xFF, 0xFF, 0xFF, 0xFC, 0x22, 0x00, 0x4C, 0x99, 0xA7,
|
||||
0xA5, 0x77, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x22,
|
||||
0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x72, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8E, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x7F, 0xE9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x00, 0x00, 0x00,
|
||||
0x00, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xE9, 0x02, 0x00, 0x00, 0x06, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0x74, 0x88, 0xE9,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x5B,
|
||||
0x00, 0x00, 0x00, 0x2A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6C, 0x00, 0x00, 0x50, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x79, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC9, 0xFF, 0xFF, 0xFF, 0xFF, 0x94, 0x00, 0x00,
|
||||
0x5D, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0x8A, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0x5D, 0x00, 0x00, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xAE, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x06, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0x3B, 0x00, 0x00, 0x55, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xC7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x61, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x02, 0x00, 0x00,
|
||||
0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x1B, 0x00, 0x00, 0x00, 0x11, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x9D, 0x00, 0x00, 0x00, 0x00, 0xEB, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0x1F, 0x00, 0x2C, 0xC7, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x8A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xE9, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0x08, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x39, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB4, 0x11, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xA3, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE,
|
||||
0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x3F, 0x50,
|
||||
0x50, 0x48, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A,
|
||||
0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE, 0xAE,
|
||||
0x35, 0x00, 0x00, 0x02, 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1D, 0x00, 0x00, 0x37, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00,
|
||||
0x00, 0x00, 0x96, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xEB, 0xF8, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFC, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x19, 0xF2, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA5, 0xFF, 0xFF, 0xFF, 0xFF, 0xEB, 0x13, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xDA,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x9B, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xF0, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x57, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x0C, 0xE5, 0xFF, 0xFF, 0xFF, 0xFF, 0xD4, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFC, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xA5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0xC9, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0x1B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x77, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x13, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xD8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9B,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xD4, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x22, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x1B, 0xF4, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4E, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB8,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xAA, 0xF0, 0xFF, 0xFF, 0xFF, 0xF6, 0xB2,
|
||||
0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0xD0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xBB, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0xEB, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD4, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0xEE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x4C, 0x00, 0x00, 0x00,
|
||||
0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x50, 0x00, 0x00, 0x2A, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF, 0xA5,
|
||||
0x00, 0x00, 0x00, 0xA5, 0xFF, 0xFF, 0xFF, 0xFF, 0x85, 0x00, 0x00, 0x00, 0x00, 0x6E, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xB4, 0x00, 0x00, 0x00, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0x4C, 0x00, 0x00, 0x00, 0x00,
|
||||
0x50, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x00, 0x00, 0x00, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0x52, 0x00,
|
||||
0x00, 0x00, 0x00, 0x72, 0xFF, 0xFF, 0xFF, 0xFF, 0x99, 0x00, 0x00, 0x00, 0xA5, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xA7, 0x00, 0x00, 0x00, 0x13, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00, 0x48,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x61, 0x00, 0x2C, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6,
|
||||
0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xF2, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x6E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xB4, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xE3, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x9F, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xF2, 0xDA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x92, 0x00, 0x00, 0x00, 0x00, 0x9B,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x83, 0x0C, 0x08, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00,
|
||||
0x00, 0x3B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x48, 0x00, 0x00, 0x00, 0x00, 0xC1, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xBD, 0x00, 0x00, 0xAA, 0xFF, 0xFF, 0xFF, 0xFF, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x39,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x02, 0x00, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0x4A, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0C, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x00, 0xFC, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0xFF, 0xFF, 0xFF, 0xFF, 0xF6, 0x00, 0x00,
|
||||
0xCC, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0x2C, 0x00, 0x00, 0x00, 0x26, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x9F, 0x00, 0x00, 0x72, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xB6, 0xA5, 0xB8, 0xFC, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFC, 0x28, 0x00, 0x00, 0x04, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x70, 0x00, 0x00, 0x00, 0x00, 0x19, 0xD6, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x6A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x77,
|
||||
0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x94, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x15, 0x48, 0x50, 0x50, 0x4C, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x35, 0x9D, 0xDF, 0xFC, 0xFF,
|
||||
0xFF, 0xF6, 0xB2, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0xA7, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0xD6,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xAA, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xCE, 0x57, 0x4A, 0x7F, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xA7, 0x00, 0x00, 0x00, 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xC5, 0x08, 0x00, 0x00, 0x00,
|
||||
0x85, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x00,
|
||||
0x00, 0x00, 0x00, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x06, 0x00, 0x83, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x26, 0x00, 0xAE, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3D,
|
||||
0x00, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x24, 0x00, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB2,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x00, 0xB2, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x00, 0x00, 0x00,
|
||||
0x00, 0x5F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xAC, 0x4A, 0x4A, 0x94, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xD8, 0x00, 0x00, 0x33, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xA7, 0x00, 0x00,
|
||||
0x00, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x6E, 0x00, 0x00, 0x00, 0x13, 0xCE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE9, 0x39, 0xDD, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x33, 0x00, 0x00, 0x00, 0x00, 0x06, 0x74, 0xC1, 0xF4, 0xF6, 0xD6, 0x88, 0x13,
|
||||
0x37, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0xA3, 0xFF, 0xFF, 0xFF, 0xFF, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x24, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xB2, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0xC5, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
|
||||
0x28, 0x00, 0x00, 0x00, 0x3F, 0x66, 0x2E, 0x02, 0x00, 0x02, 0x35, 0x81, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xB6, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF4, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x55, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0x81, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x02, 0x2C, 0x4C, 0x50, 0x50, 0x48, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x4E, 0x6F, 0x74, 0x6F, 0x20, 0x53, 0x61, 0x6E,
|
||||
0x73, 0x20, 0x42, 0x6F, 0x6C, 0x64, 0x20, 0x49, 0x74, 0x61, 0x6C, 0x69, 0x63, 0x00, 0x13, 0x4E,
|
||||
0x6F, 0x74, 0x6F, 0x53, 0x61, 0x6E, 0x73, 0x2D, 0x42, 0x6F, 0x6C, 0x64, 0x49, 0x74, 0x61, 0x6C,
|
||||
0x69, 0x63, 0x01
|
||||
};
|
||||
BIN
libraries/TFT_eSPI/examples/Sprite/Animated_dial/data/dial.jpg
Normal file
BIN
libraries/TFT_eSPI/examples/Sprite/Animated_dial/data/dial.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
1151
libraries/TFT_eSPI/examples/Sprite/Animated_dial/dial.h
Normal file
1151
libraries/TFT_eSPI/examples/Sprite/Animated_dial/dial.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Sketch to show creation of a 1bpp sprite with a transparent
|
||||
background, then plot it on the TFT.
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
A Sprite is notionally an invisible graphics screen that is
|
||||
kept in the processors RAM. Graphics can be drawn into the
|
||||
Sprite just as it can be drawn directly to the screen. Once
|
||||
the Sprite is completed it can be plotted onto the screen in
|
||||
any position. If there is sufficient RAM then the Sprite can
|
||||
be the same size as the screen and used as a frame buffer.
|
||||
|
||||
A 1 bit Sprite occupies (width * height)/8 bytes in RAM. So,
|
||||
for example, a 320 x 240 pixel Sprite occupies 9600 bytes.
|
||||
*/
|
||||
// A new setBitmapColor(fg_color, bg_color) function allows
|
||||
// any 2 colours to be used for the 1 bit sprite.
|
||||
// One colour can also be defined as transparent when
|
||||
// rendering to the screen.
|
||||
|
||||
|
||||
#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
|
||||
|
||||
#define BITS_PER_PIXEL 1 // How many bits per pixel in Sprite
|
||||
|
||||
// =========================================================================
|
||||
void setup(void) {
|
||||
Serial.begin(250000);
|
||||
|
||||
tft.init();
|
||||
|
||||
tft.setRotation(0);
|
||||
}
|
||||
// =========================================================================
|
||||
void loop() {
|
||||
|
||||
tft.fillScreen(TFT_NAVY);
|
||||
|
||||
// Draw 10 sprites containing a "transparent" colour
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int x = random(240 - 70);
|
||||
int y = random(320 - 80);
|
||||
int c = random(0x10000); // Random colour 0 - 0xFFFF
|
||||
drawStar(x, y, c);
|
||||
}
|
||||
|
||||
delay(2000);
|
||||
|
||||
// Now go bananas and draw 500 more
|
||||
for (int i = 0; i < 500; i++)
|
||||
{
|
||||
int x = random(240 - 70);
|
||||
int y = random(320 - 80);
|
||||
int c = random(0x10000); // Random colour
|
||||
drawStar(x, y, c);
|
||||
yield(); // Stop watchdog reset
|
||||
}
|
||||
|
||||
delay(2000);
|
||||
}
|
||||
// =========================================================================
|
||||
// Create sprite, plot graphics in it, plot to screen, then delete sprite
|
||||
// =========================================================================
|
||||
void drawStar(int x, int y, int star_color)
|
||||
{
|
||||
// 1 bpp colour values can only be 1 or 0 (one or zero)
|
||||
uint16_t transparent = 0; // The transparent colour, can only be 1 or 0
|
||||
|
||||
// Create an 1 bit (2 colour) sprite 70x80 pixels (uses 70*80/8 = 700 bytes of RAM)
|
||||
// Colour depths of 8 bits per pixel and 16 bits are also supported.
|
||||
img.setColorDepth(BITS_PER_PIXEL); // Set colour depth first
|
||||
img.createSprite(70, 80); // then create the sprite
|
||||
|
||||
// Fill Sprite with the colour that will be defined later as "transparent"
|
||||
// We could also fill with any colour as transparent, and later specify that
|
||||
// same colour when we push the Sprite onto the display screen.
|
||||
img.fillSprite(transparent);
|
||||
|
||||
// Draw 2 triangles to create a filled in star
|
||||
img.fillTriangle(35, 0, 0, 59, 69, 59, star_color);
|
||||
img.fillTriangle(35, 79, 0, 20, 69, 20, star_color);
|
||||
|
||||
// Punch a star shaped hole in the middle with a smaller "transparent" star
|
||||
img.fillTriangle(35, 7, 6, 56, 63, 56, transparent);
|
||||
img.fillTriangle(35, 73, 6, 24, 63, 24, transparent);
|
||||
|
||||
// Set the 2 pixel colours that 1 and 0 represent on the display screen
|
||||
img.setBitmapColor(star_color, transparent);
|
||||
|
||||
// Push sprite to TFT screen CGRAM at coordinate x,y (top left corner)
|
||||
// Specify what colour is to be treated as transparent (black in this example)
|
||||
img.pushSprite(x, y, transparent);
|
||||
|
||||
// Delete Sprite to free memory, creating and deleting takes very little time.
|
||||
img.deleteSprite();
|
||||
}
|
||||
// =========================================================================
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
// This sketch draws a rotating Yin and Yang symbol. It illustrates
|
||||
// the drawing and rendering of simple animated graphics using
|
||||
// a 1 bit per pixel (1 bpp) Sprite.
|
||||
|
||||
// Note: TFT_BLACK sets the pixel value to 0
|
||||
// Any other colour sets the pixel value to 1
|
||||
|
||||
// A square sprite of side = 2 x RADIUS will be created
|
||||
// (80 * 80)/8 = 800 bytes needed for 1 bpp sprite
|
||||
// 6400 bytes for 8 bpp
|
||||
// 12800 bytes for 16 bpp
|
||||
#define RADIUS 40 // Radius of completed symbol = 40
|
||||
|
||||
#define WAIT 0 // Loop delay
|
||||
|
||||
// 1bpp Sprites are economical on memory but slower to render
|
||||
#define COLOR_DEPTH 1 // Colour depth (1, 8 or 16 bits per pixel)
|
||||
|
||||
// Rotation angle increment and start angle
|
||||
#define ANGLE_INC 3
|
||||
int angle = 0;
|
||||
|
||||
#include <TFT_eSPI.h> // Hardware-specific library
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Invoke library
|
||||
|
||||
TFT_eSprite img = TFT_eSprite(&tft); // Sprite class
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
void setup(void)
|
||||
{
|
||||
tft.begin();
|
||||
tft.setRotation(0);
|
||||
tft.fillScreen(TFT_BLUE);
|
||||
|
||||
img.setColorDepth(COLOR_DEPTH);
|
||||
img.createSprite(RADIUS*2+1, RADIUS*2+1);
|
||||
img.fillSprite(TFT_BLACK);
|
||||
}
|
||||
// -------------------------------------------------------------------------
|
||||
// -------------------------------------------------------------------------
|
||||
void loop() {
|
||||
// Draw Yin and Yang symbol circles into Sprite
|
||||
yinyang(RADIUS, RADIUS, angle, RADIUS);
|
||||
|
||||
// Set the 2 pixel palette colours that 1 and 0 represent on the display screen
|
||||
img.setBitmapColor(TFT_WHITE, TFT_BLACK);
|
||||
|
||||
// Push Sprite image to the TFT screen at x, y
|
||||
img.pushSprite(tft.width()/2 - RADIUS, 0); // Plot sprite
|
||||
|
||||
angle+=3; //Increment angle to rotate circle positions
|
||||
if (angle > 359) angle = 0; // Limit angle range
|
||||
|
||||
// Slow things down
|
||||
delay(WAIT);
|
||||
}
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// Draw circles for Yin and Yang - rotate positions to create symbol
|
||||
// =========================================================================
|
||||
// x,y == coordinate center within Sprite
|
||||
// start_angle = 0 - 359
|
||||
// r = radius
|
||||
|
||||
void yinyang(int x, int y, int start_angle, int r)
|
||||
{
|
||||
int x1 = 0; // getCoord() will update these
|
||||
int y1 = 0;
|
||||
|
||||
getCoord(x, y, &x1, &y1, r/2, start_angle); // Get x1 ,y1
|
||||
img.fillCircle( x1, y1, r/2, TFT_WHITE);
|
||||
img.fillCircle( x1, y1, r/8, TFT_BLACK);
|
||||
|
||||
getCoord(x, y, &x1, &y1, r/2, start_angle + 180);
|
||||
img.fillCircle( x1, y1, r/2, TFT_BLACK);
|
||||
img.fillCircle( x1, y1, r/8, TFT_WHITE);
|
||||
|
||||
img.drawCircle(x, y, r, TFT_WHITE);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Get coordinates of end of a vector, pivot at x,y, length r, angle a
|
||||
// =========================================================================
|
||||
// Coordinates are returned to caller via the xp and yp pointers
|
||||
#define RAD2DEG 0.0174532925
|
||||
void getCoord(int x, int y, int *xp, int *yp, int r, int a)
|
||||
{
|
||||
float sx1 = cos( (a-90) * RAD2DEG );
|
||||
float sy1 = sin( (a-90) * RAD2DEG );
|
||||
*xp = sx1 * r + x;
|
||||
*yp = sy1 * r + y;
|
||||
}
|
||||
|
||||
163
libraries/TFT_eSPI/examples/Sprite/Orrery/Orrery.ino
Normal file
163
libraries/TFT_eSPI/examples/Sprite/Orrery/Orrery.ino
Normal file
@@ -0,0 +1,163 @@
|
||||
// Display an Orrery
|
||||
// Works for all display sizes but 320x480 minimum size recommended
|
||||
// Whole planet orbits only visible in 480 x 800 display
|
||||
|
||||
// Flicker free sprite example for TFT_eSPI:
|
||||
// https://github.com/Bodmer/TFT_eSPI
|
||||
// Sketch coded by Bodmer
|
||||
// Uses astronomy engine created by Don Cross
|
||||
|
||||
#include <TFT_eSPI.h> // Hardware-specific library
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Invoke library
|
||||
|
||||
TFT_eSprite img = TFT_eSprite(&tft); // Sprite class
|
||||
|
||||
#define sunX tft.width()/2
|
||||
#define sunY tft.height()/2
|
||||
|
||||
uint16_t orb_inc;
|
||||
uint16_t planet_r;
|
||||
|
||||
#include <stdio.h>
|
||||
#include "astronomy.h"
|
||||
#define TIME_TEXT_BYTES 25
|
||||
|
||||
astro_time_t astro_time;
|
||||
|
||||
uint16_t grey;
|
||||
|
||||
static const astro_body_t body[] = {
|
||||
BODY_SUN, BODY_MERCURY, BODY_VENUS, BODY_EARTH, BODY_MARS,
|
||||
BODY_JUPITER, BODY_SATURN, BODY_URANUS, BODY_NEPTUNE
|
||||
};
|
||||
|
||||
static const uint16_t bodyColour[] = {
|
||||
TFT_YELLOW, TFT_DARKGREY, TFT_ORANGE, TFT_BLUE, TFT_RED,
|
||||
TFT_GOLD, TFT_BROWN, TFT_DARKCYAN, TFT_CYAN
|
||||
};
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// Setup
|
||||
// =========================================================================
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
tft.begin();
|
||||
tft.setRotation(1);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// Test with smaller display sizes
|
||||
//tft.setViewport(10,10,160,128);
|
||||
//tft.setViewport(10,10,320,240);
|
||||
//tft.setViewport(10,10,480,320);
|
||||
//tft.frameViewport(TFT_GREEN, -1);
|
||||
|
||||
img.createSprite(19, 19);
|
||||
|
||||
grey = tft.color565(30, 30, 30);
|
||||
|
||||
astro_time = Astronomy_MakeTime(2020, 10, 16, 19, 31, 0) ;
|
||||
tft.fillCircle(sunX, sunY, 10, TFT_YELLOW);
|
||||
|
||||
// i initialised to 1 so Sun is skipped
|
||||
for (int i = 1; i < sizeof(body) / sizeof(body[0]); ++i)
|
||||
{
|
||||
tft.drawCircle(sunX, sunY, i * 28, grey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// Loop
|
||||
// =========================================================================
|
||||
void loop() {
|
||||
uint32_t dt = millis();
|
||||
plot_planets();
|
||||
showTime(astro_time);
|
||||
|
||||
// Add time increment (more than 0.6 days will lead to stray pixel on screen
|
||||
// due to the way previous object images are erased)
|
||||
astro_time = Astronomy_AddDays(astro_time, 0.25); // 0.25 day (6 hour) increment
|
||||
|
||||
dt = millis()-dt;
|
||||
//Serial.println(dt);
|
||||
//delay(1000);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Get coordinates of end of a vector, pivot at x,y, length r, angle a
|
||||
// =========================================================================
|
||||
// Coordinates are returned to caller via the xp and yp pointers
|
||||
#define DEG2RAD 0.0174532925
|
||||
void getCoord(int x, int y, int *xp, int *yp, int r, float a)
|
||||
{
|
||||
float sx1 = cos( -a * DEG2RAD );
|
||||
float sy1 = sin( -a * DEG2RAD );
|
||||
*xp = sx1 * r + x;
|
||||
*yp = sy1 * r + y;
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Convert astronomical time to UTC and display
|
||||
// =========================================================================
|
||||
void showTime(astro_time_t time)
|
||||
{
|
||||
astro_status_t status;
|
||||
char text[TIME_TEXT_BYTES];
|
||||
|
||||
status = Astronomy_FormatTime(time, TIME_FORMAT_SECOND, text, sizeof(text));
|
||||
if (status != ASTRO_SUCCESS)
|
||||
{
|
||||
fprintf(stderr, "\nFATAL(PrintTime): status %d\n", status);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tft.drawString(text, 0, 0, 2);
|
||||
}
|
||||
|
||||
// =========================================================================
|
||||
// Plot planet positions as an Orrery
|
||||
// =========================================================================
|
||||
int plot_planets(void)
|
||||
{
|
||||
astro_angle_result_t ang;
|
||||
|
||||
int i;
|
||||
int num_bodies = sizeof(body) / sizeof(body[0]);
|
||||
|
||||
// i initialised to 1 so Sun is skipped
|
||||
for (i = 1; i < num_bodies; ++i)
|
||||
{
|
||||
ang = Astronomy_EclipticLongitude(body[i], astro_time);
|
||||
|
||||
int x1 = 0; // getCoord() will update these
|
||||
int y1 = 0;
|
||||
|
||||
getCoord(0, 0, &x1, &y1, i * 28, ang.angle); // Get x1 ,y1
|
||||
|
||||
img.fillSprite(TFT_TRANSPARENT);
|
||||
img.fillCircle(9, 9, 9, TFT_BLACK);
|
||||
img.drawCircle(9 - x1, 9 - y1, i * 28, grey);
|
||||
img.fillCircle(9, 9, 5, bodyColour[i]);
|
||||
img.pushSprite(sunX + x1 - 9, sunY + y1 - 9, TFT_TRANSPARENT);
|
||||
|
||||
if (body[i] == BODY_EARTH)
|
||||
{
|
||||
astro_angle_result_t mang = Astronomy_LongitudeFromSun(BODY_MOON, astro_time);
|
||||
|
||||
int xm = 0;
|
||||
int ym = 0;
|
||||
|
||||
getCoord(x1, y1, &xm, &ym, 15, 180 + ang.angle + mang.angle); // Get x1 ,y1
|
||||
|
||||
img.fillSprite(TFT_TRANSPARENT);
|
||||
img.fillCircle(9, 9, 7, TFT_BLACK);
|
||||
img.drawCircle(9 - xm, 9 - ym, i * 28, grey);
|
||||
img.fillCircle(9, 9, 2, TFT_WHITE);
|
||||
img.pushSprite(sunX + xm - 9, sunY + ym - 9, TFT_TRANSPARENT);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
8822
libraries/TFT_eSPI/examples/Sprite/Orrery/astronomy.c
Normal file
8822
libraries/TFT_eSPI/examples/Sprite/Orrery/astronomy.c
Normal file
File diff suppressed because it is too large
Load Diff
904
libraries/TFT_eSPI/examples/Sprite/Orrery/astronomy.h
Normal file
904
libraries/TFT_eSPI/examples/Sprite/Orrery/astronomy.h
Normal file
@@ -0,0 +1,904 @@
|
||||
/*
|
||||
Astronomy Engine for C/C++.
|
||||
https://github.com/cosinekitty/astronomy
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019-2020 Don Cross <cosinekitty@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __ASTRONOMY_H
|
||||
#define __ASTRONOMY_H
|
||||
|
||||
#include <stddef.h> /* for size_t */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------- types ----------*/
|
||||
|
||||
/**
|
||||
* @brief Indicates success/failure of an Astronomy Engine function call.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ASTRO_SUCCESS, /**< The operation was successful. */
|
||||
ASTRO_NOT_INITIALIZED, /**< A placeholder that can be used for data that is not yet initialized. */
|
||||
ASTRO_INVALID_BODY, /**< The celestial body was not valid. Different sets of bodies are supported depending on the function. */
|
||||
ASTRO_NO_CONVERGE, /**< A numeric solver failed to converge. This should not happen unless there is a bug in Astronomy Engine. */
|
||||
ASTRO_BAD_TIME, /**< The provided date/time is outside the range allowed by this function. */
|
||||
ASTRO_BAD_VECTOR, /**< Vector magnitude is too small to be normalized into a unit vector. */
|
||||
ASTRO_SEARCH_FAILURE, /**< Search was not able to find an ascending root crossing of the function in the specified time interval. */
|
||||
ASTRO_EARTH_NOT_ALLOWED, /**< The Earth cannot be treated as a celestial body seen from an observer on the Earth itself. */
|
||||
ASTRO_NO_MOON_QUARTER, /**< No lunar quarter occurs inside the specified time range. */
|
||||
ASTRO_WRONG_MOON_QUARTER, /**< Internal error: Astronomy_NextMoonQuarter found the wrong moon quarter. */
|
||||
ASTRO_INTERNAL_ERROR, /**< A self-check failed inside the code somewhere, indicating a bug needs to be fixed. */
|
||||
ASTRO_INVALID_PARAMETER, /**< A parameter value passed to a function was not valid. */
|
||||
ASTRO_FAIL_APSIS, /**< Special-case logic for finding Neptune/Pluto apsis failed. */
|
||||
ASTRO_BUFFER_TOO_SMALL, /**< A provided buffer's size is too small to receive the requested data. */
|
||||
ASTRO_OUT_OF_MEMORY /**< An attempt to allocate memory failed. */
|
||||
}
|
||||
astro_status_t;
|
||||
|
||||
/**
|
||||
* @brief A date and time used for astronomical calculations.
|
||||
*
|
||||
* This type is of fundamental importance to Astronomy Engine.
|
||||
* It is used to represent dates and times for all astronomical calculations.
|
||||
* It is also included in the values returned by many Astronomy Engine functions.
|
||||
*
|
||||
* To create a valid astro_time_t value from scratch, call #Astronomy_MakeTime
|
||||
* (for a given calendar date and time) or #Astronomy_CurrentTime (for the system's
|
||||
* current date and time).
|
||||
*
|
||||
* To adjust an existing astro_time_t by a certain real number of days,
|
||||
* call #Astronomy_AddDays.
|
||||
*
|
||||
* The astro_time_t type contains `ut` to represent Universal Time (UT1/UTC) and
|
||||
* `tt` to represent Terrestrial Time (TT, also known as *ephemeris time*).
|
||||
* The difference `tt-ut` is known as *ΔT*, and is obtained from
|
||||
* a model provided by the
|
||||
* [United States Naval Observatory](http://maia.usno.navy.mil/ser7/).
|
||||
*
|
||||
* Both `tt` and `ut` are necessary for performing different astronomical calculations.
|
||||
* Indeed, certain calculations (such as rise/set times) require both time scales.
|
||||
* See the documentation for the `ut` and `tt` fields for more detailed information.
|
||||
*
|
||||
* In cases where astro_time_t is included in a structure returned by
|
||||
* a function that can fail, the astro_status_t field `status` will contain a value
|
||||
* other than `ASTRO_SUCCESS`; in that case the `ut` and `tt` will hold `NAN` (not a number).
|
||||
* In general, when there is an error code stored in a struct field `status`, the
|
||||
* caller should ignore all other values in that structure, including the `ut` and `tt`
|
||||
* inside astro_time_t.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/**
|
||||
* @brief UT1/UTC number of days since noon on January 1, 2000.
|
||||
*
|
||||
* The floating point number of days of Universal Time since noon UTC January 1, 2000.
|
||||
* Astronomy Engine approximates UTC and UT1 as being the same thing, although they are
|
||||
* not exactly equivalent; UTC and UT1 can disagree by up to ±0.9 seconds.
|
||||
* This approximation is sufficient for the accuracy requirements of Astronomy Engine.
|
||||
*
|
||||
* Universal Time Coordinate (UTC) is the international standard for legal and civil
|
||||
* timekeeping and replaces the older Greenwich Mean Time (GMT) standard.
|
||||
* UTC is kept in sync with unpredictable observed changes in the Earth's rotation
|
||||
* by occasionally adding leap seconds as needed.
|
||||
*
|
||||
* UT1 is an idealized time scale based on observed rotation of the Earth, which
|
||||
* gradually slows down in an unpredictable way over time, due to tidal drag by the Moon and Sun,
|
||||
* large scale weather events like hurricanes, and internal seismic and convection effects.
|
||||
* Conceptually, UT1 drifts from atomic time continuously and erratically, whereas UTC
|
||||
* is adjusted by a scheduled whole number of leap seconds as needed.
|
||||
*
|
||||
* The value in `ut` is appropriate for any calculation involving the Earth's rotation,
|
||||
* such as calculating rise/set times, culumination, and anything involving apparent
|
||||
* sidereal time.
|
||||
*
|
||||
* Before the era of atomic timekeeping, days based on the Earth's rotation
|
||||
* were often known as *mean solar days*.
|
||||
*/
|
||||
double ut;
|
||||
|
||||
/**
|
||||
* @brief Terrestrial Time days since noon on January 1, 2000.
|
||||
*
|
||||
* Terrestrial Time is an atomic time scale defined as a number of days since noon on January 1, 2000.
|
||||
* In this system, days are not based on Earth rotations, but instead by
|
||||
* the number of elapsed [SI seconds](https://physics.nist.gov/cuu/Units/second.html)
|
||||
* divided by 86400. Unlike `ut`, `tt` increases uniformly without adjustments
|
||||
* for changes in the Earth's rotation.
|
||||
*
|
||||
* The value in `tt` is used for calculations of movements not involving the Earth's rotation,
|
||||
* such as the orbits of planets around the Sun, or the Moon around the Earth.
|
||||
*
|
||||
* Historically, Terrestrial Time has also been known by the term *Ephemeris Time* (ET).
|
||||
*/
|
||||
double tt;
|
||||
|
||||
/**
|
||||
* @brief For internal use only. Used to optimize Earth tilt calculations.
|
||||
*/
|
||||
double psi;
|
||||
|
||||
/**
|
||||
* @brief For internal use only. Used to optimize Earth tilt calculations.
|
||||
*/
|
||||
double eps;
|
||||
}
|
||||
astro_time_t;
|
||||
|
||||
/**
|
||||
* @brief A calendar date and time expressed in UTC.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int year; /**< The year value, e.g. 2019. */
|
||||
int month; /**< The month value: 1=January, 2=February, ..., 12=December. */
|
||||
int day; /**< The day of the month in the range 1..31. */
|
||||
int hour; /**< The hour of the day in the range 0..23. */
|
||||
int minute; /**< The minute of the hour in the range 0..59. */
|
||||
double second; /**< The floating point number of seconds in the range [0,60). */
|
||||
}
|
||||
astro_utc_t;
|
||||
|
||||
/**
|
||||
* @brief A 3D Cartesian vector whose components are expressed in Astronomical Units (AU).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
double x; /**< The Cartesian x-coordinate of the vector in AU. */
|
||||
double y; /**< The Cartesian y-coordinate of the vector in AU. */
|
||||
double z; /**< The Cartesian z-coordinate of the vector in AU. */
|
||||
astro_time_t t; /**< The date and time at which this vector is valid. */
|
||||
}
|
||||
astro_vector_t;
|
||||
|
||||
/**
|
||||
* @brief Spherical coordinates: latitude, longitude, distance.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
double lat; /**< The latitude angle: -90..+90 degrees. */
|
||||
double lon; /**< The longitude angle: 0..360 degrees. */
|
||||
double dist; /**< Distance in AU. */
|
||||
}
|
||||
astro_spherical_t;
|
||||
|
||||
/**
|
||||
* @brief An angular value expressed in degrees.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
double angle; /**< An angle expressed in degrees. */
|
||||
}
|
||||
astro_angle_result_t;
|
||||
|
||||
/**
|
||||
* @brief A celestial body.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
BODY_INVALID = -1, /**< An invalid or undefined celestial body. */
|
||||
BODY_MERCURY, /**< Mercury */
|
||||
BODY_VENUS, /**< Venus */
|
||||
BODY_EARTH, /**< Earth */
|
||||
BODY_MARS, /**< Mars */
|
||||
BODY_JUPITER, /**< Jupiter */
|
||||
BODY_SATURN, /**< Saturn */
|
||||
BODY_URANUS, /**< Uranus */
|
||||
BODY_NEPTUNE, /**< Neptune */
|
||||
BODY_PLUTO, /**< Pluto */
|
||||
BODY_SUN, /**< Sun */
|
||||
BODY_MOON, /**< Moon */
|
||||
BODY_EMB, /**< Earth/Moon Barycenter */
|
||||
BODY_SSB /**< Solar System Barycenter */
|
||||
}
|
||||
astro_body_t;
|
||||
|
||||
#define MIN_BODY BODY_MERCURY /**< Minimum valid astro_body_t value; useful for iteration. */
|
||||
#define MAX_BODY BODY_SSB /**< Maximum valid astro_body_t value; useful for iteration. */
|
||||
|
||||
#define MIN_YEAR 1700 /**< Minimum year value supported by Astronomy Engine. */
|
||||
#define MAX_YEAR 2200 /**< Maximum year value supported by Astronomy Engine. */
|
||||
|
||||
/**
|
||||
* @brief The location of an observer on (or near) the surface of the Earth.
|
||||
*
|
||||
* This structure is passed to functions that calculate phenomena as observed
|
||||
* from a particular place on the Earth.
|
||||
*
|
||||
* You can create this structure directly, or you can call the convenience function
|
||||
* #Astronomy_MakeObserver# to create one for you.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double latitude; /**< Geographic latitude in degrees north (positive) or south (negative) of the equator. */
|
||||
double longitude; /**< Geographic longitude in degrees east (positive) or west (negative) of the prime meridian at Greenwich, England. */
|
||||
double height; /**< The height above (positive) or below (negative) sea level, expressed in meters. */
|
||||
}
|
||||
astro_observer_t;
|
||||
|
||||
/**
|
||||
* @brief Equatorial angular coordinates.
|
||||
*
|
||||
* Coordinates of a celestial body as seen from the Earth (geocentric or topocentric, depending on context),
|
||||
* oriented with respect to the projection of the Earth's equator onto the sky.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
double ra; /**< right ascension in sidereal hours. */
|
||||
double dec; /**< declination in degrees */
|
||||
double dist; /**< distance to the celestial body in AU. */
|
||||
}
|
||||
astro_equatorial_t;
|
||||
|
||||
/**
|
||||
* @brief Ecliptic angular and Cartesian coordinates.
|
||||
*
|
||||
* Coordinates of a celestial body as seen from the center of the Sun (heliocentric),
|
||||
* oriented with respect to the plane of the Earth's orbit around the Sun (the ecliptic).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
double ex; /**< Cartesian x-coordinate: in the direction of the equinox along the ecliptic plane. */
|
||||
double ey; /**< Cartesian y-coordinate: in the ecliptic plane 90 degrees prograde from the equinox. */
|
||||
double ez; /**< Cartesian z-coordinate: perpendicular to the ecliptic plane. Positive is north. */
|
||||
double elat; /**< Latitude in degrees north (positive) or south (negative) of the ecliptic plane. */
|
||||
double elon; /**< Longitude in degrees around the ecliptic plane prograde from the equinox. */
|
||||
}
|
||||
astro_ecliptic_t;
|
||||
|
||||
/**
|
||||
* @brief Coordinates of a celestial body as seen by a topocentric observer.
|
||||
*
|
||||
* Contains horizontal and equatorial coordinates seen by an observer on or near
|
||||
* the surface of the Earth (a topocentric observer).
|
||||
* Optionally corrected for atmospheric refraction.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double azimuth; /**< Compass direction around the horizon in degrees. 0=North, 90=East, 180=South, 270=West. */
|
||||
double altitude; /**< Angle in degrees above (positive) or below (negative) the observer's horizon. */
|
||||
double ra; /**< Right ascension in sidereal hours. */
|
||||
double dec; /**< Declination in degrees. */
|
||||
}
|
||||
astro_horizon_t;
|
||||
|
||||
/**
|
||||
* @brief Contains a rotation matrix that can be used to transform one coordinate system to another.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
double rot[3][3]; /**< A normalized 3x3 rotation matrix. */
|
||||
}
|
||||
astro_rotation_t;
|
||||
|
||||
/**
|
||||
* @brief Selects whether to correct for atmospheric refraction, and if so, how.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
REFRACTION_NONE, /**< No atmospheric refraction correction (airless). */
|
||||
REFRACTION_NORMAL, /**< Recommended correction for standard atmospheric refraction. */
|
||||
REFRACTION_JPLHOR /**< Used only for compatibility testing with JPL Horizons online tool. */
|
||||
}
|
||||
astro_refraction_t;
|
||||
|
||||
/**
|
||||
* @brief The result of a search for an astronomical event.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_time_t time; /**< The time at which a searched-for event occurs. */
|
||||
}
|
||||
astro_search_result_t;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* The dates and times of changes of season for a given calendar year.
|
||||
* Call #Astronomy_Seasons to calculate this data structure for a given year.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_time_t mar_equinox; /**< The date and time of the March equinox for the specified year. */
|
||||
astro_time_t jun_solstice; /**< The date and time of the June soltice for the specified year. */
|
||||
astro_time_t sep_equinox; /**< The date and time of the September equinox for the specified year. */
|
||||
astro_time_t dec_solstice; /**< The date and time of the December solstice for the specified year. */
|
||||
}
|
||||
astro_seasons_t;
|
||||
|
||||
/**
|
||||
* @brief A lunar quarter event (new moon, first quarter, full moon, or third quarter) along with its date and time.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
int quarter; /**< 0=new moon, 1=first quarter, 2=full moon, 3=third quarter. */
|
||||
astro_time_t time; /**< The date and time of the lunar quarter. */
|
||||
}
|
||||
astro_moon_quarter_t;
|
||||
|
||||
/**
|
||||
* @brief A real value returned by a function whose ascending root is to be found.
|
||||
*
|
||||
* When calling #Astronomy_Search, the caller must pass in a callback function
|
||||
* compatible with the function-pointer type #astro_search_func_t
|
||||
* whose ascending root is to be found. That callback function must return astro_func_result_t.
|
||||
* If the function call is successful, it will set `status` to `ASTRO_SUCCESS` and `value`
|
||||
* to the numeric value appropriate for the given date and time.
|
||||
* If the call fails for some reason, it should set `status` to an appropriate error value
|
||||
* other than `ASTRO_SUCCESS`; in the error case, to guard against any possible misuse of `value`,
|
||||
* it is recommended to set `value` to `NAN`, though this is not strictly necessary.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
double value; /**< The value returned by a function whose ascending root is to be found. */
|
||||
}
|
||||
astro_func_result_t;
|
||||
|
||||
/**
|
||||
* @brief A pointer to a function that is to be passed as a callback to #Astronomy_Search.
|
||||
*
|
||||
* The function #Astronomy_Search numerically solves for the time that a given event occurs.
|
||||
* An event is defined as the time when an arbitrary function transitions between having
|
||||
* a negative value and a non-negative value. This transition is called an *ascending root*.
|
||||
*
|
||||
* The type astro_search_func_t represents such a callback function that accepts a
|
||||
* custom `context` pointer and an astro_time_t representing the time to probe.
|
||||
* The function returns an astro_func_result_t that contains either a real
|
||||
* number in `value` or an error code in `status` that aborts the search.
|
||||
*
|
||||
* The `context` points to some data whose type varies depending on the callback function.
|
||||
* It can contain any auxiliary parameters (other than time) needed to evaluate the function.
|
||||
* For example, a function may pertain to a specific celestial body, in which case `context`
|
||||
* may point to a value of type astro_body_t. The `context` parameter is supplied by
|
||||
* the caller of #Astronomy_Search, which passes it along to every call to the callback function.
|
||||
* If the caller of `Astronomy_Search` knows that the callback function does not need a context,
|
||||
* it is safe to pass `NULL` as the context pointer.
|
||||
*/
|
||||
typedef astro_func_result_t (* astro_search_func_t) (void *context, astro_time_t time);
|
||||
|
||||
/**
|
||||
* @brief A pointer to a function that calculates Delta T.
|
||||
*
|
||||
* Delta T is the discrepancy between times measured using an atomic clock
|
||||
* and times based on observations of the Earth's rotation, which is gradually
|
||||
* slowing down over time. Delta T = TT - UT, where
|
||||
* TT = Terrestrial Time, based on atomic time, and
|
||||
* UT = Universal Time, civil time based on the Earth's rotation.
|
||||
* Astronomy Engine defaults to using a Delta T function defined by
|
||||
* Espenak and Meeus in their "Five Millennium Canon of Solar Eclipses".
|
||||
* See: https://eclipse.gsfc.nasa.gov/SEhelp/deltatpoly2004.html
|
||||
*/
|
||||
typedef double (* astro_deltat_func) (double ut);
|
||||
|
||||
double Astronomy_DeltaT_EspenakMeeus(double ut);
|
||||
double Astronomy_DeltaT_JplHorizons(double ut);
|
||||
|
||||
void Astronomy_SetDeltaTFunction(astro_deltat_func func);
|
||||
|
||||
/**
|
||||
* @brief Indicates whether a body (especially Mercury or Venus) is best seen in the morning or evening.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
VISIBLE_MORNING, /**< The body is best visible in the morning, before sunrise. */
|
||||
VISIBLE_EVENING /**< The body is best visible in the evening, after sunset. */
|
||||
}
|
||||
astro_visibility_t;
|
||||
|
||||
/**
|
||||
* @brief
|
||||
* Contains information about the visibility of a celestial body at a given date and time.
|
||||
* See #Astronomy_Elongation for more detailed information about the members of this structure.
|
||||
* See also #Astronomy_SearchMaxElongation for how to search for maximum elongation events.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_time_t time; /**< The date and time of the observation. */
|
||||
astro_visibility_t visibility; /**< Whether the body is best seen in the morning or the evening. */
|
||||
double elongation; /**< The angle in degrees between the body and the Sun, as seen from the Earth. */
|
||||
double ecliptic_separation; /**< The difference between the ecliptic longitudes of the body and the Sun, as seen from the Earth. */
|
||||
}
|
||||
astro_elongation_t;
|
||||
|
||||
/**
|
||||
* @brief Information about a celestial body crossing a specific hour angle.
|
||||
*
|
||||
* Returned by the function #Astronomy_SearchHourAngle to report information about
|
||||
* a celestial body crossing a certain hour angle as seen by a specified topocentric observer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_time_t time; /**< The date and time when the body crosses the specified hour angle. */
|
||||
astro_horizon_t hor; /**< Apparent coordinates of the body at the time it crosses the specified hour angle. */
|
||||
}
|
||||
astro_hour_angle_t;
|
||||
|
||||
/**
|
||||
* @brief Information about the brightness and illuminated shape of a celestial body.
|
||||
*
|
||||
* Returned by the functions #Astronomy_Illumination and #Astronomy_SearchPeakMagnitude
|
||||
* to report the visual magnitude and illuminated fraction of a celestial body at a given date and time.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_time_t time; /**< The date and time of the observation. */
|
||||
double mag; /**< The visual magnitude of the body. Smaller values are brighter. */
|
||||
double phase_angle; /**< The angle in degrees between the Sun and the Earth, as seen from the body. Indicates the body's phase as seen from the Earth. */
|
||||
double helio_dist; /**< The distance between the Sun and the body at the observation time. */
|
||||
double ring_tilt; /**< For Saturn, the tilt angle in degrees of its rings as seen from Earth. For all other bodies, 0. */
|
||||
}
|
||||
astro_illum_t;
|
||||
|
||||
/**
|
||||
* @brief The type of apsis: pericenter (closest approach) or apocenter (farthest distance).
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
APSIS_PERICENTER, /**< The body is at its closest approach to the object it orbits. */
|
||||
APSIS_APOCENTER, /**< The body is at its farthest distance from the object it orbits. */
|
||||
APSIS_INVALID /**< Undefined or invalid apsis. */
|
||||
}
|
||||
astro_apsis_kind_t;
|
||||
|
||||
/**
|
||||
* @brief An apsis event: pericenter (closest approach) or apocenter (farthest distance).
|
||||
*
|
||||
* For the Moon orbiting the Earth, or a planet orbiting the Sun, an *apsis* is an
|
||||
* event where the orbiting body reaches its closest or farthest point from the primary body.
|
||||
* The closest approach is called *pericenter* and the farthest point is *apocenter*.
|
||||
*
|
||||
* More specific terminology is common for particular orbiting bodies.
|
||||
* The Moon's closest approach to the Earth is called *perigee* and its farthest
|
||||
* point is called *apogee*. The closest approach of a planet to the Sun is called
|
||||
* *perihelion* and the furthest point is called *aphelion*.
|
||||
*
|
||||
* This data structure is returned by #Astronomy_SearchLunarApsis and #Astronomy_NextLunarApsis
|
||||
* to iterate through consecutive alternating perigees and apogees.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_time_t time; /**< The date and time of the apsis. */
|
||||
astro_apsis_kind_t kind; /**< Whether this is a pericenter or apocenter event. */
|
||||
double dist_au; /**< The distance between the centers of the bodies in astronomical units. */
|
||||
double dist_km; /**< The distance between the centers of the bodies in kilometers. */
|
||||
}
|
||||
astro_apsis_t;
|
||||
|
||||
/**
|
||||
* @brief The different kinds of lunar/solar eclipses.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ECLIPSE_NONE, /**< No eclipse found. */
|
||||
ECLIPSE_PENUMBRAL, /**< A penumbral lunar eclipse. (Never used for a solar eclipse.) */
|
||||
ECLIPSE_PARTIAL, /**< A partial lunar/solar eclipse. */
|
||||
ECLIPSE_ANNULAR, /**< An annular solar eclipse. (Never used for a lunar eclipse.) */
|
||||
ECLIPSE_TOTAL /**< A total lunar/solar eclipse. */
|
||||
}
|
||||
astro_eclipse_kind_t;
|
||||
|
||||
/**
|
||||
* @brief Information about a lunar eclipse.
|
||||
*
|
||||
* Returned by #Astronomy_SearchLunarEclipse or #Astronomy_NextLunarEclipse
|
||||
* to report information about a lunar eclipse event.
|
||||
* If a lunar eclipse is found, `status` holds `ASTRO_SUCCESS` and the other fields are set.
|
||||
* If `status` holds any other value, it is an error code and the other fields are undefined.
|
||||
*
|
||||
* When a lunar eclipse is found, it is classified as penumbral, partial, or total.
|
||||
* Penumbral eclipses are difficult to observe, because the moon is only slightly dimmed
|
||||
* by the Earth's penumbra; no part of the Moon touches the Earth's umbra.
|
||||
* Partial eclipses occur when part, but not all, of the Moon touches the Earth's umbra.
|
||||
* Total eclipses occur when the entire Moon passes into the Earth's umbra.
|
||||
*
|
||||
* The `kind` field thus holds `ECLIPSE_PENUMBRAL`, `ECLIPSE_PARTIAL`, or `ECLIPSE_TOTAL`,
|
||||
* depending on the kind of lunar eclipse found.
|
||||
*
|
||||
* Field `peak` holds the date and time of the center of the eclipse, when it is at its peak.
|
||||
*
|
||||
* Fields `sd_penum`, `sd_partial`, and `sd_total` hold the semi-duration of each phase
|
||||
* of the eclipse, which is half of the amount of time the eclipse spends in each
|
||||
* phase (expressed in minutes), or 0 if the eclipse never reaches that phase.
|
||||
* By converting from minutes to days, and subtracting/adding with `center`, the caller
|
||||
* may determine the date and time of the beginning/end of each eclipse phase.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_eclipse_kind_t kind; /**< The type of lunar eclipse found. */
|
||||
astro_time_t peak; /**< The time of the eclipse at its peak. */
|
||||
double sd_penum; /**< The semi-duration of the penumbral phase in minutes. */
|
||||
double sd_partial; /**< The semi-duration of the partial phase in minutes, or 0.0 if none. */
|
||||
double sd_total; /**< The semi-duration of the total phase in minutes, or 0.0 if none. */
|
||||
}
|
||||
astro_lunar_eclipse_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reports the time and geographic location of the peak of a solar eclipse.
|
||||
*
|
||||
* Returned by #Astronomy_SearchGlobalSolarEclipse or #Astronomy_NextGlobalSolarEclipse
|
||||
* to report information about a solar eclipse event.
|
||||
* If a solar eclipse is found, `status` holds `ASTRO_SUCCESS` and `kind`, `peak`, and `distance`
|
||||
* have valid values. The `latitude` and `longitude` are set only for total and annular eclipses
|
||||
* (see more below).
|
||||
* If `status` holds any value other than `ASTRO_SUCCESS`, it is an error code;
|
||||
* in that case, `kind` holds `ECLIPSE_NONE` and all the other fields are undefined.
|
||||
*
|
||||
* Field `peak` holds the date and time of the peak of the eclipse, defined as
|
||||
* the instant when the axis of the Moon's shadow cone passes closest to the Earth's center.
|
||||
*
|
||||
* The eclipse is classified as partial, annular, or total, depending on the
|
||||
* maximum amount of the Sun's disc obscured, as seen at the peak location
|
||||
* on the surface of the Earth.
|
||||
*
|
||||
* The `kind` field thus holds `ECLIPSE_PARTIAL`, `ECLIPSE_ANNULAR`, or `ECLIPSE_TOTAL`.
|
||||
* A total eclipse is when the peak observer sees the Sun completely blocked by the Moon.
|
||||
* An annular eclipse is like a total eclipse, but the Moon is too far from the Earth's surface
|
||||
* to completely block the Sun; instead, the Sun takes on a ring-shaped appearance.
|
||||
* A partial eclipse is when the Moon blocks part of the Sun's disc, but nobody on the Earth
|
||||
* observes either a total or annular eclipse.
|
||||
*
|
||||
* If `kind` is `ECLIPSE_TOTAL` or `ECLIPSE_ANNULAR`, the `latitude` and `longitude`
|
||||
* fields give the geographic coordinates of the center of the Moon's shadow projected
|
||||
* onto the daytime side of the Earth at the instant of the eclipse's peak.
|
||||
* If `kind` has any other value, `latitude` and `longitude` are undefined and should
|
||||
* not be used.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_eclipse_kind_t kind; /**< The type of solar eclipse found. */
|
||||
astro_time_t peak; /**< The date and time of the eclipse at its peak. */
|
||||
double distance; /**< The distance between the Sun/Moon shadow axis and the center of the Earth, in kilometers. */
|
||||
double latitude; /**< The geographic latitude at the center of the peak eclipse shadow. */
|
||||
double longitude; /**< The geographic longitude at the center of the peak eclipse shadow. */
|
||||
}
|
||||
astro_global_solar_eclipse_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Holds a time and the observed altitude of the Sun at that time.
|
||||
*
|
||||
* When reporting a solar eclipse observed at a specific location on the Earth
|
||||
* (a "local" solar eclipse), a series of events occur. In addition
|
||||
* to the time of each event, it is important to know the altitude of the Sun,
|
||||
* because each event may be invisible to the observer if the Sun is below
|
||||
* the horizon (i.e. it at night).
|
||||
*
|
||||
* If `altitude` is negative, the event is theoretical only; it would be
|
||||
* visible if the Earth were transparent, but the observer cannot actually see it.
|
||||
* If `altitude` is positive but less than a few degrees, visibility will be impaired by
|
||||
* atmospheric interference (sunrise or sunset conditions).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_time_t time; /**< The date and time of the event. */
|
||||
double altitude; /**< The angular altitude of the center of the Sun above/below the horizon, at `time`, corrected for atmospheric refraction and expressed in degrees. */
|
||||
}
|
||||
astro_eclipse_event_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Information about a solar eclipse as seen by an observer at a given time and geographic location.
|
||||
*
|
||||
* Returned by #Astronomy_SearchLocalSolarEclipse or #Astronomy_NextLocalSolarEclipse
|
||||
* to report information about a solar eclipse as seen at a given geographic location.
|
||||
* If a solar eclipse is found, `status` holds `ASTRO_SUCCESS` and the other fields are set.
|
||||
* If `status` holds any other value, it is an error code and the other fields are undefined.
|
||||
*
|
||||
* When a solar eclipse is found, it is classified as partial, annular, or total.
|
||||
* The `kind` field thus holds `ECLIPSE_PARTIAL`, `ECLIPSE_ANNULAR`, or `ECLIPSE_TOTAL`.
|
||||
* A partial solar eclipse is when the Moon does not line up directly enough with the Sun
|
||||
* to completely block the Sun's light from reaching the observer.
|
||||
* An annular eclipse occurs when the Moon's disc is completely visible against the Sun
|
||||
* but the Moon is too far away to completely block the Sun's light; this leaves the
|
||||
* Sun with a ring-like appearance.
|
||||
* A total eclipse occurs when the Moon is close enough to the Earth and aligned with the
|
||||
* Sun just right to completely block all sunlight from reaching the observer.
|
||||
*
|
||||
* There are 5 "event" fields, each of which contains a time and a solar altitude.
|
||||
* Field `peak` holds the date and time of the center of the eclipse, when it is at its peak.
|
||||
* The fields `partial_begin` and `partial_end` are always set, and indicate when
|
||||
* the eclipse begins/ends. If the eclipse reaches totality or becomes annular,
|
||||
* `total_begin` and `total_end` indicate when the total/annular phase begins/ends.
|
||||
* When an event field is valid, the caller must also check its `altitude` field to
|
||||
* see whether the Sun is above the horizon at that time. See #astro_eclipse_kind_t
|
||||
* for more information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_eclipse_kind_t kind; /**< The type of solar eclipse found: `ECLIPSE_PARTIAL`, `ECLIPSE_ANNULAR`, or `ECLIPSE_TOTAL`. */
|
||||
astro_eclipse_event_t partial_begin; /**< The time and Sun altitude at the beginning of the eclipse. */
|
||||
astro_eclipse_event_t total_begin; /**< If this is an annular or a total eclipse, the time and Sun altitude when annular/total phase begins; otherwise invalid. */
|
||||
astro_eclipse_event_t peak; /**< The time and Sun altitude when the eclipse reaches its peak. */
|
||||
astro_eclipse_event_t total_end; /**< If this is an annular or a total eclipse, the time and Sun altitude when annular/total phase ends; otherwise invalid. */
|
||||
astro_eclipse_event_t partial_end; /**< The time and Sun altitude at the end of the eclipse. */
|
||||
}
|
||||
astro_local_solar_eclipse_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Information about a transit of Mercury or Venus, as seen from the Earth.
|
||||
*
|
||||
* Returned by #Astronomy_SearchTransit or #Astronomy_NextTransit to report
|
||||
* information about a transit of Mercury or Venus.
|
||||
* A transit is when Mercury or Venus passes between the Sun and Earth so that
|
||||
* the other planet is seen in silhouette against the Sun.
|
||||
*
|
||||
* The `start` field reports the moment in time when the planet first becomes
|
||||
* visible against the Sun in its background.
|
||||
* The `peak` field reports when the planet is most aligned with the Sun,
|
||||
* as seen from the Earth.
|
||||
* The `finish` field reports the last moment when the planet is visible
|
||||
* against the Sun in its background.
|
||||
*
|
||||
* The calculations are performed from the point of view of a geocentric observer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
astro_time_t start; /**< Date and time at the beginning of the transit. */
|
||||
astro_time_t peak; /**< Date and time of the peak of the transit. */
|
||||
astro_time_t finish; /**< Date and time at the end of the transit. */
|
||||
double separation; /**< Angular separation in arcminutes between the centers of the Sun and the planet at time `peak`. */
|
||||
}
|
||||
astro_transit_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Aberration calculation options.
|
||||
*
|
||||
* [Aberration](https://en.wikipedia.org/wiki/Aberration_of_light) is an effect
|
||||
* causing the apparent direction of an observed body to be shifted due to transverse
|
||||
* movement of the Earth with respect to the rays of light coming from that body.
|
||||
* This angular correction can be anywhere from 0 to about 20 arcseconds,
|
||||
* depending on the position of the observed body relative to the instantaneous
|
||||
* velocity vector of the Earth.
|
||||
*
|
||||
* Some Astronomy Engine functions allow optional correction for aberration by
|
||||
* passing in a value of this enumerated type.
|
||||
*
|
||||
* Aberration correction is useful to improve accuracy of coordinates of
|
||||
* apparent locations of bodies seen from the Earth.
|
||||
* However, because aberration affects not only the observed body (such as a planet)
|
||||
* but the surrounding stars, aberration may be unhelpful (for example)
|
||||
* for determining exactly when a planet crosses from one constellation to another.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
ABERRATION, /**< Request correction for aberration. */
|
||||
NO_ABERRATION /**< Do not correct for aberration. */
|
||||
}
|
||||
astro_aberration_t;
|
||||
|
||||
/**
|
||||
* @brief Selects the date for which the Earth's equator is to be used for representing equatorial coordinates.
|
||||
*
|
||||
* The Earth's equator is not always in the same plane due to precession and nutation.
|
||||
*
|
||||
* Sometimes it is useful to have a fixed plane of reference for equatorial coordinates
|
||||
* across different calendar dates. In these cases, a fixed *epoch*, or reference time,
|
||||
* is helpful. Astronomy Engine provides the J2000 epoch for such cases. This refers
|
||||
* to the plane of the Earth's orbit as it was on noon UTC on 1 January 2000.
|
||||
*
|
||||
* For some other purposes, it is more helpful to represent coordinates using the Earth's
|
||||
* equator exactly as it is on that date. For example, when calculating rise/set times
|
||||
* or horizontal coordinates, it is most accurate to use the orientation of the Earth's
|
||||
* equator at that same date and time. For these uses, Astronomy Engine allows *of-date*
|
||||
* calculations.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
EQUATOR_J2000, /**< Represent equatorial coordinates in the J2000 epoch. */
|
||||
EQUATOR_OF_DATE /**< Represent equatorial coordinates using the Earth's equator at the given date and time. */
|
||||
}
|
||||
astro_equator_date_t;
|
||||
|
||||
/**
|
||||
* @brief Selects whether to search for a rise time or a set time.
|
||||
*
|
||||
* The #Astronomy_SearchRiseSet function finds the rise or set time of a body
|
||||
* depending on the value of its `direction` parameter.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
DIRECTION_RISE = +1, /**< Search for the time a body begins to rise above the horizon. */
|
||||
DIRECTION_SET = -1, /**< Search for the time a body finishes sinking below the horizon. */
|
||||
}
|
||||
astro_direction_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reports the constellation that a given celestial point lies within.
|
||||
*
|
||||
* The #Astronomy_Constellation function returns this struct
|
||||
* to report which constellation corresponds with a given point in the sky.
|
||||
* Constellations are defined with respect to the B1875 equatorial system
|
||||
* per IAU standard. Although `Astronomy.Constellation` requires J2000 equatorial
|
||||
* coordinates, the struct contains converted B1875 coordinates for reference.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
astro_status_t status; /**< `ASTRO_SUCCESS` if this struct is valid; otherwise an error code. */
|
||||
const char *symbol; /**< 3-character mnemonic symbol for the constellation, e.g. "Ori". */
|
||||
const char *name; /**< Full name of constellation, e.g. "Orion". */
|
||||
double ra_1875; /**< Right ascension expressed in B1875 coordinates. */
|
||||
double dec_1875; /**< Declination expressed in B1875 coordinates. */
|
||||
}
|
||||
astro_constellation_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Selects the output format of the function #Astronomy_FormatTime.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
TIME_FORMAT_DAY, /**< Truncate to UTC calendar date only, e.g. `2020-12-31`. Buffer size must be at least 11 characters. */
|
||||
TIME_FORMAT_MINUTE, /**< Round to nearest UTC minute, e.g. `2020-12-31T15:47Z`. Buffer size must be at least 18 characters. */
|
||||
TIME_FORMAT_SECOND, /**< Round to nearest UTC second, e.g. `2020-12-31T15:47:32Z`. Buffer size must be at least 21 characters. */
|
||||
TIME_FORMAT_MILLI /**< Round to nearest UTC millisecond, e.g. `2020-12-31T15:47:32.397Z`. Buffer size must be at least 25 characters. */
|
||||
}
|
||||
astro_time_format_t;
|
||||
|
||||
#define TIME_TEXT_BYTES 25 /**< The smallest number of characters that is always large enough for #Astronomy_FormatTime. */
|
||||
|
||||
/*---------- functions ----------*/
|
||||
|
||||
void Astronomy_Reset(void);
|
||||
double Astronomy_VectorLength(astro_vector_t vector);
|
||||
const char *Astronomy_BodyName(astro_body_t body);
|
||||
astro_body_t Astronomy_BodyCode(const char *name);
|
||||
astro_observer_t Astronomy_MakeObserver(double latitude, double longitude, double height);
|
||||
astro_time_t Astronomy_CurrentTime(void);
|
||||
astro_time_t Astronomy_MakeTime(int year, int month, int day, int hour, int minute, double second);
|
||||
astro_time_t Astronomy_TimeFromUtc(astro_utc_t utc);
|
||||
astro_utc_t Astronomy_UtcFromTime(astro_time_t time);
|
||||
astro_status_t Astronomy_FormatTime(astro_time_t time, astro_time_format_t format, char *text, size_t size);
|
||||
astro_time_t Astronomy_TimeFromDays(double ut);
|
||||
astro_time_t Astronomy_AddDays(astro_time_t time, double days);
|
||||
astro_func_result_t Astronomy_HelioDistance(astro_body_t body, astro_time_t time);
|
||||
astro_vector_t Astronomy_HelioVector(astro_body_t body, astro_time_t time);
|
||||
astro_vector_t Astronomy_GeoVector(astro_body_t body, astro_time_t time, astro_aberration_t aberration);
|
||||
astro_vector_t Astronomy_GeoMoon(astro_time_t time);
|
||||
|
||||
astro_equatorial_t Astronomy_Equator(
|
||||
astro_body_t body,
|
||||
astro_time_t *time,
|
||||
astro_observer_t observer,
|
||||
astro_equator_date_t equdate,
|
||||
astro_aberration_t aberration
|
||||
);
|
||||
|
||||
astro_ecliptic_t Astronomy_SunPosition(astro_time_t time);
|
||||
astro_ecliptic_t Astronomy_Ecliptic(astro_vector_t equ);
|
||||
astro_angle_result_t Astronomy_EclipticLongitude(astro_body_t body, astro_time_t time);
|
||||
|
||||
astro_horizon_t Astronomy_Horizon(
|
||||
astro_time_t *time,
|
||||
astro_observer_t observer,
|
||||
double ra,
|
||||
double dec,
|
||||
astro_refraction_t refraction);
|
||||
|
||||
astro_angle_result_t Astronomy_AngleFromSun(astro_body_t body, astro_time_t time);
|
||||
astro_elongation_t Astronomy_Elongation(astro_body_t body, astro_time_t time);
|
||||
astro_elongation_t Astronomy_SearchMaxElongation(astro_body_t body, astro_time_t startTime);
|
||||
astro_angle_result_t Astronomy_LongitudeFromSun(astro_body_t body, astro_time_t time);
|
||||
astro_search_result_t Astronomy_SearchRelativeLongitude(astro_body_t body, double targetRelLon, astro_time_t startTime);
|
||||
astro_angle_result_t Astronomy_MoonPhase(astro_time_t time);
|
||||
astro_search_result_t Astronomy_SearchMoonPhase(double targetLon, astro_time_t startTime, double limitDays);
|
||||
astro_moon_quarter_t Astronomy_SearchMoonQuarter(astro_time_t startTime);
|
||||
astro_moon_quarter_t Astronomy_NextMoonQuarter(astro_moon_quarter_t mq);
|
||||
astro_lunar_eclipse_t Astronomy_SearchLunarEclipse(astro_time_t startTime);
|
||||
astro_lunar_eclipse_t Astronomy_NextLunarEclipse(astro_time_t prevEclipseTime);
|
||||
astro_global_solar_eclipse_t Astronomy_SearchGlobalSolarEclipse(astro_time_t startTime);
|
||||
astro_global_solar_eclipse_t Astronomy_NextGlobalSolarEclipse(astro_time_t prevEclipseTime);
|
||||
astro_local_solar_eclipse_t Astronomy_SearchLocalSolarEclipse(astro_time_t startTime, astro_observer_t observer);
|
||||
astro_local_solar_eclipse_t Astronomy_NextLocalSolarEclipse(astro_time_t prevEclipseTime, astro_observer_t observer);
|
||||
astro_transit_t Astronomy_SearchTransit(astro_body_t body, astro_time_t startTime);
|
||||
astro_transit_t Astronomy_NextTransit(astro_body_t body, astro_time_t prevTransitTime);
|
||||
|
||||
astro_search_result_t Astronomy_Search(
|
||||
astro_search_func_t func,
|
||||
void *context,
|
||||
astro_time_t t1,
|
||||
astro_time_t t2,
|
||||
double dt_tolerance_seconds);
|
||||
|
||||
astro_search_result_t Astronomy_SearchSunLongitude(
|
||||
double targetLon,
|
||||
astro_time_t startTime,
|
||||
double limitDays);
|
||||
|
||||
astro_hour_angle_t Astronomy_SearchHourAngle(
|
||||
astro_body_t body,
|
||||
astro_observer_t observer,
|
||||
double hourAngle,
|
||||
astro_time_t startTime);
|
||||
|
||||
astro_search_result_t Astronomy_SearchRiseSet(
|
||||
astro_body_t body,
|
||||
astro_observer_t observer,
|
||||
astro_direction_t direction,
|
||||
astro_time_t startTime,
|
||||
double limitDays);
|
||||
|
||||
astro_seasons_t Astronomy_Seasons(int year);
|
||||
astro_illum_t Astronomy_Illumination(astro_body_t body, astro_time_t time);
|
||||
astro_illum_t Astronomy_SearchPeakMagnitude(astro_body_t body, astro_time_t startTime);
|
||||
astro_apsis_t Astronomy_SearchLunarApsis(astro_time_t startTime);
|
||||
astro_apsis_t Astronomy_NextLunarApsis(astro_apsis_t apsis);
|
||||
astro_apsis_t Astronomy_SearchPlanetApsis(astro_body_t body, astro_time_t startTime);
|
||||
astro_apsis_t Astronomy_NextPlanetApsis(astro_body_t body, astro_apsis_t apsis);
|
||||
|
||||
astro_rotation_t Astronomy_InverseRotation(astro_rotation_t rotation);
|
||||
astro_rotation_t Astronomy_CombineRotation(astro_rotation_t a, astro_rotation_t b);
|
||||
astro_vector_t Astronomy_VectorFromSphere(astro_spherical_t sphere, astro_time_t time);
|
||||
astro_spherical_t Astronomy_SphereFromVector(astro_vector_t vector);
|
||||
astro_vector_t Astronomy_VectorFromEquator(astro_equatorial_t equ, astro_time_t time);
|
||||
astro_equatorial_t Astronomy_EquatorFromVector(astro_vector_t vector);
|
||||
astro_vector_t Astronomy_VectorFromHorizon(astro_spherical_t sphere, astro_time_t time, astro_refraction_t refraction);
|
||||
astro_spherical_t Astronomy_HorizonFromVector(astro_vector_t vector, astro_refraction_t refraction);
|
||||
astro_vector_t Astronomy_RotateVector(astro_rotation_t rotation, astro_vector_t vector);
|
||||
|
||||
astro_rotation_t Astronomy_Rotation_EQD_EQJ(astro_time_t time);
|
||||
astro_rotation_t Astronomy_Rotation_EQD_ECL(astro_time_t time);
|
||||
astro_rotation_t Astronomy_Rotation_EQD_HOR(astro_time_t time, astro_observer_t observer);
|
||||
astro_rotation_t Astronomy_Rotation_EQJ_EQD(astro_time_t time);
|
||||
astro_rotation_t Astronomy_Rotation_EQJ_ECL(void);
|
||||
astro_rotation_t Astronomy_Rotation_EQJ_HOR(astro_time_t time, astro_observer_t observer);
|
||||
astro_rotation_t Astronomy_Rotation_ECL_EQD(astro_time_t time);
|
||||
astro_rotation_t Astronomy_Rotation_ECL_EQJ(void);
|
||||
astro_rotation_t Astronomy_Rotation_ECL_HOR(astro_time_t time, astro_observer_t observer);
|
||||
astro_rotation_t Astronomy_Rotation_HOR_EQD(astro_time_t time, astro_observer_t observer);
|
||||
astro_rotation_t Astronomy_Rotation_HOR_EQJ(astro_time_t time, astro_observer_t observer);
|
||||
astro_rotation_t Astronomy_Rotation_HOR_ECL(astro_time_t time, astro_observer_t observer);
|
||||
|
||||
double Astronomy_Refraction(astro_refraction_t refraction, double altitude);
|
||||
double Astronomy_InverseRefraction(astro_refraction_t refraction, double bent_altitude);
|
||||
|
||||
astro_constellation_t Astronomy_Constellation(double ra, double dec);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ifndef __ASTRONOMY_H */
|
||||
@@ -0,0 +1,186 @@
|
||||
// This example plots a rotated Sprite to the screen using the pushRotated()
|
||||
// function. It is written for a 240 x 320 TFT screen.
|
||||
|
||||
// Two rotation pivot points must be set, one for the Sprite and one for the TFT
|
||||
// using setPivot(). These pivot points do not need to be within the visible screen
|
||||
// or Sprite boundary.
|
||||
|
||||
// When the Sprite is rotated and pushed to the TFT with pushRotated(angle) it will be
|
||||
// drawn so that the two pivot points coincide. This makes rotation about a point on the
|
||||
// screen very simple. The rotation is clockwise with increasing angle. The angle is in
|
||||
// degrees, an angle of 0 means no Sprite rotation.
|
||||
|
||||
// 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.
|
||||
|
||||
// Optionally a transparent colour can be defined, pixels of this colour will
|
||||
// not be plotted to the TFT.
|
||||
|
||||
// For 1 bpp Sprites the foreground and background colours are defined with the
|
||||
// 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:
|
||||
// https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // TFT object
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft); // Sprite object
|
||||
|
||||
// =======================================================================================
|
||||
// Setup
|
||||
// =======================================================================================
|
||||
|
||||
void setup() {
|
||||
Serial.begin(250000); // Debug only
|
||||
|
||||
tft.begin(); // initialize
|
||||
tft.setRotation(0);
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Loop
|
||||
// =======================================================================================
|
||||
|
||||
void loop() {
|
||||
|
||||
int xw = tft.width()/2; // xw, yh is middle of screen
|
||||
int yh = tft.height()/2;
|
||||
|
||||
|
||||
showMessage("90 degree angles");
|
||||
tft.setPivot(xw, yh); // Set pivot to middle of TFT screen
|
||||
drawX(xw, yh); // Show where screen pivot is
|
||||
|
||||
// Create the Sprite
|
||||
spr.setColorDepth(8); // Create an 8bpp Sprite of 60x30 pixels
|
||||
spr.createSprite(64, 30); // 8bpp requires 64 * 30 = 1920 bytes
|
||||
spr.setPivot(32, 55); // Set pivot relative to top left corner of Sprite
|
||||
spr.fillSprite(TFT_BLACK); // Fill the Sprite with black
|
||||
|
||||
spr.setTextColor(TFT_GREEN); // Green text
|
||||
spr.setTextDatum(MC_DATUM); // Middle centre datum
|
||||
spr.drawString("Hello", 32, 15, 4); // Plot text, font 4, in Sprite at 30, 15
|
||||
|
||||
spr.pushRotated(0);
|
||||
spr.pushRotated(90);
|
||||
spr.pushRotated(180);
|
||||
spr.pushRotated(270);
|
||||
|
||||
delay(2000);
|
||||
|
||||
|
||||
showMessage("45 degree angles");
|
||||
drawX(xw, yh); // Show where screen pivot is
|
||||
|
||||
spr.pushRotated(45);
|
||||
spr.pushRotated(135);
|
||||
spr.pushRotated(225);
|
||||
spr.pushRotated(315);
|
||||
|
||||
delay(2000); // Pause so we see it
|
||||
|
||||
|
||||
showMessage("Moved Sprite pivot point");
|
||||
drawX(xw, yh); // Show where screen pivot is
|
||||
|
||||
spr.setPivot(-20, 15); // Change just the Sprite pivot point
|
||||
|
||||
spr.pushRotated(45);
|
||||
spr.pushRotated(135);
|
||||
spr.pushRotated(225);
|
||||
spr.pushRotated(315);
|
||||
|
||||
delay(2000); // Pause so we see it
|
||||
|
||||
|
||||
showMessage("Moved TFT pivot point");
|
||||
tft.setPivot(100, 100); // Change just the TFT pivot point
|
||||
drawX(100, 100); // Show where pivot is
|
||||
|
||||
spr.pushRotated(45);
|
||||
spr.pushRotated(135);
|
||||
spr.pushRotated(225);
|
||||
spr.pushRotated(315);
|
||||
|
||||
delay(2000); // Pause so we see it
|
||||
|
||||
|
||||
showMessage("Transparent rotations");
|
||||
tft.fillCircle(xw, yh, 70, TFT_DARKGREY); // Draw a filled circle
|
||||
|
||||
tft.setPivot(xw, yh); // Set pivot to middle of screen
|
||||
drawX(xw, yh); // Show where pivot is
|
||||
|
||||
spr.deleteSprite();
|
||||
|
||||
spr.setColorDepth(8); // Create a 8bpp Sprite
|
||||
spr.createSprite(40, 30); // Create a new Sprite 40x30
|
||||
spr.setPivot(20, 70); // Set Sprite pivot at 20,80
|
||||
|
||||
spr.setTextColor(TFT_RED); // Red text in Sprite
|
||||
spr.setTextDatum(MC_DATUM); // Middle centre datum
|
||||
|
||||
int num = 1;
|
||||
|
||||
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 20,15 and with font 4
|
||||
spr.pushRotated(angle, TFT_BLACK); // Plot rotated Sprite, black being transparent
|
||||
num++;
|
||||
}
|
||||
|
||||
spr.setTextColor(TFT_WHITE); // White text in Sprite
|
||||
spr.setPivot(-75, 15); // Set Sprite pivot at -75,15
|
||||
|
||||
for (int16_t angle = -90; angle < 270; angle += 30)
|
||||
{
|
||||
spr.fillSprite(TFT_BLACK); // Clear the Sprite
|
||||
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++;
|
||||
}
|
||||
|
||||
delay(8000); // Pause so we see it
|
||||
|
||||
spr.deleteSprite();
|
||||
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Draw an X centered on x,y
|
||||
// =======================================================================================
|
||||
|
||||
void drawX(int x, int y)
|
||||
{
|
||||
tft.drawLine(x-5, y-5, x+5, y+5, TFT_WHITE);
|
||||
tft.drawLine(x-5, y+5, x+5, y-5, TFT_WHITE);
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Show a message at the top of the screen
|
||||
// =======================================================================================
|
||||
|
||||
void showMessage(String msg)
|
||||
{
|
||||
// Clear the screen areas
|
||||
tft.fillRect(0, 0, tft.width(), 20, TFT_BLACK);
|
||||
tft.fillRect(0, 20, tft.width(), tft.height()-20, TFT_BLUE);
|
||||
|
||||
uint8_t td = tft.getTextDatum(); // Get current datum
|
||||
|
||||
tft.setTextDatum(TC_DATUM); // Set new datum
|
||||
|
||||
tft.drawString(msg, tft.width()/2, 2, 2); // Message in font 2
|
||||
|
||||
tft.setTextDatum(td); // Restore old datum
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
@@ -0,0 +1,181 @@
|
||||
// This example plots a rotated Sprite into another Sprite and then the resultant composited
|
||||
// Sprite is pushed to the TFT screen. This example is for a 240 x 320 screen.
|
||||
|
||||
// The motivation for developing this capability is that animated dials can be drawn easily
|
||||
// and the complex calculations involved are handled by the TFT_eSPI library. To create a dial
|
||||
// with a moving needle a graphic of a meter needle is plotted at a specified angle into another
|
||||
// Sprite that contains the dial face. When the needle Sprite is pushed to the dial Sprite the
|
||||
// plotting ensures two pivot points for each Sprite coincide with pixel level accuracy.
|
||||
|
||||
// Two rotation pivot points must be set, one for the first Sprite and one for the second
|
||||
// Sprite using setPivot(). These pivot points do not need to be within the Sprite boundaries.
|
||||
|
||||
// In this example a needle graphic is also be plotted direct to a defined TFT pivot point.
|
||||
|
||||
// The rotation angle is in degrees, an angle of 0 means no Sprite rotation.
|
||||
|
||||
// The pushRotated() function works with 1, 8 and 16 bit per pixel (bpp) Sprites.
|
||||
|
||||
// For 1 bpp Sprites the foreground and background colours are defined with the
|
||||
// member function setBitmapColor(foregroundColor, backgroundColor).
|
||||
|
||||
// Created by Bodmer 6/1/19 as an example to the TFT_eSPI library:
|
||||
// https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
TFT_eSprite dial = TFT_eSprite(&tft); // Sprite object for dial
|
||||
TFT_eSprite needle = TFT_eSprite(&tft); // Sprite object for needle
|
||||
|
||||
uint32_t startMillis;
|
||||
|
||||
int16_t angle = 0;
|
||||
|
||||
// =======================================================================================
|
||||
// Setup
|
||||
// =======================================================================================
|
||||
|
||||
void setup() {
|
||||
Serial.begin(250000); // Debug only
|
||||
|
||||
tft.begin();
|
||||
tft.setRotation(1);
|
||||
|
||||
// Clear TFT screen
|
||||
tft.fillScreen(TFT_NAVY);
|
||||
|
||||
// Create the dial Sprite and dial (this temporarily hijacks the use of the needle Sprite)
|
||||
createDialScale(-120, 120, 30); // create scale (start angle, end angle, increment angle)
|
||||
drawEmptyDial("Label", 12345); // draw the centre of dial in the Sprite
|
||||
|
||||
dial.pushSprite(110, 0); // push a copy of the dial to the screen so we can see it
|
||||
|
||||
// Create the needle Sprite
|
||||
createNeedle(); // draw the needle graphic
|
||||
needle.pushSprite(95, 7); // push a copy of the needle to the screen so we can see it
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Loop
|
||||
// =======================================================================================
|
||||
|
||||
void loop() {
|
||||
|
||||
// Push the needle sprite to the dial Sprite at different angles and then push the dial to the screen
|
||||
// Use angle increments in range 1 to 6 for smoother or faster movement
|
||||
for (int16_t angle = -120; angle <= 120; angle += 2) {
|
||||
plotDial(0, 0, angle, "RPM", angle + 120);
|
||||
delay(25);
|
||||
yield(); // Avoid a watchdog time-out
|
||||
}
|
||||
|
||||
delay(1000); // Pause
|
||||
|
||||
// Update the dial Sprite with decreasing angle and plot to screen at 0,0, no delay
|
||||
for (int16_t angle = 120; angle >= -120; angle -= 2) {
|
||||
plotDial(0, 0, angle, "RPM", angle + 120);
|
||||
yield(); // Avoid a watchdog time-out
|
||||
}
|
||||
|
||||
// Now show plotting of the rotated needle direct to the TFT
|
||||
tft.setPivot(45, 150); // Set the TFT pivot point that the needle will rotate around
|
||||
|
||||
// The needle graphic has a black border so if the angle increment is small
|
||||
// (6 degrees or less in this case) it wipes the last needle position when
|
||||
// it is rotated and hence it clears the swept area to black
|
||||
for (int16_t angle = 0; angle <= 360; angle += 5)
|
||||
{
|
||||
needle.pushRotated(angle); // Plot direct to TFT at specified angle
|
||||
yield(); // Avoid a watchdog time-out
|
||||
}
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Create the dial sprite, the dial outer and place scale markers
|
||||
// =======================================================================================
|
||||
|
||||
void createDialScale(int16_t start_angle, int16_t end_angle, int16_t increment)
|
||||
{
|
||||
// Create the dial Sprite
|
||||
dial.setColorDepth(8); // Size is odd (i.e. 91) so there is a centre pixel at 45,45
|
||||
dial.createSprite(91, 91); // 8bpp requires 91 * 91 = 8281 bytes
|
||||
dial.setPivot(45, 45); // set pivot in middle of dial Sprite
|
||||
|
||||
// Draw dial outline
|
||||
dial.fillSprite(TFT_TRANSPARENT); // Fill with transparent colour
|
||||
dial.fillCircle(45, 45, 43, TFT_DARKGREY); // Draw dial outer
|
||||
|
||||
// Hijack the use of the needle Sprite since that has not been used yet!
|
||||
needle.createSprite(3, 3); // 3 pixels wide, 3 high
|
||||
needle.fillSprite(TFT_WHITE); // Fill with white
|
||||
needle.setPivot(1, 43); // Set pivot point x to the Sprite centre and y to marker radius
|
||||
|
||||
for (int16_t angle = start_angle; angle <= end_angle; angle += increment) {
|
||||
needle.pushRotated(&dial, angle); // Sprite is used to make scale markers
|
||||
yield(); // Avoid a watchdog time-out
|
||||
}
|
||||
|
||||
needle.deleteSprite(); // Delete the hijacked Sprite
|
||||
}
|
||||
|
||||
|
||||
// =======================================================================================
|
||||
// Add the empty dial face with label and value
|
||||
// =======================================================================================
|
||||
|
||||
void drawEmptyDial(String label, int16_t val)
|
||||
{
|
||||
// Draw black face
|
||||
dial.fillCircle(45, 45, 40, TFT_BLACK);
|
||||
dial.drawPixel(45, 45, TFT_WHITE); // For demo only, mark pivot point with a while pixel
|
||||
|
||||
dial.setTextDatum(TC_DATUM); // Draw dial text
|
||||
dial.drawString(label, 45, 15, 2);
|
||||
dial.drawNumber(val, 45, 60, 2);
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Update the dial and plot to screen with needle at defined angle
|
||||
// =======================================================================================
|
||||
|
||||
void plotDial(int16_t x, int16_t y, int16_t angle, String label, uint16_t val)
|
||||
{
|
||||
// Draw the blank dial in the Sprite, add label and number
|
||||
drawEmptyDial(label, val);
|
||||
|
||||
// Push a rotated needle Sprite to the dial Sprite, with black as transparent colour
|
||||
needle.pushRotated(&dial, angle, TFT_BLACK); // dial is the destination Sprite
|
||||
|
||||
// Push the resultant dial Sprite to the screen, with transparent colour
|
||||
dial.pushSprite(x, y, TFT_TRANSPARENT);
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
// Create the needle Sprite and the image of the needle
|
||||
// =======================================================================================
|
||||
|
||||
void createNeedle(void)
|
||||
{
|
||||
needle.setColorDepth(8);
|
||||
needle.createSprite(11, 49); // create the needle Sprite 11 pixels wide by 49 high
|
||||
|
||||
needle.fillSprite(TFT_BLACK); // Fill with black
|
||||
|
||||
// Define needle pivot point
|
||||
uint16_t piv_x = needle.width() / 2; // x pivot of Sprite (middle)
|
||||
uint16_t piv_y = needle.height() - 10; // y pivot of Sprite (10 pixels from bottom)
|
||||
needle.setPivot(piv_x, piv_y); // Set pivot point in this Sprite
|
||||
|
||||
// Draw the red needle with a yellow tip
|
||||
// Keep needle tip 1 pixel inside dial circle to avoid leaving stray pixels
|
||||
needle.fillRect(piv_x - 1, 2, 3, piv_y + 8, TFT_RED);
|
||||
needle.fillRect(piv_x - 1, 2, 3, 5, TFT_YELLOW);
|
||||
|
||||
// Draw needle centre boss
|
||||
needle.fillCircle(piv_x, piv_y, 5, TFT_MAROON);
|
||||
needle.drawPixel( piv_x, piv_y, TFT_WHITE); // Mark needle pivot point with a white pixel
|
||||
}
|
||||
|
||||
// =======================================================================================
|
||||
@@ -0,0 +1,140 @@
|
||||
/*====================================================================================
|
||||
|
||||
This example draws a jpeg image in a Sprite then plot a rotated copy of the Sprite
|
||||
to the TFT.
|
||||
|
||||
The jpeg used in in the sketch Data folder (press Ctrl+K to see folder)
|
||||
|
||||
The jpeg must be uploaded to the ESP8266 or ESP32 SPIFFS by using the Tools menu
|
||||
sketch data upload option of the Arduino IDE. If you do not have that option it can
|
||||
be added. Close the Serial Monitor window before uploading to avoid an error message!
|
||||
|
||||
To add the upload option for the ESP8266 see:
|
||||
http://www.esp8266.com/viewtopic.php?f=32&t=10081
|
||||
https://github.com/esp8266/arduino-esp8266fs-plugin/releases
|
||||
|
||||
To add the upload option for the ESP32 see:
|
||||
https://github.com/me-no-dev/arduino-esp32fs-plugin
|
||||
|
||||
Created by Bodmer 6/1/19 as an example to the TFT_eSPI library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
Extension functions in the TFT_eFEX library are used to list SPIFFS files and render
|
||||
the jpeg to the TFT and to the Sprite:
|
||||
https://github.com/Bodmer/TFT_eFEX
|
||||
|
||||
To render the Jpeg image the JPEGDecoder library is needed, this can be obtained
|
||||
with the IDE library manager, or downloaded from here:
|
||||
https://github.com/Bodmer/JPEGDecoder
|
||||
|
||||
==================================================================================*/
|
||||
|
||||
//====================================================================================
|
||||
// Libraries
|
||||
//====================================================================================
|
||||
// Call up the SPIFFS FLASH filing system, this is part of the ESP Core
|
||||
#define FS_NO_GLOBALS
|
||||
#include <FS.h>
|
||||
|
||||
#ifdef ESP32
|
||||
#include "SPIFFS.h" // Needed for ESP32 only
|
||||
#endif
|
||||
|
||||
// https://github.com/Bodmer/TFT_eSPI
|
||||
#include <TFT_eSPI.h> // Hardware-specific library
|
||||
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
|
||||
TFT_eSprite spr = TFT_eSprite(&tft); // Create Sprite object "spr" with pointer to "tft" object
|
||||
|
||||
// https://github.com/Bodmer/TFT_eFEX
|
||||
#include <TFT_eFEX.h> // Include the function extension library
|
||||
TFT_eFEX fex = TFT_eFEX(&tft); // Create TFT_eFX object "fex" with pointer to "tft" object
|
||||
|
||||
|
||||
//====================================================================================
|
||||
// Setup
|
||||
//====================================================================================
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(250000); // Used for messages
|
||||
|
||||
tft.begin();
|
||||
tft.setRotation(0); // 0 & 2 Portrait. 1 & 3 landscape
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// Create a sprite to hold the jpeg (or part of it)
|
||||
spr.createSprite(80, 64);
|
||||
|
||||
// Initialise SPIFFS
|
||||
if (!SPIFFS.begin()) {
|
||||
Serial.println("SPIFFS initialisation failed!");
|
||||
while (1) yield(); // Stay here twiddling thumbs waiting
|
||||
}
|
||||
Serial.println("\r\nInitialisation done.\r\n");
|
||||
|
||||
// Lists the files so you can see what is in the SPIFFS
|
||||
fex.listSPIFFS();
|
||||
|
||||
// Note the / before the SPIFFS file name must be present, this means the file is in
|
||||
// the root directory of the SPIFFS, e.g. "/tiger.jpg" for a file called "tiger.jpg"
|
||||
|
||||
// Send jpeg info to serial port
|
||||
fex.jpegInfo("/Eye_80x64.jpg");
|
||||
|
||||
// Draw jpeg iamge in Sprite spr at 0,0
|
||||
fex.drawJpeg("/Eye_80x64.jpg", 0 , 0, &spr);
|
||||
}
|
||||
|
||||
//====================================================================================
|
||||
// Loop
|
||||
//====================================================================================
|
||||
void loop()
|
||||
{
|
||||
|
||||
tft.fillScreen(random(0xFFFF));
|
||||
|
||||
|
||||
// Set the TFT pivot point to the centre of the screen
|
||||
tft.setPivot(tft.width() / 2, tft.height() / 2);
|
||||
|
||||
// Set Sprite pivot point to centre of Sprite
|
||||
spr.setPivot(spr.width() / 2, spr.height() / 2);
|
||||
|
||||
// Push Sprite to the TFT at 0,0 (not rotated)
|
||||
spr.pushSprite(0, 0);
|
||||
|
||||
delay(1000);
|
||||
|
||||
// Push copies of Sprite rotated through increasing angles 0-360 degrees
|
||||
// with 45 fegree increments
|
||||
for (int16_t angle = 0; angle <= 360; angle += 45) {
|
||||
spr.pushRotated(angle);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
delay(2000);
|
||||
|
||||
// Move Sprite pivot to a point above the image at 40,-60
|
||||
// (Note: Top left corner is Sprite coordinate 0,0)
|
||||
// The TFT pivot point has already been set to middle of screen.
|
||||
/* .Pivot point at 40,-60
|
||||
^
|
||||
|
|
||||
-60
|
||||
< 40 >|
|
||||
______V______
|
||||
| |
|
||||
| Sprite |
|
||||
|_____________|
|
||||
*/
|
||||
spr.setPivot(40, -60);
|
||||
|
||||
// Push Sprite to screen rotated about the new pivot points
|
||||
// negative angle rotates Sprite anticlockwise
|
||||
for (int16_t angle = 330; angle >= 0; angle -= 30) {
|
||||
spr.pushRotated(angle);
|
||||
yield(); // Stop watchdog triggering
|
||||
}
|
||||
|
||||
delay(5000);
|
||||
}
|
||||
//====================================================================================
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
Display all the fast rendering fonts in a sprite
|
||||
|
||||
Make sure all the display driver and pin connections are correct by
|
||||
editing the User_Setup.h file in the TFT_eSPI library folder.
|
||||
|
||||
#########################################################################
|
||||
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
|
||||
#########################################################################
|
||||
*/
|
||||
|
||||
// Specify sprite 160 x 128 pixels (needs 40Kbytes of RAM for 16 bit colour)
|
||||
#define IWIDTH 160
|
||||
#define IHEIGHT 128
|
||||
|
||||
// Pause in milliseconds between screens, change to 0 to time font rendering
|
||||
#define WAIT 500
|
||||
|
||||
#include <TFT_eSPI.h> // Graphics and font library for ST7735 driver chip
|
||||
#include <SPI.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h
|
||||
|
||||
TFT_eSprite img = TFT_eSprite(&tft);
|
||||
|
||||
unsigned long targetTime = 0; // Used for testing draw times
|
||||
|
||||
void setup(void) {
|
||||
tft.init();
|
||||
tft.setRotation(0);
|
||||
|
||||
tft.fillScreen(TFT_BLUE);
|
||||
|
||||
//img.setColorDepth(8); // Optionally set depth to 8 to halve RAM use
|
||||
img.createSprite(IWIDTH, IHEIGHT);
|
||||
img.fillSprite(TFT_BLACK);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
targetTime = millis();
|
||||
|
||||
// First we test them with a background colour set
|
||||
img.setTextSize(1);
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
|
||||
img.drawString(" !\"#$%&'()*+,-./0123456", 0, 0, 2);
|
||||
img.drawString("789:;<=>?@ABCDEFGHIJKL", 0, 16, 2);
|
||||
img.drawString("MNOPQRSTUVWXYZ[\\]^_`", 0, 32, 2);
|
||||
img.drawString("abcdefghijklmnopqrstuvw", 0, 48, 2);
|
||||
|
||||
int xpos = 0;
|
||||
xpos += img.drawString("xyz{|}~", 0, 64, 2);
|
||||
img.drawChar(127, xpos, 64, 2);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_GREEN, TFT_BLACK);
|
||||
|
||||
img.drawString(" !\"#$%&'()*+,-.", 0, 0, 4);
|
||||
img.drawString("/0123456789:;", 0, 26, 4);
|
||||
img.drawString("<=>?@ABCDE", 0, 52, 4);
|
||||
img.drawString("FGHIJKLMNO", 0, 78, 4);
|
||||
img.drawString("PQRSTUVWX", 0, 104, 4);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.drawString("YZ[\\]^_`abc", 0, 0, 4);
|
||||
img.drawString("defghijklmno", 0, 26, 4);
|
||||
img.drawString("pqrstuvwxyz", 0, 52, 4);
|
||||
xpos = 0;
|
||||
xpos += img.drawString("{|}~", 0, 78, 4);
|
||||
img.drawChar(127, xpos, 78, 4);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_BLUE, TFT_BLACK);
|
||||
|
||||
img.drawString("012345", 0, 0, 6);
|
||||
img.drawString("6789", 0, 40, 6);
|
||||
img.drawString("apm-:.", 0, 80, 6);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_RED, TFT_BLACK);
|
||||
|
||||
img.drawString("0123", 0, 0, 7);
|
||||
img.drawString("4567", 0, 60, 7);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.drawString("890:.", 0, 0, 7);
|
||||
img.drawString("", 0, 60, 7);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_YELLOW, TFT_BLACK);
|
||||
|
||||
img.drawString("01", 0, 0, 8);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.drawString("23", 0, 0, 8);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.drawString("45", 0, 0, 8);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.drawString("67", 0, 0, 8);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.drawString("89", 0, 0, 8);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.drawString("0:.", 0, 0, 8);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.setTextColor(TFT_WHITE);
|
||||
img.drawNumber(millis() - targetTime, 0, 100, 4);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
delay(4000);
|
||||
|
||||
// Now test them with transparent background
|
||||
targetTime = millis();
|
||||
|
||||
img.setTextSize(1);
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_GREEN);
|
||||
|
||||
img.drawString(" !\"#$%&'()*+,-./0123456", 0, 0, 2);
|
||||
img.drawString("789:;<=>?@ABCDEFGHIJKL", 0, 16, 2);
|
||||
img.drawString("MNOPQRSTUVWXYZ[\\]^_`", 0, 32, 2);
|
||||
img.drawString("abcdefghijklmnopqrstuvw", 0, 48, 2);
|
||||
xpos = 0;
|
||||
xpos += img.drawString("xyz{|}~", 0, 64, 2);
|
||||
img.drawChar(127, xpos, 64, 2);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_GREEN);
|
||||
|
||||
img.drawString(" !\"#$%&'()*+,-.", 0, 0, 4);
|
||||
img.drawString("/0123456789:;", 0, 26, 4);
|
||||
img.drawString("<=>?@ABCDE", 0, 52, 4);
|
||||
img.drawString("FGHIJKLMNO", 0, 78, 4);
|
||||
img.drawString("PQRSTUVWX", 0, 104, 4);
|
||||
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.drawString("YZ[\\]^_`abc", 0, 0, 4);
|
||||
img.drawString("defghijklmno", 0, 26, 4);
|
||||
img.drawString("pqrstuvwxyz", 0, 52, 4);
|
||||
xpos = 0;
|
||||
xpos += img.drawString("{|}~", 0, 78, 4);
|
||||
img.drawChar(127, xpos, 78, 4);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_BLUE);
|
||||
|
||||
img.drawString("012345", 0, 0, 6);
|
||||
img.drawString("6789", 0, 40, 6);
|
||||
img.drawString("apm-:.", 0, 80, 6);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_RED);
|
||||
|
||||
img.drawString("0123", 0, 0, 7);
|
||||
img.drawString("4567", 0, 60, 7);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.drawString("890:.", 0, 0, 7);
|
||||
img.drawString("", 0, 60, 7);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.setTextColor(TFT_YELLOW);
|
||||
|
||||
img.drawString("0123", 0, 0, 8);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.drawString("4567", 0, 0, 8);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.fillSprite(TFT_BLACK);
|
||||
img.drawString("890:.", 0, 0, 8);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
|
||||
img.setTextColor(TFT_WHITE);
|
||||
|
||||
img.drawNumber(millis() - targetTime, 0, 100, 4);
|
||||
img.pushSprite(0, 0); delay(WAIT);
|
||||
delay(4000);;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
An example showing rainbow colours on a 160x128 TFT LCD screen
|
||||
and to show a basic example of font use.
|
||||
|
||||
This example plots the text in a sprite then pushes the sprite to the
|
||||
TFT screen.
|
||||
|
||||
Make sure all the display driver and pin connections are correct by
|
||||
editing the User_Setup.h file in the TFT_eSPI library folder.
|
||||
|
||||
Note that yield() or delay(0) must be called in long duration for/while
|
||||
loops to stop the ESP8266 watchdog triggering.
|
||||
|
||||
#########################################################################
|
||||
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
|
||||
#########################################################################
|
||||
*/
|
||||
|
||||
#define IWIDTH 160
|
||||
#define IHEIGHT 128
|
||||
|
||||
#include <TFT_eSPI.h> // Graphics and font library
|
||||
#include <SPI.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h
|
||||
|
||||
TFT_eSprite img = TFT_eSprite(&tft);
|
||||
|
||||
unsigned long targetTime = 0;
|
||||
byte red = 31;
|
||||
byte green = 0;
|
||||
byte blue = 0;
|
||||
byte state = 0;
|
||||
unsigned int colour = red << 11;
|
||||
|
||||
void setup(void) {
|
||||
tft.init();
|
||||
tft.setRotation(1);
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
img.createSprite(IWIDTH, IHEIGHT);
|
||||
img.fillSprite(TFT_BLACK);
|
||||
|
||||
targetTime = millis() + 1000;
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
if (targetTime < millis()) {
|
||||
targetTime = millis() + 100;//10000;
|
||||
|
||||
// Colour changing state machine
|
||||
for (int i = 0; i < 160; i++) {
|
||||
img.drawFastVLine(i, 0, img.height(), colour);
|
||||
switch (state) {
|
||||
case 0:
|
||||
green += 2;
|
||||
if (green == 64) {
|
||||
green = 63;
|
||||
state = 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
red--;
|
||||
if (red == 255) {
|
||||
red = 0;
|
||||
state = 2;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
blue ++;
|
||||
if (blue == 32) {
|
||||
blue = 31;
|
||||
state = 3;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
green -= 2;
|
||||
if (green == 255) {
|
||||
green = 0;
|
||||
state = 4;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
red ++;
|
||||
if (red == 32) {
|
||||
red = 31;
|
||||
state = 5;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
blue --;
|
||||
if (blue == 255) {
|
||||
blue = 0;
|
||||
state = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
colour = red << 11 | green << 5 | blue;
|
||||
}
|
||||
|
||||
// The standard ADAFruit font still works as before
|
||||
img.setTextColor(TFT_BLACK);
|
||||
img.setCursor (12, 5);
|
||||
img.print("Original ADAfruit font!");
|
||||
|
||||
// The new larger fonts do not use the .setCursor call, coords are embedded
|
||||
img.setTextColor(TFT_BLACK, TFT_BLACK); // Do not plot the background colour
|
||||
|
||||
// Overlay the black text on top of the rainbow plot (the advantage of not drawing the background colour!)
|
||||
img.drawCentreString("Font size 2", 80, 14, 2); // Draw text centre at position 80, 12 using font 2
|
||||
|
||||
//img.drawCentreString("Font size 2",81,12,2); // Draw text centre at position 80, 12 using font 2
|
||||
|
||||
img.drawCentreString("Font size 4", 80, 30, 4); // Draw text centre at position 80, 24 using font 4
|
||||
|
||||
img.drawCentreString("12.34", 80, 54, 6); // Draw text centre at position 80, 24 using font 6
|
||||
|
||||
img.drawCentreString("12.34 is in font size 6", 80, 92, 2); // Draw text centre at position 80, 90 using font 2
|
||||
|
||||
// Note the x position is the top left of the font!
|
||||
|
||||
// draw a floating point number
|
||||
float pi = 3.14159; // Value to print
|
||||
int precision = 3; // Number of digits after decimal point
|
||||
int xpos = 50; // x position
|
||||
int ypos = 110; // y position
|
||||
int font = 2; // font number only 2,4,6,7 valid. Font 6 only contains characters [space] 0 1 2 3 4 5 6 7 8 9 0 : a p m
|
||||
xpos += img.drawFloat(pi, precision, xpos, ypos, font); // Draw rounded number and return new xpos delta for next print position
|
||||
img.drawString(" is pi", xpos, ypos, font); // Continue printing from new x position
|
||||
|
||||
img.pushSprite(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
141
libraries/TFT_eSPI/examples/Sprite/Sprite_draw/Sprite_draw.ino
Normal file
141
libraries/TFT_eSPI/examples/Sprite/Sprite_draw/Sprite_draw.ino
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
|
||||
Sketch to show how a Sprite is created, how to draw pixels
|
||||
and text within the Sprite and then push the Sprite onto
|
||||
the display screen.
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
A Sprite is notionally an invisible graphics screen that is
|
||||
kept in the processors RAM. Graphics can be drawn into the
|
||||
Sprite just as it can be drawn directly to the screen. Once
|
||||
the Sprite is completed it can be plotted onto the screen in
|
||||
any position. If there is sufficient RAM then the Sprite can
|
||||
be the same size as the screen and used as a frame buffer.
|
||||
|
||||
A 16 bit Sprite occupies (2 * width * height) bytes in RAM.
|
||||
|
||||
On a ESP8266 Sprite sizes up to 126 x 160 can be accommodated,
|
||||
this size requires 40kBytes of RAM for a 16 bit colour depth.
|
||||
|
||||
When 8 bit colour depth sprites are created they occupy
|
||||
(width * height) bytes in RAM, so larger sprites can be
|
||||
created, or the RAM required is halved.
|
||||
|
||||
*/
|
||||
|
||||
// Set delay after plotting the sprite
|
||||
#define DELAY 1000
|
||||
|
||||
// Width and height of sprite
|
||||
#define WIDTH 128
|
||||
#define HEIGHT 128
|
||||
|
||||
#include <TFT_eSPI.h> // Include the graphics library (this includes the sprite functions)
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Declare object "tft"
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft); // Declare Sprite object "spr" with pointer to "tft" object
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(250000);
|
||||
Serial.println();
|
||||
|
||||
// Initialise the TFT registers
|
||||
tft.init();
|
||||
|
||||
// Optionally set colour depth to 8 or 16 bits, default is 16 if not specified
|
||||
// spr.setColorDepth(8);
|
||||
|
||||
// Create a sprite of defined size
|
||||
spr.createSprite(WIDTH, HEIGHT);
|
||||
|
||||
// Clear the TFT screen to blue
|
||||
tft.fillScreen(TFT_BLUE);
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
// Fill the whole sprite with black (Sprite is in memory so not visible yet)
|
||||
spr.fillSprite(TFT_BLACK);
|
||||
|
||||
// Number of pixels to draw
|
||||
uint16_t n = 100;
|
||||
|
||||
// Draw 100 random colour pixels at random positions in sprite
|
||||
while (n--)
|
||||
{
|
||||
uint16_t colour = random(0x10000); // Returns colour 0 - 0xFFFF
|
||||
int16_t x = random(WIDTH); // Random x coordinate
|
||||
int16_t y = random(HEIGHT); // Random y coordinate
|
||||
spr.drawPixel( x, y, colour); // Draw pixel in sprite
|
||||
}
|
||||
|
||||
// Draw some lines
|
||||
spr.drawLine(1, 0, WIDTH, HEIGHT-1, TFT_GREEN);
|
||||
spr.drawLine(0, 0, WIDTH, HEIGHT, TFT_GREEN);
|
||||
spr.drawLine(0, 1, WIDTH-1, HEIGHT, TFT_GREEN);
|
||||
spr.drawLine(0, HEIGHT-1, WIDTH-1, 0, TFT_RED);
|
||||
spr.drawLine(0, HEIGHT, WIDTH, 0, TFT_RED);
|
||||
spr.drawLine(1, HEIGHT, WIDTH, 1, TFT_RED);
|
||||
|
||||
// Draw some text with Middle Centre datum
|
||||
spr.setTextDatum(MC_DATUM);
|
||||
spr.drawString("Sprite", WIDTH / 2, HEIGHT / 2, 4);
|
||||
|
||||
// Now push the sprite to the TFT at position 0,0 on screen
|
||||
spr.pushSprite(-40, -40);
|
||||
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2);
|
||||
spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
|
||||
|
||||
delay(DELAY);
|
||||
|
||||
// Fill TFT screen with blue
|
||||
tft.fillScreen(TFT_BLUE);
|
||||
|
||||
// Draw a blue rectangle in sprite so when we move it 1 pixel it does not leave a trail
|
||||
// on the blue screen background
|
||||
spr.drawRect(0, 0, WIDTH, HEIGHT, TFT_BLUE);
|
||||
|
||||
int x = tft.width() / 2 - WIDTH / 2;
|
||||
int y = tft.height() / 2 - HEIGHT / 2;
|
||||
|
||||
uint32_t updateTime = 0; // time for next update
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Random movement direction
|
||||
int dx = 1; if (random(2)) dx = -1;
|
||||
int dy = 1; if (random(2)) dy = -1;
|
||||
|
||||
// Pull it back onto screen if it wanders off
|
||||
if (x < -WIDTH/2) dx = 1;
|
||||
if (x >= tft.width()-WIDTH/2) dx = -1;
|
||||
if (y < -HEIGHT/2) dy = 1;
|
||||
if (y >= tft.height()-HEIGHT/2) dy = -1;
|
||||
|
||||
// Draw it 50 time, moving in random direct or staying still
|
||||
n = 50;
|
||||
int wait = random (50);
|
||||
while (n)
|
||||
{
|
||||
if (updateTime <= millis())
|
||||
{
|
||||
// Use time delay so sprite does not move fast when not all on screen
|
||||
updateTime = millis() + wait;
|
||||
|
||||
// Push the sprite to the TFT screen
|
||||
spr.pushSprite(x, y);
|
||||
|
||||
// Change coord for next loop
|
||||
x += dx;
|
||||
y += dy;
|
||||
n--;
|
||||
yield(); // Stop watchdog reset
|
||||
}
|
||||
}
|
||||
} // Infinite while, will not exit!
|
||||
}
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
Sketch to show how a 4 bit Sprite is created, how to draw pixels
|
||||
and text within the Sprite and then push the Sprite onto
|
||||
the display screen.
|
||||
|
||||
The advantage of 4 bit sprites is:
|
||||
1. Small memory footprint
|
||||
2. Any set of 16 colours can be specified
|
||||
3. Colours can be changed without redrawing in Sprite
|
||||
4. Simple animations like flashing text can be achieved
|
||||
by colour palette cycling and pushing sprite to TFT:
|
||||
https://en.wikipedia.org/wiki/Color_cycling
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
A Sprite is notionally an invisible graphics screen that is
|
||||
kept in the processors RAM. Graphics can be drawn into the
|
||||
Sprite just as it can be drawn directly to the screen. Once
|
||||
the Sprite is completed it can be plotted onto the screen in
|
||||
any position. If there is sufficient RAM then the Sprite can
|
||||
be the same size as the screen and used as a frame buffer.
|
||||
|
||||
A 4 bit Sprite occupies (width * height)/2 bytes in RAM.
|
||||
|
||||
*/
|
||||
|
||||
// Set delay after plotting the sprite
|
||||
#define DELAY 1000
|
||||
|
||||
// Width and height of sprite
|
||||
#define WIDTH 128
|
||||
#define HEIGHT 128
|
||||
|
||||
#include <TFT_eSPI.h> // Include the graphics library (this includes the sprite functions)
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Declare object "tft"
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft); // Declare Sprite object "spr" with pointer to "tft" object
|
||||
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
Serial.println();
|
||||
|
||||
delay(500);
|
||||
|
||||
// Initialise the TFT registers
|
||||
tft.init();
|
||||
|
||||
// Set the sprite colour depth to 4
|
||||
spr.setColorDepth(4);
|
||||
|
||||
// Create a sprite of defined size
|
||||
spr.createSprite(WIDTH, HEIGHT);
|
||||
|
||||
// Clear the TFT screen to blue
|
||||
tft.fillScreen(TFT_BLUE);
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
// Fill the whole sprite with color 0 (Sprite is in memory so not visible yet)
|
||||
spr.fillSprite(0);
|
||||
|
||||
// create a color map with known colors (16 maximum for 4 bit Sprite
|
||||
uint16_t cmap[16];
|
||||
|
||||
|
||||
cmap[0] = TFT_BLACK; // We will keep this as black
|
||||
cmap[1] = TFT_NAVY;
|
||||
cmap[2] = TFT_DARKGREEN;
|
||||
cmap[3] = TFT_DARKCYAN;
|
||||
cmap[4] = TFT_MAROON;
|
||||
cmap[5] = TFT_PURPLE;
|
||||
cmap[6] = TFT_PINK;
|
||||
cmap[7] = TFT_LIGHTGREY;
|
||||
cmap[8] = TFT_YELLOW;
|
||||
cmap[9] = TFT_BLUE;
|
||||
cmap[10] = TFT_GREEN;
|
||||
cmap[11] = TFT_CYAN;
|
||||
cmap[12] = TFT_RED;
|
||||
cmap[13] = TFT_MAGENTA;
|
||||
cmap[14] = TFT_WHITE; // Keep as white for text
|
||||
cmap[15] = TFT_BLUE; // Keep as blue for sprite border
|
||||
|
||||
// Pass the palette to the Sprite class
|
||||
spr.createPalette(cmap);
|
||||
|
||||
// Push Sprite partially off-screen to test cropping
|
||||
spr.pushSprite(-40, -40);
|
||||
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2, 10);
|
||||
spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
|
||||
|
||||
// Number of pixels to draw
|
||||
uint16_t n = 100;
|
||||
|
||||
// Draw 100 random color pixels at random positions in sprite
|
||||
while (n--)
|
||||
{
|
||||
uint16_t color = random(0x10); // Returns color 0 - 0x0F (i.e. 0-15)
|
||||
int16_t x = random(WIDTH); // Random x coordinate
|
||||
int16_t y = random(HEIGHT); // Random y coordinate
|
||||
spr.drawPixel(x, y, color); // Draw pixel in sprite
|
||||
}
|
||||
|
||||
// Draw some lines
|
||||
spr.drawLine(1, 0, WIDTH, HEIGHT-1, 10);
|
||||
spr.drawLine(0, 0, WIDTH, HEIGHT, 10);
|
||||
spr.drawLine(0, 1, WIDTH-1, HEIGHT, 10);
|
||||
spr.drawLine(0, HEIGHT-1, WIDTH-1, 0, 12);
|
||||
spr.drawLine(0, HEIGHT, WIDTH, 0, 12);
|
||||
spr.drawLine(1, HEIGHT, WIDTH, 1, 12);
|
||||
|
||||
// Draw some text with Middle Centre datum
|
||||
spr.setTextDatum(MC_DATUM);
|
||||
spr.setTextColor(14); // White text
|
||||
spr.drawString("Sprite", WIDTH / 2, HEIGHT / 2, 4);
|
||||
|
||||
// Now push the sprite to the TFT at 3 positions on screen
|
||||
spr.pushSprite(-40, -40);
|
||||
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2);
|
||||
spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
|
||||
|
||||
delay(DELAY * 4);
|
||||
|
||||
// create a new color map for colours 1-13 and use it instead
|
||||
for (auto i = 1; i <= 13; i++)
|
||||
{
|
||||
cmap[i] = random(0x10000);
|
||||
}
|
||||
|
||||
spr.createPalette(cmap, 16);
|
||||
// Now push the sprite to the TFT at position 0,0 on screen
|
||||
|
||||
spr.pushSprite(-40, -40);
|
||||
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2);
|
||||
spr.pushSprite(tft.width() - WIDTH + 40, tft.height() - HEIGHT + 40);
|
||||
|
||||
delay(DELAY);
|
||||
|
||||
// Fill TFT screen with blue
|
||||
tft.fillScreen(TFT_BLUE);
|
||||
|
||||
// Draw a blue rectangle in sprite so when we move it 1 pixel it does not leave a trail
|
||||
// on the blue screen background
|
||||
spr.createPalette(cmap);
|
||||
|
||||
spr.drawRect(0, 0, WIDTH, HEIGHT, 15); // Blue rectangle
|
||||
|
||||
int x = tft.width() / 2 - WIDTH / 2;
|
||||
int y = tft.height() / 2 - HEIGHT / 2;
|
||||
|
||||
uint32_t updateTime = 0; // time for next update
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Random movement direction
|
||||
int dx = 1; if (random(2)) dx = -1;
|
||||
int dy = 1; if (random(2)) dy = -1;
|
||||
|
||||
// Pull it back onto screen if it wanders off
|
||||
if (x < -WIDTH/2) dx = 1;
|
||||
if (x >= tft.width()-WIDTH/2) dx = -1;
|
||||
if (y < -HEIGHT/2) dy = 1;
|
||||
if (y >= tft.height()-HEIGHT/2) dy = -1;
|
||||
|
||||
// Randomise the palette to change colours without redrawing
|
||||
// the sprite
|
||||
for (auto i = 1; i <= 13; i++)
|
||||
{
|
||||
cmap[i] = random(0x10000);
|
||||
}
|
||||
spr.createPalette(cmap); // Update sprite class palette
|
||||
|
||||
// Draw it 50 times, moving in random direct or staying still
|
||||
n = 50;
|
||||
int wait = random (50);
|
||||
while (n)
|
||||
{
|
||||
if (updateTime <= millis())
|
||||
{
|
||||
// Use time delay so sprite does not move fast when not all on screen
|
||||
updateTime = millis() + wait;
|
||||
|
||||
// Push the sprite to the TFT screen
|
||||
spr.pushSprite(x, y);
|
||||
|
||||
// Change coord for next loop
|
||||
x += dx;
|
||||
y += dy;
|
||||
n--;
|
||||
yield(); // Stop watchdog reset
|
||||
}
|
||||
}
|
||||
} // Infinite while, will not exit!
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
|
||||
Sketch to show how a Sprite can use a four-bit image with
|
||||
a palette to change the appearance of an image while rendering
|
||||
it only once.
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
A Sprite is notionally an invisible graphics screen that is
|
||||
kept in the processors RAM. Graphics can be drawn into the
|
||||
Sprite just as it can be drawn directly to the screen. Once
|
||||
the Sprite is completed it can be plotted onto the screen in
|
||||
any position. If there is sufficient RAM then the Sprite can
|
||||
be the same size as the screen and used as a frame buffer.
|
||||
|
||||
A 16 bit Sprite occupies (2 * width * height) bytes in RAM.
|
||||
|
||||
On a ESP8266 Sprite sizes up to 126 x 160 can be accommodated,
|
||||
this size requires 40kBytes of RAM for a 16 bit color depth.
|
||||
|
||||
When 8 bit color depth sprites are created they occupy
|
||||
(width * height) bytes in RAM, so larger sprites can be
|
||||
created, or the RAM required is halved.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
// Set delay after plotting the sprite
|
||||
#define DELAY 30
|
||||
|
||||
// Width and height of sprite
|
||||
#define WIDTH 164
|
||||
#define HEIGHT 164
|
||||
|
||||
#include "sample_images.h"
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Declare object "tft"
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft); // Declare Sprite object "spr" with pointer to "tft" object
|
||||
|
||||
byte red = 31; // 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 state = 0;
|
||||
|
||||
int rloop = 0;
|
||||
int incr = 1;
|
||||
|
||||
uint16_t cmap[16];
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
Serial.println();
|
||||
|
||||
delay(50);
|
||||
|
||||
// Initialise the TFT registers
|
||||
tft.init();
|
||||
|
||||
spr.setColorDepth(4);
|
||||
|
||||
// Create a sprite of defined size
|
||||
spr.createSprite(WIDTH, HEIGHT);
|
||||
|
||||
// Clear the TFT screen to black
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// push the image - only need to do this once.
|
||||
spr.pushImage(2, 2, 160, 160, (uint16_t *)stars);
|
||||
|
||||
for (int i = 0; i < 16; i++)
|
||||
cmap[i] = rainbow();
|
||||
}
|
||||
|
||||
void loop(void)
|
||||
{
|
||||
// create a palette with the defined colors and push it.
|
||||
spr.createPalette(cmap, 16);
|
||||
spr.pushSprite(tft.width() / 2 - WIDTH / 2, tft.height() / 2 - HEIGHT / 2);
|
||||
|
||||
// update the colors
|
||||
for (int i = 0; i < 15; i++) {
|
||||
cmap[i] = cmap[i + 1];
|
||||
}
|
||||
if (incr == 2) {
|
||||
(void)rainbow(); // skip alternate steps to go faster
|
||||
}
|
||||
cmap[15] = rainbow();
|
||||
rloop += incr;
|
||||
if (rloop > 0xc0) {
|
||||
incr = incr == 2 ? 1 : 2;
|
||||
rloop = 0;
|
||||
|
||||
}
|
||||
delay(DELAY);
|
||||
|
||||
}
|
||||
|
||||
// #########################################################################
|
||||
// Return a 16 bit rainbow colour
|
||||
// #########################################################################
|
||||
unsigned int rainbow()
|
||||
{
|
||||
switch (state) {
|
||||
case 0:
|
||||
green ++;
|
||||
if (green == 64) {
|
||||
green = 63;
|
||||
state = 1;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
red--;
|
||||
if (red == 255) {
|
||||
red = 0;
|
||||
state = 2;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
blue ++;
|
||||
if (blue == 32) {
|
||||
blue = 31;
|
||||
state = 3;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
green --;
|
||||
if (green == 255) {
|
||||
green = 0;
|
||||
state = 4;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
red ++;
|
||||
if (red == 32) {
|
||||
red = 31;
|
||||
state = 5;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
blue --;
|
||||
if (blue == 255) {
|
||||
blue = 0;
|
||||
state = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return red << 11 | green << 5 | blue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#include <TFT_eSPI.h> // Include the graphics library (this includes the sprite functions)
|
||||
|
||||
extern const uint8_t stars[12800] PROGMEM ;
|
||||
1444
libraries/TFT_eSPI/examples/Sprite/Sprite_image_4bit/starImage.cpp
Normal file
1444
libraries/TFT_eSPI/examples/Sprite/Sprite_image_4bit/starImage.cpp
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
Sketch to show scrolling of the graphics in sprites.
|
||||
Scrolling in this way moves the pixels in a defined rectangle
|
||||
within the Sprite. By default the whole sprite is scrolled.
|
||||
The gap left by scrolling is filled with a defined colour.
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
A Sprite is notionally an invisible graphics screen that is
|
||||
kept in the processors RAM. Graphics can be drawn into the
|
||||
Sprite just as it can be drawn directly to the screen. Once
|
||||
the Sprite is completed it can be plotted onto the screen in
|
||||
any position. If there is sufficient RAM then the Sprite can
|
||||
be the same size as the screen and used as a frame buffer.
|
||||
|
||||
A 16 bit Sprite occupies (2 * width * height) bytes in RAM.
|
||||
|
||||
An 8 bit Sprite occupies (width * height) bytes in RAM.
|
||||
|
||||
*/
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
TFT_eSprite graph1 = TFT_eSprite(&tft); // Sprite object graph1
|
||||
|
||||
TFT_eSprite stext1 = TFT_eSprite(&tft); // Sprite object stext1
|
||||
|
||||
TFT_eSprite stext2 = TFT_eSprite(&tft); // Sprite object stext2
|
||||
|
||||
int graphVal = 1;
|
||||
int delta = 1;
|
||||
int grid = 0;
|
||||
int tcount = 0;
|
||||
|
||||
//==========================================================================================
|
||||
void setup() {
|
||||
tft.init();
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// Create a sprite for the graph
|
||||
graph1.setColorDepth(8);
|
||||
graph1.createSprite(128, 61);
|
||||
graph1.fillSprite(TFT_BLUE); // Note: Sprite is filled with black when created
|
||||
|
||||
// The scroll area is set to the full sprite size upon creation of the sprite
|
||||
// but we can change that by defining a smaller area using "setScrollRect()"if needed
|
||||
// parameters are x,y,w,h,color as in drawRect(), the color fills the gap left by scrolling
|
||||
//graph1.setScrollRect(64, 0, 64, 61, TFT_DARKGREY); // Try this line to change the graph scroll area
|
||||
|
||||
// Create a sprite for the scrolling numbers
|
||||
stext1.setColorDepth(8);
|
||||
stext1.createSprite(32, 64);
|
||||
stext1.fillSprite(TFT_BLUE); // Fill sprite with blue
|
||||
stext1.setScrollRect(0, 0, 32, 64, TFT_BLUE); // here we set scroll gap fill color to blue
|
||||
stext1.setTextColor(TFT_WHITE); // White text, no background
|
||||
stext1.setTextDatum(BR_DATUM); // Bottom right coordinate datum
|
||||
|
||||
// Create a sprite for Hello World
|
||||
stext2.setColorDepth(8);
|
||||
stext2.createSprite(80, 16);
|
||||
stext2.fillSprite(TFT_DARKGREY);
|
||||
stext2.setScrollRect(0, 0, 40, 16, TFT_DARKGREY); // Scroll the "Hello" in the first 40 pixels
|
||||
stext2.setTextColor(TFT_WHITE); // White text, no background
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
void loop() {
|
||||
// Draw point in graph1 sprite at far right edge (this will scroll left later)
|
||||
graph1.drawFastVLine(127,60-graphVal,2,TFT_YELLOW); // draw 2 pixel point on graph
|
||||
|
||||
// Draw number in stext1 sprite at 31,63 (bottom right datum set)
|
||||
stext1.drawNumber(graphVal, 31, 63, 2); // plot value in font 2
|
||||
|
||||
// Push the sprites onto the TFT at specified coordinates
|
||||
graph1.pushSprite(0, 0);
|
||||
stext1.pushSprite(0, 64);
|
||||
stext2.pushSprite(40, 70);
|
||||
|
||||
// Change the value to plot
|
||||
graphVal+=delta;
|
||||
|
||||
// If the value reaches a limit, then change delta of value
|
||||
if (graphVal >= 60) delta = -1; // ramp down value
|
||||
else if (graphVal <= 1) delta = +1; // ramp up value
|
||||
|
||||
delay(50); // wait so things do not scroll too fast
|
||||
|
||||
// Now scroll the sprites scroll(dt, dy) where:
|
||||
// dx is pixels to scroll, left = negative value, right = positive value
|
||||
// dy is pixels to scroll, up = negative value, down = positive value
|
||||
graph1.scroll(-1, 0); // scroll graph 1 pixel left, 0 up/down
|
||||
stext1.scroll(0,-16); // scroll stext 0 pixels left/right, 16 up
|
||||
stext2.scroll(1); // scroll stext 1 pixel right, up/down default is 0
|
||||
|
||||
// Draw the grid on far right edge of sprite as graph has now moved 1 pixel left
|
||||
grid++;
|
||||
if (grid >= 10)
|
||||
{ // Draw a vertical line if we have scrolled 10 times (10 pixels)
|
||||
grid = 0;
|
||||
graph1.drawFastVLine(127, 0, 61, TFT_NAVY); // draw line on graph
|
||||
}
|
||||
else
|
||||
{ // Otherwise draw points spaced 10 pixels for the horizontal grid lines
|
||||
for (int p = 0; p <= 60; p += 10) graph1.drawPixel(127, p, TFT_NAVY);
|
||||
}
|
||||
|
||||
tcount--;
|
||||
if (tcount <=0)
|
||||
{ // If we have scrolled 40 pixels the redraw text
|
||||
tcount = 40;
|
||||
stext2.drawString("Hello World", 6, 0, 2); // draw at 6,0 in sprite, font 2
|
||||
}
|
||||
|
||||
} // Loop back and do it all again
|
||||
//==========================================================================================
|
||||
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
Display "flicker free" scrolling text and updating number
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
The sketch has been tested on a 320x240 ILI9341 based TFT, it
|
||||
could be adapted for other screen sizes.
|
||||
|
||||
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.
|
||||
|
||||
The Sprite occupies (2 * width * height) bytes.
|
||||
|
||||
On a ESP8266 Sprite sizes up to 128 x 160 can be accommodated,
|
||||
this size requires 128*160*2 bytes (40kBytes) of RAM, this must be
|
||||
available or the processor will crash. 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 15/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)
|
||||
{
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
Sketch to show scrolling of the graphics in sprites.
|
||||
|
||||
This sketch scrolls a 1 bit per pixel (1 bpp) Sprite.
|
||||
|
||||
In a 1 bit Sprite any colour except TFT_BLACK turns a pixel "ON"
|
||||
TFT_BLACK turns a pixel "OFF".
|
||||
|
||||
ON and OFF pixels can be set to any two colours before
|
||||
rendering to the screen with pushSprite, for example:
|
||||
tft.setBitmapColor(ON_COLOR, OFF_COLOR);
|
||||
|
||||
Scrolling moves the pixels in a defined rectangle within
|
||||
the Sprite. By default the whole sprite is scrolled.
|
||||
The gap left by scrolling is filled with a defined colour.
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
A Sprite is notionally an invisible graphics screen that is
|
||||
kept in the processors RAM. Graphics can be drawn into the
|
||||
Sprite just as it can be drawn directly to the screen. Once
|
||||
the Sprite is completed it can be plotted onto the screen in
|
||||
any position. If there is sufficient RAM then the Sprite can
|
||||
be the same size as the screen and used as a frame buffer.
|
||||
|
||||
A 1 bit Sprite occupies (width * height)/8 bytes in RAM.
|
||||
|
||||
*/
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
TFT_eSprite graph1 = TFT_eSprite(&tft); // Sprite object graph1
|
||||
|
||||
TFT_eSprite stext1 = TFT_eSprite(&tft); // Sprite object stext1
|
||||
|
||||
TFT_eSprite stext2 = TFT_eSprite(&tft); // Sprite object stext2
|
||||
|
||||
int graphVal = 1;
|
||||
int delta = 1;
|
||||
int grid = 0;
|
||||
int tcount = 0;
|
||||
|
||||
//==========================================================================================
|
||||
void setup() {
|
||||
tft.init();
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// Create a sprite for the graph
|
||||
graph1.setColorDepth(1);
|
||||
graph1.createSprite(128, 61);
|
||||
graph1.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created
|
||||
|
||||
// The scroll area is set to the full sprite size upon creation of the sprite
|
||||
// but we can change that by defining a smaller area using "setScrollRect()"if needed
|
||||
// parameters are x,y,w,h,color as in drawRect(), the color fills the gap left by scrolling
|
||||
//graph1.setScrollRect(64, 0, 64, 61, TFT_BLACK); // Try this line to change the graph scroll area
|
||||
|
||||
// Create a sprite for the scrolling numbers
|
||||
stext1.setColorDepth(1);
|
||||
stext1.createSprite(32, 64);
|
||||
stext1.fillSprite(TFT_BLACK); // Fill sprite with blue
|
||||
stext1.setScrollRect(0, 0, 32, 64, TFT_BLACK); // here we set scroll gap fill color to blue
|
||||
stext1.setTextColor(TFT_WHITE); // White text, no background
|
||||
stext1.setTextDatum(BR_DATUM); // Bottom right coordinate datum
|
||||
|
||||
// Create a sprite for Hello World
|
||||
stext2.setColorDepth(1);
|
||||
stext2.createSprite(80, 16);
|
||||
stext2.fillSprite(TFT_BLACK);
|
||||
stext2.setScrollRect(0, 0, 40, 16, TFT_BLACK); // Scroll the "Hello" in the first 40 pixels
|
||||
stext2.setTextColor(TFT_WHITE); // White text, no background
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
void loop() {
|
||||
// Draw point in graph1 sprite at far right edge (this will scroll left later)
|
||||
graph1.drawFastVLine(127,60-graphVal,2,TFT_WHITE); // draw 2 pixel point on graph
|
||||
|
||||
// Draw number in stext1 sprite at 31,63 (bottom right datum set)
|
||||
stext1.drawNumber(graphVal, 31, 63, 2); // plot value in font 2
|
||||
|
||||
// Push the sprites onto the TFT at specified coordinates
|
||||
tft.setBitmapColor(TFT_WHITE, TFT_BLUE); // Specify the colours of the ON and OFF pixels
|
||||
graph1.pushSprite(0, 0);
|
||||
|
||||
tft.setBitmapColor(TFT_GREEN, TFT_BLACK);
|
||||
stext1.pushSprite(0, 64);
|
||||
|
||||
tft.setBitmapColor(TFT_BLACK, TFT_YELLOW);
|
||||
stext2.pushSprite(60, 70);
|
||||
|
||||
// Change the value to plot
|
||||
graphVal+=delta;
|
||||
|
||||
// If the value reaches a limit, then change delta of value
|
||||
if (graphVal >= 60) delta = -1; // ramp down value
|
||||
else if (graphVal <= 1) delta = +1; // ramp up value
|
||||
|
||||
delay(50); // wait so things do not scroll too fast
|
||||
|
||||
// Now scroll the sprites scroll(dt, dy) where:
|
||||
// dx is pixels to scroll, left = negative value, right = positive value
|
||||
// dy is pixels to scroll, up = negative value, down = positive value
|
||||
graph1.scroll(-1, 0); // scroll graph 1 pixel left, 0 up/down
|
||||
stext1.scroll(0,-16); // scroll stext 0 pixels left/right, 16 up
|
||||
stext2.scroll(1); // scroll stext 1 pixel right, up/down default is 0
|
||||
|
||||
// Draw the grid on far right edge of sprite as graph has now moved 1 pixel left
|
||||
grid++;
|
||||
if (grid >= 10)
|
||||
{ // Draw a vertical line if we have scrolled 10 times (10 pixels)
|
||||
grid = 0;
|
||||
graph1.drawFastVLine(127, 0, 61, TFT_WHITE); // draw line on graph
|
||||
}
|
||||
else
|
||||
{ // Otherwise draw points spaced 10 pixels for the horizontal grid lines
|
||||
for (int p = 0; p <= 60; p += 10) graph1.drawPixel(127, p, TFT_WHITE);
|
||||
}
|
||||
|
||||
tcount--;
|
||||
if (tcount <=0)
|
||||
{ // If we have scrolled 40 pixels the redraw text
|
||||
tcount = 40;
|
||||
stext2.drawString("Hello World", 6, 0, 2); // draw at 6,0 in sprite, font 2
|
||||
}
|
||||
|
||||
} // Loop back and do it all again
|
||||
//==========================================================================================
|
||||
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
Sketch to show scrolling of the graphics in 4 bit sprites.
|
||||
Scrolling in this way moves the pixels in a defined rectangle
|
||||
within the Sprite. By default the whole sprite is scrolled.
|
||||
The gap left by scrolling is filled with a defined colour.
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
A Sprite is notionally an invisible graphics screen that is
|
||||
kept in the processors RAM. Graphics can be drawn into the
|
||||
Sprite just as it can be drawn directly to the screen. Once
|
||||
the Sprite is completed it can be plotted onto the screen in
|
||||
any position. If there is sufficient RAM then the Sprite can
|
||||
be the same size as the screen and used as a frame buffer.
|
||||
|
||||
A 4 bit Sprite occupies (width * height)/2 bytes in RAM.
|
||||
*/
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
TFT_eSprite graph1 = TFT_eSprite(&tft); // Sprite object graph1
|
||||
|
||||
TFT_eSprite stext1 = TFT_eSprite(&tft); // Sprite object stext1
|
||||
|
||||
TFT_eSprite stext2 = TFT_eSprite(&tft); // Sprite object stext2
|
||||
|
||||
int graphVal = 1;
|
||||
int delta = 1;
|
||||
int grid = 0;
|
||||
int tcount = 0;
|
||||
|
||||
// Palette colour table
|
||||
uint16_t palette[16];
|
||||
|
||||
//==========================================================================================
|
||||
void setup() {
|
||||
Serial.begin(250000);
|
||||
tft.init();
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
// Populate the palette table, table must have 16 entries
|
||||
palette[0] = TFT_BLACK;
|
||||
palette[1] = TFT_ORANGE;
|
||||
palette[2] = TFT_DARKGREEN;
|
||||
palette[3] = TFT_DARKCYAN;
|
||||
palette[4] = TFT_MAROON;
|
||||
palette[5] = TFT_PURPLE;
|
||||
palette[6] = TFT_OLIVE;
|
||||
palette[7] = TFT_DARKGREY;
|
||||
palette[8] = TFT_ORANGE;
|
||||
palette[9] = TFT_BLUE;
|
||||
palette[10] = TFT_GREEN;
|
||||
palette[11] = TFT_CYAN;
|
||||
palette[12] = TFT_RED;
|
||||
palette[13] = TFT_NAVY;
|
||||
palette[14] = TFT_YELLOW;
|
||||
palette[15] = TFT_WHITE;
|
||||
|
||||
// Create a sprite for the graph
|
||||
graph1.setColorDepth(4);
|
||||
graph1.createSprite(128, 61);
|
||||
graph1.createPalette(palette);
|
||||
graph1.fillSprite(9); // Note: Sprite is filled with palette[0] colour when created
|
||||
|
||||
// The scroll area is set to the full sprite size upon creation of the sprite
|
||||
// but we can change that by defining a smaller area using "setScrollRect()"if needed
|
||||
// parameters are x,y,w,h,color as in drawRect(), the color fills the gap left by scrolling
|
||||
|
||||
//graph1.setScrollRect(64, 0, 64, 61, TFT_DARKGREY); // Try this line to change the graph scroll area
|
||||
|
||||
// Create a sprite for the scrolling numbers
|
||||
stext1.setColorDepth(4);
|
||||
stext1.createSprite(32, 64);
|
||||
stext1.createPalette(palette);
|
||||
stext1.fillSprite(9); // Fill sprite with palette colour 9 (blue in this example)
|
||||
stext1.setScrollRect(0, 0, 32, 64, 9); // here we set scroll gap fill color to blue
|
||||
stext1.setTextColor(15); // Palette colour 15 (white) text, no background
|
||||
stext1.setTextDatum(BR_DATUM); // Bottom right coordinate datum
|
||||
|
||||
// Create a sprite for Hello World
|
||||
stext2.setColorDepth(4);
|
||||
stext2.createSprite(80, 16);
|
||||
stext2.createPalette(palette);
|
||||
stext2.fillSprite(7);
|
||||
stext2.setScrollRect(0, 0, 40, 16, 7); // Scroll the "Hello" in the first 40 pixels
|
||||
stext2.setTextColor(15); // White text, no background
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
void loop() {
|
||||
// Draw point in graph1 sprite at far right edge (this will scroll left later)
|
||||
graph1.drawFastVLine(127,60-graphVal,2,14); // draw 2 pixel point on graph
|
||||
|
||||
// Draw number in stext1 sprite at 31,63 (bottom right datum set)
|
||||
stext1.drawNumber(graphVal, 31, 63, 2); // plot value in font 2
|
||||
|
||||
// Push the sprites onto the TFT at specified coordinates
|
||||
graph1.pushSprite(0, 0);
|
||||
stext1.pushSprite(0, 64);
|
||||
stext2.pushSprite(40, 70);
|
||||
|
||||
// Change the value to plot
|
||||
graphVal+=delta;
|
||||
|
||||
// If the value reaches a limit, then change delta of value
|
||||
if (graphVal >= 60) delta = -1; // ramp down value
|
||||
else if (graphVal <= 1) delta = +1; // ramp up value
|
||||
|
||||
delay(50); // wait so things do not scroll too fast
|
||||
|
||||
// Now scroll the sprites scroll(dt, dy) where:
|
||||
// dx is pixels to scroll, left = negative value, right = positive value
|
||||
// dy is pixels to scroll, up = negative value, down = positive value
|
||||
graph1.scroll(-1, 0); // scroll graph 1 pixel left, 0 up/down
|
||||
stext1.scroll(0,-16); // scroll stext 0 pixels left/right, 16 up
|
||||
stext2.scroll(1); // scroll stext 1 pixel right, up/down default is 0
|
||||
|
||||
// Draw the grid on far right edge of sprite as graph has now moved 1 pixel left
|
||||
grid++;
|
||||
if (grid >= 10)
|
||||
{ // Draw a vertical line if we have scrolled 10 times (10 pixels)
|
||||
grid = 0;
|
||||
graph1.drawFastVLine(127, 0, 61, 13); // draw line on graph
|
||||
}
|
||||
else
|
||||
{ // Otherwise draw points spaced 10 pixels for the horizontal grid lines
|
||||
for (int p = 0; p <= 60; p += 10) graph1.drawPixel(127, p, 13);
|
||||
}
|
||||
|
||||
tcount--;
|
||||
if (tcount <=0)
|
||||
{ // If we have scrolled 40 pixels then redraw text
|
||||
tcount = 40;
|
||||
stext2.drawString("Hello World", 6, 0, 2); // draw at 6,0 in sprite, font 2
|
||||
}
|
||||
|
||||
} // Loop back and do it all again
|
||||
//==========================================================================================
|
||||
@@ -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 accommodated,
|
||||
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 appear 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
// This **ONLY** works for 1 bpp Sprites due to lack of bounds checking in the
|
||||
// Sprite pushImage() function for 8 and 16 bit Sprites (it is on the TO DO list)
|
||||
|
||||
// Wrapping scroll example by Bodmer for the TFT_eSPI library
|
||||
|
||||
//==========================================================================================
|
||||
|
||||
#include <TFT_eSPI.h>
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI();
|
||||
|
||||
TFT_eSprite gfx = TFT_eSprite(&tft); // Sprite object for graphics write
|
||||
|
||||
TFT_eSprite fb = TFT_eSprite(&tft); // Sprite object for frame buffer
|
||||
|
||||
// Width and height of the Sprite
|
||||
#define WIDTH 60
|
||||
#define HEIGHT 60
|
||||
|
||||
// Define scroll increment in x and y directions
|
||||
// positive numbers = right, down
|
||||
// negative numbers = left, up
|
||||
#define XDELTA 1
|
||||
#define YDELTA 1
|
||||
|
||||
int16_t scroll_x = 0; // Keep track of the scrolled position, this is where the origin
|
||||
int16_t scroll_y = 0; // (top left) of the gfx Sprite will be
|
||||
|
||||
int16_t radius = 5; // radius of circle
|
||||
|
||||
bool grow = true; // grow or shrink circle
|
||||
|
||||
uint16_t *gfxPtr; // Pointer to start of graphics sprite memory area
|
||||
|
||||
//==========================================================================================
|
||||
//==========================================================================================
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
tft.init();
|
||||
tft.fillScreen(TFT_BLACK);
|
||||
|
||||
tft.setRotation(1);
|
||||
|
||||
//tft.invertDisplay(true);
|
||||
|
||||
// Create a sprite for the graphics
|
||||
gfx.setColorDepth(1);
|
||||
gfxPtr = (uint16_t*) gfx.createSprite(WIDTH, HEIGHT); // 450 bytes needed
|
||||
gfx.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created
|
||||
|
||||
// Create a sprite for the frame buffer
|
||||
fb.setColorDepth(1);
|
||||
fb.createSprite(WIDTH, HEIGHT); // 450 bytes needed
|
||||
fb.fillSprite(TFT_BLACK); // Note: Sprite is filled with black when created
|
||||
|
||||
// Text colour and alignment in graphics Sprite
|
||||
gfx.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
gfx.setTextDatum(MC_DATUM);
|
||||
|
||||
// Text colour and alignment in frame buffer
|
||||
fb.setTextColor(TFT_WHITE, TFT_BLACK);
|
||||
fb.setTextDatum(MC_DATUM);
|
||||
|
||||
// Next 3 lines are for test only to see what we have drawn
|
||||
drawGraphics(); // draw the graphics in the gfx sprite and copy to buffer
|
||||
gfx.pushSprite(0, 0); // Plot to screen so we see what it looks like
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
//==========================================================================================
|
||||
|
||||
void loop() {
|
||||
uint32_t tnow = millis();
|
||||
drawGraphics(); // Not needed if scrolling graphics are static
|
||||
|
||||
wrappingScroll(XDELTA, YDELTA);
|
||||
|
||||
// Plot two copies without "Hello", then one in the middle with "Hello"
|
||||
//fb.setBitmapColor(TFT_WHITE, TFT_RED );
|
||||
fb.pushSprite(0, 0); // Plot frame buffer onto the TFT screen
|
||||
//fb.setBitmapColor(TFT_WHITE, TFT_BLUE );
|
||||
fb.pushSprite(120, 0); // Plot frame buffer onto the TFT screen
|
||||
|
||||
fb.drawString("Hello", 30, 20, 2); // Plot hello in frame buffer
|
||||
//fb.setBitmapColor(TFT_BLACK, TFT_GREEN);
|
||||
fb.pushSprite(60, 0); // Plot frame buffer in middle of other two
|
||||
|
||||
//Serial.println(millis() - tnow);
|
||||
delay(20);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
// Draw graphics in the master Sprite
|
||||
//==========================================================================================
|
||||
|
||||
void drawGraphics(void)
|
||||
{
|
||||
gfx.fillSprite(TFT_BLACK); // Clear sprite each time and completely redraw
|
||||
|
||||
//gfx.drawRect(0,0,60,60,TFT_WHITE); // Test to check alignment
|
||||
|
||||
gfx.drawCircle( 30 , 30, radius, TFT_WHITE);
|
||||
if (grow) radius++;
|
||||
else radius--;
|
||||
|
||||
if ( radius > 25 ) grow = false;
|
||||
if ( radius < 1 ) grow = true;
|
||||
|
||||
gfx.drawString("World", 30, 40, 2); // Plot hello in frame buffer
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
// This function scrolls and wraps the graphic in a 1 bit per pixel Sprite, dy and dy
|
||||
// control the scroll direction. Pixels that scroll off one side appear on the other.
|
||||
// Scrolling is achieved by plotting one Sprite inside another with an offset. This has
|
||||
// to be done by plotting 4 times into a second frame buffer Sprite.
|
||||
//==========================================================================================
|
||||
void wrappingScroll(int16_t dx, int16_t dy)
|
||||
{
|
||||
// Position the quadrants so they overlap all areas of the buffer
|
||||
scroll_x += dx;
|
||||
if (scroll_x < -WIDTH) scroll_x += WIDTH;
|
||||
if (scroll_x > 0) scroll_x -= WIDTH;
|
||||
|
||||
scroll_y += dy;
|
||||
if (scroll_y < -HEIGHT) scroll_y += HEIGHT;
|
||||
if (scroll_y > 0) scroll_y -= HEIGHT;
|
||||
|
||||
// push the 4 quadrants of gfx. sprite into the fb. sprite
|
||||
// pushImage will do the cropping
|
||||
fb.pushImage(scroll_x, scroll_y, WIDTH, HEIGHT, gfxPtr);
|
||||
fb.pushImage(scroll_x + WIDTH, scroll_y, WIDTH, HEIGHT, gfxPtr);
|
||||
fb.pushImage(scroll_x, scroll_y + HEIGHT, WIDTH, HEIGHT, gfxPtr);
|
||||
fb.pushImage(scroll_x + WIDTH, scroll_y + HEIGHT, WIDTH, HEIGHT, gfxPtr);
|
||||
}
|
||||
|
||||
//==========================================================================================
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
Sketch to show creation of a sprite with a transparent
|
||||
background, then plot it on the TFT.
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
A Sprite is notionally an invisible graphics screen that is
|
||||
kept in the processors RAM. Graphics can be drawn into the
|
||||
Sprite just as it can be drawn directly to the screen. Once
|
||||
the Sprite is completed it can be plotted onto the screen in
|
||||
any position. If there is sufficient RAM then the Sprite can
|
||||
be the same size as the screen and used as a frame buffer.
|
||||
|
||||
A 16 bit Sprite occupies (2 * width * height) bytes in RAM.
|
||||
|
||||
On a ESP8266 Sprite sizes up to 126 x 160 can be accommodated,
|
||||
this size requires 40kBytes of RAM for a 16 bit colour depth.
|
||||
|
||||
When 8 bit colour depth sprites are created they occupy
|
||||
(width * height) bytes in RAM, so larger sprites can be
|
||||
created, or the RAM required is halved.
|
||||
*/
|
||||
|
||||
#include <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
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(250000);
|
||||
|
||||
tft.init();
|
||||
|
||||
tft.setRotation(0);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
tft.fillScreen(TFT_NAVY);
|
||||
|
||||
// Draw 10 sprites containing a "transparent" colour
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int x = random(240-70);
|
||||
int y = random(320-80);
|
||||
int c = random(0x10000); // Random colour
|
||||
drawStar(x, y, c);
|
||||
}
|
||||
|
||||
delay(2000);
|
||||
|
||||
uint32_t dt = millis();
|
||||
|
||||
// Now go bananas and draw 500 more
|
||||
for (int i = 0; i < 500; i++)
|
||||
{
|
||||
int x = random(240-70);
|
||||
int y = random(320-80);
|
||||
int c = random(0x10000); // Random colour
|
||||
drawStar(x, y, c);
|
||||
yield(); // Stop watchdog reset
|
||||
}
|
||||
|
||||
// Show time in milliseconds to draw and then push 1 sprite to TFT screen
|
||||
numberBox( 10, 10, (millis()-dt)/500.0 );
|
||||
|
||||
delay(2000);
|
||||
|
||||
}
|
||||
|
||||
// #########################################################################
|
||||
// Create sprite, plot graphics in it, plot to screen, then delete sprite
|
||||
// #########################################################################
|
||||
void drawStar(int x, int y, int star_color)
|
||||
{
|
||||
// Create an 8 bit sprite 70x 80 pixels (uses 5600 bytes of RAM)
|
||||
img.setColorDepth(8);
|
||||
img.createSprite(70, 80);
|
||||
|
||||
// Fill Sprite with a "transparent" colour
|
||||
// TFT_TRANSPARENT is already defined for convenience
|
||||
// We could also fill with any colour as "transparent" and later specify that
|
||||
// same colour when we push the Sprite onto the screen.
|
||||
img.fillSprite(TFT_TRANSPARENT);
|
||||
|
||||
// Draw 2 triangles to create a filled in star
|
||||
img.fillTriangle(35, 0, 0,59, 69,59, star_color);
|
||||
img.fillTriangle(35,79, 0,20, 69,20, star_color);
|
||||
|
||||
// Punch a star shaped hole in the middle with a smaller transparent star
|
||||
img.fillTriangle(35, 7, 6,56, 63,56, TFT_TRANSPARENT);
|
||||
img.fillTriangle(35,73, 6,24, 63,24, TFT_TRANSPARENT);
|
||||
|
||||
// Push sprite to TFT screen CGRAM at coordinate x,y (top left corner)
|
||||
// Specify what colour is to be treated as transparent.
|
||||
img.pushSprite(x, y, TFT_TRANSPARENT);
|
||||
|
||||
// Delete it to free memory
|
||||
img.deleteSprite();
|
||||
|
||||
}
|
||||
|
||||
// #########################################################################
|
||||
// Draw a number in a rounded rectangle with some transparent pixels
|
||||
// #########################################################################
|
||||
void numberBox(int x, int y, float num )
|
||||
{
|
||||
|
||||
// Size of sprite
|
||||
#define IWIDTH 80
|
||||
#define IHEIGHT 35
|
||||
|
||||
// Create a 8 bit sprite 80 pixels wide, 35 high (2800 bytes of RAM needed)
|
||||
img.setColorDepth(8);
|
||||
img.createSprite(IWIDTH, IHEIGHT);
|
||||
|
||||
// Fill it with black (this will be the transparent colour this time)
|
||||
img.fillSprite(TFT_BLACK);
|
||||
|
||||
// Draw a background for the numbers
|
||||
img.fillRoundRect( 0, 0, 80, 35, 15, TFT_RED);
|
||||
img.drawRoundRect( 0, 0, 80, 35, 15, TFT_WHITE);
|
||||
|
||||
// Set the font parameters
|
||||
img.setTextSize(1); // Font size scaling is x1
|
||||
img.setTextColor(TFT_WHITE); // White text, no background colour
|
||||
|
||||
// Set text coordinate datum to middle right
|
||||
img.setTextDatum(MR_DATUM);
|
||||
|
||||
// Draw the number to 3 decimal places at 70,20 in font 4
|
||||
img.drawFloat(num, 3, 70, 20, 4);
|
||||
|
||||
// Push sprite to TFT screen CGRAM at coordinate x,y (top left corner)
|
||||
// All black pixels will not be drawn hence will show as "transparent"
|
||||
img.pushSprite(x, y, TFT_BLACK);
|
||||
|
||||
// Delete sprite to free up the RAM
|
||||
img.deleteSprite();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Sketch to show creation of a 4 bit sprite with a transparent
|
||||
background, then plot it on the TFT. The palette setup and
|
||||
palette update functions are also shown in this example.
|
||||
|
||||
Example for library:
|
||||
https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
A Sprite is notionally an invisible graphics screen that is
|
||||
kept in the processors RAM. Graphics can be drawn into the
|
||||
Sprite just as it can be drawn directly to the screen. Once
|
||||
the Sprite is completed it can be plotted onto the screen in
|
||||
any position. If there is sufficient RAM then the Sprite can
|
||||
be the same size as the screen and used as a frame buffer.
|
||||
|
||||
A 4 bit Sprite occupies (width * height)/2 bytes in RAM.
|
||||
For example the "star" 70x80 Sprite uses 2800 bytes.
|
||||
*/
|
||||
|
||||
// This is the default palette for 4 bit colour sprites
|
||||
// which is built into the library. You can create your
|
||||
// own palette (use a different array name!). The palette
|
||||
// is captured and stored in RAM by the Sprite class so a
|
||||
// copy does not need to be kept in the sketch.
|
||||
|
||||
// The default library palette is stored in FLASH and is called:
|
||||
// default_4bit_palette
|
||||
// To edit colours change the default_4bit_palette array name
|
||||
// at line 32, then edit line 77 to match new name.
|
||||
// To setup you own palette edit the next line to //*
|
||||
/*
|
||||
static const uint16_t default_4bit_palette[] PROGMEM = {
|
||||
TFT_BLACK, // 0 ^
|
||||
TFT_BROWN, // 1 |
|
||||
TFT_RED, // 2 |
|
||||
TFT_ORANGE, // 3 |
|
||||
TFT_YELLOW, // 4 Colours 0-9 follow the resistor colour code!
|
||||
TFT_GREEN, // 5 |
|
||||
TFT_BLUE, // 6 |
|
||||
TFT_PURPLE, // 7 |
|
||||
TFT_DARKGREY, // 8 |
|
||||
TFT_WHITE, // 9 v
|
||||
TFT_CYAN, // 10 Blue+green mix
|
||||
TFT_MAGENTA, // 11 Blue+red mix
|
||||
TFT_MAROON, // 12 Darker red colour
|
||||
TFT_DARKGREEN,// 13 Darker green colour
|
||||
TFT_NAVY, // 14 Darker blue colour
|
||||
TFT_PINK // 15
|
||||
};
|
||||
//*/
|
||||
|
||||
#include <TFT_eSPI.h> // Include the graphics library (this includes the sprite functions)
|
||||
|
||||
TFT_eSPI tft = TFT_eSPI(); // Create object "tft"
|
||||
|
||||
TFT_eSprite spr = TFT_eSprite(&tft); // Create Sprite object "spr" with pointer to "tft" object
|
||||
// the pointer is used by pushSprite() to push it onto the TFT
|
||||
|
||||
void setup(void) {
|
||||
Serial.begin(115200);
|
||||
|
||||
tft.init();
|
||||
|
||||
tft.setRotation(0);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
||||
tft.fillScreen(TFT_DARKGREY);
|
||||
|
||||
// Set color depth to 4 bits
|
||||
spr.setColorDepth(4);
|
||||
spr.createSprite(70, 80); // The Sprite MUST be created before setting the palette!
|
||||
|
||||
// Pass the default library palette to the Sprite class
|
||||
// Edit palette array name if you use your own palette
|
||||
spr.createPalette(default_4bit_palette); // <<<<<<<<<<<<<<<<<<<<<<<<< palette array name
|
||||
|
||||
// If <16 colours are defined then specify how many
|
||||
// spr.createPalette(default_4bit_palette, 12);
|
||||
|
||||
// After rendering a Sprite you can change the palette to increase the range of colours
|
||||
// plotted to the screen to the full 16 bit set.
|
||||
|
||||
// Change palette colour 11 to violet
|
||||
spr.setPaletteColor(11, TFT_VIOLET);
|
||||
|
||||
uint16_t color15 = spr.getPaletteColor(15); // The 16 bit colour in a palette can be read back
|
||||
|
||||
// Draw 50 sprites containing a "transparent" colour
|
||||
for (int i = 0; i < 50; i++)
|
||||
{
|
||||
int x = random(tft.width() - 70);
|
||||
int y = random(tft.height() - 80);
|
||||
int c = random(15); // Random colour 0-14 (4 bit index into color map). Leave 15 for transparent.
|
||||
drawStar(x, y, c);
|
||||
}
|
||||
|
||||
delay(2000);
|
||||
|
||||
// Change the palette to a 16 bit grey scale colour
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
// (i*16+i) produces a value in range 0-255 for the RGB colours
|
||||
// Red Green Blue
|
||||
spr.setPaletteColor(i, tft.color565(i*16+i, i*16+i, i*16+i));
|
||||
}
|
||||
|
||||
// Now go bananas and draw 500 more
|
||||
for (int i = 0; i < 500; i++)
|
||||
{
|
||||
int x = random(tft.width() - 70);
|
||||
int y = random(tft.height() - 80);
|
||||
int c = random(0x10); // Random colour
|
||||
drawStar(x, y, c);
|
||||
yield(); // Stop watchdog reset
|
||||
}
|
||||
|
||||
// Delete it to free memory, the Sprite copy of the palette is also deleted
|
||||
spr.deleteSprite();
|
||||
|
||||
delay(2000);
|
||||
}
|
||||
|
||||
// #########################################################################
|
||||
// Plot graphics to sprite using defined color and plot to screen
|
||||
// #########################################################################
|
||||
void drawStar(int x, int y, int star_color)
|
||||
{
|
||||
// star_color will be in the range 0-14 so that 15 is reserved for the
|
||||
// transparent colour
|
||||
|
||||
// Fill Sprite with the chosen "transparent" colour
|
||||
spr.fillSprite(15); // Fill with color 15
|
||||
|
||||
// Draw 2 triangles to create a filled in star
|
||||
spr.fillTriangle(35, 0, 0, 59, 69, 59, star_color);
|
||||
spr.fillTriangle(35, 79, 0, 20, 69, 20, star_color);
|
||||
|
||||
// Punch a star shaped hole in the middle with a smaller transparent star
|
||||
spr.fillTriangle(35, 7, 6, 56, 63, 56, 15);
|
||||
spr.fillTriangle(35, 73, 6, 24, 63, 24, 15);
|
||||
|
||||
// Push sprite to TFT screen at coordinate x,y (top left corner)
|
||||
// Specify what colour from the palette is treated as transparent.
|
||||
spr.pushSprite(x, y, 15);
|
||||
}
|
||||
Reference in New Issue
Block a user