Delete weather-station example

Because Weather Underground will no longer support free API's
This commit is contained in:
Bodmer 2019-01-22 19:09:18 +00:00
parent 054a824eb8
commit 0460ab64d2
9 changed files with 0 additions and 1712 deletions

View File

@ -1,224 +0,0 @@
/**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

@ -1,226 +0,0 @@
/**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 printed
// 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

@ -1,342 +0,0 @@
/**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.print(F("BMP format not recognised. File:"));
Serial.println(filename);
}
else
_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 edge
if (mcu_x + mcu_w <= max_x) win_w = mcu_w;
else win_w = min_w;
// check if the image block size needs to be changed for the bottom edge
if (mcu_y + mcu_h <= max_y) win_h = mcu_h;
else win_h = min_h;
// copy pixels into a contiguous block
if (win_w != mcu_w)
{
uint16_t *cImg;
int p = 0;
cImg = pImg + win_w;
for (int h = 1; h < win_h; h++)
{
p += mcu_w;
for (int w = 0; w < win_w; w++)
{
*cImg = *(pImg + w + p);
cImg++;
}
}
}
// 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())
{
_tft->pushImage(mcu_x, mcu_y, win_w, win_h, pImg);
}
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

@ -1,60 +0,0 @@
/**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

@ -1,42 +0,0 @@
/*====================================================================================
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

@ -1,105 +0,0 @@
/**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

@ -1,46 +0,0 @@
/**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

@ -1,72 +0,0 @@
/**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_eSPI
Version 9
*/
// ***************************************************************************************
// WARNING - READ THIS
//
// 3M Flash Size MUST be allocated to SPIFFS using the IDE Tools menu option or else the
// ESP8266 may crash or do strange things (due to lack of error checks in SPIFFS library?)
// ***************************************************************************************
//
// Setup
const int UPDATE_INTERVAL_SECS = 10 * 60; // Update every 10 minutes
// Pins for the TFT interface are defined in the User_Config.h file inside the TFT_eSPI library
// TimeClient settings
const float UTC_OFFSET = 1;
// Wunderground Settings, EDIT to suit your Wunderground key and 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 showing how the above line should look
// 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 = "Base_Naval"; // 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

@ -1,595 +0,0 @@
/**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 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
Barometric pressure added
*/
#define SERIAL_MESSAGES
#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() {
#ifdef SERIAL_MESSAGES
Serial.begin(250000);
#endif
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 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.setTextDatum(BC_DATUM);
tft.setTextPadding(240); // Pad next drawString() text to full width to over-write old text
tft.drawString(" ", 120, 200); // Clear line above using set padding width
tft.drawString("Fetching weather data...", 120, 200);
//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, 18, 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();
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_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, 53);
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, 16);
drawSeparator(54);
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);
//tft.drawString(wunderground.getPressure(), 180, 30);
weatherText = ""; //wunderground.getWindDir() + " ";
weatherText += String((int)(wunderground.getWindSpeed().toInt() * WIND_SPEED_SCALING)) + WIND_SPEED_UNITS;
tft.setTextDatum(TC_DATUM);
tft.setTextPadding(tft.textWidth(" 888 mph")); // Max string length?
tft.drawString(weatherText, 128, 136);
weatherText = wunderground.getPressure();
tft.setTextDatum(TR_DATUM);
tft.setTextPadding(tft.textWidth(" 8888mb")); // Max string length?
tft.drawString(weatherText, 230, 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.setTextDatum(TL_DATUM); // Reset datum to normal
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;
}
}