Example update now complete

This commit is contained in:
Bodmer 2017-02-25 02:14:17 +00:00
parent b7315803f4
commit 747931266b
38 changed files with 1948 additions and 288 deletions

View File

@ -22,7 +22,7 @@
// out the different options below if the screen does not display graphics correctly,
// e.g. colours wrong, mirror images, or tray pixels at the edges.
// Comment out ALL BUT ONE of these options for a ST7735 display driver, save this
// this User_Setup file, then rebuild and upload the sketch to the board again:
// User_Setup file, then rebuild and upload the sketch to the board again:
//#define ST7735_INITB
//#define ST7735_GREENTAB

View File

@ -9,9 +9,13 @@
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define GRIDX 64
#define GRIDY 48
#define CELLXY 5
//#define GRIDX 80
//#define GRIDY 60
//#define CELLXY 4
#define GRIDX 160
#define GRIDY 120
#define CELLXY 2
#define GEN_DELAY 0
@ -23,6 +27,7 @@ uint8_t newgrid[GRIDX][GRIDY];
//Number of generations
#define NUMGEN 600
uint16_t genCount = 0;
void setup() {

View File

@ -261,7 +261,7 @@ void loop() {
}
// Print the header for a display screen
void header(char *string, uint16_t color)
void header(const char *string, uint16_t color)
{
tft.fillScreen(color);
tft.setTextSize(1);

View File

@ -6,13 +6,15 @@ TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define DEG2RAD 0.0174532925
#define LOOP_DELAY 10 // Loop delay to slow things down
byte inc = 0;
unsigned int col = 0;
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;
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;
void setup(void) {
tft.begin();
@ -27,19 +29,20 @@ void setup(void) {
void loop() {
// Continuous elliptical arc drawing
fillArc(160, 120, inc*6, 1, 140, 100, 10, rainbow(col));
fillArc(160, 120, inc * 6, 1, 140, 100, 10, rainbow(col));
// Continuous segmented (inc*2) elliptical arc drawing
fillArc(160, 120, ((inc*2)%60)*6, 1, 120, 80, 30, rainbow(col));
fillArc(160, 120, ((inc * 2) % 60) * 6, 1, 120, 80, 30, rainbow(col));
// Circle drawing using arc with arc width = radius
fillArc(160, 120, inc*6, 1, 42, 42, 42, rainbow(col));
fillArc(160, 120, inc * 6, 1, 42, 42, 42, rainbow(col));
inc++;
col+=1;
if (col>191) col = 0;
col += 1;
if (col > 191) col = 0;
if (inc > 59) inc = 0;
//delay(10);
delay(LOOP_DELAY);
}
@ -62,13 +65,13 @@ int fillArc(int x, int y, int start_angle, int seg_count, int rx, int ry, int w,
byte seg = 6; // Segments are 3 degrees wide = 120 segments for 360 degrees
byte inc = 6; // Draw segments every 3 degrees, increase to 6 for segmented ring
// Calculate first pair of coordinates for segment start
float sx = cos((start_angle - 90) * DEG2RAD);
float sy = sin((start_angle - 90) * DEG2RAD);
uint16_t x0 = sx * (rx - w) + x;
uint16_t y0 = sy * (ry - w) + y;
uint16_t x1 = sx * rx + x;
uint16_t y1 = sy * ry + y;
// Calculate first pair of coordinates for segment start
float sx = cos((start_angle - 90) * DEG2RAD);
float sy = sin((start_angle - 90) * DEG2RAD);
uint16_t x0 = sx * (rx - w) + x;
uint16_t y0 = sy * (ry - w) + y;
uint16_t x1 = sx * rx + x;
uint16_t y1 = sy * ry + y;
// Draw colour blocks every inc degrees
for (int i = start_angle; i < start_angle + seg * seg_count; i += inc) {
@ -101,9 +104,9 @@ unsigned int brightness(unsigned int colour, int brightness)
byte green = (colour & 0x7E0) >> 5;
byte blue = colour & 0x1F;
blue = (blue * brightness)/100;
green = (green * brightness)/100;
red = (red * brightness)/100;
blue = (blue * brightness) / 100;
green = (green * brightness) / 100;
red = (red * brightness) / 100;
return (red << 11) + (green << 5) + blue;
}
@ -116,50 +119,50 @@ unsigned int rainbow(byte value)
// Value is expected to be in range 0-127
// The value is converted to a spectrum colour from 0 = blue through to 127 = red
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;
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;
}

View File

@ -5,10 +5,11 @@
Needs fonts 2, 4, 6, 7 and 8
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
*/

View File

@ -1,15 +1,17 @@
/*
An example analogue clock using a TFT LCD screen to show the time
use of some of the drawing commands with the modified Adafruit_TFT_AS library.
use of some of the drawing commands with the library.
For a more accurate clock, it would be better to use the RTClib library.
But this is just a demo.
This sketch uses font 4 only.
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
Based on a sketch by Gilchrist 6/2/2014 1.0
@ -35,7 +37,7 @@ boolean initial = 1;
void setup(void) {
tft.init();
tft.setRotation(2);
tft.setRotation(0);
//tft.fillScreen(TFT_BLACK);
//tft.fillScreen(TFT_RED);
@ -88,7 +90,7 @@ void setup(void) {
void loop() {
if (targetTime < millis()) {
targetTime = millis()+1000;
targetTime += 1000;
ss++; // Advance second
if (ss==60) {
ss=0;

View File

@ -6,10 +6,11 @@
For a more accurate clock, it would be better to use the RTClib library.
But this is just a demo...
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
Based on clock sketch by Gilchrist 6/2/2014 1.0

View File

@ -20,7 +20,7 @@ void loop() {
tft.fillScreen(TFT_BLACK);
// Draw some random circles
// Draw some random ellipses
for (int i = 0; i < 40; i++)
{
int rx = random(60);

View File

@ -28,7 +28,7 @@ void setup(void) {
void loop() {
fillArc(160, 120, segment*6, 1, 120-segment/4, 120-segment/4, 6, rainbow(col));
fillArc(160, 120, segment*6, 1, 120-segment/4, 120-segment/4, 3, rainbow(col));
segment+=delta;
col+=1;

View File

@ -5,7 +5,6 @@
const uint16_t alertWidth = 32;
const uint16_t alertHeight = 32;
// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here
const unsigned short alert[1024] PROGMEM={
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0840,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x1080,0xAC66,0xEDE8,0xFE69,0xC4C6,0x2901,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels

View File

@ -5,7 +5,6 @@
const uint16_t closeWidth = 32;
const uint16_t closeHeight = 32;
// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here
const unsigned short close[1024] PROGMEM={
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x30C3,0x4124,0x61C7,0x61C7,0x4124,0x30E3,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x48E3,0xA249,0xEB8E,0xFCB2,0xFD14,0xFD75,0xFD96,0xFD34,0xFCF3,0xEBEF,0xA28A,0x4904,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels

View File

@ -5,7 +5,6 @@
const uint16_t infoWidth = 32;
const uint16_t infoHeight = 32;
// The icon file can be created with the "UTFT ImageConverter 565" bitmap to .c file creation utility, more can be pasted in here
const unsigned short info[1024] PROGMEM={
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 0, 32 pixels
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0861,0x4A69,0x8C71,0xA514,0xBDF7,0xBDF7,0xA514,0x8C71,0x4A69,0x0861,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, // row 1, 64 pixels

View File

@ -9,18 +9,14 @@
This sketch does not use/need any fonts at all...
Arrays containing FLASH images can be created with UTFT library tool:
(libraries\UTFT\Tools\ImageConverter565.exe)
Convert to .c format then copy into a new tab
The number and size of icons is limited by available FLASH memory. The icon array will
use width x height x 2 bytes of FLASH, i.e. 32 x 32 icon uses ~2048 bytes
Performance is good enough for most applications:
A 32 x 32 icon can be drawn by a humble ESP8266 in ~3.6 milliseconds, i.e. ~280 icons per second!
A 320 x 240 screen can be completely filled with icons in about 270ms
Code derived from ILI9341_due example
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
#########################################################################
*/
#include <TFT_eSPI.h> // Hardware-specific library
@ -48,14 +44,14 @@ void setup()
drawIcon(close, 180, 100, closeWidth, closeHeight);
// Pause here to admire the icons!
delay(4000);
delay(2000);
}
void loop()
{
// Loop filling and clearing screen to show draw speed
drawIcon(info, random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight);
// Loop filling and clearing screen
drawIcon(info, random(tft.width() - infoWidth), random(tft.height() - infoHeight), infoWidth, infoHeight);
drawIcon(alert, random(tft.width() - alertWidth), random(tft.height() - alertHeight), alertWidth, alertHeight);
drawIcon(close, random(tft.width() - closeWidth), random(tft.height() - closeHeight), alertWidth, closeHeight);
@ -65,7 +61,7 @@ void loop()
tft.setRotation(2 * random(2)); // Rotate randomly to clear display left>right or right>left to reduce monotony!
tft.fillScreen(TFT_BLACK);
tft.setRotation(1);
Serial.println(millis());
//Serial.println(millis());
}
}

View File

@ -21,10 +21,11 @@ BR_DATUM 8 //Bottom right
Needs fonts 2 and 6
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
*/

View File

@ -1,6 +1,6 @@
// Mandlebrot
// This will run slowly due to the large number of calculations per pixel
// This will run quite slowly due to the large number of floating point calculations per pixel
#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>
@ -17,10 +17,7 @@ uint16_t x0 = 0, x1 = 0, yy0 = 0, yy1 = 0;
void setup()
{
//randomSeed(analogRead(A0));
//pinMode(7, OUTPUT);
//digitalWrite(7, LOW);
//delay(10);
//digitalWrite(7, HIGH);
// Setup the LCD
tft.init();
tft.setRotation(3);
@ -59,7 +56,7 @@ unsigned int rainbow(int value)
{
// Value is expected to be in range 0-127
// The value is converted to a spectrum colour from 0 = blue through to red = blue
//int value = random (128);
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

View File

@ -2,7 +2,16 @@
// Screen will flicker initially until fully drawn
// then scroll smoothly
// Needs GLCD font enabled in User_Setup.h
// Needs GLCD font
/*
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
#########################################################################
*/
#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>
@ -11,7 +20,7 @@ TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define TEXT_HEIGHT 8 // Height of text to be printed and scrolled
#define BOT_FIXED_AREA 0 // Number of lines in bottom fixed area (lines counted from bottom of screen)
#define TOP_FIXED_AREA 0 // Number of lines in top fixed area (lines counted from top of screen)
#define TOP_FIXED_AREA 0 // Number of lines in top fixed area (lines counted from top of screen)
uint16_t yStart = TOP_FIXED_AREA;
uint16_t yArea = 320 - TOP_FIXED_AREA - BOT_FIXED_AREA;
@ -21,21 +30,21 @@ uint16_t xPos = 0;
void setup() {
Serial.begin(115200);
//randomSeed(analogRead(A0));
randomSeed(analogRead(A0));
tft.init();
tft.setRotation(0);
tft.setRotation(2);
tft.fillScreen(ILI9341_BLACK);
setupScrollArea(TOP_FIXED_AREA, BOT_FIXED_AREA);
}
void loop(void) {
// First fill the screen with randomt streaks of characters
// First fill the screen with random streaks of characters
for (int j = 0; j < 600; j += TEXT_HEIGHT) {
for (int i = 0; i < 40; i++) {
if (pos[i] > 20) pos[i] -= 3; // Rapid fade initially brightness values
if (pos[i] > 0) pos[i] -= 1; // Slow fade later
if ((random(20) == 1) && (j<400)) pos[i] = 63; // ~1 in 20 probability of a new character
tft.setTextColor(pos[i] << 5, ILI9341_BLACK); // Set the character brightness
tft.setTextColor(pos[i] << 5, ILI9341_BLACK); // Set the green character brightness
if (pos[i] == 63) tft.setTextColor(ILI9341_WHITE, ILI9341_BLACK); // Draw white character
xPos += tft.drawChar(random(32, 128), xPos, yDraw, 1); // Draw the character
}
@ -49,7 +58,7 @@ void loop(void) {
//tft.setRotation(0);
// Now scroll smoothly forever
while (1) yDraw = scroll_slow(320,8); // Scroll 320 lines, 8ms per line
while (1) {yield(); yDraw = scroll_slow(320,5); }// Scroll 320 lines, 5ms per line
}

View File

@ -1,13 +1,13 @@
/*
An example analogue meter using a ILI9341 TFT LCD screen
This example uses the hardware SPI only
Needs Font 2 (also Font 4 if using large scale label)
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
Updated by Bodmer for variable meter size

View File

@ -1,12 +1,15 @@
/*
Example animated analogue meters using a ILI9341 TFT LCD screen
Example animated analogue meters using a ILI9341 TFT LCD screen
Needs Font 2 (also Font 4 if using large scale label)
Needs Font 2 (also Font 4 if using large scale label)
Comment out lines 153 and 197 to reduce needle flicker and
to remove need for Font 4 (which uses ~5k of FLASH!)
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
*/
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
#########################################################################
*/
#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>
@ -15,6 +18,8 @@ TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define TFT_GREY 0x5AEB
#define LOOP_PERIOD 35 // Display updates every 35 ms
float ltx = 0; // Saved x coord of bottom of needle
uint16_t osx = 120, osy = 120; // Saved x & y coords
uint32_t updateTime = 0; // time for next update
@ -49,16 +54,11 @@ void setup(void) {
void loop() {
if (updateTime <= millis()) {
updateTime = millis() + 35;
updateTime = millis() + LOOP_PERIOD;
d += 4; if (d >= 360) d = 0;
//value[0] = map(analogRead(A0), 0, 1023, 0, 100); // Test with value form Analogue 0
//value[1] = map(analogRead(A1), 0, 1023, 0, 100); // Test with value form Analogue 1
//value[2] = map(analogRead(A2), 0, 1023, 0, 100); // Test with value form Analogue 2
//value[3] = map(analogRead(A3), 0, 1023, 0, 100); // Test with value form Analogue 3
//value[4] = map(analogRead(A4), 0, 1023, 0, 100); // Test with value form Analogue 4
//value[5] = map(analogRead(A5), 0, 1023, 0, 100); // Test with value form Analogue 5
// Create a Sine wave for testing
value[0] = 50 + 50 * sin((d + 0) * 0.0174532925);
@ -67,11 +67,13 @@ void loop() {
value[3] = 50 + 50 * sin((d + 180) * 0.0174532925);
value[4] = 50 + 50 * sin((d + 240) * 0.0174532925);
value[5] = 50 + 50 * sin((d + 300) * 0.0174532925);
//unsigned long t = millis();
plotPointer(); // It takes aout 3.5ms to plot each gauge for a 1 pixel move, 21ms for 6 gauges
plotNeedle(value[0], 0); // It takes between 2 and 12ms to replot the needle with zero delay
//unsigned long t = millis();
plotPointer();
plotNeedle(value[0], 0);
//Serial.println(millis()-t); // Print time taken for meter update
}
}
@ -235,7 +237,7 @@ void plotLinear(char *label, int x, int y)
{
int w = 36;
tft.drawRect(x, y, w, 155, TFT_GREY);
tft.fillRect(x+2, y + 19, w-3, 155 - 38, TFT_WHITE);
tft.fillRect(x + 2, y + 19, w - 3, 155 - 38, TFT_WHITE);
tft.setTextColor(TFT_CYAN, TFT_BLACK);
tft.drawCentreString(label, x + w / 2, y + 2, 2);
@ -248,10 +250,10 @@ void plotLinear(char *label, int x, int y)
{
tft.drawFastHLine(x + 20, y + 27 + i, 9, TFT_BLACK);
}
tft.fillTriangle(x+3, y + 127, x+3+16, y+127, x + 3, y + 127 - 5, TFT_RED);
tft.fillTriangle(x+3, y + 127, x+3+16, y+127, x + 3, y + 127 + 5, TFT_RED);
tft.fillTriangle(x + 3, y + 127, x + 3 + 16, y + 127, x + 3, y + 127 - 5, TFT_RED);
tft.fillTriangle(x + 3, y + 127, x + 3 + 16, y + 127, x + 3, y + 127 + 5, TFT_RED);
tft.drawCentreString("---", x + w / 2, y + 155 - 18, 2);
}

View File

@ -22,7 +22,8 @@ void setup(void)
}
void loop() {
// Draw 4 pie chart segments
fillSegment(160, 120, 0, 60, 100, TFT_RED);
fillSegment(160, 120, 60, 30, 100, TFT_GREEN);
fillSegment(160, 120, 60 + 30, 120, 100, TFT_BLUE);
@ -30,6 +31,7 @@ void loop() {
delay(4000);
// Erase old chart with 360 degree black plot
fillSegment(160, 120, 0, 360, 100, TFT_BLACK);
}

View File

@ -100,7 +100,7 @@ void initgame() {
tft.setTextDatum(TC_DATUM);
tft.setTextColor(WHITE,GREY);
//tft.drawString("TFT_eSPI example", w/2, h-26 , 4);
tft.drawString("TFT_eSPI example", w/2, h-26 , 4);
}
void midline() {

View File

@ -3,10 +3,11 @@
This sketch used font 2, 4, 7
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
*/

View File

@ -4,10 +4,11 @@
This sketch uses the GLCD, 2, 4, 6 fonts only.
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
*/

View File

@ -6,6 +6,8 @@
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
#define DEG2RAD 0.0174532925 // Convert angles in degrees to radians
unsigned long runTime = 0;
float sx = 0, sy = 0;
@ -14,10 +16,7 @@ uint16_t x0 = 0, x1 = 0, yy0 = 0, yy1 = 0;
void setup()
{
//randomSeed(analogRead(A0));
//pinMode(7, OUTPUT);
//digitalWrite(7, LOW);
//delay(10);
//digitalWrite(7, HIGH);
// Setup the LCD
tft.init();
tft.setRotation(3);
@ -31,14 +30,14 @@ void loop()
int n = random(2, 23), r = random(20, 100), colour = 0; //rainbow();
for (long i = 0; i < (360 * n); i++) {
sx = cos((i / n - 90) * 0.0174532925);
sy = sin((i / n - 90) * 0.0174532925);
sx = cos((i / n - 90) * DEG2RAD);
sy = sin((i / n - 90) * DEG2RAD);
x0 = sx * (120 - r) + 159;
yy0 = sy * (120 - r) + 119;
sy = cos(((i % 360) - 90) * 0.0174532925);
sx = sin(((i % 360) - 90) * 0.0174532925);
sy = cos(((i % 360) - 90) * DEG2RAD);
sx = sin(((i % 360) - 90) * DEG2RAD);
x1 = sx * r + x0;
yy1 = sy * r + yy0;
tft.drawPixel(x1, yy1, rainbow(map(i%360,0,360,0,127))); //colour);
@ -46,14 +45,14 @@ void loop()
r = random(20, 100);//r = r / random(2,4);
for (long i = 0; i < (360 * n); i++) {
sx = cos((i / n - 90) * 0.0174532925);
sy = sin((i / n - 90) * 0.0174532925);
sx = cos((i / n - 90) * DEG2RAD);
sy = sin((i / n - 90) * DEG2RAD);
x0 = sx * (120 - r) + 159;
yy0 = sy * (120 - r) + 119;
sy = cos(((i % 360) - 90) * 0.0174532925);
sx = sin(((i % 360) - 90) * 0.0174532925);
sy = cos(((i % 360) - 90) * DEG2RAD);
sx = sin(((i % 360) - 90) * DEG2RAD);
x1 = sx * r + x0;
yy1 = sy * r + yy0;
tft.drawPixel(x1, yy1, rainbow(map(i%360,0,360,0,127))); //colour);

View File

@ -1,7 +1,4 @@
// Animates 256 white pixels to simulate flying through a star field
// Demonstrates use of the fastPixel() function in the library
// which is about 15% faster than drawPixel()
// Animates white pixels to simulate flying through a star field
#include <SPI.h>
#include <TFT_eSPI.h>
@ -9,8 +6,8 @@
// Use hardware SPI
TFT_eSPI tft = TFT_eSPI();
// With 256 stars the update frame rate is about 45Hz
#define NSTARS 256
// With 1024 stars the update rate is ~65 frames per second
#define NSTARS 1024
uint8_t sx[NSTARS] = {};
uint8_t sy[NSTARS] = {};
uint8_t sz[NSTARS] = {};
@ -85,7 +82,8 @@ void loop()
unsigned long t1 = micros();
//static char timeMicros[8] = {};
Serial.println(t1 - t0);
// Calcualte frames per second
Serial.println(1.0/((t1 - t0)/1000000.0));
}

View File

@ -17,10 +17,11 @@ BR_DATUM = Bottom right
Needs fonts 2, 4, 6, 7 and 8
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
*/

View File

@ -23,14 +23,6 @@
redistribution
*************************************************************/
// In most cases characters don't get lost at 9600 baud but
// it is a good idea to increase the serial Rx buffer from 64
// to 512 or 1024 bytes especially if higher baud rates are
// used (this sketch does not need much RAM).
// The method described here works well:
// http://www.hobbytronics.co.uk/arduino-serial-buffer-size
//
#include <TFT_eSPI.h> // Hardware-specific library
#include <SPI.h>

View File

@ -1,23 +1,21 @@
/*
Adapted from the Adafruit and Xark's PDQ graphicstest sketch.
See end of file for original header text and MIT license info.
This sketch uses the GLCD font only.
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
*/
#include "SPI.h"
#include "TFT_eSPI.h"
// These are used to get information about static SRAM and flash memory sizes
extern "C" char __data_start[]; // start of SRAM data
extern "C" char _end[]; // end of SRAM data (used to check amount of SRAM this program's variables use)
extern "C" char __data_load_end[]; // end of FLASH (used to check amount of Flash this program's code and data uses)
// Use hardware SPI
TFT_eSPI tft = TFT_eSPI();
@ -26,17 +24,14 @@ unsigned long tn = 0;
void setup() {
Serial.begin(115200);
while (!Serial);
Serial.println("Bodmer's 2.2\" SPI TFT Test!");
Serial.println(""); Serial.println("");
Serial.println("Bodmer's TFT_eSPI library Test!");
tft.init();
}
void loop(void)
{
Serial.print(F(__DATE__ " " __TIME__ " - Flash=0x"));
//Serial.print((uint16_t)__data_load_end, HEX);
Serial.print(F(" RAM=0x"));
//Serial.println((uint16_t)_end - (uint16_t)__data_start, HEX);
Serial.println(F("Benchmark Time (microseconds)"));
@ -126,21 +121,18 @@ void loop(void)
tft.setTextColor(TFT_MAGENTA);
tft.setTextSize(2);
tft.println(F(" TFT_eSPI "));
tft.println(F(" TFT_eSPI test"));
tft.setTextSize(1);
tft.setTextColor(TFT_WHITE);
tft.println(F(" SPI LCD Benchmark (Atmega328p @ 16MHz)"));
tft.println(F(""));
tft.setTextSize(1);
tft.println(F(""));
tft.setTextColor(tft.color565(0x80, 0x80, 0x80));
tft.print(F(" Memory Used: Flash=0x"));
//tft.print((uint16_t)__data_load_end, HEX);
tft.print(F(" RAM=0x"));
// tft.println((uint16_t)_end - (uint16_t)__data_start, HEX);
tft.println(F(""));
tft.println(F(""));
tft.setTextColor(TFT_GREEN);
tft.println(F(" Benchmark microseconds"));
tft.println(F(""));

View File

@ -1,102 +1,106 @@
/*
Adapted from the Adafruit graphicstest sketch.
Adapted from the Adafruit graphicstest sketch, see orignal header at end
of sketch.
This sketch uses the GLCD font (font 1) only.
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
*/
*/
#include "SPI.h"
#include "TFT_eSPI.h"
// Use hardware SPI
TFT_eSPI tft = TFT_eSPI();
unsigned long total = 0;
unsigned long tn = 0;
void setup() {
yield();Serial.begin(9600);
Serial.begin(9600);
while (!Serial);
yield();Serial.println("TFT_eSPI 2.2\" SPI TFT Test!");
Serial.println(""); Serial.println("");
Serial.println("TFT_eSPI library test!");
tft.init();
tn = micros();
tft.fillScreen(TFT_BLACK);
yield();Serial.println(F("Benchmark Time (microseconds)"));
yield(); Serial.println(F("Benchmark Time (microseconds)"));
yield();Serial.print(F("Screen fill "));
yield();Serial.println(testFillScreen());
yield(); Serial.print(F("Screen fill "));
yield(); Serial.println(testFillScreen());
//total+=testFillScreen();
//delay(500);
yield();Serial.print(F("Text "));
yield();Serial.println(testText());
yield(); Serial.print(F("Text "));
yield(); Serial.println(testText());
//total+=testText();
//delay(3000);
yield();Serial.print(F("Lines "));
yield();Serial.println(testLines(TFT_CYAN));
yield(); Serial.print(F("Lines "));
yield(); Serial.println(testLines(TFT_CYAN));
//total+=testLines(TFT_CYAN);
//delay(500);
yield();Serial.print(F("Horiz/Vert Lines "));
yield();Serial.println(testFastLines(TFT_RED, TFT_BLUE));
yield(); Serial.print(F("Horiz/Vert Lines "));
yield(); Serial.println(testFastLines(TFT_RED, TFT_BLUE));
//total+=testFastLines(TFT_RED, TFT_BLUE);
//delay(500);
yield();Serial.print(F("Rectangles (outline) "));
yield();Serial.println(testRects(TFT_GREEN));
yield(); Serial.print(F("Rectangles (outline) "));
yield(); Serial.println(testRects(TFT_GREEN));
//total+=testRects(TFT_GREEN);
//delay(500);
yield();Serial.print(F("Rectangles (filled) "));
yield();Serial.println(testFilledRects(TFT_YELLOW, TFT_MAGENTA));
yield(); Serial.print(F("Rectangles (filled) "));
yield(); Serial.println(testFilledRects(TFT_YELLOW, TFT_MAGENTA));
//total+=testFilledRects(TFT_YELLOW, TFT_MAGENTA);
//delay(500);
yield();Serial.print(F("Circles (filled) "));
yield();Serial.println(testFilledCircles(10, TFT_MAGENTA));
yield(); Serial.print(F("Circles (filled) "));
yield(); Serial.println(testFilledCircles(10, TFT_MAGENTA));
//total+= testFilledCircles(10, TFT_MAGENTA);
yield();Serial.print(F("Circles (outline) "));
yield();Serial.println(testCircles(10, TFT_WHITE));
yield(); Serial.print(F("Circles (outline) "));
yield(); Serial.println(testCircles(10, TFT_WHITE));
//total+=testCircles(10, TFT_WHITE);
//delay(500);
yield();Serial.print(F("Triangles (outline) "));
yield();Serial.println(testTriangles());
yield(); Serial.print(F("Triangles (outline) "));
yield(); Serial.println(testTriangles());
//total+=testTriangles();
//delay(500);
yield();Serial.print(F("Triangles (filled) "));
yield();Serial.println(testFilledTriangles());
yield(); Serial.print(F("Triangles (filled) "));
yield(); Serial.println(testFilledTriangles());
//total += testFilledTriangles();
//delay(500);
yield();Serial.print(F("Rounded rects (outline) "));
yield();Serial.println(testRoundRects());
yield(); Serial.print(F("Rounded rects (outline) "));
yield(); Serial.println(testRoundRects());
//total+=testRoundRects();
//delay(500);
yield();Serial.print(F("Rounded rects (filled) "));
yield();Serial.println(testFilledRoundRects());
yield(); Serial.print(F("Rounded rects (filled) "));
yield(); Serial.println(testFilledRoundRects());
//total+=testFilledRoundRects();
//delay(500);
yield();Serial.print(F("Done! Total = ")); yield();Serial.println(total);
yield(); Serial.println(F("Done!")); yield();
//Serial.print(F("Total = ")); Serial.println(total);
//yield();Serial.println(millis()-tn);
}
void loop(void) {
for(uint8_t rotation=0; rotation<4; rotation++) {
for (uint8_t rotation = 0; rotation < 4; rotation++) {
tft.setRotation(rotation);
testText();
delay(2000);
@ -153,9 +157,9 @@ unsigned long testLines(uint16_t color) {
x1 = y1 = 0;
y2 = h - 1;
start = micros();
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = w - 1;
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
t = micros() - start; // fillScreen doesn't count against timing
tft.fillScreen(TFT_BLACK);
@ -164,9 +168,9 @@ unsigned long testLines(uint16_t color) {
y1 = 0;
y2 = h - 1;
start = micros();
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = 0;
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
t += micros() - start;
tft.fillScreen(TFT_BLACK);
@ -175,9 +179,9 @@ unsigned long testLines(uint16_t color) {
y1 = h - 1;
y2 = 0;
start = micros();
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = w - 1;
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
t += micros() - start;
tft.fillScreen(TFT_BLACK);
@ -186,9 +190,9 @@ unsigned long testLines(uint16_t color) {
y1 = h - 1;
y2 = 0;
start = micros();
for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (x2 = 0; x2 < w; x2 += 6) tft.drawLine(x1, y1, x2, y2, color);
x2 = 0;
for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
for (y2 = 0; y2 < h; y2 += 6) tft.drawLine(x1, y1, x2, y2, color);
return micros() - start;
}
@ -199,8 +203,8 @@ unsigned long testFastLines(uint16_t color1, uint16_t color2) {
tft.fillScreen(TFT_BLACK);
start = micros();
for(y=0; y<h; y+=5) tft.drawFastHLine(0, y, w, color1);
for(x=0; x<w; x+=5) tft.drawFastVLine(x, 0, h, color2);
for (y = 0; y < h; y += 5) tft.drawFastHLine(0, y, w, color1);
for (x = 0; x < w; x += 5) tft.drawFastVLine(x, 0, h, color2);
return micros() - start;
}
@ -214,9 +218,9 @@ unsigned long testRects(uint16_t color) {
tft.fillScreen(TFT_BLACK);
n = min(tft.width(), tft.height());
start = micros();
for(i=2; i<n; i+=6) {
for (i = 2; i < n; i += 6) {
i2 = i / 2;
tft.drawRect(cx-i2, cy-i2, i, i, color);
tft.drawRect(cx - i2, cy - i2, i, i, color);
}
return micros() - start;
@ -230,13 +234,13 @@ unsigned long testFilledRects(uint16_t color1, uint16_t color2) {
tft.fillScreen(TFT_BLACK);
n = min(tft.width(), tft.height());
for(i=n-1; i>0; i-=6) {
for (i = n - 1; i > 0; i -= 6) {
i2 = i / 2;
start = micros();
tft.fillRect(cx-i2, cy-i2, i, i, color1);
tft.fillRect(cx - i2, cy - i2, i, i, color1);
t += micros() - start;
// Outlines are not included in timing results
tft.drawRect(cx-i2, cy-i2, i, i, color2);
tft.drawRect(cx - i2, cy - i2, i, i, color2);
}
return t;
@ -248,8 +252,8 @@ unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
tft.fillScreen(TFT_BLACK);
start = micros();
for(x=radius; x<w; x+=r2) {
for(y=radius; y<h; y+=r2) {
for (x = radius; x < w; x += r2) {
for (y = radius; y < h; y += r2) {
tft.fillCircle(x, y, radius, color);
}
}
@ -260,14 +264,14 @@ unsigned long testFilledCircles(uint8_t radius, uint16_t color) {
unsigned long testCircles(uint8_t radius, uint16_t color) {
unsigned long start;
int x, y, r2 = radius * 2,
w = tft.width() + radius,
h = tft.height() + radius;
w = tft.width() + radius,
h = tft.height() + radius;
// Screen is not cleared for this one -- this is
// intentional and does not affect the reported time.
start = micros();
for(x=0; x<w; x+=r2) {
for(y=0; y<h; y+=r2) {
for (x = 0; x < w; x += r2) {
for (y = 0; y < h; y += r2) {
tft.drawCircle(x, y, radius, color);
}
}
@ -283,7 +287,7 @@ unsigned long testTriangles() {
tft.fillScreen(TFT_BLACK);
n = min(cx, cy);
start = micros();
for(i=0; i<n; i+=5) {
for (i = 0; i < n; i += 5) {
tft.drawTriangle(
cx , cy - i, // peak
cx - i, cy + i, // bottom left
@ -301,13 +305,13 @@ unsigned long testFilledTriangles() {
tft.fillScreen(TFT_BLACK);
start = micros();
for(i=min(cx,cy); i>10; i-=5) {
for (i = min(cx, cy); i > 10; i -= 5) {
start = micros();
tft.fillTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
tft.color565(0, i, i));
tft.color565(0, i, i));
t += micros() - start;
tft.drawTriangle(cx, cy - i, cx - i, cy + i, cx + i, cy + i,
tft.color565(i, i, 0));
tft.color565(i, i, 0));
}
return t;
@ -322,9 +326,9 @@ unsigned long testRoundRects() {
tft.fillScreen(TFT_BLACK);
w = min(tft.width(), tft.height());
start = micros();
for(i=0; i<w; i+=6) {
for (i = 0; i < w; i += 6) {
i2 = i / 2;
tft.drawRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(i, 0, 0));
tft.drawRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(i, 0, 0));
}
return micros() - start;
@ -338,9 +342,9 @@ unsigned long testFilledRoundRects() {
tft.fillScreen(TFT_BLACK);
start = micros();
for(i=min(tft.width(), tft.height()); i>20; i-=6) {
for (i = min(tft.width(), tft.height()); i > 20; i -= 6) {
i2 = i / 2;
tft.fillRoundRect(cx-i2, cy-i2, i, i, i/8, tft.color565(0, i, 0));
tft.fillRoundRect(cx - i2, cy - i2, i, i, i / 8, tft.color565(0, i, 0));
}
return micros() - start;
@ -352,7 +356,7 @@ unsigned long testFilledRoundRects() {
This is an example sketch for the Adafruit 2.2" SPI display.
This library works with the Adafruit 2.2" TFT Breakout w/SD card
----> http://www.adafruit.com/products/1480
Check out the links above for our tutorials and wiring diagrams
These displays use SPI to communicate, 4 or 5 pins are required to
interface (RST is optional)
@ -363,4 +367,4 @@ unsigned long testFilledRoundRects() {
Written by Limor Fried/Ladyada for Adafruit Industries.
MIT license, all text above must be included in any redistribution
****************************************************/

View File

@ -4,43 +4,14 @@
//
/*
This sketch uses the GLCD and font 2 only. Disable other fonts to make
the sketch fit in an UNO!
This sketch uses the GLCD and font 2 only.
Make sure all the display driver and pin comnenctions are correct by
editting the User_Setup.h file in the TFT_eSPI library folder.
Make sure all the required fonts are loaded by editting the
User_Setup.h file in the TFT_eSPI library folder.
If using an UNO or Mega (ATmega328 or ATmega2560 processor) then for best
performance use the F_AS_T option found in the User_Setup.h file in the
TFT_eSPI library folder.
The library uses the hardware SPI pins only:
For UNO, Nano, Micro Pro ATmega328 based processors
MOSI = pin 11, SCK = pin 13
For Mega:
MOSI = pin 51, SCK = pin 52
The pins used for the TFT chip select (CS) and Data/command (DC) and Reset (RST)
signal lines to the TFT must also be defined in the library User_Setup.h file.
Sugested TFT connections for UNO and Atmega328 based boards
sclk 13 // Don't change, this is the hardware SPI SCLK line
mosi 11 // Don't change, this is the hardware SPI MOSI line
cs 10 // Chip select for TFT display
dc 9 // Data/command line
rst 7 // Reset, you could connect this to the Arduino reset pin
Suggested TFT connections for the MEGA and ATmega2560 based boards
sclk 52 // Don't change, this is the hardware SPI SCLK line
mosi 51 // Don't change, this is the hardware SPI MOSI line
cs 47 // TFT chip select line
dc 48 // TFT data/command line
rst 44 // you could alternatively connect this to the Arduino reset
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
###### TO SELECT THE FONTS AND PINS YOU USE, SEE ABOVE ######
#########################################################################
#########################################################################
###### DON'T FORGET TO UPDATE THE User_Setup.h FILE IN THE LIBRARY ######
#########################################################################
*/
#include "SPI.h"

View File

@ -0,0 +1,226 @@
/**The MIT License (MIT)
Copyright (c) 2015 by Daniel Eichhorn
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.
See more at http://blog.squix.ch
*/
// Created by http://oleddisplay.squix.ch/ Consider a donation
// In case of problems make sure that you are using the font file with the correct version!
// Bodmer fix: End character is 0x7D not 0x7E, so bug in last line of the file corrected
// this avoids screen corruption if ~ is printer
// Bodmer change: '`' changed to tiny degree symbol (typically this character is on top left key of a QWERTY keyboard)
const uint8_t ArialRoundedMTBold_36Bitmaps[] PROGMEM = {
// Bitmap Data:
0x00, // ' '
0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0x39,0xCE,0x73,0x00,0x00,0x3B,0xFF,0xFB,0x80, // '!'
0xFC,0xFF,0xF3,0xFF,0xCF,0xFF,0x3F,0xFC,0xFF,0xF3,0xFF,0xCF,0xDE,0x1E,0x78,0x78, // '"'
0x01,0x83,0x80,0x78,0x70,0x0F,0x0E,0x01,0xC3,0xC0,0x78,0x78,0x0F,0x0F,0x01,0xE1,0xE3,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x07,0x87,0x80,0xF0,0xE0,0x1E,0x3C,0x07,0x87,0x80,0xF0,0xF0,0x7F,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xE3,0xC3,0xC0,0x78,0x78,0x0F,0x0E,0x01,0xC3,0xC0,0x78,0x78,0x07,0x06,0x00, // '#'
0x00,0x60,0x00,0x0C,0x00,0x01,0x80,0x00,0x30,0x00,0x7F,0xE0,0x3F,0xFE,0x0F,0xFF,0xE1,0xF3,0x7E,0x7C,0x67,0xCF,0x0C,0x79,0xE1,0x8F,0x3C,0x30,0xC7,0xC6,0x00,0xFE,0xC0,0x0F,0xF8,0x00,0xFF,0xE0,0x0F,0xFF,0x00,0x7F,0xF0,0x01,0xFF,0x00,0x37,0xE0,0x06,0x3E,0xE0,0xC3,0xFC,0x18,0x7F,0xC3,0x0F,0xF8,0x61,0xEF,0x8C,0x79,0xFD,0x9F,0x1F,0xFF,0xC1,0xFF,0xF0,0x0F,0xFC,0x00,0x38,0x00,0x03,0x00,0x00,0x60,0x00,0x0C,0x00,0x01,0x80,0x00,0x30,0x00,0x06,0x00, // '$'
0x1F,0x00,0x06,0x03,0xFC,0x00,0x70,0x1C,0x70,0x03,0x01,0xC1,0x80,0x38,0x0E,0x0E,0x03,0x80,0x70,0x70,0x1C,0x03,0x83,0x81,0xC0,0x1C,0x1C,0x0C,0x00,0xE0,0xE0,0xE0,0x07,0x07,0x0E,0x00,0x1C,0x70,0x70,0x00,0xFF,0x87,0x00,0x03,0xF8,0x30,0x00,0x00,0x03,0x87,0xF0,0x00,0x38,0x7F,0xC0,0x01,0xC3,0x8E,0x00,0x1C,0x38,0x38,0x00,0xC1,0xC1,0xC0,0x0E,0x0E,0x0E,0x00,0xE0,0x70,0x70,0x07,0x03,0x83,0x80,0x70,0x1C,0x1C,0x07,0x00,0xE0,0xE0,0x38,0x03,0x8E,0x03,0x80,0x0F,0xE0,0x1C,0x00,0x3E,0x00,0xC0,0x00,0x00, // '%'
0x00,0xFC,0x00,0x01,0xFF,0x80,0x01,0xFF,0xE0,0x01,0xF0,0xF0,0x00,0xF0,0x3C,0x00,0x78,0x1E,0x00,0x3C,0x0F,0x00,0x1F,0x0F,0x80,0x0F,0xDF,0x80,0x03,0xFF,0x80,0x00,0xFF,0x80,0x00,0xFF,0x00,0x00,0xFF,0xC1,0x81,0xFF,0xF0,0xE1,0xF9,0xF8,0xF8,0xF8,0x7E,0x78,0xF8,0x1F,0xFC,0x7C,0x07,0xFC,0x3E,0x01,0xFE,0x1F,0x00,0x7F,0x0F,0xC0,0x3F,0xC3,0xF0,0x7F,0xF1,0xFF,0xFF,0xFC,0x7F,0xFF,0x3F,0x0F,0xFE,0x0F,0x01,0xFC,0x03,0x80, // '&'
0xFF,0xFF,0xFF,0xFF,0xFF,0xDE,0x78, // '''
0x03,0x81,0xC1,0xC1,0xE0,0xF0,0xF0,0xF8,0x78,0x3C,0x3E,0x1F,0x0F,0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x7C,0x3E,0x1F,0x0F,0x83,0xC1,0xF0,0xF8,0x3C,0x1E,0x0F,0x83,0xC0,0xF0,0x78,0x1C,0x07,0x01,0x80, // '('
0xE0,0x70,0x1C,0x0F,0x03,0x81,0xE0,0xF8,0x3C,0x1E,0x0F,0x87,0xC1,0xE0,0xF8,0x7C,0x3E,0x1F,0x0F,0x87,0xC3,0xE1,0xF0,0xF8,0x78,0x7C,0x3E,0x1E,0x0F,0x0F,0x87,0x83,0x83,0xC1,0xC1,0xC0,0xE0,0x00, // ')'
0x03,0x80,0x07,0x00,0x0E,0x00,0x1C,0x0E,0x38,0xFF,0x77,0xDF,0xFF,0x07,0xF0,0x07,0xC0,0x1D,0xC0,0x3B,0xC0,0xE3,0x83,0xC7,0x83,0x06,0x00, // '*'
0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00, // '+'
0x7B,0xEF,0xFF,0x7C,0x71,0xCE,0x7B,0xCE,0x00, // ','
0x7F,0xDF,0xFF,0xFF,0xBF,0xE0, // '-'
0x77,0xFF,0xF7,0x00, // '.'
0x03,0x81,0xC1,0xE0,0xF0,0x70,0x78,0x3C,0x1E,0x0E,0x07,0x07,0x83,0xC1,0xC0,0xE0,0xF0,0x78,0x38,0x1C,0x1E,0x0F,0x07,0x03,0x83,0xC1,0xE0,0xE0,0x70,0x00, // '/'
0x03,0xF0,0x03,0xFF,0x01,0xFF,0xE0,0xFF,0xFC,0x3E,0x1F,0x1F,0x03,0xE7,0xC0,0xF9,0xE0,0x1E,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xF7,0x80,0x79,0xF0,0x3E,0x7C,0x0F,0x8F,0x87,0xC3,0xFF,0xF0,0x7F,0xF8,0x0F,0xFC,0x00,0xFC,0x00, // '0'
0x00,0x30,0x03,0xC0,0x3E,0x03,0xF0,0x3F,0x83,0xFC,0x7F,0xEF,0xDF,0xFC,0xFF,0xC7,0xD8,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x03,0x80, // '1'
0x03,0xF8,0x03,0xFF,0x83,0xFF,0xF0,0xFF,0xFE,0x7E,0x1F,0x9F,0x03,0xFF,0x80,0x7F,0xE0,0x1F,0xF0,0x07,0xD8,0x01,0xF0,0x00,0xF8,0x00,0x7E,0x00,0x1F,0x00,0x1F,0x80,0x0F,0xC0,0x07,0xE0,0x03,0xF0,0x01,0xF8,0x00,0xFC,0x00,0x7E,0x00,0x3F,0x00,0x1F,0x80,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xF0, // '2'
0x03,0xF0,0x07,0xFF,0x03,0xFF,0xE1,0xF0,0xFC,0x78,0x1F,0x1E,0x03,0xE7,0x00,0xF8,0x80,0x3E,0x00,0x1F,0x00,0x0F,0xC0,0x7F,0xE0,0x1F,0xF0,0x07,0xFE,0x01,0xFF,0xC0,0x01,0xF8,0x00,0x3F,0x00,0x07,0xD8,0x01,0xFF,0x00,0x7F,0xE0,0x1F,0xF8,0x0F,0x9F,0x07,0xE7,0xFF,0xF0,0xFF,0xF8,0x1F,0xFC,0x01,0xFC,0x00, // '3'
0x00,0x0F,0x00,0x00,0xFC,0x00,0x07,0xE0,0x00,0x7F,0x00,0x07,0xF8,0x00,0x7F,0xC0,0x03,0xFE,0x00,0x3D,0xF0,0x03,0xCF,0x80,0x3C,0x7C,0x03,0xE3,0xE0,0x1E,0x1F,0x01,0xE0,0xF8,0x1E,0x07,0xC1,0xF0,0x3E,0x0F,0x01,0xF0,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xE0,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x38,0x00, // '4'
0x1F,0xFF,0x8F,0xFF,0xE3,0xFF,0xF8,0xFF,0xFC,0x3C,0x00,0x0F,0x00,0x07,0xC0,0x01,0xF0,0x00,0x78,0x00,0x1E,0x7E,0x07,0xFF,0xE1,0xFF,0xFC,0xFF,0xFF,0xBF,0x07,0xE7,0x80,0xFC,0x80,0x1F,0x00,0x07,0xC0,0x01,0xF6,0x00,0x7F,0xC0,0x1F,0xF0,0x0F,0xBE,0x03,0xE7,0xC1,0xF1,0xFF,0xF8,0x1F,0xFC,0x01,0xFC,0x00, // '5'
0x03,0xF8,0x01,0xFF,0x81,0xFF,0xF0,0x7C,0x7C,0x3C,0x0F,0x9F,0x03,0xE7,0x80,0x71,0xE0,0x00,0xF8,0x00,0x3E,0x3E,0x0F,0xBF,0xE3,0xFF,0xFC,0xFE,0x1F,0xBF,0x03,0xEF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xF7,0x80,0x7D,0xF0,0x1F,0x7C,0x0F,0x8F,0x87,0xE3,0xFF,0xF0,0x7F,0xFC,0x0F,0xFC,0x00,0xFC,0x00, // '6'
0x7F,0xFF,0xBF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0x00,0x0F,0x80,0x07,0xC0,0x01,0xE0,0x00,0xF8,0x00,0x7C,0x00,0x1E,0x00,0x0F,0x80,0x03,0xC0,0x01,0xF0,0x00,0x78,0x00,0x3E,0x00,0x0F,0x80,0x07,0xC0,0x01,0xF0,0x00,0x7C,0x00,0x3F,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x01,0xC0,0x00, // '7'
0x03,0xF8,0x01,0xFF,0xC0,0x7F,0xFC,0x1F,0x0F,0xC7,0xC0,0xFC,0xF8,0x0F,0x9F,0x01,0xF3,0xE0,0x3E,0x7C,0x07,0xCF,0x80,0xF0,0xF8,0x7E,0x0F,0xFF,0x80,0xFF,0xE0,0x7F,0xFE,0x1F,0x83,0xF3,0xE0,0x3E,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0x80,0x3E,0xF8,0x0F,0x9F,0x83,0xF1,0xFF,0xFC,0x1F,0xFF,0x00,0x7F,0x00, // '8'
0x03,0xF0,0x03,0xFF,0x03,0xFF,0xE0,0xFF,0xFC,0x7E,0x1F,0x1F,0x03,0xEF,0x80,0xFB,0xE0,0x1E,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0x7C,0x0F,0xDF,0x87,0xF3,0xFF,0xFC,0x7F,0xDF,0x07,0xC7,0xC0,0x01,0xF0,0x00,0x78,0xE0,0x1E,0x78,0x0F,0x9F,0x03,0xC3,0xE3,0xE0,0xFF,0xF8,0x1F,0xF8,0x01,0xF8,0x00, // '9'
0x77,0xFF,0xF7,0x00,0x00,0x00,0x00,0x00,0x01,0xDF,0xFF,0xDC, // ':'
0x77,0xFF,0xF7,0x00,0x00,0x00,0x00,0x00,0x01,0xDE,0xFF,0xFE,0x73,0x9B,0xDC,0xC0, // ';'
0x00,0x00,0x40,0x00,0x70,0x00,0xFC,0x00,0xFF,0x00,0xFF,0xC1,0xFF,0xE1,0xFF,0xC1,0xFF,0xC0,0xFF,0x80,0x3F,0x80,0x0F,0xE0,0x03,0xFE,0x00,0x7F,0xF0,0x07,0xFF,0x00,0x7F,0xF8,0x03,0xFF,0x00,0x3F,0xC0,0x03,0xF0,0x00,0x1C,0x00,0x01, // '<'
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0, // '='
0x80,0x00,0x38,0x00,0x0F,0xC0,0x03,0xFC,0x00,0xFF,0xC0,0x1F,0xFE,0x00,0xFF,0xE0,0x0F,0xFE,0x00,0x7F,0xC0,0x07,0xF0,0x01,0xFC,0x01,0xFF,0x03,0xFF,0x83,0xFF,0x87,0xFF,0x83,0xFF,0x00,0xFF,0x00,0x3F,0x00,0x0E,0x00,0x02,0x00,0x00, // '>'
0x03,0xF8,0x03,0xFF,0x83,0xFF,0xF0,0xFF,0xFE,0x7E,0x1F,0xBF,0x03,0xFF,0x80,0x7F,0xE0,0x1F,0x70,0x07,0xC8,0x03,0xE0,0x01,0xF8,0x00,0xFC,0x00,0x7E,0x00,0x3F,0x00,0x0F,0x80,0x03,0xC0,0x01,0xF0,0x00,0x78,0x00,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x00,0x1F,0x00,0x07,0xC0,0x01,0xF0,0x00,0x38,0x00, // '?'
0x00,0x07,0xFE,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x0F,0xFF,0xFE,0x00,0x07,0xE0,0x0F,0xE0,0x07,0xC0,0x00,0x7C,0x03,0xE0,0x00,0x0F,0x00,0xE0,0x00,0x01,0xE0,0x70,0x1F,0x9F,0x3C,0x3C,0x1F,0xF7,0xC7,0x0E,0x0F,0xFF,0xE1,0xC7,0x07,0xE3,0xF8,0x39,0xC3,0xE0,0x7E,0x0E,0x70,0xF8,0x0F,0x83,0xB8,0x7C,0x03,0xE0,0xEE,0x1F,0x00,0xF0,0x3B,0x8F,0x80,0x3C,0x0E,0xE3,0xE0,0x1F,0x07,0xB8,0xF8,0x07,0xC1,0xCE,0x3E,0x01,0xE0,0xF3,0x8F,0x80,0xF8,0x78,0xE3,0xE0,0x3E,0x1E,0x1C,0x7C,0x1F,0x9F,0x07,0x1F,0xFF,0xFF,0x81,0xC3,0xFF,0xFF,0xC0,0x38,0x7F,0xBF,0xE0,0x0F,0x07,0x87,0xE0,0x01,0xE0,0x00,0x00,0x3C,0x3C,0x00,0x00,0x3E,0x07,0xC0,0x00,0x1F,0x00,0xFE,0x00,0x3F,0x80,0x1F,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0x80,0x00,0x07,0xFF,0x00,0x00, // '@'
0x00,0x3C,0x00,0x00,0x7E,0x00,0x00,0xFF,0x00,0x00,0xFF,0x00,0x01,0xFF,0x00,0x01,0xFF,0x80,0x01,0xEF,0x80,0x03,0xE7,0xC0,0x03,0xE7,0xC0,0x07,0xC7,0xC0,0x07,0xC3,0xE0,0x07,0xC3,0xE0,0x0F,0x81,0xF0,0x0F,0x81,0xF0,0x1F,0x81,0xF8,0x1F,0x00,0xF8,0x1F,0xFF,0xF8,0x3F,0xFF,0xFC,0x3F,0xFF,0xFC,0x7F,0xFF,0xFE,0x7C,0x00,0x7E,0x7C,0x00,0x3E,0xFC,0x00,0x3F,0xF8,0x00,0x1F,0xF8,0x00,0x1F,0x70,0x00,0x0E, // 'A'
0x7F,0xFF,0x07,0xFF,0xFC,0x3F,0xFF,0xF1,0xFF,0xFF,0xCF,0x80,0x7F,0x7C,0x01,0xFB,0xE0,0x07,0xDF,0x00,0x3E,0xF8,0x01,0xF7,0xC0,0x1F,0x3E,0x01,0xF9,0xFF,0xFF,0x8F,0xFF,0xF0,0x7F,0xFF,0xE3,0xFF,0xFF,0x9F,0x00,0x7E,0xF8,0x01,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x1F,0xFC,0x01,0xFB,0xFF,0xFF,0xDF,0xFF,0xFC,0xFF,0xFF,0xC3,0xFF,0xF8,0x00, // 'B'
0x00,0xFF,0x00,0x07,0xFF,0x80,0x3F,0xFF,0xC0,0xFF,0xFF,0xC3,0xF8,0x1F,0xC7,0xE0,0x1F,0x9F,0x80,0x1F,0x3E,0x00,0x1F,0x7C,0x00,0x3D,0xF0,0x00,0x33,0xE0,0x00,0x07,0xC0,0x00,0x0F,0x80,0x00,0x1F,0x00,0x00,0x3E,0x00,0x00,0x7C,0x00,0x04,0xF8,0x00,0x1C,0xF8,0x00,0x7D,0xF0,0x00,0xFB,0xF0,0x03,0xE3,0xF0,0x0F,0xC7,0xF0,0x3F,0x07,0xFF,0xFE,0x07,0xFF,0xF8,0x03,0xFF,0xC0,0x01,0xFE,0x00, // 'C'
0x7F,0xFE,0x03,0xFF,0xFE,0x0F,0xFF,0xFC,0x3F,0xFF,0xF8,0xF8,0x07,0xF3,0xE0,0x07,0xEF,0x80,0x1F,0xBE,0x00,0x3E,0xF8,0x00,0xFF,0xE0,0x01,0xFF,0x80,0x07,0xFE,0x00,0x1F,0xF8,0x00,0x7F,0xE0,0x01,0xFF,0x80,0x07,0xFE,0x00,0x1F,0xF8,0x00,0x7F,0xE0,0x03,0xFF,0x80,0x0F,0xBE,0x00,0x7E,0xF8,0x01,0xFB,0xE0,0x1F,0xCF,0xFF,0xFE,0x3F,0xFF,0xF0,0xFF,0xFF,0x81,0xFF,0xF8,0x00, // 'D'
0x7F,0xFF,0xEF,0xFF,0xFE,0xFF,0xFF,0xEF,0xFF,0xFE,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xFF,0xFF,0xCF,0xFF,0xFC,0xFF,0xFF,0xCF,0xFF,0xFC,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xF8,0x00,0x0F,0x80,0x00,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFE, // 'E'
0x7F,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xFF,0xF8,0xFF,0xFF,0x3F,0xFF,0xCF,0xFF,0xE3,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x1C,0x00,0x00, // 'F'
0x00,0x7F,0x80,0x03,0xFF,0xF0,0x07,0xFF,0xF8,0x1F,0xFF,0xFC,0x1F,0xC1,0xFE,0x3F,0x00,0x7E,0x7E,0x00,0x3E,0x7C,0x00,0x3E,0x7C,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0xF8,0x00,0x00,0xF8,0x07,0xFE,0xF8,0x0F,0xFF,0xF8,0x0F,0xFF,0xF8,0x07,0xFF,0xF8,0x00,0x1F,0x7C,0x00,0x1F,0x7C,0x00,0x1F,0x7E,0x00,0x1F,0x3F,0x00,0x3F,0x1F,0xC0,0xFF,0x1F,0xFF,0xFE,0x07,0xFF,0xFC,0x03,0xFF,0xF0,0x00,0x7F,0x80, // 'G'
0x70,0x00,0x77,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFB,0x80,0x03,0x80, // 'H'
0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x80, // 'I'
0x00,0x07,0x00,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x70,0x0F,0xFC,0x07,0xFE,0x03,0xFF,0x01,0xFF,0xC1,0xFB,0xF1,0xF9,0xFF,0xFC,0x7F,0xFC,0x1F,0xFC,0x03,0xF8,0x00, // 'J'
0x70,0x00,0xE3,0xE0,0x07,0xCF,0x80,0x3F,0x3E,0x01,0xFC,0xF8,0x0F,0xE3,0xE0,0x7F,0x0F,0x83,0xF8,0x3E,0x1F,0xC0,0xF8,0xFE,0x03,0xE7,0xF0,0x0F,0xBF,0x80,0x3F,0xFF,0x00,0xFF,0xFC,0x03,0xFF,0xF8,0x0F,0xFB,0xF0,0x3F,0xCF,0xE0,0xFE,0x1F,0x83,0xE0,0x3F,0x0F,0x80,0xFE,0x3E,0x01,0xF8,0xF8,0x03,0xF3,0xE0,0x0F,0xEF,0x80,0x1F,0xBE,0x00,0x3F,0xF8,0x00,0xFD,0xC0,0x01,0xE0, // 'K'
0x70,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xE0, // 'L'
0x7E,0x00,0x3F,0x7F,0x80,0x3F,0xFF,0xE0,0x1F,0xFF,0xF0,0x1F,0xFF,0xF8,0x0F,0xFF,0xFC,0x07,0xFF,0xFF,0x07,0xFF,0xFF,0x83,0xFF,0xFB,0xC1,0xEF,0xFD,0xE0,0xF7,0xFE,0xF8,0xFB,0xFF,0x7C,0x7D,0xFF,0x9E,0x3C,0xFF,0xCF,0x1E,0x7F,0xE7,0xDF,0x3F,0xF3,0xEF,0x9F,0xF8,0xF7,0x8F,0xFC,0x7B,0xC7,0xFE,0x3F,0xE3,0xFF,0x1F,0xF1,0xFF,0x87,0xF0,0xFF,0xC3,0xF8,0x7F,0xE1,0xFC,0x3F,0xF0,0x7C,0x1F,0xF8,0x3E,0x0F,0xB8,0x0E,0x03,0x80, // 'M'
0x78,0x00,0x3B,0xF0,0x01,0xFF,0xC0,0x07,0xFF,0x80,0x1F,0xFF,0x00,0x7F,0xFE,0x01,0xFF,0xF8,0x07,0xFF,0xF0,0x1F,0xFF,0xE0,0x7F,0xEF,0x81,0xFF,0x9F,0x07,0xFE,0x7E,0x1F,0xF8,0xF8,0x7F,0xE1,0xF1,0xFF,0x87,0xE7,0xFE,0x0F,0x9F,0xF8,0x1F,0x7F,0xE0,0x7F,0xFF,0x80,0xFF,0xFE,0x01,0xFF,0xF8,0x07,0xFF,0xE0,0x0F,0xFF,0x80,0x1F,0xFE,0x00,0x7F,0xF8,0x00,0xFD,0xC0,0x01,0xE0, // 'N'
0x00,0xFF,0x00,0x01,0xFF,0xF0,0x03,0xFF,0xFE,0x03,0xFF,0xFF,0x83,0xFC,0x1F,0xE1,0xF8,0x03,0xF1,0xF8,0x00,0xFC,0xF8,0x00,0x3E,0x7C,0x00,0x1F,0x7C,0x00,0x07,0xFE,0x00,0x03,0xFF,0x00,0x01,0xFF,0x80,0x00,0xFF,0xC0,0x00,0x7F,0xE0,0x00,0x3F,0xF0,0x00,0x1F,0xFC,0x00,0x0F,0xBE,0x00,0x0F,0x9F,0x00,0x07,0xCF,0xC0,0x07,0xE3,0xF0,0x07,0xE0,0xFE,0x0F,0xF0,0x7F,0xFF,0xF0,0x1F,0xFF,0xF0,0x03,0xFF,0xE0,0x00,0x3F,0xC0,0x00, // 'O'
0x7F,0xFC,0x1F,0xFF,0xE3,0xFF,0xFE,0x7F,0xFF,0xEF,0x80,0xFD,0xF0,0x0F,0xFE,0x00,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x1F,0xFC,0x07,0xEF,0xFF,0xFD,0xFF,0xFF,0x3F,0xFF,0xC7,0xFF,0xE0,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x0E,0x00,0x00, // 'P'
0x00,0xFF,0x00,0x00,0xFF,0xF8,0x00,0xFF,0xFF,0x80,0x7F,0xFF,0xF0,0x3F,0xC1,0xFE,0x0F,0xC0,0x1F,0x87,0xE0,0x03,0xF1,0xF0,0x00,0x7C,0x7C,0x00,0x1F,0x3E,0x00,0x03,0xEF,0x80,0x00,0xFB,0xE0,0x00,0x3E,0xF8,0x00,0x0F,0xBE,0x00,0x03,0xEF,0x80,0x00,0xFB,0xE0,0x00,0x3E,0xF8,0x00,0x0F,0x9F,0x07,0x07,0xC7,0xC1,0xF1,0xF1,0xF8,0x3F,0xFC,0x3F,0x03,0xFE,0x07,0xF0,0x7F,0x81,0xFF,0xFF,0xC0,0x1F,0xFF,0xF8,0x03,0xFF,0xFF,0x80,0x1F,0xE3,0xF0,0x00,0x00,0x7C,0x00,0x00,0x07, // 'Q'
0x7F,0xFF,0x07,0xFF,0xFE,0x3F,0xFF,0xF9,0xFF,0xFF,0xEF,0x80,0x3F,0xFC,0x00,0xFF,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x0F,0xFE,0x00,0xFD,0xFF,0xFF,0xEF,0xFF,0xFE,0x7F,0xFF,0xC3,0xFF,0xF8,0x1F,0x07,0xE0,0xF8,0x1F,0x87,0xC0,0x7E,0x3E,0x01,0xF9,0xF0,0x0F,0xCF,0x80,0x3F,0x7C,0x00,0xFF,0xE0,0x07,0xFF,0x00,0x1F,0xF8,0x00,0xFB,0x80,0x03,0xC0, // 'R'
0x03,0xF8,0x01,0xFF,0xF0,0x3F,0xFF,0x87,0xFF,0xFC,0x7E,0x0F,0xCF,0xC0,0x7E,0xF8,0x03,0xEF,0x80,0x1E,0xFC,0x00,0xCF,0xF0,0x00,0x7F,0xF0,0x03,0xFF,0xE0,0x1F,0xFF,0x80,0x7F,0xFC,0x00,0x7F,0xE0,0x00,0x7F,0x60,0x03,0xFF,0x00,0x1F,0xF0,0x01,0xFF,0x80,0x1F,0xFC,0x03,0xFF,0xE0,0x7E,0x7F,0xFF,0xC3,0xFF,0xFC,0x0F,0xFF,0x00,0x3F,0xC0, // 'S'
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF0,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x03,0x80,0x00, // 'T'
0x70,0x00,0x77,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF0,0x01,0xFF,0x80,0x0F,0xFC,0x00,0x7F,0xE0,0x03,0xFF,0x00,0x1F,0xF8,0x00,0xFF,0xC0,0x07,0xFE,0x00,0x3F,0xF8,0x03,0xF7,0xC0,0x1F,0x3F,0x83,0xF8,0xFF,0xFF,0x83,0xFF,0xF8,0x0F,0xFF,0x80,0x1F,0xF0,0x00, // 'U'
0x70,0x00,0x1D,0xF0,0x00,0x7F,0xE0,0x00,0xFF,0xE0,0x03,0xF7,0xC0,0x07,0xCF,0x80,0x0F,0x9F,0x80,0x3F,0x1F,0x00,0x7C,0x3F,0x00,0xF8,0x7E,0x03,0xE0,0x7C,0x07,0xC0,0xFC,0x0F,0x80,0xF8,0x3E,0x01,0xF0,0x7C,0x03,0xF0,0xF8,0x03,0xE3,0xE0,0x07,0xC7,0xC0,0x07,0xDF,0x00,0x0F,0xBE,0x00,0x1F,0x7C,0x00,0x1F,0xF0,0x00,0x3F,0xE0,0x00,0x7F,0x80,0x00,0x7F,0x00,0x00,0xFE,0x00,0x00,0x70,0x00, // 'V'
0x70,0x03,0xC0,0x0E,0xF8,0x07,0xE0,0x1F,0xF8,0x07,0xE0,0x1F,0xF8,0x0F,0xF0,0x1F,0xF8,0x0F,0xF0,0x1F,0x7C,0x0F,0xF0,0x3E,0x7C,0x0F,0xF0,0x3E,0x7C,0x1F,0xF8,0x3E,0x7C,0x1E,0x78,0x3E,0x3E,0x1E,0x78,0x7C,0x3E,0x1E,0x78,0x7C,0x3E,0x3E,0x7C,0x7C,0x3E,0x3C,0x3C,0x7C,0x1E,0x3C,0x3C,0x78,0x1F,0x7C,0x3E,0xF8,0x1F,0x78,0x1E,0xF8,0x1F,0x78,0x1E,0xF8,0x0F,0x78,0x1E,0xF0,0x0F,0xF8,0x1F,0xF0,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0,0x0F,0xF0,0x07,0xF0,0x0F,0xE0,0x07,0xF0,0x0F,0xE0,0x07,0xE0,0x07,0xE0,0x03,0xE0,0x07,0xC0,0x03,0xC0,0x03,0xC0, // 'W'
0x38,0x00,0x73,0xE0,0x07,0x9F,0x00,0x7E,0xFC,0x07,0xE3,0xF0,0x3F,0x1F,0x83,0xF0,0x7E,0x3F,0x01,0xF9,0xF8,0x0F,0xDF,0x80,0x3F,0xF8,0x00,0xFF,0xC0,0x07,0xFC,0x00,0x1F,0xC0,0x00,0xFE,0x00,0x0F,0xF8,0x00,0xFF,0xE0,0x07,0xFF,0x80,0x7E,0xFC,0x07,0xE3,0xF0,0x7F,0x1F,0xC3,0xF0,0x7E,0x3F,0x01,0xFB,0xF0,0x07,0xFF,0x80,0x3F,0xF8,0x00,0xFB,0x80,0x03,0x80, // 'X'
0x70,0x00,0x77,0xC0,0x07,0xFF,0x00,0x3E,0xF8,0x03,0xF7,0xE0,0x3F,0x1F,0x01,0xF0,0xFC,0x1F,0x83,0xF0,0xF8,0x0F,0x8F,0x80,0x7E,0xFC,0x01,0xF7,0xC0,0x07,0xFC,0x00,0x3F,0xE0,0x00,0xFE,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x07,0xC0,0x00,0x3E,0x00,0x01,0xF0,0x00,0x0F,0x80,0x00,0x7C,0x00,0x03,0xE0,0x00,0x1F,0x00,0x00,0xF8,0x00,0x03,0x80,0x00, // 'Y'
0x3F,0xFF,0xF8,0x7F,0xFF,0xF9,0xFF,0xFF,0xF1,0xFF,0xFF,0xE0,0x00,0x1F,0x80,0x00,0x7F,0x00,0x01,0xFC,0x00,0x07,0xF0,0x00,0x0F,0xC0,0x00,0x3F,0x00,0x00,0xFC,0x00,0x03,0xF0,0x00,0x0F,0xE0,0x00,0x3F,0x80,0x00,0x7E,0x00,0x01,0xF8,0x00,0x07,0xE0,0x00,0x1F,0x80,0x00,0x7F,0x00,0x01,0xFC,0x00,0x07,0xF0,0x00,0x0F,0xC0,0x00,0x3F,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xF8, // 'Z'
0x7F,0xFF,0xFF,0xFF,0xFF,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3E,0x0F,0x83,0xE0,0xF8,0x3F,0xFF,0xFF,0xFF,0x7F,0xC0, // '['
0x70,0x3C,0x07,0x01,0xE0,0x78,0x1E,0x03,0x80,0xF0,0x3C,0x0F,0x01,0xC0,0x78,0x1E,0x07,0x80,0xE0,0x3C,0x0F,0x03,0xC0,0x70,0x1E,0x07,0x81,0xE0,0x38,0x0F,0x03,0xC0,0x60, // '\'
0xFF,0xBF,0xFF,0xFF,0xFF,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0x80, // ']'
0x03,0xE0,0x01,0xF0,0x01,0xFC,0x00,0xFE,0x00,0x7F,0x80,0x7B,0xC0,0x3D,0xF0,0x3E,0xF8,0x1E,0x3C,0x1F,0x1F,0x0F,0x07,0x8F,0x83,0xE7,0xC1,0xF7,0xC0,0x7C, // '^'
0xFF,0xFF,0xFF,0xFF,0xF0, // '_'
0x0E,0x1B,0x11,0x1B,0x0E, // '`' Changed into a degree symbol
0x03,0xFC,0x03,0xFF,0xE0,0xFF,0xFE,0x3F,0x07,0xC7,0xC0,0x7C,0xF0,0x0F,0x9C,0x01,0xF0,0x00,0xFE,0x01,0xFF,0xC3,0xFF,0xF8,0xFF,0x9F,0x3F,0x03,0xEF,0x80,0x7D,0xF0,0x0F,0xBE,0x03,0xF7,0xE1,0xFE,0x7F,0xFF,0xE7,0xFE,0x7C,0x3E,0x07,0x00, // 'a'
0x70,0x00,0x1F,0x00,0x03,0xE0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC7,0xE0,0xF9,0xFF,0x1F,0x7F,0xF3,0xFF,0xFF,0x7F,0x87,0xEF,0xE0,0x7D,0xF8,0x0F,0xFF,0x00,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFE,0x03,0xFF,0xC0,0x7D,0xFE,0x1F,0xBF,0xFF,0xE7,0xDF,0xFC,0xF9,0xFF,0x0E,0x1F,0x80, // 'b'
0x03,0xF8,0x03,0xFF,0x81,0xFF,0xF0,0xFF,0xFE,0x7F,0x0F,0xDF,0x01,0xFF,0xC0,0x3F,0xE0,0x04,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x07,0xFC,0x03,0xDF,0x01,0xF7,0xF0,0xFC,0xFF,0xFE,0x1F,0xFF,0x83,0xFF,0x80,0x3F,0x80, // 'c'
0x00,0x01,0xC0,0x00,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x3F,0x1F,0x1F,0xF3,0xE7,0xFF,0x7D,0xFF,0xFF,0xBF,0x0F,0xF7,0xC0,0xFF,0xF8,0x0F,0xFE,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x1F,0xFE,0x03,0xF7,0xC0,0x7E,0xFC,0x3F,0xCF,0xFF,0xF9,0xFF,0xDF,0x1F,0xF3,0xE0,0xF8,0x38, // 'd'
0x03,0xF8,0x03,0xFF,0x81,0xFF,0xF0,0xF8,0x7E,0x7C,0x07,0x9F,0x01,0xFF,0x80,0x7F,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xE0,0x00,0xF8,0x00,0x1F,0x00,0x77,0xC0,0x3C,0xFC,0x3F,0x1F,0xFF,0x83,0xFF,0xC0,0x3F,0x80, // 'e'
0x01,0xF8,0x0F,0xF8,0x1F,0xF8,0x7F,0xE0,0xF8,0x01,0xF0,0x03,0xE0,0x3F,0xF8,0x7F,0xF9,0xFF,0xF1,0xFF,0xC0,0x7C,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x80,0x1F,0x00,0x3E,0x00,0x7C,0x00,0xF8,0x01,0xF0,0x03,0xE0,0x07,0xC0,0x0F,0x80,0x0E,0x00, // 'f'
0x07,0xE1,0xC3,0xFE,0x7C,0xFF,0xEF,0xBF,0xFF,0xF7,0xE1,0xFE,0xF8,0x0F,0xFF,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0xC0,0x7E,0xF8,0x0F,0xDF,0x87,0xF9,0xFF,0xFF,0x3F,0xFB,0xE3,0xFE,0x7C,0x1F,0x8F,0x80,0x01,0xF7,0x00,0x7E,0xF0,0x0F,0x9F,0x83,0xF3,0xFF,0xFC,0x1F,0xFF,0x00,0xFF,0x80, // 'g'
0x70,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x03,0xE3,0xF0,0xF9,0xFF,0x3E,0xFF,0xEF,0xFF,0xFB,0xF8,0x3F,0xFC,0x0F,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xDC,0x00,0xE0, // 'h'
0x77,0xFF,0xF7,0x00,0x0E,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x80, // 'i'
0x03,0x81,0xF0,0x7C,0x1F,0x03,0x80,0x00,0x00,0x0E,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xC1,0xF0,0x7C,0x1F,0x07,0xFF,0xFF,0xFB,0xFE,0x7E,0x00, // 'j'
0x70,0x00,0x7C,0x00,0x3E,0x00,0x1F,0x00,0x0F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x1C,0xF8,0x1E,0x7C,0x1F,0x3E,0x1F,0x9F,0x1F,0x8F,0x9F,0x07,0xDF,0x03,0xFF,0x81,0xFF,0xE0,0xFF,0xF0,0x7F,0x7C,0x3F,0x1F,0x1F,0x0F,0x8F,0x83,0xE7,0xC1,0xFB,0xE0,0x7D,0xF0,0x1F,0xF8,0x0F,0xB8,0x03,0x80, // 'k'
0x77,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0x80, // 'l'
0x70,0xFC,0x0F,0x8F,0x3F,0xE3,0xFC,0xFF,0xFF,0x7F,0xEF,0xFF,0xFF,0xFE,0xFE,0x1F,0xE3,0xFF,0xC0,0xFC,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0xF8,0x0F,0x81,0xFF,0x80,0xF8,0x1F,0x70,0x07,0x00,0xE0, // 'm'
0x70,0xFC,0x3C,0x7F,0xCF,0xBF,0xFB,0xFF,0xFE,0xFE,0x0F,0xFF,0x03,0xFF,0xC0,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xF7,0x00,0x38, // 'n'
0x01,0xF8,0x00,0xFF,0xF0,0x1F,0xFF,0x83,0xFF,0xFC,0x7F,0x0F,0xE7,0xC0,0x3E,0xFC,0x03,0xFF,0x80,0x1F,0xF8,0x01,0xFF,0x80,0x1F,0xF8,0x01,0xFF,0x80,0x1F,0xFC,0x03,0xF7,0xC0,0x3E,0x7F,0x0F,0xE3,0xFF,0xFC,0x1F,0xFF,0x80,0xFF,0xF0,0x01,0xF8,0x00, // 'o'
0x70,0xFC,0x1F,0x3F,0xE3,0xEF,0xFE,0x7F,0xFF,0xCF,0xF0,0xFD,0xF8,0x0F,0xBF,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0xC0,0x7F,0xF8,0x0F,0xBF,0xC3,0xF7,0xFF,0xFC,0xFB,0xFF,0x9F,0x3F,0xE3,0xE3,0xF0,0x7C,0x00,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x0E,0x00,0x00, // 'p'
0x07,0xE1,0xC3,0xFE,0x7C,0xFF,0xEF,0x9F,0xFF,0xF7,0xE1,0xFE,0xF8,0x0F,0xFF,0x01,0xFF,0xC0,0x1F,0xF8,0x03,0xFF,0x00,0x7F,0xE0,0x0F,0xFC,0x01,0xFF,0xC0,0x7E,0xF8,0x0F,0xDF,0x87,0xF9,0xFF,0xFF,0x3F,0xFB,0xE3,0xFE,0x7C,0x1F,0x0F,0x80,0x01,0xF0,0x00,0x3E,0x00,0x07,0xC0,0x00,0xF8,0x00,0x1F,0x00,0x03,0xE0,0x00,0x38, // 'q'
0x71,0xE7,0xDF,0xFF,0xFF,0xFF,0xFF,0xE1,0x7E,0x03,0xF0,0x1F,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x07,0xC0,0x1C,0x00, // 'r'
0x0F,0xF0,0x1F,0xFE,0x1F,0xFF,0x8F,0x87,0xEF,0x81,0xF7,0xC0,0x7B,0xF0,0x00,0xFF,0x80,0x3F,0xF8,0x0F,0xFF,0x00,0xFF,0xC0,0x0F,0xF6,0x01,0xFF,0x80,0x7F,0xE0,0x3F,0xF8,0x3E,0x7F,0xFF,0x1F,0xFF,0x03,0xFC,0x00, // 's'
0x0E,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x0F,0xFC,0xFF,0xF7,0xFF,0x9F,0xF8,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7F,0xE3,0xFF,0x0F,0xF8,0x3F,0x80, // 't'
0x70,0x03,0xBE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFE,0x01,0xFF,0x80,0x7F,0xE0,0x1F,0xF8,0x07,0xFF,0x03,0xFF,0xE3,0xFD,0xFF,0xFF,0x7F,0xF7,0xCF,0xF8,0xF0,0xF8,0x38, // 'u'
0x70,0x03,0xBC,0x00,0xFF,0x80,0x7F,0xE0,0x1F,0x7C,0x07,0x9F,0x03,0xE3,0xC0,0xF0,0xF8,0x7C,0x3E,0x1E,0x07,0x87,0x81,0xF3,0xE0,0x3C,0xF0,0x0F,0x3C,0x01,0xFE,0x00,0x7F,0x80,0x1F,0xE0,0x03,0xF0,0x00,0xFC,0x00,0x1E,0x00, // 'v'
0x70,0x0F,0x00,0xEF,0x00,0xF0,0x0F,0xF8,0x1F,0x81,0xFF,0x81,0xF8,0x1F,0x78,0x1F,0x81,0xE7,0x83,0xFC,0x1E,0x7C,0x3F,0xC3,0xE3,0xC3,0xFC,0x3C,0x3C,0x79,0xE3,0xC3,0xE7,0x9E,0x7C,0x1E,0x79,0xE7,0x81,0xE7,0x0E,0x78,0x0E,0xF0,0xF7,0x00,0xFF,0x0F,0xF0,0x0F,0xE0,0x7F,0x00,0x7E,0x07,0xE0,0x07,0xE0,0x7E,0x00,0x7C,0x03,0xE0,0x03,0xC0,0x3C,0x00, // 'w'
0x70,0x07,0x3C,0x07,0xBF,0x07,0xEF,0xC7,0xE3,0xE3,0xE0,0xFB,0xE0,0x7F,0xE0,0x1F,0xF0,0x07,0xF0,0x03,0xF8,0x03,0xFE,0x01,0xFF,0x01,0xF7,0xC1,0xF1,0xF1,0xF8,0xFC,0xF8,0x3E,0xF8,0x0F,0xFC,0x07,0xDC,0x01,0xC0, // 'x'
0x38,0x01,0xCF,0x80,0x3D,0xF0,0x0F,0xBE,0x01,0xF3,0xE0,0x3C,0x7C,0x0F,0x87,0x81,0xE0,0xF8,0x7C,0x1F,0x0F,0x81,0xE1,0xE0,0x3E,0x7C,0x03,0xCF,0x00,0x7D,0xE0,0x07,0xFC,0x00,0xFF,0x00,0x1F,0xE0,0x01,0xF8,0x00,0x3F,0x00,0x07,0xE0,0x00,0xF8,0x00,0x1F,0x00,0x07,0xC0,0x1F,0xF8,0x07,0xFE,0x00,0x7F,0xC0,0x07,0xE0,0x00, // 'y'
0x7F,0xFF,0x1F,0xFF,0xE7,0xFF,0xF9,0xFF,0xFE,0x00,0x3F,0x00,0x1F,0x80,0x07,0xC0,0x03,0xE0,0x01,0xF0,0x00,0xF8,0x00,0x7E,0x00,0x3F,0x00,0x1F,0x80,0x0F,0xC0,0x07,0xE0,0x03,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF8, // 'z'
0x01,0xF0,0x1F,0xC1,0xFE,0x1F,0xE0,0xFC,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x01,0xF8,0x0F,0x81,0xFC,0x1F,0xC0,0xF8,0x07,0xF0,0x1F,0xC0,0x3E,0x01,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xFC,0x07,0xF8,0x1F,0xE0,0x7F,0x01,0xF0, // '{'
0x6F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x60, // '|'
0x7C,0x07,0xF0,0x3F,0xC0,0xFF,0x01,0xF8,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x00,0xFC,0x03,0xE0,0x1F,0xC0,0x7F,0x00,0xF8,0x1F,0xC1,0xFC,0x0F,0x80,0xFC,0x07,0xC0,0x3E,0x01,0xF0,0x0F,0x80,0x7C,0x03,0xE0,0x1F,0x01,0xF8,0x3F,0xC3,0xFC,0x1F,0xC0,0x7C,0x00 // '}'
};
const GFXglyph ArialRoundedMTBold_36Glyphs[] PROGMEM = {
// bitmapOffset, width, height, xAdvance, xOffset, yOffset
{ 0, 1, 1, 10, 0, 0 }, // ' '
{ 1, 5, 26, 13, 4, -26 }, // '!'
{ 18, 14, 9, 18, 2, -26 }, // '"'
{ 34, 19, 26, 21, 0, -26 }, // '#'
{ 96, 19, 37, 22, 1, -30 }, // '$'
{ 184, 29, 27, 32, 1, -26 }, // '%'
{ 282, 25, 26, 28, 2, -26 }, // '&'
{ 364, 6, 9, 10, 1, -26 }, // '''
{ 371, 9, 33, 14, 2, -26 }, // '('
{ 409, 9, 33, 14, 2, -26 }, // ')'
{ 447, 15, 14, 17, 0, -28 }, // '*'
{ 474, 19, 18, 22, 1, -22 }, // '+'
{ 517, 6, 11, 12, 3, -5 }, // ','
{ 526, 11, 4, 13, 1, -11 }, // '-'
{ 532, 5, 5, 12, 3, -5 }, // '.'
{ 536, 9, 26, 11, 1, -26 }, // '/'
{ 566, 18, 26, 22, 2, -26 }, // '0'
{ 625, 13, 26, 22, 2, -26 }, // '1'
{ 668, 18, 26, 22, 2, -26 }, // '2'
{ 727, 18, 26, 22, 2, -26 }, // '3'
{ 786, 21, 26, 22, 0, -26 }, // '4'
{ 855, 18, 26, 22, 2, -26 }, // '5'
{ 914, 18, 26, 22, 2, -26 }, // '6'
{ 973, 18, 26, 22, 3, -26 }, // '7'
{ 1032, 19, 26, 22, 1, -26 }, // '8'
{ 1094, 18, 26, 22, 1, -26 }, // '9'
{ 1153, 5, 19, 12, 3, -19 }, // ':'
{ 1165, 5, 25, 12, 3, -19 }, // ';'
{ 1181, 18, 20, 22, 1, -23 }, // '<'
{ 1226, 18, 13, 22, 2, -19 }, // '='
{ 1256, 18, 20, 22, 1, -23 }, // '>'
{ 1301, 18, 26, 22, 1, -26 }, // '?'
{ 1360, 34, 33, 36, 1, -26 }, // '@'
{ 1501, 24, 26, 27, 1, -26 }, // 'A'
{ 1579, 21, 26, 27, 3, -26 }, // 'B'
{ 1648, 23, 26, 28, 2, -26 }, // 'C'
{ 1723, 22, 26, 28, 3, -26 }, // 'D'
{ 1795, 20, 26, 25, 3, -26 }, // 'E'
{ 1860, 18, 26, 23, 3, -26 }, // 'F'
{ 1919, 24, 26, 30, 2, -26 }, // 'G'
{ 1997, 21, 26, 28, 3, -26 }, // 'H'
{ 2066, 5, 26, 12, 3, -26 }, // 'I'
{ 2083, 17, 26, 22, 1, -26 }, // 'J'
{ 2139, 22, 26, 28, 3, -26 }, // 'K'
{ 2211, 18, 26, 23, 3, -26 }, // 'L'
{ 2270, 25, 26, 31, 3, -26 }, // 'M'
{ 2352, 22, 26, 28, 3, -26 }, // 'N'
{ 2424, 25, 26, 30, 2, -26 }, // 'O'
{ 2506, 19, 26, 25, 3, -26 }, // 'P'
{ 2568, 26, 28, 30, 2, -26 }, // 'Q'
{ 2659, 21, 26, 27, 3, -26 }, // 'R'
{ 2728, 20, 26, 25, 2, -26 }, // 'S'
{ 2793, 21, 26, 24, 1, -26 }, // 'T'
{ 2862, 21, 26, 28, 3, -26 }, // 'U'
{ 2931, 23, 26, 26, 1, -26 }, // 'V'
{ 3006, 32, 26, 35, 1, -26 }, // 'W'
{ 3110, 21, 26, 23, 0, -26 }, // 'X'
{ 3179, 21, 26, 24, 1, -26 }, // 'Y'
{ 3248, 23, 26, 24, 0, -26 }, // 'Z'
{ 3323, 10, 33, 14, 2, -26 }, // '['
{ 3365, 10, 26, 11, 0, -26 }, // '\'
{ 3398, 10, 33, 14, 0, -26 }, // ']'
{ 3440, 17, 14, 22, 2, -26 }, // '^'
{ 3470, 18, 2, 19, 0, 3 }, // '_'
{ 3475, 8, 5, 10, 0, -26 }, // '`' Changed to degree symbol
{ 3480, 19, 19, 22, 1, -19 }, // 'a'
{ 3526, 19, 26, 24, 2, -26 }, // 'b'
{ 3588, 18, 19, 22, 1, -19 }, // 'c'
{ 3631, 19, 26, 24, 1, -26 }, // 'd'
{ 3693, 18, 19, 22, 2, -19 }, // 'e'
{ 3736, 15, 26, 13, -1, -26 }, // 'f'
{ 3785, 19, 26, 24, 1, -19 }, // 'g'
{ 3847, 18, 26, 23, 2, -26 }, // 'h'
{ 3906, 5, 26, 11, 2, -26 }, // 'i'
{ 3923, 10, 33, 11, -3, -26 }, // 'j'
{ 3965, 17, 26, 22, 3, -26 }, // 'k'
{ 4021, 5, 26, 11, 2, -26 }, // 'l'
{ 4038, 28, 19, 33, 2, -19 }, // 'm'
{ 4105, 18, 19, 23, 2, -19 }, // 'n'
{ 4148, 20, 19, 23, 1, -19 }, // 'o'
{ 4196, 19, 26, 24, 2, -19 }, // 'p'
{ 4258, 19, 26, 24, 1, -19 }, // 'q'
{ 4320, 13, 19, 17, 2, -19 }, // 'r'
{ 4351, 17, 19, 21, 1, -19 }, // 's'
{ 4392, 13, 26, 14, 0, -26 }, // 't'
{ 4435, 18, 19, 23, 2, -19 }, // 'u'
{ 4478, 18, 19, 21, 1, -19 }, // 'v'
{ 4521, 28, 19, 30, 1, -19 }, // 'w'
{ 4588, 17, 19, 20, 1, -19 }, // 'x'
{ 4629, 19, 26, 21, 0, -19 }, // 'y'
{ 4691, 18, 19, 20, 1, -19 }, // 'z'
{ 4734, 13, 33, 15, 1, -26 }, // '{'
{ 4788, 4, 33, 11, 3, -26 }, // '|'
{ 4805, 13, 33, 15, 0, -26 } // '}' character 0x7D
};
const GFXfont ArialRoundedMTBold_36 PROGMEM = { // Last character bug fixed 0x7E to 0x7D
(uint8_t *)ArialRoundedMTBold_36Bitmaps,(GFXglyph *)ArialRoundedMTBold_36Glyphs,0x20, 0x7D, 43};

View File

@ -0,0 +1,224 @@
/**The MIT License (MIT)
Copyright (c) 2015 by Daniel Eichhorn
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.
See more at http://blog.squix.ch
*/
// Created by http://oleddisplay.squix.ch/ Consider a donation
// In case of problems make sure that you are using the font file with the correct version!
// Bodmer fix: End character is 0x7D not 0x7E, so bug in last line of the file corrected
// this avoids screen corruption if ~ is printer
const uint8_t ArialRoundedMTBold_14Bitmaps[] PROGMEM = {
// Bitmap Data:
0x00, // ' '
0xFF,0xF8,0xF0, // '!'
0xDE,0xF6, // '"'
0x12,0x32,0x36,0xFF,0xFF,0x24,0xFF,0xFF,0x4C,0x48, // '#'
0x10,0x61,0xF6,0xAD,0x7A,0x1E,0x0E,0xD7,0xAF,0x5B,0xE1,0x02,0x04,0x00, // '$'
0x60,0x92,0x22,0x44,0x49,0x07,0x60,0x0B,0x82,0x48,0xC9,0x11,0x24,0x18, // '%'
0x3C,0x19,0x82,0x60,0xF0,0x39,0x33,0x6C,0x73,0x1C,0xFF,0x8E,0x30, // '&'
0xFC, // '''
0x32,0x64,0xCC,0xCC,0xC4,0x62,0x30, // '('
0xC4,0x62,0x33,0x33,0x32,0x64,0xC0, // ')'
0x21,0x2A,0xE5,0x28, // '*'
0x18,0x18,0x18,0xFF,0xFF,0x18,0x18, // '+'
0xF6, // ','
0xFF, // '-'
0xF0, // '.'
0x33,0x32,0x66,0x4C,0xCC, // '/'
0x38,0xFB,0x9E,0x3C,0x78,0xF1,0xF6,0x7C,0x70, // '0'
0x19,0xDF,0xB1,0x8C,0x63,0x18,0xC0, // '1'
0x38,0xFF,0x1E,0x30,0xC3,0x0C,0x30,0xFF,0xFC, // '2'
0x79,0x9B,0x10,0x63,0xC7,0x81,0xC3,0xC6,0xF0, // '3'
0x06,0x0E,0x1E,0x16,0x26,0x46,0xFF,0xFF,0x06,0x06, // '4'
0x7E,0xFD,0x06,0x0F,0xD8,0xC1,0xC3,0xCC,0xF0, // '5'
0x38,0xDB,0x1E,0x0F,0xD8,0xF1,0xE3,0x66,0x78, // '6'
0xFF,0xFC,0x30,0x41,0x82,0x0C,0x18,0x30,0xC0, // '7'
0x38,0xDB,0x1F,0x63,0x98,0xF1,0xE3,0xC6,0xF8, // '8'
0x3C,0x66,0xC3,0xC3,0xE7,0x3F,0x03,0xC3,0x66,0x3C, // '9'
0xF0,0x3C, // ':'
0xF0,0x3D,0x80, // ';'
0x02,0x1D,0xF7,0x0E,0x0F,0x83,0x81, // '<'
0xFF,0xFC,0x07,0xFF,0xE0, // '='
0x81,0xC1,0xF0,0x70,0xEF,0xB8,0x40, // '>'
0x3C,0xFF,0x1E,0x30,0xC7,0x0C,0x00,0x30,0x60, // '?'
0x0F,0x83,0x06,0x60,0x24,0xED,0x99,0x9B,0x19,0xB1,0xBB,0x12,0xBF,0xE4,0xDC,0x40,0x13,0x06,0x0F,0xC0, // '@'
0x1C,0x0E,0x05,0x06,0xC3,0x63,0x19,0xFC,0xFE,0xC1,0xE0,0xC0, // 'A'
0xFC,0xFE,0xC7,0xC6,0xFE,0xFE,0xC3,0xC3,0xFF,0xFE, // 'B'
0x3E,0x3F,0xB8,0xF8,0x3C,0x06,0x03,0x06,0xC7,0x7F,0x0F,0x00, // 'C'
0xFE,0x7F,0xB0,0xF8,0x3C,0x1E,0x0F,0x07,0x87,0xFF,0x7F,0x00, // 'D'
0xFE,0xFF,0xC0,0xC0,0xFE,0xFE,0xC0,0xC0,0xFF,0xFF, // 'E'
0xFF,0xFF,0x06,0x0F,0xDF,0xB0,0x60,0xC1,0x80, // 'F'
0x1E,0x3F,0x98,0xF8,0x2C,0x06,0x3F,0x1E,0xC3,0x7F,0x9F,0x00, // 'G'
0xC1,0xE0,0xF0,0x78,0x3F,0xFF,0xFF,0x07,0x83,0xC1,0xE0,0xC0, // 'H'
0xFF,0xFF,0xF0, // 'I'
0x06,0x0C,0x18,0x30,0x60,0xF1,0xF3,0x7E,0x78, // 'J'
0xC3,0x63,0xB3,0x9B,0x8F,0x87,0x63,0x19,0x8E,0xC3,0x60,0xC0, // 'K'
0xC1,0x83,0x06,0x0C,0x18,0x30,0x60,0xFF,0xFC, // 'L'
0xE1,0xFC,0xFF,0x3F,0xCF,0xD2,0xF7,0xBD,0xEF,0x7B,0xCC,0xF3,0x30, // 'M'
0xC1,0xF0,0xFC,0x7E,0x3D,0x9E,0x6F,0x3F,0x8F,0xC3,0xE0,0xC0, // 'N'
0x1E,0x1F,0xE6,0x1B,0x03,0xC0,0xF0,0x3C,0x0D,0x86,0x7F,0x87,0x80, // 'O'
0xFE,0xFF,0xC3,0xC3,0xFF,0xFE,0xC0,0xC0,0xC0,0xC0, // 'P'
0x1E,0x0F,0xF1,0x87,0x60,0x6C,0x0D,0x81,0xB1,0x33,0x7C,0x7F,0x83,0xD8,0x01,0x80, // 'Q'
0xFE,0xFF,0xC3,0xC3,0xFE,0xFC,0xCE,0xC6,0xC3,0xC3, // 'R'
0x7C,0xFE,0xC7,0xC2,0x7C,0x0F,0xC3,0xC3,0x7E,0x3C, // 'S'
0xFF,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18, // 'T'
0xC1,0xE0,0xF0,0x78,0x3C,0x1E,0x0F,0x07,0xC7,0x7F,0x1F,0x00, // 'U'
0xC1,0xE0,0xD8,0xCC,0x66,0x31,0xB0,0xD8,0x6C,0x1C,0x0E,0x00, // 'V'
0xC7,0x1E,0x38,0xF1,0x46,0xDB,0x66,0xDB,0x36,0xD9,0xA2,0xC7,0x1C,0x38,0xE1,0x83,0x00, // 'W'
0xC3,0x66,0x7E,0x3C,0x18,0x3C,0x7E,0x66,0xC3,0xC3, // 'X'
0xC3,0xC3,0x66,0x3E,0x3C,0x18,0x18,0x18,0x18,0x18, // 'Y'
0x7F,0x3F,0x80,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFF,0xFF,0xC0, // 'Z'
0xFF,0xCC,0xCC,0xCC,0xCC,0xCF,0xF0, // '['
0xCC,0x44,0x66,0x22,0x33, // '\'
0xFF,0x33,0x33,0x33,0x33,0x3F,0xF0, // ']'
0x30,0xE7,0x9A,0xCF,0x30, // '^'
0xFE, // '_'
0xD0, // '`'
0x7D,0x8C,0x7F,0x3C,0x79,0xDD,0x80, // 'a'
0xC1,0x83,0x06,0xEF,0xF8,0xF1,0xE3,0xFF,0xB8, // 'b'
0x3C,0xFF,0x1E,0x0C,0x6F,0xCF,0x00, // 'c'
0x06,0x0C,0x1B,0xBF,0xF8,0xF1,0xE3,0xFE,0xEC, // 'd'
0x3C,0xCF,0x1F,0xFC,0x0C,0xCF,0x00, // 'e'
0x3B,0x19,0xF6,0x31,0x8C,0x63,0x00, // 'f'
0x77,0xFF,0x1E,0x3C,0x7F,0xDD,0xE3,0xC6,0xF8, // 'g'
0xC1,0x83,0x06,0xEF,0xF8,0xF1,0xE3,0xC7,0x8C, // 'h'
0xF3,0xFF,0xF0, // 'i'
0x33,0x03,0x33,0x33,0x33,0x3F,0xE0, // 'j'
0xC1,0x83,0x06,0x6D,0x9E,0x3E,0x66,0xCD,0x8C, // 'k'
0xFF,0xFF,0xF0, // 'l'
0xD9,0xDF,0xFF,0x31,0xE6,0x3C,0xC7,0x98,0xF3,0x18, // 'm'
0xDD,0xFF,0x1E,0x3C,0x78,0xF1,0x80, // 'n'
0x38,0xFB,0x1E,0x3C,0x6F,0x8E,0x00, // 'o'
0xDD,0xFF,0x1E,0x3C,0x7F,0xF7,0x60,0xC1,0x80, // 'p'
0x77,0xFF,0x1E,0x3C,0x7F,0xDD,0x83,0x06,0x0C, // 'q'
0xDF,0xF1,0x8C,0x63,0x00, // 'r'
0x7B,0x3E,0x1E,0x0F,0x37,0x80, // 's'
0x63,0x19,0xF6,0x31,0x8C,0x79,0xC0, // 't'
0xC7,0x8F,0x1E,0x3C,0x7F,0xDD,0x80, // 'u'
0xC7,0x8D,0x93,0x62,0x87,0x04,0x00, // 'v'
0xC4,0x79,0xCD,0x29,0x35,0x67,0xBC,0x63,0x0C,0x60, // 'w'
0xC6,0xD9,0xF1,0xC7,0xCD,0xB1,0x80, // 'x'
0xC7,0x8D,0x93,0x62,0xC7,0x06,0x18,0xF1,0xC0, // 'y'
0xFE,0x18,0x61,0x86,0x1F,0xFF,0x80, // 'z'
0x19,0xCC,0x63,0x3B,0x8E,0x31,0x8C,0x71,0x80, // '{'
0xFF,0xFF,0xFF,0xC0, // '|'
0xC7,0x18,0xC6,0x38,0xEE,0x63,0x19,0xCC,0x00 // '}'
};
const GFXglyph ArialRoundedMTBold_14Glyphs[] PROGMEM = {
// bitmapOffset, width, height, xAdvance, xOffset, yOffset
{ 0, 1, 1, 5, 0, 0 }, // ' '
{ 1, 2, 10, 6, 1, -10 }, // '!'
{ 4, 5, 3, 8, 1, -10 }, // '"'
{ 6, 8, 10, 9, 0, -10 }, // '#'
{ 16, 7, 15, 9, 1, -12 }, // '$'
{ 30, 11, 10, 13, 0, -10 }, // '%'
{ 44, 10, 10, 12, 1, -10 }, // '&'
{ 57, 2, 3, 4, 1, -10 }, // '''
{ 58, 4, 13, 6, 1, -10 }, // '('
{ 65, 4, 13, 6, 0, -10 }, // ')'
{ 72, 5, 6, 7, 1, -11 }, // '*'
{ 76, 8, 7, 9, 0, -9 }, // '+'
{ 83, 2, 4, 5, 1, -2 }, // ','
{ 84, 4, 2, 6, 0, -5 }, // '-'
{ 85, 2, 2, 5, 1, -2 }, // '.'
{ 86, 4, 10, 5, 0, -10 }, // '/'
{ 91, 7, 10, 9, 1, -10 }, // '0'
{ 100, 5, 10, 9, 1, -10 }, // '1'
{ 107, 7, 10, 9, 1, -10 }, // '2'
{ 116, 7, 10, 9, 1, -10 }, // '3'
{ 125, 8, 10, 9, 0, -10 }, // '4'
{ 135, 7, 10, 9, 1, -10 }, // '5'
{ 144, 7, 10, 9, 1, -10 }, // '6'
{ 153, 7, 10, 9, 1, -10 }, // '7'
{ 162, 7, 10, 9, 1, -10 }, // '8'
{ 171, 8, 10, 9, 0, -10 }, // '9'
{ 181, 2, 7, 5, 1, -7 }, // ':'
{ 183, 2, 9, 5, 1, -7 }, // ';'
{ 186, 7, 8, 9, 1, -9 }, // '<'
{ 193, 7, 5, 9, 1, -7 }, // '='
{ 198, 7, 8, 9, 1, -9 }, // '>'
{ 205, 7, 10, 9, 1, -10 }, // '?'
{ 214, 12, 13, 15, 1, -10 }, // '@'
{ 234, 9, 10, 11, 1, -10 }, // 'A'
{ 246, 8, 10, 11, 1, -10 }, // 'B'
{ 256, 9, 10, 11, 1, -10 }, // 'C'
{ 268, 9, 10, 11, 1, -10 }, // 'D'
{ 280, 8, 10, 10, 1, -10 }, // 'E'
{ 290, 7, 10, 9, 1, -10 }, // 'F'
{ 299, 9, 10, 12, 1, -10 }, // 'G'
{ 311, 9, 10, 12, 1, -10 }, // 'H'
{ 323, 2, 10, 5, 1, -10 }, // 'I'
{ 326, 7, 10, 9, 0, -10 }, // 'J'
{ 335, 9, 10, 11, 1, -10 }, // 'K'
{ 347, 7, 10, 9, 1, -10 }, // 'L'
{ 356, 10, 10, 13, 1, -10 }, // 'M'
{ 369, 9, 10, 12, 1, -10 }, // 'N'
{ 381, 10, 10, 12, 1, -10 }, // 'O'
{ 394, 8, 10, 10, 1, -10 }, // 'P'
{ 404, 11, 11, 12, 1, -10 }, // 'Q'
{ 420, 8, 10, 11, 1, -10 }, // 'R'
{ 430, 8, 10, 10, 1, -10 }, // 'S'
{ 440, 8, 10, 10, 0, -10 }, // 'T'
{ 450, 9, 10, 12, 1, -10 }, // 'U'
{ 462, 9, 10, 11, 0, -10 }, // 'V'
{ 474, 13, 10, 14, 0, -10 }, // 'W'
{ 491, 8, 10, 9, 0, -10 }, // 'X'
{ 501, 8, 10, 10, 0, -10 }, // 'Y'
{ 511, 9, 10, 10, 0, -10 }, // 'Z'
{ 523, 4, 13, 6, 1, -10 }, // '['
{ 530, 4, 10, 5, 0, -10 }, // '\'
{ 535, 4, 13, 6, 0, -10 }, // ']'
{ 542, 6, 6, 9, 1, -10 }, // '^'
{ 547, 7, 1, 8, 0, 1 }, // '_'
{ 548, 2, 2, 6, 1, -10 }, // '`'
{ 549, 7, 7, 9, 1, -7 }, // 'a'
{ 556, 7, 10, 10, 1, -10 }, // 'b'
{ 565, 7, 7, 9, 1, -7 }, // 'c'
{ 572, 7, 10, 10, 1, -10 }, // 'd'
{ 581, 7, 7, 9, 1, -7 }, // 'e'
{ 588, 5, 10, 6, 0, -10 }, // 'f'
{ 595, 7, 10, 10, 1, -7 }, // 'g'
{ 604, 7, 10, 9, 1, -10 }, // 'h'
{ 613, 2, 10, 5, 1, -10 }, // 'i'
{ 616, 4, 13, 5, -1, -10 }, // 'j'
{ 623, 7, 10, 9, 1, -10 }, // 'k'
{ 632, 2, 10, 5, 1, -10 }, // 'l'
{ 635, 11, 7, 13, 1, -7 }, // 'm'
{ 645, 7, 7, 9, 1, -7 }, // 'n'
{ 652, 7, 7, 9, 1, -7 }, // 'o'
{ 659, 7, 10, 10, 1, -7 }, // 'p'
{ 668, 7, 10, 10, 1, -7 }, // 'q'
{ 677, 5, 7, 7, 1, -7 }, // 'r'
{ 682, 6, 7, 9, 1, -7 }, // 's'
{ 688, 5, 10, 6, 0, -10 }, // 't'
{ 695, 7, 7, 9, 1, -7 }, // 'u'
{ 702, 7, 7, 9, 0, -7 }, // 'v'
{ 709, 11, 7, 12, 0, -7 }, // 'w'
{ 719, 7, 7, 8, 0, -7 }, // 'x'
{ 726, 7, 10, 9, 0, -7 }, // 'y'
{ 735, 7, 7, 8, 0, -7 }, // 'z'
{ 742, 5, 13, 6, 0, -10 }, // '{'
{ 751, 2, 13, 5, 1, -10 }, // '|'
{ 755, 5, 13, 6, 1, -10 } // '}' character 0x7D
};
const GFXfont ArialRoundedMTBold_14 PROGMEM = { // Last character bug fixed 0x7E to 0x7D
(uint8_t *)ArialRoundedMTBold_14Bitmaps,(GFXglyph *)ArialRoundedMTBold_14Glyphs,0x20, 0x7D, 17};

View File

@ -0,0 +1,332 @@
/**The MIT License (MIT)
Copyright (c) 2015 by Daniel Eichhorn
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.
See more at http://blog.squix.ch
Adapted by Bodmer to use the faster TFT_eSPI library:
https://github.com/Bodmer/TFT_eSPI
Bodmer: Functions no longer needed weeded out, Jpeg decoder functions added
Bodmer: drawBMP() updated to buffer in and out pixels and use screen CGRAM rotation for faster bottom up drawing (now ~2x faster)
*/
#include "GfxUi.h"
GfxUi::GfxUi(TFT_eSPI *tft) {
_tft = tft;
}
void GfxUi::drawProgressBar(uint16_t x0, uint16_t y0, uint16_t w, uint16_t h, uint8_t percentage, uint16_t frameColor, uint16_t barColor) {
if (percentage == 0) {
_tft->fillRoundRect(x0, y0, w, h, 3, TFT_BLACK);
}
uint8_t margin = 2;
uint16_t barHeight = h - 2 * margin;
uint16_t barWidth = w - 2 * margin;
_tft->drawRoundRect(x0, y0, w, h, 3, frameColor);
_tft->fillRect(x0 + margin, y0 + margin, barWidth * percentage / 100.0, barHeight, barColor);
}
// This drawBMP function contains code from:
// https://github.com/adafruit/Adafruit_ILI9341/blob/master/examples/spitftbitmap/spitftbitmap.ino
// Here is Bodmer's version: this uses the ILI9341 CGRAM coordinate rotation features inside the display and
// buffers both file and TFT pixel blocks, it typically runs about 2x faster for bottom up encoded BMP images
//void GfxUi::drawBMP(String filename, uint8_t x, uint16_t y, boolean flip) { // Alernative for caller control of flip
void GfxUi::drawBmp(String filename, uint8_t x, uint16_t y) {
// Flips the TFT internal SGRAM coords to draw bottom up BMP images faster, in this application it can be fixed
boolean flip = 1;
if ((x >= _tft->width()) || (y >= _tft->height())) return;
fs::File bmpFile;
int16_t bmpWidth, bmpHeight; // Image W+H in pixels
uint32_t bmpImageoffset; // Start address of image data in file
uint32_t rowSize; // Not always = bmpWidth; may have padding
uint8_t sdbuffer[3 * BUFFPIXEL]; // file read pixel buffer (8 bits each R+G+B per pixel)
uint16_t tftbuffer[BUFFPIXEL]; // TFT pixel out buffer (16-bit per pixel)
uint8_t rgb_ptr = sizeof(sdbuffer); // read 24 bit RGB pixel data buffer pointer (8 bit so BUFF_SIZE must be less than 86)
boolean goodBmp = false; // Flag set to true on valid header parse
int16_t w, h, row, col; // to store width, height, row and column
uint8_t rotation; // to restore rotation
uint8_t tft_ptr = 0; // TFT 16 bit 565 format pixel data buffer pointer
// Check file exists and open it
Serial.println(filename);
if ( !(bmpFile = SPIFFS.open(filename, "r")) ) {
Serial.println(F(" File not found")); // Can comment out if not needed
return;
}
// Parse BMP header to get the information we need
if (read16(bmpFile) == 0x4D42) { // BMP file start signature check
read32(bmpFile); // Dummy read to throw away and move on
read32(bmpFile); // Read & ignore creator bytes
bmpImageoffset = read32(bmpFile); // Start of image data
read32(bmpFile); // Dummy read to throw away and move on
bmpWidth = read32(bmpFile); // Image width
bmpHeight = read32(bmpFile); // Image height
// Only proceed if we pass a bitmap file check
// Number of image planes -- must be '1', depth 24 and 0 (uncompressed format)
if ((read16(bmpFile) == 1) && (read16(bmpFile) == 24) && (read32(bmpFile) == 0)) {
goodBmp = true; // Supported BMP format
// BMP rows are padded (if needed) to 4-byte boundary
rowSize = (bmpWidth * 3 + 3) & ~3;
// Crop area to be loaded
w = bmpWidth;
h = bmpHeight;
// We might need to alter rotation to avoid tedious file pointer manipulation
// Save the current value so we can restore it later
rotation = _tft->getRotation();
// Use TFT SGRAM coord rotation if flip is set for 25% faster rendering (new rotations 4-7 supported by library)
if (flip) _tft->setRotation((rotation + (flip<<2)) % 8); // Value 0-3 mapped to 4-7
// Calculate new y plot coordinate if we are flipping
switch (rotation) {
case 0:
if (flip) y = _tft->height() - y - h; break;
case 1:
y = _tft->height() - y - h; break;
break;
case 2:
if (flip) y = _tft->height() - y - h; break;
break;
case 3:
y = _tft->height() - y - h; break;
break;
}
// Set TFT address window to image bounds
// Currently, image will not draw or will be corrputed if it does not fit
// TODO -> efficient clipping, but I don't need it to be idiot proof ;-)
_tft->setAddrWindow(x, y, x + w - 1, y + h - 1);
// Finally we are ready to send rows of pixels, writing like this avoids slow 32 bit multiply in 8 bit processors
for (uint32_t pos = bmpImageoffset; pos < bmpImageoffset + h * rowSize ; pos += rowSize) {
// Seek if we need to on boundaries and arrange to dump buffer and start again
if (bmpFile.position() != pos) {
bmpFile.seek(pos, fs::SeekSet);
rgb_ptr = sizeof(sdbuffer);
//Serial.println("Seeking in file >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
}
// Fill the pixel buffer and plot
for (col = 0; col < w; col++) { // For each column...
// Time to read more pixel data?
if (rgb_ptr >= sizeof(sdbuffer)) {
// Push tft buffer to the display
if (tft_ptr) {
// Here we are sending a uint16_t array to the function
_tft->pushColors(tftbuffer, tft_ptr);
tft_ptr = 0; // tft_ptr and rgb_ptr are not always in sync...
}
// Finally reading bytes from SD Card
bmpFile.read(sdbuffer, sizeof(sdbuffer));
rgb_ptr = 0; // Set buffer index to start
}
// Convert pixel from BMP 8+8+8 format to TFT compatible 16 bit word
// Blue 5 bits, green 6 bits and red 5 bits (16 bits total)
// Is is a long line but it is faster than calling a library fn for this
tftbuffer[tft_ptr] = (sdbuffer[rgb_ptr++] >> 3) ;
tftbuffer[tft_ptr] |= ((sdbuffer[rgb_ptr++] & 0xFC) << 3);
tftbuffer[tft_ptr] |= ((sdbuffer[rgb_ptr++] & 0xF8) << 8);
tft_ptr++;
} // Next row
} // All rows done
// Write any partially full buffer to TFT
if (tft_ptr) _tft->pushColors(tftbuffer, tft_ptr);
} // End of bitmap access
} // End of bitmap file check
bmpFile.close();
if(!goodBmp) Serial.println(F("BMP format not recognised."));
_tft->setRotation(rotation); // Put back original rotation
}
// These read 16- and 32-bit types from the SD card file.
// BMP data is stored little-endian, Arduino is little-endian too.
// May need to reverse subscript order if porting elsewhere.
uint16_t GfxUi::read16(fs::File &f) {
uint16_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read(); // MSB
return result;
}
uint32_t GfxUi::read32(fs::File &f) {
uint32_t result;
((uint8_t *)&result)[0] = f.read(); // LSB
((uint8_t *)&result)[1] = f.read();
((uint8_t *)&result)[2] = f.read();
((uint8_t *)&result)[3] = f.read(); // MSB
return result;
}
/*====================================================================================
This sketch support functions to render the Jpeg images.
Created by Bodmer 15th Jan 2017
==================================================================================*/
// Return the minimum of two values a and b
#define minimum(a,b) (((a) < (b)) ? (a) : (b))
#define USE_SPI_BUFFER // Comment out to use slower 16 bit pushColor()
//====================================================================================
// Opens the image file and prime the Jpeg decoder
//====================================================================================
void GfxUi::drawJpeg(const char *filename, int xpos, int ypos) {
Serial.println("===========================");
Serial.print("Drawing file: "); Serial.println(filename);
Serial.println("===========================");
// Open the named file (the Jpeg decoder library will close it after rendering image)
fs::File jpegFile = SPIFFS.open( filename, "r"); // File handle reference for SPIFFS
// File jpegFile = SD.open( filename, FILE_READ); // or, file handle reference for SD library
if ( !jpegFile ) {
Serial.print("ERROR: File \""); Serial.print(filename); Serial.println ("\" not found!");
return;
}
// Use one of the three following methods to initialise the decoder:
//boolean decoded = JpegDec.decodeFsFile(jpegFile); // Pass a SPIFFS file handle to the decoder,
//boolean decoded = JpegDec.decodeSdFile(jpegFile); // or pass the SD file handle to the decoder,
boolean decoded = JpegDec.decodeFsFile(filename); // or pass the filename (leading / distinguishes SPIFFS files)
// Note: the filename can be a String or character array type
if (decoded) {
// print information about the image to the serial port
jpegInfo();
// render the image onto the screen at given coordinates
jpegRender(xpos, ypos);
}
else {
Serial.println("Jpeg file format not supported!");
}
}
//====================================================================================
// Decode and render the Jpeg image onto the TFT screen
//====================================================================================
void GfxUi::jpegRender(int xpos, int ypos) {
// retrieve infomration about the image
uint16_t *pImg;
uint16_t mcu_w = JpegDec.MCUWidth;
uint16_t mcu_h = JpegDec.MCUHeight;
uint32_t max_x = JpegDec.width;
uint32_t max_y = JpegDec.height;
// Jpeg images are draw as a set of image block (tiles) called Minimum Coding Units (MCUs)
// Typically these MCUs are 16x16 pixel blocks
// Determine the width and height of the right and bottom edge image blocks
uint32_t min_w = minimum(mcu_w, max_x % mcu_w);
uint32_t min_h = minimum(mcu_h, max_y % mcu_h);
// save the current image block size
uint32_t win_w = mcu_w;
uint32_t win_h = mcu_h;
// record the current time so we can measure how long it takes to draw an image
uint32_t drawTime = millis();
// save the coordinate of the right and bottom edges to assist image cropping
// to the screen size
max_x += xpos;
max_y += ypos;
// read each MCU block until there are no more
#ifdef USE_SPI_BUFFER
while( JpegDec.readSwappedBytes()){ // Swap byte order so the SPI buffer can be used
#else
while ( JpegDec.read()) { // Normal byte order read
#endif
// save a pointer to the image block
pImg = JpegDec.pImage;
// calculate where the image block should be drawn on the screen
int mcu_x = JpegDec.MCUx * mcu_w + xpos;
int mcu_y = JpegDec.MCUy * mcu_h + ypos;
// check if the image block size needs to be changed for the right and bottom edges
if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
else win_w = min_w;
if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
else win_h = min_h;
// calculate how many pixels must be drawn
uint32_t mcu_pixels = win_w * win_h;
// draw image MCU block only if it will fit on the screen
if ( ( mcu_x + win_w) <= _tft->width() && ( mcu_y + win_h) <= _tft->height())
{
#ifdef USE_SPI_BUFFER
// Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1)
_tft->setWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1);
// Write all MCU pixels to the TFT window
uint8_t *pImg8 = (uint8_t*)pImg; // Convert 16 bit pointer to an 8 bit pointer
_tft->pushColors(pImg8, mcu_pixels*2); // Send bytes via 64 byte SPI port buffer
#else
// Now set a MCU bounding window on the TFT to push pixels into (x, y, x + width - 1, y + height - 1)
_tft->setAddrWindow(mcu_x, mcu_y, mcu_x + win_w - 1, mcu_y + win_h - 1);
// Write all MCU pixels to the TFT window
while (mcu_pixels--) _tft->pushColor(*pImg++);
#endif
}
else if ( ( mcu_y + win_h) >= _tft->height()) JpegDec.abort();
}
// calculate how long it took to draw the image
drawTime = millis() - drawTime; // Calculate the time it took
// print the results to the serial port
Serial.print ("Total render time was : "); Serial.print(drawTime); Serial.println(" ms");
Serial.println("=====================================");
}
//====================================================================================
// Print information decoded from the Jpeg image
//====================================================================================
void GfxUi::jpegInfo() {
Serial.println("===============");
Serial.println("JPEG image info");
Serial.println("===============");
Serial.print ("Width :"); Serial.println(JpegDec.width);
Serial.print ("Height :"); Serial.println(JpegDec.height);
Serial.print ("Components :"); Serial.println(JpegDec.comps);
Serial.print ("MCU / row :"); Serial.println(JpegDec.MCUSPerRow);
Serial.print ("MCU / col :"); Serial.println(JpegDec.MCUSPerCol);
Serial.print ("Scan type :"); Serial.println(JpegDec.scanType);
Serial.print ("MCU width :"); Serial.println(JpegDec.MCUWidth);
Serial.print ("MCU height :"); Serial.println(JpegDec.MCUHeight);
Serial.println("===============");
Serial.println("");
}
//====================================================================================

View File

@ -0,0 +1,60 @@
/**The MIT License (MIT)
Copyright (c) 2015 by Daniel Eichhorn
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.
See more at http://blog.squix.ch
Adapted by Bodmer to use the faster TFT_eSPI library:
https://github.com/Bodmer/TFT_eSPI
*/
#include <TFT_eSPI.h> // Hardware-specific library
#define FS_NO_GLOBALS // Avoid conflict with SD library File type definition
#include <FS.h>
// JPEG decoder library
#include <JPEGDecoder.h>
#ifndef _GFX_UI_H
#define _GFX_UI_H
// Maximum of 85 for BUFFPIXEL as 3 x this value is stored in an 8 bit variable!
// 32 is an efficient size for SPIFFS due to SPI hardware pipeline buffer size
// A larger value of 80 is better for SD cards
#define BUFFPIXEL 32
class GfxUi {
public:
GfxUi(TFT_eSPI * tft);
void drawBmp(String filename, uint8_t x, uint16_t y);
void drawProgressBar(uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint8_t percentage, uint16_t frameColor, uint16_t barColor);
void jpegInfo();
void drawJpeg(const char *filename, int xpos, int ypos);
void jpegRender(int xpos, int ypos);
private:
TFT_eSPI * _tft;
uint16_t read16(fs::File &f);
uint32_t read32(fs::File &f);
};
#endif

View File

@ -0,0 +1,42 @@
/*====================================================================================
This sketch contains support functions for the ESP6266 SPIFFS filing system
Created by Bodmer 15th Jan 2017
==================================================================================*/
//====================================================================================
// Print a SPIFFS directory list (root directory)
//====================================================================================
void listFiles(void) {
Serial.println();
Serial.println("SPIFFS files found:");
fs::Dir dir = SPIFFS.openDir("/"); // Root directory
String line = "=====================================";
uint32_t totalBytes = 0;
Serial.println(line);
Serial.println(" File name Size");
Serial.println(line);
while (dir.next()) {
String fileName = dir.fileName();
Serial.print(fileName);
int spaces = 25 - fileName.length(); // Tabulate nicely
while (spaces--) Serial.print(" ");
fs::File f = dir.openFile("r");
Serial.print(f.size()); Serial.println(" bytes");
totalBytes += f.size();
}
Serial.println(); Serial.print("Total = ");
int spaces = 25 - 8; // Tabulate nicely
while (spaces--) Serial.print(" ");
Serial.print(totalBytes); Serial.println(" bytes");
Serial.println(line);
Serial.println();
delay(1000);
}
//====================================================================================

View File

@ -0,0 +1,105 @@
/**The MIT License (MIT)
Copyright (c) 2015 by Daniel Eichhorn
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.
See more at http://blog.squix.ch
*/
#include "WebResource.h"
WebResource::WebResource(){
}
void WebResource::downloadFile(String url, String filename) {
downloadFile(url, filename, nullptr);
}
void WebResource::downloadFile(String url, String filename, ProgressCallback progressCallback) {
if (SPIFFS.exists(filename) == true) {
Serial.println("Found " + filename);
return;
}
else Serial.println("Downloading " + filename + " from " + url);
// wait for WiFi connection
if((_wifiMulti.run() == WL_CONNECTED)) {
HTTPClient http;
Serial.print("[HTTP] begin...\n");
// configure server and url
http.begin(url);
Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
if(httpCode > 0) {
//SPIFFS.remove(filename);
fs::File f = SPIFFS.open(filename, "w+");
if (!f) {
Serial.println("file open failed");
return;
}
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
// file found at server
if(httpCode == HTTP_CODE_OK) {
// get length of document (is -1 when Server sends no Content-Length header)
int total = http.getSize();
int len = total;
progressCallback(filename, 0,total);
// create buffer for read
uint8_t buff[128] = { 0 };
// get tcp stream
WiFiClient * stream = http.getStreamPtr();
// read all data from server
while(http.connected() && (len > 0 || len == -1)) {
// get available data size
size_t size = stream->available();
if(size) {
// read up to 128 byte
int c = stream->readBytes(buff, ((size > sizeof(buff)) ? sizeof(buff) : size));
// write it to Serial
f.write(buff, c);
if(len > 0) {
len -= c;
}
progressCallback(filename, total - len,total);
}
delay(1);
}
Serial.println();
Serial.print("[HTTP] connection closed or file end.\n");
}
f.close();
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
}

View File

@ -0,0 +1,46 @@
/**The MIT License (MIT)
Copyright (c) 2015 by Daniel Eichhorn
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.
See more at http://blog.squix.ch
*/
#define FS_NO_GLOBALS // Avoid conflict with SD library File type definition
#include <FS.h>
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#ifndef _WEBRESOURCE_H
#define _WEBRESOURCE_H
typedef void (*ProgressCallback)(String fileName, int16_t bytesDownloaded, int16_t bytesTotal);
class WebResource {
public:
WebResource();
void downloadFile(String url, String filename, ProgressCallback progressCallback);
void downloadFile(String url, String filename);
private:
ESP8266WiFiMulti _wifiMulti;
};
#endif

View File

@ -0,0 +1,71 @@
/**The MIT License (MIT)
Copyright (c) 2015 by Daniel Eichhorn
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.
See more at http://blog.squix.ch
Adapted by Bodmer to use the faster TFT_ILI9341_ESP library:
https://github.com/Bodmer/TFT_ILI9341_ESP
*/
// Setup
const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes
// Pins for the TFT interface are defined in the User_Setup.h file inside the TFT_eSPI library
// These are the ones I used on a NodeMCU plus MOSI and SCK:
// #define TFT_DC D3
// #define TFT_CS D8
///#define TFT_RST -1 // Minus one means no pin allocated, connect to NodeMCU RST pin
// TimeClient settings
const float UTC_OFFSET = 0;
// Wunderground Settings, EDIT TO SUIT YOUR LOCATION
const boolean IS_METRIC = true; // Temperature only? Wind speed units appear to stay in mph. To do: investigate <<<<<<<<<<<<<<<<<<<<<<<<<
//const String WUNDERGRROUND_API_KEY = "<WUNDERGROUND KEY HERE>";
//const String WUNDERGRROUND_API_KEY = "1c265fajf48s0a82"; // Random key example of what the above line should look like
// For language codes see https://www.wunderground.com/weather/api/d/docs?d=language-support&_ga=1.55148395.1951311424.1484425551
const String WUNDERGRROUND_LANGUAGE = "EN"; // Language EN = English
// For a list of countries, states and cities see https://www.wunderground.com/about/faq/international_cities.asp
const String WUNDERGROUND_COUNTRY = "Peru"; // UK, US etc
const String WUNDERGROUND_CITY = "Lima"; // City, "London", "FL/Boca_Raton" for Boca Raton in Florida (State/City) etc. Use underscore_for spaces)
// Windspeed conversion, use 1 pair of #defines. To do: investigate a more convenient method <<<<<<<<<<<<<<<<<<<<<
//#define WIND_SPEED_SCALING 1.0 // mph
//#define WIND_SPEED_UNITS " mph"
//#define WIND_SPEED_SCALING 0.868976 // mph to knots
//#define WIND_SPEED_UNITS " kn"
#define WIND_SPEED_SCALING 1.60934 // mph to kph
#define WIND_SPEED_UNITS " kph"
//Thingspeak Settings - not used, no need to populate this at the moment
const String THINGSPEAK_CHANNEL_ID = "<CHANNEL_ID_HERE>";
const String THINGSPEAK_API_READ_KEY = "<API_READ_KEY_HERE>";
// List, so that the downloader knows what to fetch
String wundergroundIcons [] = {"chanceflurries","chancerain","chancesleet","chancesnow","clear","cloudy","flurries","fog","hazy","mostlycloudy","mostlysunny","partlycloudy","partlysunny","rain","sleet","snow","sunny","tstorms","unknown"};
/***************************
* End Settings
**************************/

View File

@ -0,0 +1,579 @@
/**The MIT License (MIT)
Copyright (c) 2015 by Daniel Eichhorn
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 COPYBR_DATUM 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.
See more at http://blog.squix.ch
Adapted by Bodmer to use the faster TFT_eSPI library:
https://github.com/Bodmer/TFT_eSPI
Plus:
Minor changes to text placement and auto-blanking out old text with background colour padding
Moon phase text added
Forecast text lines are automatically split onto two lines at a central space (some are long!)
Time is printed with colons aligned to tidy display
Min and max forecast temperatures spaced out
The ` character has been changed to a degree symbol in the 36 point font
New smart WU jpeg splash startup screen and updated progress messages
Display does not need to be blanked between updates
Icons nudged about slightly to add wind direction + speed
*/
#include <Arduino.h>
#include <SPI.h>
#include <TFT_eSPI.h> // Hardware-specific library
// Additional UI functions
#include "GfxUi.h"
// Fonts created by http://oleddisplay.squix.ch/
#include "ArialRoundedMTBold_14.h"
#include "ArialRoundedMTBold_36.h"
// Download helper
#include "WebResource.h"
#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>
#include <ESP8266mDNS.h>
#include <DNSServer.h>
#include <ESP8266WebServer.h>
// Helps with connecting to internet
#include <WiFiManager.h>
// check settings.h for adapting to your needs
#include "settings.h"
#include <JsonListener.h>
#include <WundergroundClient.h>
#include "TimeClient.h"
// HOSTNAME for OTA update
#define HOSTNAME "ESP8266-OTA-"
/*****************************
Important: see settings.h to configure your settings!!!
* ***************************/
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
boolean booted = true;
GfxUi ui = GfxUi(&tft);
WebResource webResource;
TimeClient timeClient(UTC_OFFSET);
// Set to false, if you prefere imperial/inches, Fahrenheit
WundergroundClient wunderground(IS_METRIC);
//declaring prototypes
void configModeCallback (WiFiManager *myWiFiManager);
void downloadCallback(String filename, int16_t bytesDownloaded, int16_t bytesTotal);
ProgressCallback _downloadCallback = downloadCallback;
void downloadResources();
void updateData();
void drawProgress(uint8_t percentage, String text);
void drawTime();
void drawCurrentWeather();
void drawForecast();
void drawForecastDetail(uint16_t x, uint16_t y, uint8_t dayIndex);
String getMeteoconIcon(String iconText);
void drawAstronomy();
void drawSeparator(uint16_t y);
long lastDownloadUpdate = millis();
void setup() {
Serial.begin(250000);
tft.begin();
tft.fillScreen(TFT_BLACK);
tft.setFreeFont(&ArialRoundedMTBold_14);
tft.setTextDatum(BC_DATUM);
tft.setTextColor(TFT_DARKGREY, TFT_BLACK);
tft.drawString("Original by: blog.squix.org", 120, 240);
tft.drawString("Adapted by: Bodmer", 120, 260);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
SPIFFS.begin();
//listFiles();
//Uncomment next line if you want to erase SPIFFS and update all internet resources, this takes some time!
tft.drawString("Formatting SPIFFS, so wait!", 120, 200); SPIFFS.format();
if (SPIFFS.exists("/WU.jpg") == true) ui.drawJpeg("/WU.jpg", 0, 10);
if (SPIFFS.exists("/Earth.jpg") == true) ui.drawJpeg("/Earth.jpg", 0, 320-56); // Image is 56 pixels high
delay(1000);
tft.drawString("Connecting to WiFi", 120, 200);
tft.setTextPadding(240); // Pad next drawString() text to full width to over-write old text
//WiFiManager
//Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wifiManager;
// Uncomment for testing wifi manager
//wifiManager.resetSettings();
wifiManager.setAPCallback(configModeCallback);
//or use this for auto generated name ESP + ChipID
wifiManager.autoConnect();
//Manual Wifi
//WiFi.begin(WIFI_SSID, WIFI_PWD);
// OTA Setup
String hostname(HOSTNAME);
hostname += String(ESP.getChipId(), HEX);
WiFi.hostname(hostname);
ArduinoOTA.setHostname((const char *)hostname.c_str());
ArduinoOTA.begin();
// download images from the net. If images already exist don't download
tft.drawString("Downloading to SPIFFS...", 120, 200);
tft.drawString(" ", 120, 240); // Clear line
tft.drawString(" ", 120, 260); // Clear line
downloadResources();
//listFiles();
tft.drawString(" ", 120, 200); // Clear line above using set padding width
tft.drawString("Fetching weather data...", 120, 220);
//delay(500);
// load the weather information
updateData();
}
long lastDrew = 0;
void loop() {
// Handle OTA update requests
ArduinoOTA.handle();
// Check if we should update the clock
if (millis() - lastDrew > 30000 && wunderground.getSeconds() == "00") {
drawTime();
lastDrew = millis();
}
// Check if we should update weather information
if (millis() - lastDownloadUpdate > 1000 * UPDATE_INTERVAL_SECS) {
updateData();
lastDownloadUpdate = millis();
}
}
// Called if WiFi has not been configured yet
void configModeCallback (WiFiManager *myWiFiManager) {
tft.setTextDatum(BC_DATUM);
tft.setFreeFont(&ArialRoundedMTBold_14);
tft.setTextColor(TFT_ORANGE);
tft.drawString("Wifi Manager", 120, 28);
tft.drawString("Please connect to AP", 120, 42);
tft.setTextColor(TFT_WHITE);
tft.drawString(myWiFiManager->getConfigPortalSSID(), 120, 56);
tft.setTextColor(TFT_ORANGE);
tft.drawString("To setup Wifi Configuration", 120, 70);
}
// callback called during download of files. Updates progress bar
void downloadCallback(String filename, int16_t bytesDownloaded, int16_t bytesTotal) {
Serial.println(String(bytesDownloaded) + " / " + String(bytesTotal));
tft.setTextDatum(BC_DATUM);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.setTextPadding(240);
int percentage = 100 * bytesDownloaded / bytesTotal;
if (percentage == 0) {
tft.drawString(filename, 120, 220);
}
if (percentage % 5 == 0) {
tft.setTextDatum(TC_DATUM);
tft.setTextPadding(tft.textWidth(" 888% "));
tft.drawString(String(percentage) + "%", 120, 245);
ui.drawProgressBar(10, 225, 240 - 20, 15, percentage, TFT_WHITE, TFT_BLUE);
}
}
// Download the bitmaps
void downloadResources() {
// tft.fillScreen(TFT_BLACK);
tft.setFreeFont(&ArialRoundedMTBold_14);
char id[5];
// Download WU graphic jpeg first and display it, then the Earth view
webResource.downloadFile((String)"http://i.imgur.com/njl1pMj.jpg", (String)"/WU.jpg", _downloadCallback);
if (SPIFFS.exists("/WU.jpg") == true) ui.drawJpeg("/WU.jpg", 0, 10);
webResource.downloadFile((String)"http://i.imgur.com/v4eTLCC.jpg", (String)"/Earth.jpg", _downloadCallback);
if (SPIFFS.exists("/Earth.jpg") == true) ui.drawJpeg("/Earth.jpg", 0, 320-56);
//webResource.downloadFile((String)"http://i.imgur.com/IY57GSv.jpg", (String)"/Horizon.jpg", _downloadCallback);
//if (SPIFFS.exists("/Horizon.jpg") == true) ui.drawJpeg("/Horizon.jpg", 0, 320-160);
//webResource.downloadFile((String)"http://i.imgur.com/jZptbtY.jpg", (String)"/Rainbow.jpg", _downloadCallback);
//if (SPIFFS.exists("/Rainbow.jpg") == true) ui.drawJpeg("/Rainbow.jpg", 0, 0);
for (int i = 0; i < 19; i++) {
sprintf(id, "%02d", i);
webResource.downloadFile("http://www.squix.org/blog/wunderground/" + wundergroundIcons[i] + ".bmp", wundergroundIcons[i] + ".bmp", _downloadCallback);
}
for (int i = 0; i < 19; i++) {
sprintf(id, "%02d", i);
webResource.downloadFile("http://www.squix.org/blog/wunderground/mini/" + wundergroundIcons[i] + ".bmp", "/mini/" + wundergroundIcons[i] + ".bmp", _downloadCallback);
}
for (int i = 0; i < 24; i++) {
webResource.downloadFile("http://www.squix.org/blog/moonphase_L" + String(i) + ".bmp", "/moon" + String(i) + ".bmp", _downloadCallback);
}
}
// Update the internet based information and update screen
void updateData() {
// booted = true; // Test only
// booted = false; // Test only
if (booted) ui.drawJpeg("/WU.jpg", 0, 10); // May have already drawn this but it does not take long
else tft.drawCircle(22, 22, 16, TFT_DARKGREY); // Outer ring - optional
if (booted) drawProgress(20, "Updating time...");
else fillSegment(22, 22, 0, (int) (20 * 3.6), 16, TFT_NAVY);
timeClient.updateTime();
if (booted) drawProgress(50, "Updating conditions...");
else fillSegment(22, 22, 0, (int) (50 * 3.6), 16, TFT_NAVY);
wunderground.updateConditions(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY);
if (booted) drawProgress(70, "Updating forecasts...");
else fillSegment(22, 22, 0, (int) (70 * 3.6), 16, TFT_NAVY);
wunderground.updateForecast(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY);
if (booted) drawProgress(90, "Updating astronomy...");
else fillSegment(22, 22, 0, (int) (90 * 3.6), 16, TFT_NAVY);
wunderground.updateAstronomy(WUNDERGRROUND_API_KEY, WUNDERGRROUND_LANGUAGE, WUNDERGROUND_COUNTRY, WUNDERGROUND_CITY);
// lastUpdate = timeClient.getFormattedTime();
// readyForWeatherUpdate = false;
if (booted) drawProgress(100, "Done...");
else fillSegment(22, 22, 0, 360, 16, TFT_NAVY);
if (booted) delay(2000);
if (booted) tft.fillScreen(TFT_BLACK);
else fillSegment(22, 22, 0, 360, 22, TFT_BLACK);
//tft.fillScreen(TFT_CYAN); // For text padding and update graphics over-write checking only
drawTime();
drawCurrentWeather();
drawForecast();
drawAstronomy();
//if (booted) screenshotToConsole(); // No supporting function in this sketch, documentation support only!
booted = false;
}
// Progress bar helper
void drawProgress(uint8_t percentage, String text) {
tft.setFreeFont(&ArialRoundedMTBold_14);
tft.setTextDatum(BC_DATUM);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.setTextPadding(240);
tft.drawString(text, 120, 220);
ui.drawProgressBar(10, 225, 240 - 20, 15, percentage, TFT_WHITE, TFT_BLUE);
tft.setTextPadding(0);
}
// draws the clock
void drawTime() {
tft.setFreeFont(&ArialRoundedMTBold_14);
String date = wunderground.getDate();
tft.setTextDatum(BC_DATUM);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextPadding(tft.textWidth(" Ddd, 44 Mmm 4444 ")); // String width + margin
tft.drawString(date, 120, 14);
tft.setFreeFont(&ArialRoundedMTBold_36);
String timeNow = timeClient.getHours() + ":" + timeClient.getMinutes();
tft.setTextDatum(BC_DATUM);
tft.setTextColor(TFT_YELLOW, TFT_BLACK);
tft.setTextPadding(tft.textWidth(" 44:44 ")); // String width + margin
tft.drawString(timeNow, 120, 50);
drawSeparator(52);
tft.setTextPadding(0);
}
// draws current weather information
void drawCurrentWeather() {
// Weather Icon
String weatherIcon = getMeteoconIcon(wunderground.getTodayIcon());
//uint32_t dt = millis();
ui.drawBmp(weatherIcon + ".bmp", 0, 59);
//Serial.print("Icon draw time = "); Serial.println(millis()-dt);
// Weather Text
String weatherText = wunderground.getWeatherText();
//weatherText = "Heavy Thunderstorms with Small Hail"; // Test line splitting with longest(?) string
tft.setFreeFont(&ArialRoundedMTBold_14);
tft.setTextDatum(BR_DATUM);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
int splitPoint = 0;
int xpos = 230;
splitPoint = splitIndex(weatherText);
if (splitPoint > 16) xpos = 235;
tft.setTextPadding(tft.textWidth("Heavy Thunderstorms")); // Max anticipated string width
if (splitPoint) tft.drawString(weatherText.substring(0, splitPoint), xpos, 72);
tft.setTextPadding(tft.textWidth(" with Small Hail")); // Max anticipated string width + margin
tft.drawString(weatherText.substring(splitPoint), xpos, 87);
tft.setFreeFont(&ArialRoundedMTBold_36);
tft.setTextDatum(TR_DATUM);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
// Font ASCII code 96 (0x60) modified to make "`" a degree symbol
tft.setTextPadding(tft.textWidth("-88`")); // Max width of vales
weatherText = wunderground.getCurrentTemp();
if (weatherText.indexOf(".")) weatherText = weatherText.substring(0, weatherText.indexOf(".")); // Make it integer temperature
if (weatherText == "") weatherText = "?"; // Handle null return
tft.drawString(weatherText + "`", 221, 100);
tft.setFreeFont(&ArialRoundedMTBold_14);
tft.setTextDatum(TL_DATUM);
tft.setTextPadding(0);
if (IS_METRIC) tft.drawString("C ", 221, 100);
else tft.drawString("F ", 221, 100);
weatherText = wunderground.getWindDir() + " ";
weatherText += String((int)(wunderground.getWindSpeed().toInt() * WIND_SPEED_SCALING)) + WIND_SPEED_UNITS;
tft.setTextPadding(tft.textWidth("Variable 888 mph ")); // Max string length?
tft.drawString(weatherText, 114, 136);
weatherText = wunderground.getWindDir();
int windAngle = 0;
String compassCardinal = "";
switch (weatherText.length()) {
case 1:
compassCardinal = "N E S W "; // Not used, see default below
windAngle = 90 * compassCardinal.indexOf(weatherText) / 2;
break;
case 2:
compassCardinal = "NE SE SW NW";
windAngle = 45 + 90 * compassCardinal.indexOf(weatherText) / 3;
break;
case 3:
compassCardinal = "NNE ENE ESE SSE SSW WSW WNW NNW";
windAngle = 22 + 45 * compassCardinal.indexOf(weatherText) / 4; // 22 should be 22.5 but accuracy is not needed!
break;
default:
if (weatherText == "Variable") windAngle = -1;
else {
// v23456v23456v23456v23456 character ruler
compassCardinal = "North East South West"; // Possible strings
windAngle = 90 * compassCardinal.indexOf(weatherText) / 6;
}
break;
}
tft.fillCircle(128, 110, 23, TFT_BLACK); // Erase old plot, radius + 1 to delete stray pixels
tft.drawCircle(128, 110, 22, TFT_DARKGREY); // Outer ring - optional
if ( windAngle >= 0 ) fillSegment(128, 110, windAngle - 15, 30, 22, TFT_GREEN); // Might replace this with a bigger rotating arrow
tft.drawCircle(128, 110, 6, TFT_RED);
drawSeparator(153);
tft.setTextPadding(0); // Reset padding width to none
}
// draws the three forecast columns
void drawForecast() {
drawForecastDetail(10, 171, 0);
drawForecastDetail(95, 171, 2);
drawForecastDetail(180, 171, 4);
drawSeparator(171 + 69);
}
// helper for the forecast columns
void drawForecastDetail(uint16_t x, uint16_t y, uint8_t dayIndex) {
tft.setFreeFont(&ArialRoundedMTBold_14);
String day = wunderground.getForecastTitle(dayIndex).substring(0, 3);
day.toUpperCase();
tft.setTextDatum(BC_DATUM);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.setTextPadding(tft.textWidth("WWW"));
tft.drawString(day, x + 25, y);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextPadding(tft.textWidth("-88 -88"));
tft.drawString(wunderground.getForecastHighTemp(dayIndex) + " " + wunderground.getForecastLowTemp(dayIndex), x + 25, y + 14);
String weatherIcon = getMeteoconIcon(wunderground.getForecastIcon(dayIndex));
ui.drawBmp("/mini/" + weatherIcon + ".bmp", x, y + 15);
tft.setTextPadding(0); // Reset padding width to none
}
// draw moonphase and sunrise/set and moonrise/set
void drawAstronomy() {
tft.setFreeFont(&ArialRoundedMTBold_14);
tft.setTextDatum(BC_DATUM);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.setTextPadding(tft.textWidth(" Waxing Crescent "));
tft.drawString(wunderground.getMoonPhase(), 120, 260 - 2);
int moonAgeImage = 24 * wunderground.getMoonAge().toInt() / 30.0;
ui.drawBmp("/moon" + String(moonAgeImage) + ".bmp", 120 - 30, 260);
tft.setTextDatum(BC_DATUM);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.setTextPadding(0); // Reset padding width to none
tft.drawString("Sun", 40, 280);
tft.setTextDatum(BR_DATUM);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextPadding(tft.textWidth(" 88:88 "));
int dt = rightOffset(wunderground.getSunriseTime(), ":"); // Draw relative to colon to them aligned
tft.drawString(wunderground.getSunriseTime(), 40 + dt, 300);
dt = rightOffset(wunderground.getSunsetTime(), ":");
tft.drawString(wunderground.getSunsetTime(), 40 + dt, 315);
tft.setTextDatum(BC_DATUM);
tft.setTextColor(TFT_ORANGE, TFT_BLACK);
tft.setTextPadding(0); // Reset padding width to none
tft.drawString("Moon", 200, 280);
tft.setTextDatum(BR_DATUM);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextPadding(tft.textWidth(" 88:88 "));
dt = rightOffset(wunderground.getMoonriseTime(), ":"); // Draw relative to colon to them aligned
tft.drawString(wunderground.getMoonriseTime(), 200 + dt, 300);
dt = rightOffset(wunderground.getMoonsetTime(), ":");
tft.drawString(wunderground.getMoonsetTime(), 200 + dt, 315);
tft.setTextPadding(0); // Reset padding width to none
}
// Helper function, should be part of the weather station library and should disappear soon
String getMeteoconIcon(String iconText) {
if (iconText == "F") return "chanceflurries";
if (iconText == "Q") return "chancerain";
if (iconText == "W") return "chancesleet";
if (iconText == "V") return "chancesnow";
if (iconText == "S") return "chancetstorms";
if (iconText == "B") return "clear";
if (iconText == "Y") return "cloudy";
if (iconText == "F") return "flurries";
if (iconText == "M") return "fog";
if (iconText == "E") return "hazy";
if (iconText == "Y") return "mostlycloudy";
if (iconText == "H") return "mostlysunny";
if (iconText == "H") return "partlycloudy";
if (iconText == "J") return "partlysunny";
if (iconText == "W") return "sleet";
if (iconText == "R") return "rain";
if (iconText == "W") return "snow";
if (iconText == "B") return "sunny";
if (iconText == "0") return "tstorms";
return "unknown";
}
// if you want separators, uncomment the tft-line
void drawSeparator(uint16_t y) {
tft.drawFastHLine(10, y, 240 - 2 * 10, 0x4228);
}
// determine the "space" split point in a long string
int splitIndex(String text)
{
int index = 0;
while ( (text.indexOf(' ', index) >= 0) && ( index <= text.length() / 2 ) ) {
index = text.indexOf(' ', index) + 1;
}
if (index) index--;
return index;
}
// Calculate coord delta from start of text String to start of sub String contained within that text
// Can be used to vertically right align text so for example a colon ":" in the time value is always
// plotted at same point on the screen irrespective of different proportional character widths,
// could also be used to align decimal points for neat formatting
int rightOffset(String text, String sub)
{
int index = text.indexOf(sub);
return tft.textWidth(text.substring(index));
}
// Calculate coord delta from start of text String to start of sub String contained within that text
// Can be used to vertically left align text so for example a colon ":" in the time value is always
// plotted at same point on the screen irrespective of different proportional character widths,
// could also be used to align decimal points for neat formatting
int leftOffset(String text, String sub)
{
int index = text.indexOf(sub);
return tft.textWidth(text.substring(0, index));
}
// Draw a segment of a circle, centred on x,y with defined start_angle and subtended sub_angle
// Angles are defined in a clockwise direction with 0 at top
// Segment has radius r and it is plotted in defined colour
// Can be used for pie charts etc, in this sketch it is used for wind direction
#define DEG2RAD 0.0174532925 // Degrees to Radians conversion factor
#define INC 2 // Minimum segment subtended angle and plotting angle increment (in degrees)
void fillSegment(int x, int y, int start_angle, int sub_angle, int r, unsigned int colour)
{
// Calculate first pair of coordinates for segment start
float sx = cos((start_angle - 90) * DEG2RAD);
float sy = sin((start_angle - 90) * DEG2RAD);
uint16_t x1 = sx * r + x;
uint16_t y1 = sy * r + y;
// Draw colour blocks every INC degrees
for (int i = start_angle; i < start_angle + sub_angle; i += INC) {
// Calculate pair of coordinates for segment end
int x2 = cos((i + 1 - 90) * DEG2RAD) * r + x;
int y2 = sin((i + 1 - 90) * DEG2RAD) * r + y;
tft.fillTriangle(x1, y1, x2, y2, x, y, colour);
// Copy segment end to sgement start for next segment
x1 = x2;
y1 = y2;
}
}