forked from btclock/btclock_v3
Use clang to make codestyle consistent
This commit is contained in:
parent
239415c7aa
commit
4aab02a040
31 changed files with 10588 additions and 10871 deletions
|
@ -1,482 +1,484 @@
|
||||||
|
#include <Adafruit_GFX.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
const uint8_t Antonio_SemiBold20pt7bBitmaps[] PROGMEM = {
|
const uint8_t Antonio_SemiBold20pt7bBitmaps[] PROGMEM = {
|
||||||
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x66, 0x66,
|
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x66, 0x66, 0x66,
|
||||||
0x66, 0x66, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7B, 0xDE, 0xF7,
|
0x66, 0x66, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x7B, 0xDE, 0xF7,
|
||||||
0x98, 0xC6, 0x00, 0x03, 0x8F, 0x01, 0xC7, 0x80, 0xE3, 0x80, 0xF1, 0xC0,
|
0x98, 0xC6, 0x00, 0x03, 0x8F, 0x01, 0xC7, 0x80, 0xE3, 0x80, 0xF1, 0xC0,
|
||||||
0x70, 0xE0, 0x38, 0x70, 0x1C, 0x78, 0x0E, 0x3C, 0x07, 0x1C, 0x07, 0x8E,
|
0x70, 0xE0, 0x38, 0x70, 0x1C, 0x78, 0x0E, 0x3C, 0x07, 0x1C, 0x07, 0x8E,
|
||||||
0x03, 0x87, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x38, 0xE0, 0x3C,
|
0x03, 0x87, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x38, 0xE0, 0x3C,
|
||||||
0x70, 0x1E, 0x38, 0x0E, 0x1C, 0x07, 0x0E, 0x03, 0x8F, 0x0F, 0xFF, 0xF7,
|
0x70, 0x1E, 0x38, 0x0E, 0x1C, 0x07, 0x0E, 0x03, 0x8F, 0x0F, 0xFF, 0xF7,
|
||||||
0xFF, 0xF8, 0xF1, 0xC0, 0x70, 0xE0, 0x38, 0x70, 0x1C, 0x78, 0x0E, 0x3C,
|
0xFF, 0xF8, 0xF1, 0xC0, 0x70, 0xE0, 0x38, 0x70, 0x1C, 0x78, 0x0E, 0x3C,
|
||||||
0x0F, 0x1C, 0x07, 0x8E, 0x03, 0x87, 0x01, 0xC3, 0x80, 0xE3, 0xC0, 0x71,
|
0x0F, 0x1C, 0x07, 0x8E, 0x03, 0x87, 0x01, 0xC3, 0x80, 0xE3, 0xC0, 0x71,
|
||||||
0xE0, 0x78, 0xE0, 0x00, 0x06, 0x00, 0x30, 0x01, 0x80, 0x0C, 0x00, 0x60,
|
0xE0, 0x78, 0xE0, 0x00, 0x06, 0x00, 0x30, 0x01, 0x80, 0x0C, 0x00, 0x60,
|
||||||
0x1F, 0xC1, 0xFF, 0x9F, 0xFC, 0xFB, 0xF7, 0x87, 0xBC, 0x3D, 0xE1, 0xEF,
|
0x1F, 0xC1, 0xFF, 0x9F, 0xFC, 0xFB, 0xF7, 0x87, 0xBC, 0x3D, 0xE1, 0xEF,
|
||||||
0x0F, 0x78, 0x7B, 0xE3, 0xDF, 0x00, 0x7C, 0x01, 0xF8, 0x0F, 0xE0, 0x3F,
|
0x0F, 0x78, 0x7B, 0xE3, 0xDF, 0x00, 0x7C, 0x01, 0xF8, 0x0F, 0xE0, 0x3F,
|
||||||
0x80, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x3E, 0xF0, 0xF7, 0x87, 0xFC, 0x3F,
|
0x80, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x3E, 0xF0, 0xF7, 0x87, 0xFC, 0x3F,
|
||||||
0xE1, 0xFF, 0x0F, 0xFC, 0x7B, 0xFF, 0xCF, 0xFE, 0x3F, 0xE0, 0xFE, 0x01,
|
0xE1, 0xFF, 0x0F, 0xFC, 0x7B, 0xFF, 0xCF, 0xFE, 0x3F, 0xE0, 0xFE, 0x01,
|
||||||
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0x1F, 0x80, 0x01, 0xC0,
|
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0x1F, 0x80, 0x01, 0xC0,
|
||||||
0x07, 0xFE, 0x00, 0x3C, 0x00, 0x7F, 0xE0, 0x03, 0xC0, 0x0F, 0x9F, 0x00,
|
0x07, 0xFE, 0x00, 0x3C, 0x00, 0x7F, 0xE0, 0x03, 0xC0, 0x0F, 0x9F, 0x00,
|
||||||
0x38, 0x00, 0xF0, 0xF0, 0x07, 0x80, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0xF0,
|
0x38, 0x00, 0xF0, 0xF0, 0x07, 0x80, 0x0F, 0x0F, 0x00, 0x70, 0x00, 0xF0,
|
||||||
0xF0, 0x0F, 0x00, 0x0F, 0x0F, 0x00, 0xF0, 0x00, 0xF0, 0xF0, 0x0E, 0x00,
|
0xF0, 0x0F, 0x00, 0x0F, 0x0F, 0x00, 0xF0, 0x00, 0xF0, 0xF0, 0x0E, 0x00,
|
||||||
0x0F, 0x0F, 0x01, 0xE0, 0x00, 0xF0, 0xF0, 0x1C, 0x00, 0x0F, 0x0F, 0x03,
|
0x0F, 0x0F, 0x01, 0xE0, 0x00, 0xF0, 0xF0, 0x1C, 0x00, 0x0F, 0x0F, 0x03,
|
||||||
0xC0, 0x60, 0xF0, 0xF0, 0x3C, 0x3F, 0xCF, 0x0F, 0x03, 0x87, 0xFE, 0xF0,
|
0xC0, 0x60, 0xF0, 0xF0, 0x3C, 0x3F, 0xCF, 0x0F, 0x03, 0x87, 0xFE, 0xF0,
|
||||||
0xF0, 0x78, 0xFF, 0xEF, 0x0F, 0x07, 0x8F, 0x0E, 0xF0, 0xF0, 0xF0, 0xF0,
|
0xF0, 0x78, 0xFF, 0xEF, 0x0F, 0x07, 0x8F, 0x0E, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||||
0xFF, 0x0F, 0x0F, 0x0E, 0x0F, 0xF0, 0xF0, 0xE0, 0xE0, 0xF7, 0xDF, 0x1E,
|
0xFF, 0x0F, 0x0F, 0x0E, 0x0F, 0xF0, 0xF0, 0xE0, 0xE0, 0xF7, 0xDF, 0x1E,
|
||||||
0x0E, 0x0F, 0x7F, 0xE1, 0xE0, 0xE0, 0xF3, 0xFC, 0x1C, 0x0E, 0x0F, 0x1F,
|
0x0E, 0x0F, 0x7F, 0xE1, 0xE0, 0xE0, 0xF3, 0xFC, 0x1C, 0x0E, 0x0F, 0x1F,
|
||||||
0x83, 0xC0, 0xE0, 0xF0, 0x00, 0x38, 0x0E, 0x0F, 0x00, 0x07, 0x80, 0xE0,
|
0x83, 0xC0, 0xE0, 0xF0, 0x00, 0x38, 0x0E, 0x0F, 0x00, 0x07, 0x80, 0xE0,
|
||||||
0xF0, 0x00, 0x78, 0x0E, 0x0F, 0x00, 0x07, 0x00, 0xE0, 0xF0, 0x00, 0xF0,
|
0xF0, 0x00, 0x78, 0x0E, 0x0F, 0x00, 0x07, 0x00, 0xE0, 0xF0, 0x00, 0xF0,
|
||||||
0x0E, 0x0F, 0x00, 0x0E, 0x00, 0xE0, 0xF0, 0x01, 0xE0, 0x0F, 0x0F, 0x00,
|
0x0E, 0x0F, 0x00, 0x0E, 0x00, 0xE0, 0xF0, 0x01, 0xE0, 0x0F, 0x0F, 0x00,
|
||||||
0x1E, 0x00, 0xF1, 0xE0, 0x01, 0xC0, 0x0F, 0xFE, 0x00, 0x3C, 0x00, 0x7F,
|
0x1E, 0x00, 0xF1, 0xE0, 0x01, 0xC0, 0x0F, 0xFE, 0x00, 0x3C, 0x00, 0x7F,
|
||||||
0xC0, 0x03, 0x80, 0x03, 0xF8, 0x03, 0xE0, 0x03, 0xFE, 0x00, 0xFF, 0x80,
|
0xC0, 0x03, 0x80, 0x03, 0xF8, 0x03, 0xE0, 0x03, 0xFE, 0x00, 0xFF, 0x80,
|
||||||
0x7C, 0xF0, 0x1E, 0x1C, 0x07, 0x87, 0x01, 0xE1, 0xC0, 0x78, 0x70, 0x1E,
|
0x7C, 0xF0, 0x1E, 0x1C, 0x07, 0x87, 0x01, 0xE1, 0xC0, 0x78, 0x70, 0x1E,
|
||||||
0x1C, 0x07, 0x8F, 0x00, 0xF3, 0x80, 0x3D, 0xE0, 0x0F, 0x78, 0x01, 0xFC,
|
0x1C, 0x07, 0x8F, 0x00, 0xF3, 0x80, 0x3D, 0xE0, 0x0F, 0x78, 0x01, 0xFC,
|
||||||
0x00, 0x7E, 0x00, 0x1F, 0x80, 0x07, 0xC0, 0x03, 0xF0, 0x00, 0xFE, 0x08,
|
0x00, 0x7E, 0x00, 0x1F, 0x80, 0x07, 0xC0, 0x03, 0xF0, 0x00, 0xFE, 0x08,
|
||||||
0x7F, 0x86, 0x3F, 0xE3, 0x8F, 0x3C, 0xF7, 0x8F, 0x79, 0xE1, 0xFC, 0x78,
|
0x7F, 0x86, 0x3F, 0xE3, 0x8F, 0x3C, 0xF7, 0x8F, 0x79, 0xE1, 0xFC, 0x78,
|
||||||
0x7F, 0x3C, 0x1F, 0x8F, 0x03, 0xE3, 0xC0, 0xF0, 0xF0, 0x3E, 0x1E, 0x1F,
|
0x7F, 0x3C, 0x1F, 0x8F, 0x03, 0xE3, 0xC0, 0xF0, 0xF0, 0x3E, 0x1E, 0x1F,
|
||||||
0x87, 0xFF, 0xF1, 0xFF, 0xFC, 0x3F, 0xE7, 0x87, 0xF1, 0xE0, 0xFF, 0xFF,
|
0x87, 0xFF, 0xF1, 0xFF, 0xFC, 0x3F, 0xE7, 0x87, 0xF1, 0xE0, 0xFF, 0xFF,
|
||||||
0xF7, 0x76, 0x66, 0x66, 0x3E, 0xFF, 0xFF, 0xCF, 0x1E, 0x3C, 0x78, 0xF1,
|
0xF7, 0x76, 0x66, 0x66, 0x3E, 0xFF, 0xFF, 0xCF, 0x1E, 0x3C, 0x78, 0xF1,
|
||||||
0xE3, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0x3C,
|
0xE3, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0x3C,
|
||||||
0x78, 0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xFB, 0xF7,
|
0x78, 0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xFB, 0xF7,
|
||||||
0xE1, 0xC0, 0xF1, 0xF3, 0xF1, 0xE3, 0xC7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9,
|
0xE1, 0xC0, 0xF1, 0xF3, 0xF1, 0xE3, 0xC7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9,
|
||||||
0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E,
|
0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E,
|
||||||
0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7B, 0xF7, 0xEF, 0x98, 0x00,
|
0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7B, 0xF7, 0xEF, 0x98, 0x00,
|
||||||
0x07, 0x00, 0x1C, 0x04, 0x71, 0x39, 0xCE, 0xFB, 0x7D, 0xFF, 0xC1, 0xFC,
|
0x07, 0x00, 0x1C, 0x04, 0x71, 0x39, 0xCE, 0xFB, 0x7D, 0xFF, 0xC1, 0xFC,
|
||||||
0x03, 0xE0, 0x3F, 0xE3, 0xEF, 0xFF, 0x73, 0x99, 0xC6, 0x07, 0x08, 0x1C,
|
0x03, 0xE0, 0x3F, 0xE3, 0xEF, 0xFF, 0x73, 0x99, 0xC6, 0x07, 0x08, 0x1C,
|
||||||
0x00, 0x70, 0x00, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,
|
0x00, 0x70, 0x00, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xF0, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xF0, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0xFF, 0xFF, 0xFF,
|
||||||
0x8C, 0xE7, 0x31, 0x9C, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x00,
|
0x8C, 0xE7, 0x31, 0x9C, 0xC0, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x00,
|
||||||
0xF8, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0E, 0x00, 0xF0, 0x07, 0x80, 0x3C,
|
0xF8, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0E, 0x00, 0xF0, 0x07, 0x80, 0x3C,
|
||||||
0x01, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x38, 0x03, 0xC0, 0x1E, 0x00,
|
0x01, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x38, 0x03, 0xC0, 0x1E, 0x00,
|
||||||
0xF0, 0x07, 0x80, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x0F, 0x00, 0x78,
|
0xF0, 0x07, 0x80, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x0F, 0x00, 0x78,
|
||||||
0x03, 0xC0, 0x1E, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x3C, 0x01,
|
0x03, 0xC0, 0x1E, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x3C, 0x01,
|
||||||
0xE0, 0x0F, 0x00, 0x78, 0x07, 0x80, 0x00, 0x0F, 0xC1, 0xFF, 0x9F, 0xFC,
|
0xE0, 0x0F, 0x00, 0x78, 0x07, 0x80, 0x00, 0x0F, 0xC1, 0xFF, 0x9F, 0xFC,
|
||||||
0xFF, 0xF7, 0x8F, 0xFC, 0x3F, 0xE1, 0xFF, 0x0F, 0xF8, 0x7F, 0xC3, 0xFE,
|
0xFF, 0xF7, 0x8F, 0xFC, 0x3F, 0xE1, 0xFF, 0x0F, 0xF8, 0x7F, 0xC3, 0xFE,
|
||||||
0x1F, 0xF0, 0xFF, 0x87, 0xFC, 0x3F, 0xE1, 0xFF, 0x0F, 0xF8, 0x7F, 0xC3,
|
0x1F, 0xF0, 0xFF, 0x87, 0xFC, 0x3F, 0xE1, 0xFF, 0x0F, 0xF8, 0x7F, 0xC3,
|
||||||
0xFE, 0x1F, 0xF0, 0xFF, 0x87, 0xFC, 0x3F, 0xE1, 0xFF, 0x0F, 0xF8, 0x7F,
|
0xFE, 0x1F, 0xF0, 0xFF, 0x87, 0xFC, 0x3F, 0xE1, 0xFF, 0x0F, 0xF8, 0x7F,
|
||||||
0xC3, 0xFE, 0x1F, 0xF0, 0xFF, 0x87, 0xBC, 0x7D, 0xF7, 0xEF, 0xFE, 0x3F,
|
0xC3, 0xFE, 0x1F, 0xF0, 0xFF, 0x87, 0xBC, 0x7D, 0xF7, 0xEF, 0xFE, 0x3F,
|
||||||
0xF0, 0xFF, 0x00, 0x03, 0x83, 0xC3, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F,
|
0xF0, 0xFF, 0x00, 0x03, 0x83, 0xC3, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F,
|
||||||
0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC3,
|
0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC3,
|
||||||
0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xF8,
|
0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xF8,
|
||||||
0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC0, 0x0F, 0x81, 0xFF, 0x1F, 0xF8, 0xFF,
|
0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC0, 0x0F, 0x81, 0xFF, 0x1F, 0xF8, 0xFF,
|
||||||
0xEF, 0x8F, 0x7C, 0x7B, 0xC3, 0xDE, 0x1E, 0xF0, 0xFF, 0x87, 0xFC, 0x3F,
|
0xEF, 0x8F, 0x7C, 0x7B, 0xC3, 0xDE, 0x1E, 0xF0, 0xFF, 0x87, 0xFC, 0x3F,
|
||||||
0xE1, 0xEF, 0x0F, 0x78, 0x78, 0x07, 0xC0, 0x3C, 0x03, 0xE0, 0x1E, 0x01,
|
0xE1, 0xEF, 0x0F, 0x78, 0x78, 0x07, 0xC0, 0x3C, 0x03, 0xE0, 0x1E, 0x01,
|
||||||
0xF0, 0x0F, 0x00, 0xF8, 0x07, 0x80, 0x7C, 0x07, 0xC0, 0x3E, 0x03, 0xE0,
|
0xF0, 0x0F, 0x00, 0xF8, 0x07, 0x80, 0x7C, 0x07, 0xC0, 0x3E, 0x03, 0xE0,
|
||||||
0x1F, 0x00, 0xF0, 0x07, 0x80, 0x7C, 0x03, 0xE0, 0x1F, 0xFE, 0xFF, 0xF7,
|
0x1F, 0x00, 0xF0, 0x07, 0x80, 0x7C, 0x03, 0xE0, 0x1F, 0xFE, 0xFF, 0xF7,
|
||||||
0xFF, 0x80, 0x0F, 0xC0, 0xFF, 0x87, 0xFF, 0x1F, 0xFE, 0x78, 0xFB, 0xE1,
|
0xFF, 0x80, 0x0F, 0xC0, 0xFF, 0x87, 0xFF, 0x1F, 0xFE, 0x78, 0xFB, 0xE1,
|
||||||
0xEF, 0x87, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1, 0xE0, 0x07, 0x80, 0x1E, 0x00,
|
0xEF, 0x87, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1, 0xE0, 0x07, 0x80, 0x1E, 0x00,
|
||||||
0x78, 0x03, 0xE0, 0x3F, 0x01, 0xF8, 0x07, 0xE0, 0x1F, 0xC0, 0x0F, 0x00,
|
0x78, 0x03, 0xE0, 0x3F, 0x01, 0xF8, 0x07, 0xE0, 0x1F, 0xC0, 0x0F, 0x00,
|
||||||
0x3E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0xBC, 0x1E, 0xF0, 0x7F, 0xC1, 0xFF,
|
0x3E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0xBC, 0x1E, 0xF0, 0x7F, 0xC1, 0xFF,
|
||||||
0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xE1, 0xE7, 0xDF, 0x9F, 0xFC, 0x3F, 0xE0,
|
0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xE1, 0xE7, 0xDF, 0x9F, 0xFC, 0x3F, 0xE0,
|
||||||
0x7F, 0x00, 0x01, 0xF0, 0x07, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x1F,
|
0x7F, 0x00, 0x01, 0xF0, 0x07, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x1F,
|
||||||
0xC0, 0x7F, 0x01, 0xFC, 0x06, 0xF0, 0x3B, 0xC0, 0xEF, 0x03, 0xBC, 0x1C,
|
0xC0, 0x7F, 0x01, 0xFC, 0x06, 0xF0, 0x3B, 0xC0, 0xEF, 0x03, 0xBC, 0x1C,
|
||||||
0xF0, 0x73, 0xC1, 0xCF, 0x0F, 0x3C, 0x38, 0xF0, 0xE3, 0xC7, 0x8F, 0x1C,
|
0xF0, 0x73, 0xC1, 0xCF, 0x0F, 0x3C, 0x38, 0xF0, 0xE3, 0xC7, 0x8F, 0x1C,
|
||||||
0x3C, 0x70, 0xF1, 0xC3, 0xCF, 0x0F, 0x38, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF,
|
0x3C, 0x70, 0xF1, 0xC3, 0xCF, 0x0F, 0x38, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0,
|
0xFF, 0xFF, 0xFF, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0,
|
||||||
0x03, 0xC0, 0xFF, 0xEF, 0xFE, 0xFF, 0xEF, 0xFE, 0xF0, 0x0F, 0x00, 0xF0,
|
0x03, 0xC0, 0xFF, 0xEF, 0xFE, 0xFF, 0xEF, 0xFE, 0xF0, 0x0F, 0x00, 0xF0,
|
||||||
0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF3, 0x0F, 0xFC, 0xFF, 0xEF, 0xFE, 0xF9,
|
0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF3, 0x0F, 0xFC, 0xFF, 0xEF, 0xFE, 0xF9,
|
||||||
0xEF, 0x1F, 0xF0, 0xF1, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00,
|
0xEF, 0x1F, 0xF0, 0xF1, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00,
|
||||||
0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x1F, 0xFB,
|
0xF0, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x1F, 0xFB,
|
||||||
0xEF, 0xFE, 0x7F, 0xC3, 0xF8, 0x0F, 0xC0, 0xFF, 0x83, 0xFF, 0x1F, 0xFC,
|
0xEF, 0xFE, 0x7F, 0xC3, 0xF8, 0x0F, 0xC0, 0xFF, 0x83, 0xFF, 0x1F, 0xFC,
|
||||||
0x78, 0xF9, 0xE1, 0xEF, 0x87, 0xBE, 0x1E, 0xF8, 0x7B, 0xE1, 0xEF, 0x80,
|
0x78, 0xF9, 0xE1, 0xEF, 0x87, 0xBE, 0x1E, 0xF8, 0x7B, 0xE1, 0xEF, 0x80,
|
||||||
0x3E, 0x00, 0xF8, 0x03, 0xEF, 0x8F, 0xFF, 0x3F, 0xFE, 0xFF, 0xFB, 0xE1,
|
0x3E, 0x00, 0xF8, 0x03, 0xEF, 0x8F, 0xFF, 0x3F, 0xFE, 0xFF, 0xFB, 0xE1,
|
||||||
0xEF, 0x87, 0xBE, 0x1E, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8,
|
0xEF, 0x87, 0xBE, 0x1E, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8,
|
||||||
0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x79, 0xE1, 0xE7, 0xFF, 0x9F,
|
0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x79, 0xE1, 0xE7, 0xFF, 0x9F,
|
||||||
0xFE, 0x3F, 0xF0, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0xFE, 0x3F, 0xF0, 0x7F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0x00, 0x7C, 0x01, 0xE0, 0x0F, 0x80, 0x3C, 0x00, 0xF0, 0x07, 0xC0, 0x1E,
|
0x00, 0x7C, 0x01, 0xE0, 0x0F, 0x80, 0x3C, 0x00, 0xF0, 0x07, 0xC0, 0x1E,
|
||||||
0x00, 0x78, 0x03, 0xE0, 0x0F, 0x80, 0x3C, 0x00, 0xF0, 0x07, 0xC0, 0x1E,
|
0x00, 0x78, 0x03, 0xE0, 0x0F, 0x80, 0x3C, 0x00, 0xF0, 0x07, 0xC0, 0x1E,
|
||||||
0x00, 0x78, 0x03, 0xE0, 0x0F, 0x80, 0x3C, 0x00, 0xF0, 0x07, 0xC0, 0x1F,
|
0x00, 0x78, 0x03, 0xE0, 0x0F, 0x80, 0x3C, 0x00, 0xF0, 0x07, 0xC0, 0x1F,
|
||||||
0x00, 0x7C, 0x01, 0xF0, 0x07, 0x80, 0x1E, 0x00, 0xF8, 0x03, 0xE0, 0x0F,
|
0x00, 0x7C, 0x01, 0xF0, 0x07, 0x80, 0x1E, 0x00, 0xF8, 0x03, 0xE0, 0x0F,
|
||||||
0x80, 0x3E, 0x00, 0xF8, 0x00, 0x1F, 0xC1, 0xFF, 0x1F, 0xFC, 0xFB, 0xFF,
|
0x80, 0x3E, 0x00, 0xF8, 0x00, 0x1F, 0xC1, 0xFF, 0x1F, 0xFC, 0xFB, 0xFF,
|
||||||
0x8F, 0xFC, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0,
|
0x8F, 0xFC, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0,
|
||||||
0xFF, 0x87, 0xBC, 0x79, 0xFF, 0xC7, 0xFC, 0x3F, 0xE3, 0xFF, 0x9E, 0x3D,
|
0xFF, 0x87, 0xBC, 0x79, 0xFF, 0xC7, 0xFC, 0x3F, 0xE3, 0xFF, 0x9E, 0x3D,
|
||||||
0xF1, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC,
|
0xF1, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC,
|
||||||
0x1F, 0xE0, 0xFF, 0x07, 0xFC, 0x3F, 0xF7, 0xEF, 0xFE, 0x3F, 0xF0, 0xFE,
|
0x1F, 0xE0, 0xFF, 0x07, 0xFC, 0x3F, 0xF7, 0xEF, 0xFE, 0x3F, 0xF0, 0xFE,
|
||||||
0x00, 0x1F, 0x81, 0xFF, 0x1F, 0xFD, 0xFF, 0xEF, 0x8F, 0x78, 0x7F, 0xC3,
|
0x00, 0x1F, 0x81, 0xFF, 0x1F, 0xFD, 0xFF, 0xEF, 0x8F, 0x78, 0x7F, 0xC3,
|
||||||
0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F,
|
0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F,
|
||||||
0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0xC7, 0xDF, 0xFE, 0xFF, 0xF3, 0xFF, 0x80,
|
0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0xC7, 0xDF, 0xFE, 0xFF, 0xF3, 0xFF, 0x80,
|
||||||
0x3C, 0x01, 0xE0, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x0F,
|
0x3C, 0x01, 0xE0, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x0F,
|
||||||
0xFC, 0x79, 0xF7, 0xCF, 0xFE, 0x3F, 0xE0, 0xFE, 0x00, 0xFF, 0xFF, 0xF0,
|
0xFC, 0x79, 0xF7, 0xCF, 0xFE, 0x3F, 0xE0, 0xFE, 0x00, 0xFF, 0xFF, 0xF0,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF3, 0x9C, 0xCE, 0x73, 0x98,
|
0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xFF, 0xF3, 0x9C, 0xCE, 0x73, 0x98,
|
||||||
0x00, 0x20, 0x0C, 0x07, 0x81, 0xF0, 0xFE, 0x3F, 0x9F, 0xC7, 0xF0, 0xF8,
|
0x00, 0x20, 0x0C, 0x07, 0x81, 0xF0, 0xFE, 0x3F, 0x9F, 0xC7, 0xF0, 0xF8,
|
||||||
0x1C, 0x03, 0xE0, 0x7E, 0x07, 0xF0, 0x3F, 0x03, 0xF8, 0x1F, 0x01, 0xE0,
|
0x1C, 0x03, 0xE0, 0x7E, 0x07, 0xF0, 0x3F, 0x03, 0xF8, 0x1F, 0x01, 0xE0,
|
||||||
0x0C, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x0F, 0xFF,
|
0x0C, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x0F, 0xFF,
|
||||||
0xFF, 0xFF, 0xC0, 0x80, 0x18, 0x03, 0x80, 0x7C, 0x0F, 0xC0, 0xFE, 0x07,
|
0xFF, 0xFF, 0xC0, 0x80, 0x18, 0x03, 0x80, 0x7C, 0x0F, 0xC0, 0xFE, 0x07,
|
||||||
0xF0, 0x7F, 0x03, 0xE0, 0x3C, 0x0F, 0x83, 0xF1, 0xFC, 0xFE, 0x3F, 0x87,
|
0xF0, 0x7F, 0x03, 0xE0, 0x3C, 0x0F, 0x83, 0xF1, 0xFC, 0xFE, 0x3F, 0x87,
|
||||||
0xC0, 0xF0, 0x18, 0x02, 0x00, 0x00, 0x1F, 0x87, 0xFC, 0x7F, 0xEF, 0xFE,
|
0xC0, 0xF0, 0x18, 0x02, 0x00, 0x00, 0x1F, 0x87, 0xFC, 0x7F, 0xEF, 0xFE,
|
||||||
0xF1, 0xEF, 0x1F, 0xF1, 0xFF, 0x1F, 0xF1, 0xFF, 0x1F, 0xF1, 0xFF, 0x1F,
|
0xF1, 0xEF, 0x1F, 0xF1, 0xFF, 0x1F, 0xF1, 0xFF, 0x1F, 0xF1, 0xFF, 0x1F,
|
||||||
0x01, 0xF0, 0x1E, 0x01, 0xE0, 0x3E, 0x03, 0xE0, 0xFC, 0x3F, 0x83, 0xF0,
|
0x01, 0xF0, 0x1E, 0x01, 0xE0, 0x3E, 0x03, 0xE0, 0xFC, 0x3F, 0x83, 0xF0,
|
||||||
0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x00, 0x3F, 0x80,
|
0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x00, 0x3F, 0x80,
|
||||||
0x00, 0xFF, 0xF0, 0x00, 0xFF, 0xFC, 0x00, 0xF8, 0x0F, 0x00, 0xF0, 0x03,
|
0x00, 0xFF, 0xF0, 0x00, 0xFF, 0xFC, 0x00, 0xF8, 0x0F, 0x00, 0xF0, 0x03,
|
||||||
0xC0, 0xF0, 0x00, 0xF0, 0xF0, 0x00, 0x38, 0x78, 0x00, 0x1C, 0x38, 0x1F,
|
0xC0, 0xF0, 0x00, 0xF0, 0xF0, 0x00, 0x38, 0x78, 0x00, 0x1C, 0x38, 0x1F,
|
||||||
0x87, 0x3C, 0x3F, 0xE3, 0x9E, 0x1E, 0xF1, 0xCE, 0x1C, 0x38, 0xE7, 0x0E,
|
0x87, 0x3C, 0x3F, 0xE3, 0x9E, 0x1E, 0xF1, 0xCE, 0x1C, 0x38, 0xE7, 0x0E,
|
||||||
0x1C, 0x77, 0x8E, 0x0E, 0x1F, 0xC7, 0x07, 0x0F, 0xE3, 0x83, 0x87, 0xF1,
|
0x1C, 0x77, 0x8E, 0x0E, 0x1F, 0xC7, 0x07, 0x0F, 0xE3, 0x83, 0x87, 0xF1,
|
||||||
0xC1, 0xC3, 0xF8, 0xE0, 0xE1, 0xFC, 0x70, 0x70, 0xFE, 0x38, 0x38, 0x7F,
|
0xC1, 0xC3, 0xF8, 0xE0, 0xE1, 0xFC, 0x70, 0x70, 0xFE, 0x38, 0x38, 0x7F,
|
||||||
0x1C, 0x1C, 0x77, 0x8E, 0x0E, 0x39, 0xC7, 0x07, 0x1C, 0xE3, 0xC7, 0xCE,
|
0x1C, 0x1C, 0x77, 0x8E, 0x0E, 0x39, 0xC7, 0x07, 0x1C, 0xE3, 0xC7, 0xCE,
|
||||||
0x70, 0xF6, 0xFE, 0x3C, 0x7F, 0x3F, 0x1E, 0x1F, 0x0F, 0x07, 0x81, 0x00,
|
0x70, 0xF6, 0xFE, 0x3C, 0x7F, 0x3F, 0x1E, 0x1F, 0x0F, 0x07, 0x81, 0x00,
|
||||||
0x03, 0xC0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1F, 0x80,
|
0x03, 0xC0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x1F, 0x80,
|
||||||
0x70, 0x07, 0xFF, 0xF8, 0x00, 0xFF, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0x07,
|
0x70, 0x07, 0xFF, 0xF8, 0x00, 0xFF, 0xFE, 0x00, 0x1F, 0xF0, 0x00, 0x07,
|
||||||
0xC0, 0x07, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F,
|
0xC0, 0x07, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F,
|
||||||
0xE0, 0x0F, 0xF0, 0x0E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E,
|
0xE0, 0x0F, 0xF0, 0x0E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E,
|
||||||
0xF0, 0x1E, 0x70, 0x1E, 0x78, 0x1C, 0x78, 0x3C, 0x78, 0x3C, 0x78, 0x3C,
|
0xF0, 0x1E, 0x70, 0x1E, 0x78, 0x1C, 0x78, 0x3C, 0x78, 0x3C, 0x78, 0x3C,
|
||||||
0x78, 0x3C, 0x78, 0x3C, 0x3C, 0x3C, 0x3C, 0x7C, 0x3C, 0x78, 0x3C, 0x7F,
|
0x78, 0x3C, 0x78, 0x3C, 0x3C, 0x3C, 0x3C, 0x7C, 0x3C, 0x78, 0x3C, 0x7F,
|
||||||
0xFC, 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFE, 0x78, 0x1E, 0xF8, 0x1E, 0xF8,
|
0xFC, 0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFE, 0x78, 0x1E, 0xF8, 0x1E, 0xF8,
|
||||||
0x1E, 0xF0, 0x1E, 0xF0, 0x1F, 0xF0, 0x1F, 0xFF, 0x03, 0xFF, 0x8F, 0xFF,
|
0x1E, 0xF0, 0x1E, 0xF0, 0x1F, 0xF0, 0x1F, 0xFF, 0x03, 0xFF, 0x8F, 0xFF,
|
||||||
0x3F, 0xFC, 0xF0, 0xFB, 0xC3, 0xEF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1,
|
0x3F, 0xFC, 0xF0, 0xFB, 0xC3, 0xEF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1,
|
||||||
0xEF, 0x07, 0xBC, 0x3E, 0xF0, 0xFB, 0xC3, 0xCF, 0xFF, 0x3F, 0xF8, 0xFF,
|
0xEF, 0x07, 0xBC, 0x3E, 0xF0, 0xFB, 0xC3, 0xCF, 0xFF, 0x3F, 0xF8, 0xFF,
|
||||||
0xF3, 0xFF, 0xCF, 0x0F, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1, 0xEF, 0x07, 0xFC,
|
0xF3, 0xFF, 0xCF, 0x0F, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1, 0xEF, 0x07, 0xFC,
|
||||||
0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC3, 0xEF,
|
0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC3, 0xEF,
|
||||||
0xFF, 0xBF, 0xFC, 0xFF, 0xE3, 0xFF, 0x00, 0x0F, 0xC0, 0x7F, 0xC3, 0xFF,
|
0xFF, 0xBF, 0xFC, 0xFF, 0xE3, 0xFF, 0x00, 0x0F, 0xC0, 0x7F, 0xC3, 0xFF,
|
||||||
0x9F, 0xFE, 0x7C, 0x79, 0xE1, 0xFF, 0x87, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0,
|
0x9F, 0xFE, 0x7C, 0x79, 0xE1, 0xFF, 0x87, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0,
|
||||||
0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8,
|
0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8,
|
||||||
0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE,
|
0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE,
|
||||||
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x1F, 0x78, 0x7D, 0xE1, 0xE7,
|
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x1F, 0x78, 0x7D, 0xE1, 0xE7,
|
||||||
0xEF, 0x8F, 0xFE, 0x3F, 0xF0, 0x3F, 0x80, 0xFF, 0x07, 0xFF, 0x3F, 0xFD,
|
0xEF, 0x8F, 0xFE, 0x3F, 0xF0, 0x3F, 0x80, 0xFF, 0x07, 0xFF, 0x3F, 0xFD,
|
||||||
0xFF, 0xEF, 0x0F, 0xF8, 0x7F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC,
|
0xFF, 0xEF, 0x0F, 0xF8, 0x7F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC,
|
||||||
0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83,
|
0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83,
|
||||||
0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F,
|
0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F,
|
||||||
0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x7F, 0xFF, 0xDF, 0xFE, 0xFF,
|
0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x7F, 0xFF, 0xDF, 0xFE, 0xFF,
|
||||||
0xE7, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x0F, 0x03,
|
0xE7, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x0F, 0x03,
|
||||||
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xFF, 0xFF,
|
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F,
|
0xFF, 0xFF, 0xFF, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F,
|
||||||
0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF,
|
0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
|
0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
|
||||||
0xC0, 0xF0, 0x3C, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xF0,
|
0xC0, 0xF0, 0x3C, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0xF0,
|
||||||
0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F,
|
0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F,
|
||||||
0x03, 0xC0, 0xF0, 0x3C, 0x00, 0x0F, 0xE0, 0x7F, 0xC3, 0xFF, 0x9F, 0xFE,
|
0x03, 0xC0, 0xF0, 0x3C, 0x00, 0x0F, 0xE0, 0x7F, 0xC3, 0xFF, 0x9F, 0xFE,
|
||||||
0x7C, 0x7D, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83,
|
0x7C, 0x7D, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83,
|
||||||
0xFE, 0x0F, 0xF8, 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF9, 0xFF, 0xE7,
|
0xFE, 0x0F, 0xF8, 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0xF9, 0xFF, 0xE7,
|
||||||
0xFF, 0x9F, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8,
|
0xFF, 0x9F, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8,
|
||||||
0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0x78, 0x3D, 0xE1, 0xF7, 0xEF, 0xCF,
|
0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0x78, 0x3D, 0xE1, 0xF7, 0xEF, 0xCF,
|
||||||
0xFF, 0x3F, 0xEC, 0x3F, 0x30, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F,
|
0xFF, 0x3F, 0xEC, 0x3F, 0x30, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F,
|
||||||
0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07,
|
0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07,
|
||||||
0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0,
|
0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0,
|
||||||
0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC,
|
0x7F, 0xC1, 0xFF, 0x07, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x07, 0xFC,
|
||||||
0x1F, 0xF0, 0x7F, 0xC1, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0x1F, 0xF0, 0x7F, 0xC1, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF8,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xF8,
|
||||||
0x07, 0xC0, 0x3E, 0x01, 0xF0, 0x0F, 0x80, 0x7C, 0x03, 0xE0, 0x1F, 0x00,
|
0x07, 0xC0, 0x3E, 0x01, 0xF0, 0x0F, 0x80, 0x7C, 0x03, 0xE0, 0x1F, 0x00,
|
||||||
0xF8, 0x07, 0xC0, 0x3E, 0x01, 0xF0, 0x0F, 0x80, 0x7C, 0x03, 0xE0, 0x1F,
|
0xF8, 0x07, 0xC0, 0x3E, 0x01, 0xF0, 0x0F, 0x80, 0x7C, 0x03, 0xE0, 0x1F,
|
||||||
0x00, 0xF8, 0x07, 0xC0, 0x3E, 0x01, 0xF0, 0x0F, 0xF8, 0x7F, 0xC3, 0xFE,
|
0x00, 0xF8, 0x07, 0xC0, 0x3E, 0x01, 0xF0, 0x0F, 0xF8, 0x7F, 0xC3, 0xFE,
|
||||||
0x1F, 0xF0, 0xFF, 0x87, 0xFC, 0x3F, 0xE1, 0xEF, 0x0F, 0x78, 0x7B, 0xF7,
|
0x1F, 0xF0, 0xFF, 0x87, 0xFC, 0x3F, 0xE1, 0xEF, 0x0F, 0x78, 0x7B, 0xF7,
|
||||||
0xCF, 0xFC, 0x7F, 0xE1, 0xFE, 0x00, 0xF0, 0x3D, 0xE0, 0xFB, 0xC1, 0xE7,
|
0xCF, 0xFC, 0x7F, 0xE1, 0xFE, 0x00, 0xF0, 0x3D, 0xE0, 0xFB, 0xC1, 0xE7,
|
||||||
0x83, 0xCF, 0x0F, 0x9E, 0x1E, 0x3C, 0x3C, 0x78, 0xF8, 0xF1, 0xE1, 0xE7,
|
0x83, 0xCF, 0x0F, 0x9E, 0x1E, 0x3C, 0x3C, 0x78, 0xF8, 0xF1, 0xE1, 0xE7,
|
||||||
0xC3, 0xCF, 0x87, 0x9E, 0x0F, 0x7C, 0x1E, 0xF8, 0x3D, 0xE0, 0x7F, 0xC0,
|
0xC3, 0xCF, 0x87, 0x9E, 0x0F, 0x7C, 0x1E, 0xF8, 0x3D, 0xE0, 0x7F, 0xC0,
|
||||||
0xFF, 0x01, 0xFE, 0x03, 0xFE, 0x07, 0xBC, 0x0F, 0x7C, 0x1E, 0xF8, 0x3C,
|
0xFF, 0x01, 0xFE, 0x03, 0xFE, 0x07, 0xBC, 0x0F, 0x7C, 0x1E, 0xF8, 0x3C,
|
||||||
0xF0, 0x79, 0xF0, 0xF1, 0xE1, 0xE3, 0xC3, 0xC7, 0xC7, 0x87, 0x8F, 0x0F,
|
0xF0, 0x79, 0xF0, 0xF1, 0xE1, 0xE3, 0xC3, 0xC7, 0xC7, 0x87, 0x8F, 0x0F,
|
||||||
0x9E, 0x1F, 0x3C, 0x1E, 0x78, 0x3E, 0xF0, 0x7D, 0xE0, 0x7C, 0xF0, 0x3C,
|
0x9E, 0x1F, 0x3C, 0x1E, 0x78, 0x3E, 0xF0, 0x7D, 0xE0, 0x7C, 0xF0, 0x3C,
|
||||||
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
|
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
|
||||||
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0,
|
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0,
|
||||||
0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F,
|
0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x03,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x03,
|
||||||
0xFF, 0xC0, 0x3F, 0xFC, 0x03, 0xFF, 0xC0, 0x3F, 0xFC, 0x03, 0xFF, 0xC0,
|
0xFF, 0xC0, 0x3F, 0xFC, 0x03, 0xFF, 0xC0, 0x3F, 0xFC, 0x03, 0xFF, 0xC0,
|
||||||
0x7F, 0xFE, 0x07, 0xFF, 0xE0, 0x7F, 0xFE, 0x07, 0xFE, 0xE0, 0x7F, 0xEE,
|
0x7F, 0xFE, 0x07, 0xFF, 0xE0, 0x7F, 0xFE, 0x07, 0xFE, 0xE0, 0x7F, 0xEE,
|
||||||
0x0F, 0xFE, 0xF0, 0xFF, 0xEF, 0x0E, 0xFE, 0x70, 0xEF, 0xE7, 0x0E, 0xFE,
|
0x0F, 0xFE, 0xF0, 0xFF, 0xEF, 0x0E, 0xFE, 0x70, 0xEF, 0xE7, 0x0E, 0xFE,
|
||||||
0x70, 0xEF, 0xE7, 0x1E, 0xFE, 0x79, 0xCF, 0xE3, 0x9C, 0xFF, 0x39, 0xCF,
|
0x70, 0xEF, 0xE7, 0x1E, 0xFE, 0x79, 0xCF, 0xE3, 0x9C, 0xFF, 0x39, 0xCF,
|
||||||
0xF3, 0x9C, 0xFF, 0x3B, 0xCF, 0xF3, 0xF8, 0xFF, 0x1F, 0x8F, 0xF1, 0xF8,
|
0xF3, 0x9C, 0xFF, 0x3B, 0xCF, 0xF3, 0xF8, 0xFF, 0x1F, 0x8F, 0xF1, 0xF8,
|
||||||
0xFF, 0x1F, 0x8F, 0xF1, 0xF8, 0xFF, 0x1F, 0x8F, 0xF0, 0xF0, 0xFF, 0x0F,
|
0xFF, 0x1F, 0x8F, 0xF1, 0xF8, 0xFF, 0x1F, 0x8F, 0xF0, 0xF0, 0xFF, 0x0F,
|
||||||
0x0F, 0xF0, 0xF0, 0xFF, 0x0F, 0x0F, 0xE0, 0x3F, 0x80, 0xFF, 0x03, 0xFC,
|
0x0F, 0xF0, 0xF0, 0xFF, 0x0F, 0x0F, 0xE0, 0x3F, 0x80, 0xFF, 0x03, 0xFC,
|
||||||
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFF, 0x0F, 0xFC, 0x3F, 0xF0, 0xFF,
|
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFF, 0x0F, 0xFC, 0x3F, 0xF0, 0xFF,
|
||||||
0xE3, 0xFF, 0x8F, 0xFE, 0x3F, 0xFC, 0xFF, 0xF3, 0xFD, 0xCF, 0xF7, 0xBF,
|
0xE3, 0xFF, 0x8F, 0xFE, 0x3F, 0xFC, 0xFF, 0xF3, 0xFD, 0xCF, 0xF7, 0xBF,
|
||||||
0xDE, 0xFF, 0x3B, 0xFC, 0xFF, 0xF3, 0xDF, 0xC7, 0x7F, 0x1F, 0xFC, 0x7F,
|
0xDE, 0xFF, 0x3B, 0xFC, 0xFF, 0xF3, 0xDF, 0xC7, 0x7F, 0x1F, 0xFC, 0x7F,
|
||||||
0xF0, 0xFF, 0xC3, 0xFF, 0x0F, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x03,
|
0xF0, 0xFF, 0xC3, 0xFF, 0x0F, 0xFC, 0x1F, 0xF0, 0x7F, 0xC1, 0xFF, 0x03,
|
||||||
0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0x70, 0x0F, 0xE0, 0x7F, 0xC3, 0xFF, 0x9F,
|
0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0x70, 0x0F, 0xE0, 0x7F, 0xC3, 0xFF, 0x9F,
|
||||||
0xFE, 0x7C, 0x7D, 0xE1, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF,
|
0xFE, 0x7C, 0x7D, 0xE1, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF,
|
||||||
0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F,
|
0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F,
|
||||||
0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F,
|
0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F,
|
||||||
0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0x78, 0x7D, 0xE1, 0xF7, 0xFF,
|
0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0x78, 0x7D, 0xE1, 0xF7, 0xFF,
|
||||||
0x8F, 0xFE, 0x3F, 0xF0, 0x3F, 0x80, 0xFF, 0x87, 0xFF, 0x3F, 0xFD, 0xFF,
|
0x8F, 0xFE, 0x3F, 0xF0, 0x3F, 0x80, 0xFF, 0x87, 0xFF, 0x3F, 0xFD, 0xFF,
|
||||||
0xEF, 0x0F, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F,
|
0xEF, 0x0F, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F,
|
||||||
0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x1F, 0xF0, 0xFF, 0xFF, 0xBF,
|
0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x1F, 0xF0, 0xFF, 0xFF, 0xBF,
|
||||||
0xFD, 0xFF, 0xCF, 0xF8, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80,
|
0xFD, 0xFF, 0xCF, 0xF8, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80,
|
||||||
0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07,
|
0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07,
|
||||||
0x80, 0x00, 0x0F, 0xE0, 0x7F, 0xC3, 0xFF, 0x9F, 0xFE, 0x7C, 0x7D, 0xE1,
|
0x80, 0x00, 0x0F, 0xE0, 0x7F, 0xC3, 0xFF, 0x9F, 0xFE, 0x7C, 0x7D, 0xE1,
|
||||||
0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8,
|
0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8,
|
||||||
0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE,
|
0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE,
|
||||||
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF,
|
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF,
|
||||||
0x83, 0xFE, 0x0F, 0x78, 0x7D, 0xE1, 0xF7, 0xFF, 0x8F, 0xFE, 0x3F, 0xF0,
|
0x83, 0xFE, 0x0F, 0x78, 0x7D, 0xE1, 0xF7, 0xFF, 0x8F, 0xFE, 0x3F, 0xF0,
|
||||||
0x3F, 0x80, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x01, 0xE0, 0x03, 0x00, 0xFF,
|
0x3F, 0x80, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x01, 0xE0, 0x03, 0x00, 0xFF,
|
||||||
0x83, 0xFF, 0x8F, 0xFF, 0x3F, 0xFE, 0xF0, 0xFB, 0xC1, 0xEF, 0x07, 0xBC,
|
0x83, 0xFF, 0x8F, 0xFF, 0x3F, 0xFE, 0xF0, 0xFB, 0xC1, 0xEF, 0x07, 0xBC,
|
||||||
0x1E, 0xF0, 0x7B, 0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC3, 0xEF,
|
0x1E, 0xF0, 0x7B, 0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC3, 0xEF,
|
||||||
0x1F, 0x3F, 0xFC, 0xFF, 0xE3, 0xFF, 0xCF, 0x0F, 0xBC, 0x1E, 0xF0, 0x7B,
|
0x1F, 0x3F, 0xFC, 0xFF, 0xE3, 0xFF, 0xCF, 0x0F, 0xBC, 0x1E, 0xF0, 0x7B,
|
||||||
0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1, 0xEF, 0x07, 0xBC, 0x1E,
|
0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1, 0xEF, 0x07, 0xBC, 0x1E,
|
||||||
0xF0, 0x7B, 0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1, 0xF0, 0x0F,
|
0xF0, 0x7B, 0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0xF0, 0x7B, 0xC1, 0xF0, 0x0F,
|
||||||
0xC0, 0xFF, 0xC3, 0xFF, 0x1F, 0xFE, 0x78, 0x79, 0xE1, 0xEF, 0x87, 0xBE,
|
0xC0, 0xFF, 0xC3, 0xFF, 0x1F, 0xFE, 0x78, 0x79, 0xE1, 0xEF, 0x87, 0xBE,
|
||||||
0x1F, 0xF8, 0x7D, 0xE1, 0xF7, 0x87, 0xDF, 0x1F, 0x7E, 0x00, 0xFC, 0x01,
|
0x1F, 0xF8, 0x7D, 0xE1, 0xF7, 0x87, 0xDF, 0x1F, 0x7E, 0x00, 0xFC, 0x01,
|
||||||
0xF8, 0x03, 0xF0, 0x0F, 0xE0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xF9,
|
0xF8, 0x03, 0xF0, 0x0F, 0xE0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xF9,
|
||||||
0xE1, 0xF7, 0x87, 0xDE, 0x0F, 0x78, 0x3D, 0xE0, 0xF7, 0x83, 0xDE, 0x0F,
|
0xE1, 0xF7, 0x87, 0xDE, 0x0F, 0x78, 0x3D, 0xE0, 0xF7, 0x83, 0xDE, 0x0F,
|
||||||
0x78, 0x3D, 0xE1, 0xF7, 0xEF, 0x8F, 0xFE, 0x3F, 0xF0, 0x3F, 0x80, 0xFF,
|
0x78, 0x3D, 0xE1, 0xF7, 0xEF, 0x8F, 0xFE, 0x3F, 0xF0, 0x3F, 0x80, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F,
|
||||||
0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F,
|
0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F,
|
||||||
0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F,
|
0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F,
|
||||||
0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F,
|
0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F,
|
||||||
0x80, 0xF8, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0,
|
0x80, 0xF8, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0,
|
||||||
0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8,
|
0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8,
|
||||||
0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE,
|
0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE,
|
||||||
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF,
|
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF,
|
||||||
0x83, 0xFE, 0x0F, 0x78, 0x3D, 0xE1, 0xF7, 0xEF, 0xCF, 0xFE, 0x3F, 0xF8,
|
0x83, 0xFE, 0x0F, 0x78, 0x3D, 0xE1, 0xF7, 0xEF, 0xCF, 0xFE, 0x3F, 0xF8,
|
||||||
0x7F, 0x80, 0xF0, 0x1F, 0xF0, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF8, 0x1E,
|
0x7F, 0x80, 0xF0, 0x1F, 0xF0, 0x1E, 0xF0, 0x1E, 0xF0, 0x1E, 0xF8, 0x1E,
|
||||||
0x78, 0x1E, 0x78, 0x1E, 0x78, 0x3C, 0x78, 0x3C, 0x78, 0x3C, 0x7C, 0x3C,
|
0x78, 0x1E, 0x78, 0x1E, 0x78, 0x3C, 0x78, 0x3C, 0x78, 0x3C, 0x7C, 0x3C,
|
||||||
0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x78, 0x3C, 0x78, 0x3C, 0x78,
|
0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x78, 0x3C, 0x78, 0x3C, 0x78,
|
||||||
0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x70, 0x1E, 0xF0,
|
0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x78, 0x1E, 0x70, 0x1E, 0xF0,
|
||||||
0x0E, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xE0,
|
0x0E, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xE0,
|
||||||
0x0F, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0xF0, 0x3C,
|
0x0F, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0xF0, 0x3C,
|
||||||
0x0F, 0xF0, 0x3C, 0x0F, 0xF0, 0x3C, 0x0F, 0xF0, 0x3C, 0x1E, 0xF0, 0x3C,
|
0x0F, 0xF0, 0x3C, 0x0F, 0xF0, 0x3C, 0x0F, 0xF0, 0x3C, 0x1E, 0xF0, 0x3C,
|
||||||
0x1E, 0x78, 0x3E, 0x1E, 0x78, 0x7E, 0x1E, 0x78, 0x7E, 0x1E, 0x78, 0x7E,
|
0x1E, 0x78, 0x3E, 0x1E, 0x78, 0x7E, 0x1E, 0x78, 0x7E, 0x1E, 0x78, 0x7E,
|
||||||
0x1E, 0x78, 0x7E, 0x1E, 0x78, 0x7E, 0x1E, 0x78, 0x7E, 0x1E, 0x38, 0x7F,
|
0x1E, 0x78, 0x7E, 0x1E, 0x78, 0x7E, 0x1E, 0x78, 0x7E, 0x1E, 0x38, 0x7F,
|
||||||
0x1C, 0x38, 0xF7, 0x1C, 0x3C, 0xF7, 0x3C, 0x3C, 0xE7, 0x3C, 0x3C, 0xE7,
|
0x1C, 0x38, 0xF7, 0x1C, 0x3C, 0xF7, 0x3C, 0x3C, 0xE7, 0x3C, 0x3C, 0xE7,
|
||||||
0x3C, 0x3C, 0xE7, 0x3C, 0x3C, 0xE7, 0x3C, 0x3C, 0xE7, 0xBC, 0x1D, 0xE3,
|
0x3C, 0x3C, 0xE7, 0x3C, 0x3C, 0xE7, 0x3C, 0x3C, 0xE7, 0xBC, 0x1D, 0xE3,
|
||||||
0xB8, 0x1D, 0xC3, 0xB8, 0x1D, 0xC3, 0xB8, 0x1F, 0xC3, 0xB8, 0x1F, 0xC3,
|
0xB8, 0x1D, 0xC3, 0xB8, 0x1D, 0xC3, 0xB8, 0x1F, 0xC3, 0xB8, 0x1F, 0xC3,
|
||||||
0xB8, 0x1F, 0xC3, 0xF8, 0x1F, 0xC3, 0xF8, 0x1F, 0xC1, 0xF8, 0x0F, 0x81,
|
0xB8, 0x1F, 0xC3, 0xF8, 0x1F, 0xC3, 0xF8, 0x1F, 0xC1, 0xF8, 0x0F, 0x81,
|
||||||
0xF8, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81,
|
0xF8, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81,
|
||||||
0xF0, 0x0F, 0x81, 0xF0, 0xF0, 0x3F, 0xC0, 0xF7, 0x07, 0x9E, 0x1E, 0x78,
|
0xF0, 0x0F, 0x81, 0xF0, 0xF0, 0x3F, 0xC0, 0xF7, 0x07, 0x9E, 0x1E, 0x78,
|
||||||
0x78, 0xE3, 0xE3, 0xCF, 0x0F, 0x3C, 0x3C, 0xF0, 0x7F, 0x81, 0xFE, 0x07,
|
0x78, 0xE3, 0xE3, 0xCF, 0x0F, 0x3C, 0x3C, 0xF0, 0x7F, 0x81, 0xFE, 0x07,
|
||||||
0xF8, 0x0F, 0xE0, 0x3F, 0x00, 0xFC, 0x01, 0xF0, 0x07, 0x80, 0x3E, 0x00,
|
0xF8, 0x0F, 0xE0, 0x3F, 0x00, 0xFC, 0x01, 0xF0, 0x07, 0x80, 0x3E, 0x00,
|
||||||
0xF8, 0x03, 0xF0, 0x0F, 0xC0, 0x7F, 0x01, 0xFE, 0x07, 0xF8, 0x3F, 0xE0,
|
0xF8, 0x03, 0xF0, 0x0F, 0xC0, 0x7F, 0x01, 0xFE, 0x07, 0xF8, 0x3F, 0xE0,
|
||||||
0xF3, 0xC3, 0xCF, 0x0F, 0x3C, 0x78, 0x71, 0xE1, 0xE7, 0x87, 0x9E, 0x0E,
|
0xF3, 0xC3, 0xCF, 0x0F, 0x3C, 0x78, 0x71, 0xE1, 0xE7, 0x87, 0x9E, 0x0E,
|
||||||
0xF0, 0x3F, 0xC0, 0xF0, 0xF8, 0x0F, 0x78, 0x1F, 0x78, 0x1E, 0x7C, 0x1E,
|
0xF0, 0x3F, 0xC0, 0xF0, 0xF8, 0x0F, 0x78, 0x1F, 0x78, 0x1E, 0x7C, 0x1E,
|
||||||
0x3C, 0x1E, 0x3C, 0x3E, 0x3C, 0x3C, 0x3E, 0x3C, 0x1E, 0x3C, 0x1E, 0x78,
|
0x3C, 0x1E, 0x3C, 0x3E, 0x3C, 0x3C, 0x3E, 0x3C, 0x1E, 0x3C, 0x1E, 0x78,
|
||||||
0x1E, 0x78, 0x0F, 0x78, 0x0F, 0x78, 0x0F, 0xF0, 0x0F, 0xF0, 0x07, 0xF0,
|
0x1E, 0x78, 0x0F, 0x78, 0x0F, 0x78, 0x0F, 0xF0, 0x0F, 0xF0, 0x07, 0xF0,
|
||||||
0x07, 0xF0, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0,
|
0x07, 0xF0, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0,
|
||||||
0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0,
|
0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0,
|
||||||
0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0,
|
0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0,
|
||||||
0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x01, 0xF0, 0x1E, 0x01, 0xE0, 0x3E,
|
0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x01, 0xF0, 0x1E, 0x01, 0xE0, 0x3E,
|
||||||
0x03, 0xE0, 0x3C, 0x07, 0xC0, 0x7C, 0x07, 0xC0, 0x78, 0x0F, 0x80, 0xF8,
|
0x03, 0xE0, 0x3C, 0x07, 0xC0, 0x7C, 0x07, 0xC0, 0x78, 0x0F, 0x80, 0xF8,
|
||||||
0x0F, 0x80, 0xF0, 0x1F, 0x01, 0xF0, 0x1E, 0x01, 0xE0, 0x3E, 0x03, 0xE0,
|
0x0F, 0x80, 0xF0, 0x1F, 0x01, 0xF0, 0x1E, 0x01, 0xE0, 0x3E, 0x03, 0xE0,
|
||||||
0x3C, 0x07, 0xC0, 0x7C, 0x07, 0xC0, 0x78, 0x0F, 0x80, 0xFF, 0xFF, 0xFF,
|
0x3C, 0x07, 0xC0, 0x7C, 0x07, 0xC0, 0x78, 0x0F, 0x80, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
|
||||||
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF,
|
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF,
|
||||||
0xFF, 0xFF, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x07, 0x00, 0xF0, 0x1E, 0x03,
|
0xFF, 0xFF, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x07, 0x00, 0xF0, 0x1E, 0x03,
|
||||||
0xC0, 0x78, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x3C, 0x07, 0x80, 0xF0,
|
0xC0, 0x78, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x3C, 0x07, 0x80, 0xF0,
|
||||||
0x1E, 0x01, 0xC0, 0x3C, 0x07, 0x80, 0xF0, 0x0E, 0x01, 0xE0, 0x3C, 0x07,
|
0x1E, 0x01, 0xC0, 0x3C, 0x07, 0x80, 0xF0, 0x0E, 0x01, 0xE0, 0x3C, 0x07,
|
||||||
0x80, 0xF0, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0x78, 0x0F, 0x01, 0xE0,
|
0x80, 0xF0, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0x78, 0x0F, 0x01, 0xE0,
|
||||||
0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||||
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
|
||||||
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF,
|
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF,
|
||||||
0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x80, 0x7F, 0x01, 0xFE, 0x03, 0xDC, 0x07,
|
0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x80, 0x7F, 0x01, 0xFE, 0x03, 0xDC, 0x07,
|
||||||
0xBC, 0x0E, 0x78, 0x3C, 0xF0, 0x79, 0xE0, 0xF1, 0xE1, 0xE3, 0xC7, 0x87,
|
0xBC, 0x0E, 0x78, 0x3C, 0xF0, 0x79, 0xE0, 0xF1, 0xE1, 0xE3, 0xC7, 0x87,
|
||||||
0x8F, 0x0F, 0x1E, 0x0F, 0x3C, 0x1E, 0xF8, 0x3D, 0xE0, 0x7C, 0xFF, 0xFF,
|
0x8F, 0x0F, 0x1E, 0x0F, 0x3C, 0x1E, 0xF8, 0x3D, 0xE0, 0x7C, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xF0, 0xF9, 0xE7, 0x8E, 0x38, 0x71, 0xC3, 0x0F, 0xC0, 0xFF,
|
0xFF, 0xFF, 0xF0, 0xF9, 0xE7, 0x8E, 0x38, 0x71, 0xC3, 0x0F, 0xC0, 0xFF,
|
||||||
0xC3, 0xFF, 0x1F, 0xFE, 0x78, 0x79, 0xE1, 0xEF, 0x87, 0xBE, 0x1E, 0xF8,
|
0xC3, 0xFF, 0x1F, 0xFE, 0x78, 0x79, 0xE1, 0xEF, 0x87, 0xBE, 0x1E, 0xF8,
|
||||||
0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x7F, 0x0F, 0xFC, 0x7F, 0xF3, 0xE7, 0xDE,
|
0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x7F, 0x0F, 0xFC, 0x7F, 0xF3, 0xE7, 0xDE,
|
||||||
0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF,
|
0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF,
|
||||||
0x87, 0xFE, 0x1F, 0xF8, 0x7D, 0xE3, 0xF7, 0xFF, 0xDF, 0xFF, 0x3F, 0x7C,
|
0x87, 0xFE, 0x1F, 0xF8, 0x7D, 0xE3, 0xF7, 0xFF, 0xDF, 0xFF, 0x3F, 0x7C,
|
||||||
0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x79, 0xE3, 0xDF, 0x9F,
|
0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x79, 0xE3, 0xDF, 0x9F,
|
||||||
0xFE, 0xFF, 0xFF, 0xC7, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1,
|
0xFE, 0xFF, 0xFF, 0xC7, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1,
|
||||||
0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F,
|
0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F,
|
||||||
0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xFC,
|
0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xFC,
|
||||||
0x7F, 0xF7, 0xFF, 0xFE, 0xF7, 0xF7, 0x9F, 0x00, 0x0F, 0xC1, 0xFF, 0x8F,
|
0x7F, 0xF7, 0xFF, 0xFE, 0xF7, 0xF7, 0x9F, 0x00, 0x0F, 0xC1, 0xFF, 0x8F,
|
||||||
0xFC, 0xFF, 0xF7, 0x87, 0xBC, 0x3F, 0xE1, 0xFF, 0x0F, 0xF8, 0x7F, 0xC3,
|
0xFC, 0xFF, 0xF7, 0x87, 0xBC, 0x3F, 0xE1, 0xFF, 0x0F, 0xF8, 0x7F, 0xC3,
|
||||||
0xFE, 0x1F, 0xF0, 0x0F, 0x80, 0x7C, 0x03, 0xE0, 0x1F, 0x00, 0xF8, 0x07,
|
0xFE, 0x1F, 0xF0, 0x0F, 0x80, 0x7C, 0x03, 0xE0, 0x1F, 0x00, 0xF8, 0x07,
|
||||||
0xC0, 0x3E, 0x1F, 0xF0, 0xFF, 0x87, 0xFC, 0x3F, 0xE1, 0xEF, 0x0F, 0x78,
|
0xC0, 0x3E, 0x1F, 0xF0, 0xFF, 0x87, 0xFC, 0x3F, 0xE1, 0xEF, 0x0F, 0x78,
|
||||||
0x7B, 0xE7, 0xDF, 0xFC, 0x7F, 0xE1, 0xFE, 0x00, 0x00, 0x7C, 0x01, 0xF0,
|
0x7B, 0xE7, 0xDF, 0xFC, 0x7F, 0xE1, 0xFE, 0x00, 0x00, 0x7C, 0x01, 0xF0,
|
||||||
0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x7D, 0xF3, 0xFF, 0xDF, 0xFF, 0x7F, 0xFD,
|
0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x7D, 0xF3, 0xFF, 0xDF, 0xFF, 0x7F, 0xFD,
|
||||||
0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F,
|
0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F,
|
||||||
0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87,
|
0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87,
|
||||||
0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7D, 0xE1,
|
0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7D, 0xE1,
|
||||||
0xF7, 0xDF, 0xDF, 0xFF, 0x3F, 0xFC, 0x7D, 0xF0, 0x0F, 0xC0, 0x7F, 0xC3,
|
0xF7, 0xDF, 0xDF, 0xFF, 0x3F, 0xFC, 0x7D, 0xF0, 0x0F, 0xC0, 0x7F, 0xC3,
|
||||||
0xFF, 0x1F, 0xFE, 0x78, 0x79, 0xE1, 0xEF, 0x87, 0xBE, 0x1E, 0xF8, 0x7B,
|
0xFF, 0x1F, 0xFE, 0x78, 0x79, 0xE1, 0xEF, 0x87, 0xBE, 0x1E, 0xF8, 0x7B,
|
||||||
0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00,
|
0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00,
|
||||||
0xF8, 0x03, 0xE0, 0x0F, 0x87, 0xBE, 0x1E, 0xF8, 0x7B, 0xE1, 0xEF, 0x87,
|
0xF8, 0x03, 0xE0, 0x0F, 0x87, 0xBE, 0x1E, 0xF8, 0x7B, 0xE1, 0xEF, 0x87,
|
||||||
0x9E, 0x1E, 0x78, 0x79, 0xF3, 0xE7, 0xFF, 0x0F, 0xFC, 0x1F, 0xE0, 0x07,
|
0x9E, 0x1E, 0x78, 0x79, 0xF3, 0xE7, 0xFF, 0x0F, 0xFC, 0x1F, 0xE0, 0x07,
|
||||||
0xC3, 0xF1, 0xFC, 0x7C, 0x1E, 0x07, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1,
|
0xC3, 0xF1, 0xFC, 0x7C, 0x1E, 0x07, 0x8F, 0xFF, 0xFF, 0xFF, 0xFF, 0xF1,
|
||||||
0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78,
|
0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78,
|
||||||
0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07,
|
0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07,
|
||||||
0x81, 0xE0, 0x78, 0x1E, 0x07, 0x80, 0x1F, 0x7C, 0xFF, 0xF7, 0xFF, 0xDF,
|
0x81, 0xE0, 0x78, 0x1E, 0x07, 0x80, 0x1F, 0x7C, 0xFF, 0xF7, 0xFF, 0xDF,
|
||||||
0xFF, 0x78, 0x7D, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF,
|
0xFF, 0x78, 0x7D, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF,
|
||||||
0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F,
|
0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F,
|
||||||
0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7D, 0xE1, 0xF7, 0xCF, 0xDF, 0xFF,
|
0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7D, 0xE1, 0xF7, 0xCF, 0xDF, 0xFF,
|
||||||
0x3F, 0xFC, 0x7D, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x79, 0xC3, 0xE7, 0xFF,
|
0x3F, 0xFC, 0x7D, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x79, 0xC3, 0xE7, 0xFF,
|
||||||
0xBF, 0xFC, 0x3F, 0xC0, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00,
|
0xBF, 0xFC, 0x3F, 0xC0, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00,
|
||||||
0x79, 0xF3, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFC, 0x1F, 0xE0, 0xFF,
|
0x79, 0xF3, 0xDF, 0xDF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFC, 0x1F, 0xE0, 0xFF,
|
||||||
0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0,
|
0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0,
|
||||||
0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F,
|
0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F,
|
||||||
0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xC0,
|
0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xC0,
|
||||||
0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x78, 0xF1, 0xE0, 0x00, 0x0F,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x78, 0xF1, 0xE0, 0x00, 0x0F,
|
||||||
0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3,
|
0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3,
|
||||||
0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C,
|
0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C,
|
||||||
0xF9, 0xFF, 0xDF, 0xBE, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00,
|
0xF9, 0xFF, 0xDF, 0xBE, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00,
|
||||||
0xF0, 0x03, 0xC1, 0xFF, 0x07, 0xBC, 0x1E, 0xF0, 0xFB, 0xC3, 0xCF, 0x1F,
|
0xF0, 0x03, 0xC1, 0xFF, 0x07, 0xBC, 0x1E, 0xF0, 0xFB, 0xC3, 0xCF, 0x1F,
|
||||||
0x3C, 0x78, 0xF1, 0xE3, 0xCF, 0x8F, 0x3C, 0x3D, 0xF0, 0xF7, 0x83, 0xDE,
|
0x3C, 0x78, 0xF1, 0xE3, 0xCF, 0x8F, 0x3C, 0x3D, 0xF0, 0xF7, 0x83, 0xDE,
|
||||||
0x0F, 0xF8, 0x3F, 0xC0, 0xFF, 0x83, 0xDE, 0x0F, 0x78, 0x3D, 0xF0, 0xF3,
|
0x0F, 0xF8, 0x3F, 0xC0, 0xFF, 0x83, 0xDE, 0x0F, 0x78, 0x3D, 0xF0, 0xF3,
|
||||||
0xC3, 0xCF, 0x8F, 0x1E, 0x3C, 0x7C, 0xF0, 0xF3, 0xC3, 0xCF, 0x0F, 0xBC,
|
0xC3, 0xCF, 0x8F, 0x1E, 0x3C, 0x7C, 0xF0, 0xF3, 0xC3, 0xCF, 0x0F, 0xBC,
|
||||||
0x1E, 0xF0, 0x7F, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0x1E, 0xF0, 0x7F, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xE1,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF3, 0xE1,
|
||||||
0xF3, 0xDF, 0xCF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFC, 0x3F,
|
0xF3, 0xDF, 0xCF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFC, 0x3F,
|
||||||
0xC1, 0xE0, 0xFF, 0x07, 0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1,
|
0xC1, 0xE0, 0xFF, 0x07, 0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1,
|
||||||
0xE0, 0xFF, 0x07, 0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1, 0xE0,
|
0xE0, 0xFF, 0x07, 0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1, 0xE0,
|
||||||
0xFF, 0x07, 0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1, 0xE0, 0xFF,
|
0xFF, 0x07, 0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1, 0xE0, 0xFF,
|
||||||
0x07, 0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1, 0xE0, 0xFF, 0x07,
|
0x07, 0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1, 0xE0, 0xFF, 0x07,
|
||||||
0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1, 0xE0, 0xFF, 0x07, 0x83,
|
0x83, 0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3F, 0xC1, 0xE0, 0xFF, 0x07, 0x83,
|
||||||
0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3C, 0xF3, 0xE7, 0xBF, 0xBF, 0xFF, 0xFF,
|
0xFC, 0x1E, 0x0F, 0xF0, 0x78, 0x3C, 0xF3, 0xE7, 0xBF, 0xBF, 0xFF, 0xFF,
|
||||||
0xFF, 0x87, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F,
|
0xFF, 0x87, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F,
|
||||||
0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC,
|
0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC,
|
||||||
0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83,
|
0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F, 0x83,
|
||||||
0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0x80, 0x0F, 0xC0, 0x7F, 0x83, 0xFF, 0x1F,
|
0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0x80, 0x0F, 0xC0, 0x7F, 0x83, 0xFF, 0x1F,
|
||||||
0xFE, 0x78, 0x79, 0xE1, 0xEF, 0x87, 0xBE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF,
|
0xFE, 0x78, 0x79, 0xE1, 0xEF, 0x87, 0xBE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF,
|
||||||
0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F,
|
0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F,
|
||||||
0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xDE, 0x1E,
|
0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xDE, 0x1E,
|
||||||
0x78, 0x79, 0xF3, 0xE7, 0xFF, 0x0F, 0xFC, 0x1F, 0xE0, 0xF3, 0xC7, 0xBF,
|
0x78, 0x79, 0xF3, 0xE7, 0xFF, 0x0F, 0xFC, 0x1F, 0xE0, 0xF3, 0xC7, 0xBF,
|
||||||
0xBF, 0xFD, 0xFF, 0xFF, 0x8F, 0xF8, 0x7F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F,
|
0xBF, 0xFD, 0xFF, 0xFF, 0x8F, 0xF8, 0x7F, 0xC1, 0xFE, 0x0F, 0xF0, 0x7F,
|
||||||
0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0,
|
0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F, 0xF0,
|
||||||
0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F,
|
0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F,
|
||||||
0xF8, 0xFF, 0xEF, 0xFF, 0xFD, 0xFF, 0xEF, 0x7E, 0x78, 0x03, 0xC0, 0x1E,
|
0xF8, 0xFF, 0xEF, 0xFF, 0xFD, 0xFF, 0xEF, 0x7E, 0x78, 0x03, 0xC0, 0x1E,
|
||||||
0x00, 0xF0, 0x07, 0x80, 0x00, 0x1E, 0x7C, 0xFF, 0xF7, 0xFF, 0xDF, 0xFF,
|
0x00, 0xF0, 0x07, 0x80, 0x00, 0x1E, 0x7C, 0xFF, 0xF7, 0xFF, 0xDF, 0xFF,
|
||||||
0x78, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87,
|
0x78, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87,
|
||||||
0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1,
|
0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1,
|
||||||
0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0x78,
|
0xFF, 0x87, 0xFE, 0x1F, 0xF8, 0x7F, 0xE1, 0xFF, 0x87, 0xFE, 0x1F, 0x78,
|
||||||
0x7D, 0xF7, 0xF7, 0xFF, 0xCF, 0xFF, 0x1F, 0x7C, 0x01, 0xF0, 0x07, 0xC0,
|
0x7D, 0xF7, 0xF7, 0xFF, 0xCF, 0xFF, 0x1F, 0x7C, 0x01, 0xF0, 0x07, 0xC0,
|
||||||
0x1F, 0x00, 0x7C, 0x01, 0xF0, 0xF3, 0xFB, 0xFF, 0xFF, 0xFF, 0xC7, 0x83,
|
0x1F, 0x00, 0x7C, 0x01, 0xF0, 0xF3, 0xFB, 0xFF, 0xFF, 0xFF, 0xC7, 0x83,
|
||||||
0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0,
|
0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0,
|
||||||
0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E,
|
0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E,
|
||||||
0x0F, 0x00, 0x1F, 0x83, 0xFE, 0x1F, 0xF9, 0xFF, 0xCF, 0x0F, 0x78, 0x7B,
|
0x0F, 0x00, 0x1F, 0x83, 0xFE, 0x1F, 0xF9, 0xFF, 0xCF, 0x0F, 0x78, 0x7B,
|
||||||
0xC3, 0xDE, 0x1E, 0xF0, 0xF7, 0xC7, 0xBE, 0x00, 0xF8, 0x07, 0xE0, 0x1F,
|
0xC3, 0xDE, 0x1E, 0xF0, 0xF7, 0xC7, 0xBE, 0x00, 0xF8, 0x07, 0xE0, 0x1F,
|
||||||
0x80, 0x7E, 0x01, 0xF8, 0x07, 0xE0, 0x1F, 0x80, 0x7D, 0xE1, 0xEF, 0x0F,
|
0x80, 0x7E, 0x01, 0xF8, 0x07, 0xE0, 0x1F, 0x80, 0x7D, 0xE1, 0xEF, 0x0F,
|
||||||
0xF8, 0x7F, 0xC3, 0xFE, 0x1F, 0xF0, 0xF7, 0xEF, 0x9F, 0xFC, 0xFF, 0xC1,
|
0xF8, 0x7F, 0xC3, 0xFE, 0x1F, 0xF0, 0xF7, 0xEF, 0x9F, 0xFC, 0xFF, 0xC1,
|
||||||
0xFC, 0x00, 0x3E, 0x0F, 0x83, 0xE0, 0xF8, 0x3E, 0x0F, 0x8F, 0xFF, 0xFF,
|
0xFC, 0x00, 0x3E, 0x0F, 0x83, 0xE0, 0xF8, 0x3E, 0x0F, 0x8F, 0xFF, 0xFF,
|
||||||
0xFF, 0xCF, 0x83, 0xE0, 0xF8, 0x3E, 0x0F, 0x83, 0xE0, 0xF8, 0x3E, 0x0F,
|
0xFF, 0xCF, 0x83, 0xE0, 0xF8, 0x3E, 0x0F, 0x83, 0xE0, 0xF8, 0x3E, 0x0F,
|
||||||
0x83, 0xE0, 0xF8, 0x3E, 0x0F, 0x83, 0xE0, 0xF8, 0x3E, 0x0F, 0x83, 0xE0,
|
0x83, 0xE0, 0xF8, 0x3E, 0x0F, 0x83, 0xE0, 0xF8, 0x3E, 0x0F, 0x83, 0xE0,
|
||||||
0xF8, 0x3E, 0x0F, 0x83, 0xF0, 0xFF, 0x1F, 0xC3, 0xF0, 0xF8, 0x3F, 0xE0,
|
0xF8, 0x3E, 0x0F, 0x83, 0xF0, 0xFF, 0x1F, 0xC3, 0xF0, 0xF8, 0x3F, 0xE0,
|
||||||
0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8,
|
0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8,
|
||||||
0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE,
|
0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE,
|
||||||
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF,
|
0x0F, 0xF8, 0x3F, 0xE0, 0xFF, 0x83, 0xFE, 0x0F, 0xF8, 0x3F, 0xE0, 0xFF,
|
||||||
0x83, 0xFE, 0x0F, 0x78, 0x7D, 0xF3, 0xF7, 0xFF, 0xCF, 0xEF, 0x1F, 0x3C,
|
0x83, 0xFE, 0x0F, 0x78, 0x7D, 0xF3, 0xF7, 0xFF, 0xCF, 0xEF, 0x1F, 0x3C,
|
||||||
0xF0, 0x7F, 0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0x78, 0x79, 0xE1, 0xE7, 0x87,
|
0xF0, 0x7F, 0xC1, 0xEF, 0x07, 0xBC, 0x1E, 0x78, 0x79, 0xE1, 0xE7, 0x87,
|
||||||
0x9E, 0x1C, 0x78, 0x71, 0xE3, 0xC7, 0x8F, 0x0E, 0x3C, 0x3C, 0xF0, 0xF3,
|
0x9E, 0x1C, 0x78, 0x71, 0xE3, 0xC7, 0x8F, 0x0E, 0x3C, 0x3C, 0xF0, 0xF3,
|
||||||
0xC3, 0xCE, 0x0F, 0x38, 0x3C, 0xE0, 0xF3, 0x81, 0xDE, 0x07, 0x78, 0x1F,
|
0xC3, 0xCE, 0x0F, 0x38, 0x3C, 0xE0, 0xF3, 0x81, 0xDE, 0x07, 0x78, 0x1F,
|
||||||
0xE0, 0x7F, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x3F, 0x00, 0xFC, 0x03,
|
0xE0, 0x7F, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x3F, 0x00, 0xFC, 0x03,
|
||||||
0xF0, 0x0F, 0x80, 0xF0, 0x78, 0x7F, 0x87, 0xC3, 0xFC, 0x3E, 0x1F, 0xE1,
|
0xF0, 0x0F, 0x80, 0xF0, 0x78, 0x7F, 0x87, 0xC3, 0xFC, 0x3E, 0x1F, 0xE1,
|
||||||
0xF0, 0xF7, 0x0F, 0x87, 0xB8, 0x7C, 0x39, 0xC3, 0xE1, 0xCE, 0x1F, 0x8E,
|
0xF0, 0xF7, 0x0F, 0x87, 0xB8, 0x7C, 0x39, 0xC3, 0xE1, 0xCE, 0x1F, 0x8E,
|
||||||
0x79, 0xDC, 0x73, 0xCE, 0xE7, 0x9E, 0x77, 0x3C, 0xF3, 0xB9, 0xE3, 0x9D,
|
0x79, 0xDC, 0x73, 0xCE, 0xE7, 0x9E, 0x77, 0x3C, 0xF3, 0xB9, 0xE3, 0x9D,
|
||||||
0xCF, 0x1C, 0xE6, 0x70, 0xE7, 0x3B, 0x87, 0x71, 0xDC, 0x3B, 0x8E, 0xE1,
|
0xCF, 0x1C, 0xE6, 0x70, 0xE7, 0x3B, 0x87, 0x71, 0xDC, 0x3B, 0x8E, 0xE1,
|
||||||
0xDC, 0x77, 0x0F, 0xE3, 0xB8, 0x7F, 0x1D, 0xC3, 0xF8, 0xFE, 0x0F, 0x83,
|
0xDC, 0x77, 0x0F, 0xE3, 0xB8, 0x7F, 0x1D, 0xC3, 0xF8, 0xFE, 0x0F, 0x83,
|
||||||
0xE0, 0x7C, 0x1F, 0x03, 0xE0, 0xF8, 0x1F, 0x07, 0xC0, 0xF8, 0x3E, 0x07,
|
0xE0, 0x7C, 0x1F, 0x03, 0xE0, 0xF8, 0x1F, 0x07, 0xC0, 0xF8, 0x3E, 0x07,
|
||||||
0xC1, 0xF0, 0x3E, 0x0F, 0x81, 0xE0, 0x7C, 0x00, 0xF0, 0x7B, 0xC1, 0xE7,
|
0xC1, 0xF0, 0x3E, 0x0F, 0x81, 0xE0, 0x7C, 0x00, 0xF0, 0x7B, 0xC1, 0xE7,
|
||||||
0x87, 0x9E, 0x3C, 0x78, 0xF0, 0xF3, 0xC3, 0xCE, 0x0F, 0x78, 0x1F, 0xE0,
|
0x87, 0x9E, 0x3C, 0x78, 0xF0, 0xF3, 0xC3, 0xCE, 0x0F, 0x78, 0x1F, 0xE0,
|
||||||
0x7F, 0x01, 0xFC, 0x03, 0xF0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x03, 0xE0,
|
0x7F, 0x01, 0xFC, 0x03, 0xF0, 0x0F, 0x80, 0x3E, 0x00, 0xF8, 0x03, 0xE0,
|
||||||
0x0F, 0x80, 0x7F, 0x01, 0xFC, 0x07, 0xF0, 0x3D, 0xE0, 0xF7, 0x83, 0xDE,
|
0x0F, 0x80, 0x7F, 0x01, 0xFC, 0x07, 0xF0, 0x3D, 0xE0, 0xF7, 0x83, 0xDE,
|
||||||
0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xCF, 0x07, 0xBC, 0x1E, 0xF0, 0x7C, 0xF0,
|
0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xCF, 0x07, 0xBC, 0x1E, 0xF0, 0x7C, 0xF0,
|
||||||
0x3F, 0xC0, 0xFF, 0x07, 0xFE, 0x1E, 0x78, 0x79, 0xE1, 0xE7, 0x87, 0x9E,
|
0x3F, 0xC0, 0xFF, 0x07, 0xFE, 0x1E, 0x78, 0x79, 0xE1, 0xE7, 0x87, 0x9E,
|
||||||
0x1E, 0x78, 0x79, 0xE1, 0xC3, 0x87, 0x0F, 0x3C, 0x3C, 0xF0, 0xF3, 0xC3,
|
0x1E, 0x78, 0x79, 0xE1, 0xC3, 0x87, 0x0F, 0x3C, 0x3C, 0xF0, 0xF3, 0xC3,
|
||||||
0xCF, 0x0F, 0x3C, 0x1C, 0xE0, 0x73, 0x81, 0xCE, 0x07, 0xB8, 0x1F, 0xE0,
|
0xCF, 0x0F, 0x3C, 0x1C, 0xE0, 0x73, 0x81, 0xCE, 0x07, 0xB8, 0x1F, 0xE0,
|
||||||
0x7F, 0x80, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0,
|
0x7F, 0x80, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0,
|
||||||
0x07, 0x80, 0x1E, 0x00, 0xF8, 0x1F, 0xE0, 0x7F, 0x01, 0xFC, 0x00, 0x7F,
|
0x07, 0x80, 0x1E, 0x00, 0xF8, 0x1F, 0xE0, 0x7F, 0x01, 0xFC, 0x00, 0x7F,
|
||||||
0xEF, 0xFD, 0xFF, 0xBF, 0xF0, 0x1E, 0x07, 0xC0, 0xF0, 0x1E, 0x07, 0xC0,
|
0xEF, 0xFD, 0xFF, 0xBF, 0xF0, 0x1E, 0x07, 0xC0, 0xF0, 0x1E, 0x07, 0xC0,
|
||||||
0xF0, 0x1E, 0x03, 0xC0, 0xF8, 0x1E, 0x03, 0xC0, 0xF8, 0x1E, 0x03, 0xC0,
|
0xF0, 0x1E, 0x03, 0xC0, 0xF8, 0x1E, 0x03, 0xC0, 0xF8, 0x1E, 0x03, 0xC0,
|
||||||
0xF8, 0x1F, 0x03, 0xC0, 0x78, 0x1F, 0x03, 0xC0, 0x78, 0x1F, 0xFF, 0xFF,
|
0xF8, 0x1F, 0x03, 0xC0, 0x78, 0x1F, 0x03, 0xC0, 0x78, 0x1F, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFE, 0x07, 0xC3, 0xF1, 0xFC, 0x7E, 0x1E, 0x07, 0x81, 0xE0,
|
0xFF, 0xFF, 0xFE, 0x07, 0xC3, 0xF1, 0xFC, 0x7E, 0x1E, 0x07, 0x81, 0xE0,
|
||||||
0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0xF8, 0x7E,
|
0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0xF8, 0x7E,
|
||||||
0x3F, 0x0F, 0x83, 0xF0, 0xFE, 0x0F, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81,
|
0x3F, 0x0F, 0x83, 0xF0, 0xFE, 0x0F, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81,
|
||||||
0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0xC1, 0xFC, 0x3F,
|
0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0xC1, 0xFC, 0x3F,
|
||||||
0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF8, 0x3F, 0x0F,
|
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF8, 0x3F, 0x0F,
|
||||||
0xC1, 0xF8, 0x3E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78,
|
0xC1, 0xF8, 0x3E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78,
|
||||||
0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1F, 0x83, 0xF0, 0x7C, 0x3F, 0x1F, 0xC7,
|
0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1F, 0x83, 0xF0, 0x7C, 0x3F, 0x1F, 0xC7,
|
||||||
0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0,
|
0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0,
|
||||||
0x78, 0x3E, 0x0F, 0x8F, 0xC3, 0xF0, 0xF8, 0x00, 0x1E, 0x07, 0x9F, 0xF3,
|
0x78, 0x3E, 0x0F, 0x8F, 0xC3, 0xF0, 0xF8, 0x00, 0x1E, 0x07, 0x9F, 0xF3,
|
||||||
0xDF, 0xFF, 0xDF, 0xFF, 0xEF, 0xFF, 0xE1, 0x03, 0xE0 };
|
0xDF, 0xFF, 0xDF, 0xFF, 0xEF, 0xFF, 0xE1, 0x03, 0xE0};
|
||||||
|
|
||||||
const GFXglyph Antonio_SemiBold20pt7bGlyphs[] PROGMEM = {
|
const GFXglyph Antonio_SemiBold20pt7bGlyphs[] PROGMEM = {
|
||||||
{ 0, 1, 1, 8, 0, 0 }, // 0x20 ' '
|
{0, 1, 1, 8, 0, 0}, // 0x20 ' '
|
||||||
{ 1, 4, 34, 10, 3, -33 }, // 0x21 '!'
|
{1, 4, 34, 10, 3, -33}, // 0x21 '!'
|
||||||
{ 18, 5, 13, 16, 6, -33 }, // 0x22 '"'
|
{18, 5, 13, 16, 6, -33}, // 0x22 '"'
|
||||||
{ 27, 17, 34, 20, 2, -33 }, // 0x23 '#'
|
{27, 17, 34, 20, 2, -33}, // 0x23 '#'
|
||||||
{ 100, 13, 39, 16, 2, -33 }, // 0x24 '$'
|
{100, 13, 39, 16, 2, -33}, // 0x24 '$'
|
||||||
{ 164, 36, 34, 42, 3, -33 }, // 0x25 '%'
|
{164, 36, 34, 42, 3, -33}, // 0x25 '%'
|
||||||
{ 317, 18, 34, 19, 1, -33 }, // 0x26 '&'
|
{317, 18, 34, 19, 1, -33}, // 0x26 '&'
|
||||||
{ 394, 4, 12, 8, 2, -33 }, // 0x27 '''
|
{394, 4, 12, 8, 2, -33}, // 0x27 '''
|
||||||
{ 400, 7, 38, 11, 3, -33 }, // 0x28 '('
|
{400, 7, 38, 11, 3, -33}, // 0x28 '('
|
||||||
{ 434, 7, 38, 11, 2, -33 }, // 0x29 ')'
|
{434, 7, 38, 11, 2, -33}, // 0x29 ')'
|
||||||
{ 468, 14, 15, 17, 2, -32 }, // 0x2A '*'
|
{468, 14, 15, 17, 2, -32}, // 0x2A '*'
|
||||||
{ 495, 12, 12, 14, 1, -20 }, // 0x2B '+'
|
{495, 12, 12, 14, 1, -20}, // 0x2B '+'
|
||||||
{ 513, 5, 12, 9, 2, -4 }, // 0x2C ','
|
{513, 5, 12, 9, 2, -4}, // 0x2C ','
|
||||||
{ 521, 9, 3, 13, 2, -16 }, // 0x2D '-'
|
{521, 9, 3, 13, 2, -16}, // 0x2D '-'
|
||||||
{ 525, 4, 4, 10, 3, -3 }, // 0x2E '.'
|
{525, 4, 4, 10, 3, -3}, // 0x2E '.'
|
||||||
{ 527, 13, 34, 15, 1, -33 }, // 0x2F '/'
|
{527, 13, 34, 15, 1, -33}, // 0x2F '/'
|
||||||
{ 583, 13, 34, 18, 2, -33 }, // 0x30 '0'
|
{583, 13, 34, 18, 2, -33}, // 0x30 '0'
|
||||||
{ 639, 9, 34, 15, 2, -33 }, // 0x31 '1'
|
{639, 9, 34, 15, 2, -33}, // 0x31 '1'
|
||||||
{ 678, 13, 34, 17, 3, -33 }, // 0x32 '2'
|
{678, 13, 34, 17, 3, -33}, // 0x32 '2'
|
||||||
{ 734, 14, 34, 17, 2, -33 }, // 0x33 '3'
|
{734, 14, 34, 17, 2, -33}, // 0x33 '3'
|
||||||
{ 794, 14, 34, 17, 2, -33 }, // 0x34 '4'
|
{794, 14, 34, 17, 2, -33}, // 0x34 '4'
|
||||||
{ 854, 12, 34, 17, 3, -33 }, // 0x35 '5'
|
{854, 12, 34, 17, 3, -33}, // 0x35 '5'
|
||||||
{ 905, 14, 34, 17, 2, -33 }, // 0x36 '6'
|
{905, 14, 34, 17, 2, -33}, // 0x36 '6'
|
||||||
{ 965, 14, 34, 17, 2, -33 }, // 0x37 '7'
|
{965, 14, 34, 17, 2, -33}, // 0x37 '7'
|
||||||
{ 1025, 13, 34, 17, 2, -33 }, // 0x38 '8'
|
{1025, 13, 34, 17, 2, -33}, // 0x38 '8'
|
||||||
{ 1081, 13, 34, 17, 2, -33 }, // 0x39 '9'
|
{1081, 13, 34, 17, 2, -33}, // 0x39 '9'
|
||||||
{ 1137, 4, 20, 10, 3, -24 }, // 0x3A ':'
|
{1137, 4, 20, 10, 3, -24}, // 0x3A ':'
|
||||||
{ 1147, 5, 27, 11, 3, -24 }, // 0x3B ';'
|
{1147, 5, 27, 11, 3, -24}, // 0x3B ';'
|
||||||
{ 1164, 11, 19, 14, 1, -23 }, // 0x3C '<'
|
{1164, 11, 19, 14, 1, -23}, // 0x3C '<'
|
||||||
{ 1191, 10, 9, 14, 2, -19 }, // 0x3D '='
|
{1191, 10, 9, 14, 2, -19}, // 0x3D '='
|
||||||
{ 1203, 11, 19, 14, 2, -23 }, // 0x3E '>'
|
{1203, 11, 19, 14, 2, -23}, // 0x3E '>'
|
||||||
{ 1230, 12, 34, 17, 3, -33 }, // 0x3F '?'
|
{1230, 12, 34, 17, 3, -33}, // 0x3F '?'
|
||||||
{ 1281, 25, 35, 29, 2, -33 }, // 0x40 '@'
|
{1281, 25, 35, 29, 2, -33}, // 0x40 '@'
|
||||||
{ 1391, 16, 34, 18, 1, -33 }, // 0x41 'A'
|
{1391, 16, 34, 18, 1, -33}, // 0x41 'A'
|
||||||
{ 1459, 14, 34, 18, 3, -33 }, // 0x42 'B'
|
{1459, 14, 34, 18, 3, -33}, // 0x42 'B'
|
||||||
{ 1519, 14, 34, 18, 2, -33 }, // 0x43 'C'
|
{1519, 14, 34, 18, 2, -33}, // 0x43 'C'
|
||||||
{ 1579, 13, 34, 19, 3, -33 }, // 0x44 'D'
|
{1579, 13, 34, 19, 3, -33}, // 0x44 'D'
|
||||||
{ 1635, 10, 34, 15, 3, -33 }, // 0x45 'E'
|
{1635, 10, 34, 15, 3, -33}, // 0x45 'E'
|
||||||
{ 1678, 10, 34, 15, 3, -33 }, // 0x46 'F'
|
{1678, 10, 34, 15, 3, -33}, // 0x46 'F'
|
||||||
{ 1721, 14, 34, 18, 2, -33 }, // 0x47 'G'
|
{1721, 14, 34, 18, 2, -33}, // 0x47 'G'
|
||||||
{ 1781, 14, 34, 19, 3, -33 }, // 0x48 'H'
|
{1781, 14, 34, 19, 3, -33}, // 0x48 'H'
|
||||||
{ 1841, 4, 34, 10, 3, -33 }, // 0x49 'I'
|
{1841, 4, 34, 10, 3, -33}, // 0x49 'I'
|
||||||
{ 1858, 13, 34, 17, 2, -33 }, // 0x4A 'J'
|
{1858, 13, 34, 17, 2, -33}, // 0x4A 'J'
|
||||||
{ 1914, 15, 34, 18, 3, -33 }, // 0x4B 'K'
|
{1914, 15, 34, 18, 3, -33}, // 0x4B 'K'
|
||||||
{ 1978, 10, 34, 14, 3, -33 }, // 0x4C 'L'
|
{1978, 10, 34, 14, 3, -33}, // 0x4C 'L'
|
||||||
{ 2021, 20, 34, 26, 3, -33 }, // 0x4D 'M'
|
{2021, 20, 34, 26, 3, -33}, // 0x4D 'M'
|
||||||
{ 2106, 14, 34, 20, 3, -33 }, // 0x4E 'N'
|
{2106, 14, 34, 20, 3, -33}, // 0x4E 'N'
|
||||||
{ 2166, 14, 34, 19, 2, -33 }, // 0x4F 'O'
|
{2166, 14, 34, 19, 2, -33}, // 0x4F 'O'
|
||||||
{ 2226, 13, 34, 17, 3, -33 }, // 0x50 'P'
|
{2226, 13, 34, 17, 3, -33}, // 0x50 'P'
|
||||||
{ 2282, 14, 39, 19, 2, -33 }, // 0x51 'Q'
|
{2282, 14, 39, 19, 2, -33}, // 0x51 'Q'
|
||||||
{ 2351, 14, 34, 18, 3, -33 }, // 0x52 'R'
|
{2351, 14, 34, 18, 3, -33}, // 0x52 'R'
|
||||||
{ 2411, 14, 34, 16, 1, -33 }, // 0x53 'S'
|
{2411, 14, 34, 16, 1, -33}, // 0x53 'S'
|
||||||
{ 2471, 12, 34, 13, 0, -33 }, // 0x54 'T'
|
{2471, 12, 34, 13, 0, -33}, // 0x54 'T'
|
||||||
{ 2522, 14, 34, 19, 2, -33 }, // 0x55 'U'
|
{2522, 14, 34, 19, 2, -33}, // 0x55 'U'
|
||||||
{ 2582, 16, 34, 17, 1, -33 }, // 0x56 'V'
|
{2582, 16, 34, 17, 1, -33}, // 0x56 'V'
|
||||||
{ 2650, 24, 34, 26, 1, -33 }, // 0x57 'W'
|
{2650, 24, 34, 26, 1, -33}, // 0x57 'W'
|
||||||
{ 2752, 14, 34, 16, 1, -33 }, // 0x58 'X'
|
{2752, 14, 34, 16, 1, -33}, // 0x58 'X'
|
||||||
{ 2812, 16, 34, 16, 0, -33 }, // 0x59 'Y'
|
{2812, 16, 34, 16, 0, -33}, // 0x59 'Y'
|
||||||
{ 2880, 12, 34, 14, 1, -33 }, // 0x5A 'Z'
|
{2880, 12, 34, 14, 1, -33}, // 0x5A 'Z'
|
||||||
{ 2931, 8, 35, 13, 3, -33 }, // 0x5B '['
|
{2931, 8, 35, 13, 3, -33}, // 0x5B '['
|
||||||
{ 2966, 11, 34, 15, 2, -33 }, // 0x5C '\'
|
{2966, 11, 34, 15, 2, -33}, // 0x5C '\'
|
||||||
{ 3013, 8, 35, 13, 2, -33 }, // 0x5D ']'
|
{3013, 8, 35, 13, 2, -33}, // 0x5D ']'
|
||||||
{ 3048, 15, 18, 18, 2, -33 }, // 0x5E '^'
|
{3048, 15, 18, 18, 2, -33}, // 0x5E '^'
|
||||||
{ 3082, 12, 3, 14, 1, 2 }, // 0x5F '_'
|
{3082, 12, 3, 14, 1, 2}, // 0x5F '_'
|
||||||
{ 3087, 6, 8, 8, 1, -38 }, // 0x60 '`'
|
{3087, 6, 8, 8, 1, -38}, // 0x60 '`'
|
||||||
{ 3093, 14, 29, 18, 2, -28 }, // 0x61 'a'
|
{3093, 14, 29, 18, 2, -28}, // 0x61 'a'
|
||||||
{ 3144, 13, 34, 18, 3, -33 }, // 0x62 'b'
|
{3144, 13, 34, 18, 3, -33}, // 0x62 'b'
|
||||||
{ 3200, 13, 29, 17, 2, -28 }, // 0x63 'c'
|
{3200, 13, 29, 17, 2, -28}, // 0x63 'c'
|
||||||
{ 3248, 14, 34, 18, 2, -33 }, // 0x64 'd'
|
{3248, 14, 34, 18, 2, -33}, // 0x64 'd'
|
||||||
{ 3308, 14, 29, 17, 2, -28 }, // 0x65 'e'
|
{3308, 14, 29, 17, 2, -28}, // 0x65 'e'
|
||||||
{ 3359, 10, 34, 13, 1, -33 }, // 0x66 'f'
|
{3359, 10, 34, 13, 1, -33}, // 0x66 'f'
|
||||||
{ 3402, 14, 33, 18, 2, -28 }, // 0x67 'g'
|
{3402, 14, 33, 18, 2, -28}, // 0x67 'g'
|
||||||
{ 3460, 13, 34, 19, 3, -33 }, // 0x68 'h'
|
{3460, 13, 34, 19, 3, -33}, // 0x68 'h'
|
||||||
{ 3516, 4, 35, 10, 3, -34 }, // 0x69 'i'
|
{3516, 4, 35, 10, 3, -34}, // 0x69 'i'
|
||||||
{ 3534, 7, 39, 10, 1, -34 }, // 0x6A 'j'
|
{3534, 7, 39, 10, 1, -34}, // 0x6A 'j'
|
||||||
{ 3569, 14, 34, 18, 3, -33 }, // 0x6B 'k'
|
{3569, 14, 34, 18, 3, -33}, // 0x6B 'k'
|
||||||
{ 3629, 4, 34, 10, 3, -33 }, // 0x6C 'l'
|
{3629, 4, 34, 10, 3, -33}, // 0x6C 'l'
|
||||||
{ 3646, 22, 29, 28, 3, -28 }, // 0x6D 'm'
|
{3646, 22, 29, 28, 3, -28}, // 0x6D 'm'
|
||||||
{ 3726, 13, 29, 19, 3, -28 }, // 0x6E 'n'
|
{3726, 13, 29, 19, 3, -28}, // 0x6E 'n'
|
||||||
{ 3774, 14, 29, 18, 2, -28 }, // 0x6F 'o'
|
{3774, 14, 29, 18, 2, -28}, // 0x6F 'o'
|
||||||
{ 3825, 13, 34, 18, 3, -28 }, // 0x70 'p'
|
{3825, 13, 34, 18, 3, -28}, // 0x70 'p'
|
||||||
{ 3881, 14, 34, 18, 2, -28 }, // 0x71 'q'
|
{3881, 14, 34, 18, 2, -28}, // 0x71 'q'
|
||||||
{ 3941, 9, 29, 13, 3, -28 }, // 0x72 'r'
|
{3941, 9, 29, 13, 3, -28}, // 0x72 'r'
|
||||||
{ 3974, 13, 29, 16, 2, -28 }, // 0x73 's'
|
{3974, 13, 29, 16, 2, -28}, // 0x73 's'
|
||||||
{ 4022, 10, 34, 12, 1, -33 }, // 0x74 't'
|
{4022, 10, 34, 12, 1, -33}, // 0x74 't'
|
||||||
{ 4065, 14, 29, 19, 2, -28 }, // 0x75 'u'
|
{4065, 14, 29, 19, 2, -28}, // 0x75 'u'
|
||||||
{ 4116, 14, 29, 15, 1, -28 }, // 0x76 'v'
|
{4116, 14, 29, 15, 1, -28}, // 0x76 'v'
|
||||||
{ 4167, 21, 29, 23, 1, -28 }, // 0x77 'w'
|
{4167, 21, 29, 23, 1, -28}, // 0x77 'w'
|
||||||
{ 4244, 14, 29, 15, 1, -28 }, // 0x78 'x'
|
{4244, 14, 29, 15, 1, -28}, // 0x78 'x'
|
||||||
{ 4295, 14, 34, 16, 1, -28 }, // 0x79 'y'
|
{4295, 14, 34, 16, 1, -28}, // 0x79 'y'
|
||||||
{ 4355, 11, 29, 13, 1, -28 }, // 0x7A 'z'
|
{4355, 11, 29, 13, 1, -28}, // 0x7A 'z'
|
||||||
{ 4395, 10, 37, 14, 2, -33 }, // 0x7B '{'
|
{4395, 10, 37, 14, 2, -33}, // 0x7B '{'
|
||||||
{ 4442, 4, 37, 10, 3, -34 }, // 0x7C '|'
|
{4442, 4, 37, 10, 3, -34}, // 0x7C '|'
|
||||||
{ 4461, 10, 37, 14, 2, -33 }, // 0x7D '}'
|
{4461, 10, 37, 14, 2, -33}, // 0x7D '}'
|
||||||
{ 4508, 17, 6, 21, 2, -21 } }; // 0x7E '~'
|
{4508, 17, 6, 21, 2, -21}}; // 0x7E '~'
|
||||||
|
|
||||||
const GFXfont Antonio_SemiBold20pt7b PROGMEM = {
|
const GFXfont Antonio_SemiBold20pt7b PROGMEM = {
|
||||||
(uint8_t *)Antonio_SemiBold20pt7bBitmaps,
|
(uint8_t *)Antonio_SemiBold20pt7bBitmaps,
|
||||||
(GFXglyph *)Antonio_SemiBold20pt7bGlyphs,
|
(GFXglyph *)Antonio_SemiBold20pt7bGlyphs, 0x20, 0x7E, 51};
|
||||||
0x20, 0x7E, 51 };
|
|
||||||
|
|
||||||
// Approx. 5193 bytes
|
// Approx. 5193 bytes
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -3,4 +3,4 @@ dependencies:
|
||||||
idf: ">=4.4"
|
idf: ">=4.4"
|
||||||
|
|
||||||
esp_littlefs:
|
esp_littlefs:
|
||||||
git: https://github.com/joltwallet/esp_littlefs.git
|
git: https://github.com/joltwallet/esp_littlefs.git
|
||||||
|
|
|
@ -48,152 +48,141 @@ uint currentBlockHeight = 816000;
|
||||||
// ew==
|
// ew==
|
||||||
// -----END CERTIFICATE-----)";
|
// -----END CERTIFICATE-----)";
|
||||||
|
|
||||||
void setupBlockNotify()
|
void setupBlockNotify() {
|
||||||
{
|
// currentBlockHeight = preferences.getUInt("blockHeight", 816000);
|
||||||
//currentBlockHeight = preferences.getUInt("blockHeight", 816000);
|
|
||||||
|
|
||||||
IPAddress result;
|
IPAddress result;
|
||||||
|
|
||||||
int dnsErr = -1;
|
int dnsErr = -1;
|
||||||
String mempoolInstance = preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
String mempoolInstance =
|
||||||
|
preferences.getString("mempoolInstance", DEFAULT_MEMPOOL_INSTANCE);
|
||||||
|
|
||||||
while (dnsErr != 1)
|
while (dnsErr != 1) {
|
||||||
{
|
dnsErr = WiFi.hostByName(mempoolInstance.c_str(), result);
|
||||||
dnsErr = WiFi.hostByName(mempoolInstance.c_str(), result);
|
|
||||||
|
|
||||||
if (dnsErr != 1)
|
if (dnsErr != 1) {
|
||||||
{
|
Serial.print(mempoolInstance);
|
||||||
Serial.print(mempoolInstance);
|
Serial.println(F("mempool DNS could not be resolved"));
|
||||||
Serial.println(F("mempool DNS could not be resolved"));
|
WiFi.reconnect();
|
||||||
WiFi.reconnect();
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get current block height through regular API
|
||||||
|
HTTPClient *http = new HTTPClient();
|
||||||
|
http->begin("https://" + mempoolInstance + "/api/blocks/tip/height");
|
||||||
|
int httpCode = http->GET();
|
||||||
|
|
||||||
|
if (httpCode > 0 && httpCode == HTTP_CODE_OK) {
|
||||||
|
String blockHeightStr = http->getString();
|
||||||
|
currentBlockHeight = blockHeightStr.toInt();
|
||||||
|
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||||
|
if (workQueue != nullptr) {
|
||||||
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::strcpy(wsServer, String("wss://" + mempoolInstance +
|
||||||
|
// "/api/v1/ws").c_str());
|
||||||
|
|
||||||
|
esp_websocket_client_config_t config = {
|
||||||
|
.uri = "wss://mempool.space/api/v1/ws",
|
||||||
|
// .task_stack = (6*1024),
|
||||||
|
// .cert_pem = mempoolWsCert,
|
||||||
|
.user_agent = USER_AGENT,
|
||||||
|
};
|
||||||
|
|
||||||
|
blockNotifyClient = esp_websocket_client_init(&config);
|
||||||
|
esp_websocket_register_events(blockNotifyClient, WEBSOCKET_EVENT_ANY,
|
||||||
|
onWebsocketEvent, blockNotifyClient);
|
||||||
|
esp_websocket_client_start(blockNotifyClient);
|
||||||
|
}
|
||||||
|
|
||||||
|
void onWebsocketEvent(void *handler_args, esp_event_base_t base,
|
||||||
|
int32_t event_id, void *event_data) {
|
||||||
|
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
||||||
|
const String sub = "{\"action\": \"want\", \"data\":[\"blocks\"]}";
|
||||||
|
switch (event_id) {
|
||||||
|
case WEBSOCKET_EVENT_CONNECTED:
|
||||||
|
Serial.println(F("Connected to Mempool.space WebSocket"));
|
||||||
|
|
||||||
|
Serial.println(sub);
|
||||||
|
if (esp_websocket_client_send_text(blockNotifyClient, sub.c_str(),
|
||||||
|
sub.length(), portMAX_DELAY) == -1) {
|
||||||
|
Serial.println(F("Mempool.space WS Block Subscribe Error"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get current block height through regular API
|
break;
|
||||||
HTTPClient *http = new HTTPClient();
|
case WEBSOCKET_EVENT_DATA:
|
||||||
http->begin("https://" + mempoolInstance + "/api/blocks/tip/height");
|
onWebsocketMessage(data);
|
||||||
int httpCode = http->GET();
|
break;
|
||||||
|
case WEBSOCKET_EVENT_ERROR:
|
||||||
|
Serial.println(F("Mempool.space WS Connnection error"));
|
||||||
|
break;
|
||||||
|
case WEBSOCKET_EVENT_DISCONNECTED:
|
||||||
|
Serial.println(F("Mempool.space WS Connnection Closed"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (httpCode > 0 && httpCode == HTTP_CODE_OK)
|
void onWebsocketMessage(esp_websocket_event_data_t *event_data) {
|
||||||
{
|
SpiRamJsonDocument doc(event_data->data_len);
|
||||||
String blockHeightStr = http->getString();
|
|
||||||
currentBlockHeight = blockHeightStr.toInt();
|
deserializeJson(doc, (char *)event_data->data_ptr);
|
||||||
// xTaskNotifyGive(blockUpdateTaskHandle);
|
|
||||||
if (workQueue != nullptr)
|
if (doc.containsKey("block")) {
|
||||||
{
|
JsonObject block = doc["block"];
|
||||||
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
|
||||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
currentBlockHeight = block["height"].as<uint>();
|
||||||
|
|
||||||
|
Serial.printf("New block found: %d\r\n", block["height"].as<uint>());
|
||||||
|
preferences.putUInt("blockHeight", currentBlockHeight);
|
||||||
|
|
||||||
|
if (workQueue != nullptr) {
|
||||||
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||||
|
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||||
|
|
||||||
|
if (getCurrentScreen() != SCREEN_BLOCK_HEIGHT &&
|
||||||
|
preferences.getBool("stealFocus", true)) {
|
||||||
|
uint64_t timerPeriod = 0;
|
||||||
|
if (isTimerActive()) {
|
||||||
|
// store timer periode before making inactive to prevent artifacts
|
||||||
|
timerPeriod = getTimerSeconds();
|
||||||
|
esp_timer_stop(screenRotateTimer);
|
||||||
}
|
}
|
||||||
}
|
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
||||||
|
if (timerPeriod > 0) {
|
||||||
// std::strcpy(wsServer, String("wss://" + mempoolInstance + "/api/v1/ws").c_str());
|
esp_timer_start_periodic(screenRotateTimer,
|
||||||
|
timerPeriod * usPerSecond);
|
||||||
esp_websocket_client_config_t config = {
|
|
||||||
.uri = "wss://mempool.space/api/v1/ws",
|
|
||||||
// .task_stack = (6*1024),
|
|
||||||
// .cert_pem = mempoolWsCert,
|
|
||||||
.user_agent = USER_AGENT,
|
|
||||||
};
|
|
||||||
|
|
||||||
blockNotifyClient = esp_websocket_client_init(&config);
|
|
||||||
esp_websocket_register_events(blockNotifyClient, WEBSOCKET_EVENT_ANY, onWebsocketEvent, blockNotifyClient);
|
|
||||||
esp_websocket_client_start(blockNotifyClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onWebsocketEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
|
||||||
{
|
|
||||||
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
|
||||||
const String sub = "{\"action\": \"want\", \"data\":[\"blocks\"]}";
|
|
||||||
switch (event_id)
|
|
||||||
{
|
|
||||||
case WEBSOCKET_EVENT_CONNECTED:
|
|
||||||
Serial.println(F("Connected to Mempool.space WebSocket"));
|
|
||||||
|
|
||||||
Serial.println(sub);
|
|
||||||
if (esp_websocket_client_send_text(blockNotifyClient, sub.c_str(), sub.length(), portMAX_DELAY) == -1)
|
|
||||||
{
|
|
||||||
Serial.println(F("Mempool.space WS Block Subscribe Error"));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
if (getCurrentScreen() == SCREEN_BLOCK_HEIGHT &&
|
||||||
case WEBSOCKET_EVENT_DATA:
|
preferences.getBool("ledFlashOnUpd", false)) {
|
||||||
onWebsocketMessage(data);
|
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
||||||
break;
|
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
||||||
case WEBSOCKET_EVENT_ERROR:
|
}
|
||||||
Serial.println(F("Mempool.space WS Connnection error"));
|
|
||||||
break;
|
|
||||||
case WEBSOCKET_EVENT_DISCONNECTED:
|
|
||||||
Serial.println(F("Mempool.space WS Connnection Closed"));
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onWebsocketMessage(esp_websocket_event_data_t *event_data)
|
uint getBlockHeight() { return currentBlockHeight; }
|
||||||
{
|
|
||||||
SpiRamJsonDocument doc(event_data->data_len);
|
|
||||||
|
|
||||||
deserializeJson(doc, (char *)event_data->data_ptr);
|
void setBlockHeight(uint newBlockHeight) {
|
||||||
|
currentBlockHeight = newBlockHeight;
|
||||||
if (doc.containsKey("block"))
|
|
||||||
{
|
|
||||||
JsonObject block = doc["block"];
|
|
||||||
|
|
||||||
currentBlockHeight = block["height"].as<uint>();
|
|
||||||
|
|
||||||
Serial.printf("New block found: %d\r\n", block["height"].as<uint>());
|
|
||||||
preferences.putUInt("blockHeight", currentBlockHeight);
|
|
||||||
|
|
||||||
if (workQueue != nullptr)
|
|
||||||
{
|
|
||||||
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
|
||||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
|
||||||
// xTaskNotifyGive(blockUpdateTaskHandle);
|
|
||||||
|
|
||||||
if (getCurrentScreen() != SCREEN_BLOCK_HEIGHT && preferences.getBool("stealFocus", true))
|
|
||||||
{
|
|
||||||
uint64_t timerPeriod = 0;
|
|
||||||
if (isTimerActive()) {
|
|
||||||
// store timer periode before making inactive to prevent artifacts
|
|
||||||
timerPeriod = getTimerSeconds();
|
|
||||||
esp_timer_stop(screenRotateTimer);
|
|
||||||
}
|
|
||||||
setCurrentScreen(SCREEN_BLOCK_HEIGHT);
|
|
||||||
if (timerPeriod > 0) {
|
|
||||||
esp_timer_start_periodic(screenRotateTimer, timerPeriod * usPerSecond);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getCurrentScreen() == SCREEN_BLOCK_HEIGHT && preferences.getBool("ledFlashOnUpd", false))
|
|
||||||
{
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(250)); // Wait until screens are updated
|
|
||||||
queueLedEffect(LED_FLASH_BLOCK_NOTIFY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
doc.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getBlockHeight()
|
bool isBlockNotifyConnected() {
|
||||||
{
|
if (blockNotifyClient == NULL)
|
||||||
return currentBlockHeight;
|
return false;
|
||||||
|
return esp_websocket_client_is_connected(blockNotifyClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setBlockHeight(uint newBlockHeight)
|
void stopBlockNotify() {
|
||||||
{
|
esp_websocket_client_stop(blockNotifyClient);
|
||||||
currentBlockHeight = newBlockHeight;
|
esp_websocket_client_destroy(blockNotifyClient);
|
||||||
}
|
|
||||||
|
|
||||||
bool isBlockNotifyConnected()
|
|
||||||
{
|
|
||||||
if (blockNotifyClient == NULL)
|
|
||||||
return false;
|
|
||||||
return esp_websocket_client_is_connected(blockNotifyClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stopBlockNotify()
|
|
||||||
{
|
|
||||||
esp_websocket_client_stop(blockNotifyClient);
|
|
||||||
esp_websocket_client_destroy(blockNotifyClient);
|
|
||||||
}
|
}
|
|
@ -1,22 +1,23 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstring>
|
#include "lib/led_handler.hpp"
|
||||||
#include <string>
|
#include "lib/screen_handler.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <HTTPClient.h>
|
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include "shared.hpp"
|
#include <HTTPClient.h>
|
||||||
#include "esp_timer.h"
|
#include <cstring>
|
||||||
#include "esp_websocket_client.h"
|
#include <esp_timer.h>
|
||||||
#include "screen_handler.hpp"
|
#include <esp_websocket_client.h>
|
||||||
#include "led_handler.hpp"
|
#include <string>
|
||||||
|
|
||||||
//using namespace websockets;
|
// using namespace websockets;
|
||||||
|
|
||||||
void setupBlockNotify();
|
void setupBlockNotify();
|
||||||
|
|
||||||
void onWebsocketEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
void onWebsocketEvent(void *handler_args, esp_event_base_t base,
|
||||||
void onWebsocketMessage(esp_websocket_event_data_t* event_data);
|
int32_t event_id, void *event_data);
|
||||||
|
void onWebsocketMessage(esp_websocket_event_data_t *event_data);
|
||||||
|
|
||||||
void setBlockHeight(uint newBlockHeight);
|
void setBlockHeight(uint newBlockHeight);
|
||||||
uint getBlockHeight();
|
uint getBlockHeight();
|
||||||
|
|
|
@ -4,64 +4,54 @@ TaskHandle_t buttonTaskHandle = NULL;
|
||||||
const TickType_t debounceDelay = pdMS_TO_TICKS(50);
|
const TickType_t debounceDelay = pdMS_TO_TICKS(50);
|
||||||
TickType_t lastDebounceTime = 0;
|
TickType_t lastDebounceTime = 0;
|
||||||
|
|
||||||
void buttonTask(void *parameter)
|
void buttonTask(void *parameter) {
|
||||||
{
|
while (1) {
|
||||||
while (1)
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
{
|
std::lock_guard<std::mutex> lock(mcpMutex);
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
std::lock_guard<std::mutex> lock(mcpMutex);
|
|
||||||
|
|
||||||
TickType_t currentTime = xTaskGetTickCount();
|
TickType_t currentTime = xTaskGetTickCount();
|
||||||
if ((currentTime - lastDebounceTime) >= debounceDelay)
|
if ((currentTime - lastDebounceTime) >= debounceDelay) {
|
||||||
{
|
lastDebounceTime = currentTime;
|
||||||
lastDebounceTime = currentTime;
|
|
||||||
|
|
||||||
if (!digitalRead(MCP_INT_PIN))
|
if (!digitalRead(MCP_INT_PIN)) {
|
||||||
{
|
uint pin = mcp1.getLastInterruptPin();
|
||||||
uint pin = mcp1.getLastInterruptPin();
|
|
||||||
|
|
||||||
switch (pin)
|
switch (pin) {
|
||||||
{
|
case 3:
|
||||||
case 3:
|
toggleTimerActive();
|
||||||
toggleTimerActive();
|
break;
|
||||||
break;
|
case 2:
|
||||||
case 2:
|
nextScreen();
|
||||||
nextScreen();
|
break;
|
||||||
break;
|
case 1:
|
||||||
case 1:
|
previousScreen();
|
||||||
previousScreen();
|
break;
|
||||||
break;
|
case 0:
|
||||||
case 0:
|
showSystemStatusScreen();
|
||||||
showSystemStatusScreen();
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mcp1.clearInterrupts();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
}
|
|
||||||
// Very ugly, but for some reason this is necessary
|
|
||||||
while (!digitalRead(MCP_INT_PIN))
|
|
||||||
{
|
|
||||||
mcp1.clearInterrupts();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
mcp1.clearInterrupts();
|
||||||
|
} else {
|
||||||
}
|
}
|
||||||
}
|
// Very ugly, but for some reason this is necessary
|
||||||
|
while (!digitalRead(MCP_INT_PIN)) {
|
||||||
void IRAM_ATTR handleButtonInterrupt()
|
mcp1.clearInterrupts();
|
||||||
{
|
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
|
||||||
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
|
|
||||||
if (xHigherPriorityTaskWoken == pdTRUE)
|
|
||||||
{
|
|
||||||
portYIELD_FROM_ISR();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupButtonTask()
|
void IRAM_ATTR handleButtonInterrupt() {
|
||||||
{
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
xTaskCreate(buttonTask, "ButtonTask", 4096, NULL, tskIDLE_PRIORITY, &buttonTaskHandle); // Create the FreeRTOS task
|
xTaskNotifyFromISR(buttonTaskHandle, 0, eNoAction, &xHigherPriorityTaskWoken);
|
||||||
// Use interrupt instead of task
|
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||||
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE);
|
portYIELD_FROM_ISR();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupButtonTask() {
|
||||||
|
xTaskCreate(buttonTask, "ButtonTask", 4096, NULL, tskIDLE_PRIORITY,
|
||||||
|
&buttonTaskHandle); // Create the FreeRTOS task
|
||||||
|
// Use interrupt instead of task
|
||||||
|
attachInterrupt(MCP_INT_PIN, handleButtonInterrupt, CHANGE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "lib/screen_handler.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "shared.hpp"
|
|
||||||
#include "screen_handler.hpp"
|
|
||||||
|
|
||||||
extern TaskHandle_t buttonTaskHandle;
|
extern TaskHandle_t buttonTaskHandle;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,26 +1,23 @@
|
||||||
#pragma once;
|
#pragma once;
|
||||||
#include <WiFiManager.h>
|
|
||||||
#include "base64.h"
|
|
||||||
|
|
||||||
#include <WiFiClientSecure.h>
|
|
||||||
#include <Preferences.h>
|
|
||||||
#include <Adafruit_MCP23X17.h>
|
#include <Adafruit_MCP23X17.h>
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include "shared.hpp"
|
#include <Preferences.h>
|
||||||
#include "epd.hpp"
|
#include <WiFiClientSecure.h>
|
||||||
#include "improv.hpp"
|
#include <WiFiManager.h>
|
||||||
#include "esp_task_wdt.h"
|
#include <base64.h>
|
||||||
|
#include <esp_task_wdt.h>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "ota.hpp"
|
|
||||||
#include "lib/screen_handler.hpp"
|
|
||||||
#include "lib/webserver.hpp"
|
|
||||||
#include "lib/block_notify.hpp"
|
#include "lib/block_notify.hpp"
|
||||||
#include "lib/price_notify.hpp"
|
|
||||||
#include "lib/button_handler.hpp"
|
#include "lib/button_handler.hpp"
|
||||||
|
#include "lib/epd.hpp"
|
||||||
|
#include "lib/improv.hpp"
|
||||||
#include "lib/led_handler.hpp"
|
#include "lib/led_handler.hpp"
|
||||||
|
#include "lib/ota.hpp"
|
||||||
|
#include "lib/price_notify.hpp"
|
||||||
|
#include "lib/screen_handler.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
|
#include "lib/webserver.hpp"
|
||||||
|
|
||||||
#define NTP_SERVER "pool.ntp.org"
|
#define NTP_SERVER "pool.ntp.org"
|
||||||
#define DEFAULT_MEMPOOL_INSTANCE "mempool.space"
|
#define DEFAULT_MEMPOOL_INSTANCE "mempool.space"
|
||||||
|
|
645
src/lib/epd.cpp
645
src/lib/epd.cpp
|
@ -16,21 +16,12 @@ Native_Pin EPD_CS[NUM_SCREENS] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
Native_Pin EPD_BUSY[NUM_SCREENS] = {
|
Native_Pin EPD_BUSY[NUM_SCREENS] = {
|
||||||
Native_Pin(3),
|
Native_Pin(3), Native_Pin(5), Native_Pin(7), Native_Pin(9),
|
||||||
Native_Pin(5),
|
Native_Pin(37), Native_Pin(18), Native_Pin(16),
|
||||||
Native_Pin(7),
|
|
||||||
Native_Pin(9),
|
|
||||||
Native_Pin(37),
|
|
||||||
Native_Pin(18),
|
|
||||||
Native_Pin(16),
|
|
||||||
};
|
};
|
||||||
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp1, 8),
|
MCP23X17_Pin(mcp1, 8), MCP23X17_Pin(mcp1, 9), MCP23X17_Pin(mcp1, 10),
|
||||||
MCP23X17_Pin(mcp1, 9),
|
MCP23X17_Pin(mcp1, 11), MCP23X17_Pin(mcp1, 12), MCP23X17_Pin(mcp1, 13),
|
||||||
MCP23X17_Pin(mcp1, 10),
|
|
||||||
MCP23X17_Pin(mcp1, 11),
|
|
||||||
MCP23X17_Pin(mcp1, 12),
|
|
||||||
MCP23X17_Pin(mcp1, 13),
|
|
||||||
MCP23X17_Pin(mcp1, 14),
|
MCP23X17_Pin(mcp1, 14),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,36 +30,20 @@ Native_Pin EPD_DC = Native_Pin(14);
|
||||||
Native_Pin EPD_DC = Native_Pin(38);
|
Native_Pin EPD_DC = Native_Pin(38);
|
||||||
|
|
||||||
MCP23X17_Pin EPD_BUSY[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_BUSY[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp1, 8),
|
MCP23X17_Pin(mcp1, 8), MCP23X17_Pin(mcp1, 9), MCP23X17_Pin(mcp1, 10),
|
||||||
MCP23X17_Pin(mcp1, 9),
|
MCP23X17_Pin(mcp1, 11), MCP23X17_Pin(mcp1, 12), MCP23X17_Pin(mcp1, 13),
|
||||||
MCP23X17_Pin(mcp1, 10),
|
MCP23X17_Pin(mcp1, 14), MCP23X17_Pin(mcp1, 4),
|
||||||
MCP23X17_Pin(mcp1, 11),
|
|
||||||
MCP23X17_Pin(mcp1, 12),
|
|
||||||
MCP23X17_Pin(mcp1, 13),
|
|
||||||
MCP23X17_Pin(mcp1, 14),
|
|
||||||
MCP23X17_Pin(mcp1, 4),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
MCP23X17_Pin EPD_CS[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_CS[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp2, 8),
|
MCP23X17_Pin(mcp2, 8), MCP23X17_Pin(mcp2, 10), MCP23X17_Pin(mcp2, 12),
|
||||||
MCP23X17_Pin(mcp2, 10),
|
MCP23X17_Pin(mcp2, 14), MCP23X17_Pin(mcp2, 0), MCP23X17_Pin(mcp2, 2),
|
||||||
MCP23X17_Pin(mcp2, 12),
|
MCP23X17_Pin(mcp2, 4), MCP23X17_Pin(mcp2, 6)};
|
||||||
MCP23X17_Pin(mcp2, 14),
|
|
||||||
MCP23X17_Pin(mcp2, 0),
|
|
||||||
MCP23X17_Pin(mcp2, 2),
|
|
||||||
MCP23X17_Pin(mcp2, 4),
|
|
||||||
MCP23X17_Pin(mcp2, 6)
|
|
||||||
};
|
|
||||||
|
|
||||||
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
MCP23X17_Pin EPD_RESET_MPD[NUM_SCREENS] = {
|
||||||
MCP23X17_Pin(mcp2, 9),
|
MCP23X17_Pin(mcp2, 9), MCP23X17_Pin(mcp2, 11), MCP23X17_Pin(mcp2, 13),
|
||||||
MCP23X17_Pin(mcp2, 11),
|
MCP23X17_Pin(mcp2, 15), MCP23X17_Pin(mcp2, 1), MCP23X17_Pin(mcp2, 3),
|
||||||
MCP23X17_Pin(mcp2, 13),
|
MCP23X17_Pin(mcp2, 5), MCP23X17_Pin(mcp2, 7),
|
||||||
MCP23X17_Pin(mcp2, 15),
|
|
||||||
MCP23X17_Pin(mcp2, 1),
|
|
||||||
MCP23X17_Pin(mcp2, 3),
|
|
||||||
MCP23X17_Pin(mcp2, 5),
|
|
||||||
MCP23X17_Pin(mcp2, 7),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -108,369 +83,329 @@ std::mutex epdMutex[NUM_SCREENS];
|
||||||
|
|
||||||
uint8_t qrcode[800];
|
uint8_t qrcode[800];
|
||||||
|
|
||||||
void forceFullRefresh()
|
void forceFullRefresh() {
|
||||||
{
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
lastFullRefresh[i] = NULL;
|
||||||
{
|
}
|
||||||
lastFullRefresh[i] = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void refreshFromMemory()
|
void refreshFromMemory() {
|
||||||
{
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
int *taskParam = new int;
|
||||||
{
|
*taskParam = i;
|
||||||
int *taskParam = new int;
|
|
||||||
*taskParam = i;
|
|
||||||
|
|
||||||
xTaskCreate([](void *pvParameters)
|
xTaskCreate(
|
||||||
{
|
[](void *pvParameters) {
|
||||||
const int epdIndex = *(int *)pvParameters;
|
const int epdIndex = *(int *)pvParameters;
|
||||||
delete (int *)pvParameters;
|
delete (int *)pvParameters;
|
||||||
displays[epdIndex].refresh(false);
|
displays[epdIndex].refresh(false);
|
||||||
vTaskDelete(NULL); },
|
vTaskDelete(NULL);
|
||||||
"PrepareUpd", 4096, taskParam, tskIDLE_PRIORITY, NULL);
|
},
|
||||||
}
|
"PrepareUpd", 4096, taskParam, tskIDLE_PRIORITY, NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupDisplays()
|
void setupDisplays() {
|
||||||
{
|
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
||||||
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
{
|
displays[i].init(0, true, 30);
|
||||||
displays[i].init(0, true, 30);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
updateQueue = xQueueCreate(UPDATE_QUEUE_SIZE, sizeof(UpdateDisplayTaskItem));
|
updateQueue = xQueueCreate(UPDATE_QUEUE_SIZE, sizeof(UpdateDisplayTaskItem));
|
||||||
|
|
||||||
xTaskCreate(prepareDisplayUpdateTask, "PrepareUpd", 4096, NULL, 11, NULL);
|
xTaskCreate(prepareDisplayUpdateTask, "PrepareUpd", 4096, NULL, 11, NULL);
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
{
|
// epdUpdateSemaphore[i] = xSemaphoreCreateBinary();
|
||||||
// epdUpdateSemaphore[i] = xSemaphoreCreateBinary();
|
// xSemaphoreGive(epdUpdateSemaphore[i]);
|
||||||
// xSemaphoreGive(epdUpdateSemaphore[i]);
|
|
||||||
|
|
||||||
int *taskParam = new int;
|
int *taskParam = new int;
|
||||||
*taskParam = i;
|
*taskParam = i;
|
||||||
|
|
||||||
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 2048, taskParam, 11, &tasks[i]); // create task
|
xTaskCreate(updateDisplay, ("EpdUpd" + String(i)).c_str(), 2048, taskParam,
|
||||||
}
|
11, &tasks[i]); // create task
|
||||||
|
}
|
||||||
|
|
||||||
epdContent = {"B",
|
epdContent = {"B", "T", "C", "L", "O", "C", "K"};
|
||||||
"T",
|
|
||||||
"C",
|
|
||||||
"L",
|
|
||||||
"O",
|
|
||||||
"C",
|
|
||||||
"K"};
|
|
||||||
|
|
||||||
setEpdContent(epdContent);
|
setEpdContent(epdContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent)
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent) {
|
||||||
{
|
setEpdContent(newEpdContent, false);
|
||||||
setEpdContent(newEpdContent, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent) {
|
void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent) {
|
||||||
std::array<String, NUM_SCREENS> conv;
|
std::array<String, NUM_SCREENS> conv;
|
||||||
|
|
||||||
for (size_t i = 0; i < newEpdContent.size(); ++i) {
|
for (size_t i = 0; i < newEpdContent.size(); ++i) {
|
||||||
conv[i] = String(newEpdContent[i].c_str());
|
conv[i] = String(newEpdContent[i].c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
return setEpdContent(conv);
|
return setEpdContent(conv);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent, bool forceUpdate)
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent,
|
||||||
{
|
bool forceUpdate) {
|
||||||
std::lock_guard<std::mutex> lock(epdUpdateMutex);
|
std::lock_guard<std::mutex> lock(epdUpdateMutex);
|
||||||
|
|
||||||
waitUntilNoneBusy();
|
waitUntilNoneBusy();
|
||||||
|
|
||||||
|
for (uint i = 0; i < NUM_SCREENS; i++) {
|
||||||
|
if (newEpdContent[i].compareTo(currentEpdContent[i]) != 0 || forceUpdate) {
|
||||||
|
epdContent[i] = newEpdContent[i];
|
||||||
|
UpdateDisplayTaskItem dispUpdate = {i};
|
||||||
|
xQueueSend(updateQueue, &dispUpdate, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepareDisplayUpdateTask(void *pvParameters) {
|
||||||
|
UpdateDisplayTaskItem receivedItem;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
// Wait for a work item to be available in the queue
|
||||||
|
if (xQueueReceive(updateQueue, &receivedItem, portMAX_DELAY)) {
|
||||||
|
uint epdIndex = receivedItem.dispNum;
|
||||||
|
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
|
||||||
|
// displays[epdIndex].init(0, false); // Little longer reset duration
|
||||||
|
// because of MCP
|
||||||
|
|
||||||
|
bool updatePartial = true;
|
||||||
|
|
||||||
|
if (strstr(epdContent[epdIndex].c_str(), "/") != NULL) {
|
||||||
|
String top = epdContent[epdIndex].substring(
|
||||||
|
0, epdContent[epdIndex].indexOf("/"));
|
||||||
|
String bottom = epdContent[epdIndex].substring(
|
||||||
|
epdContent[epdIndex].indexOf("/") + 1);
|
||||||
|
splitText(epdIndex, top, bottom, updatePartial);
|
||||||
|
} else if (epdContent[epdIndex].startsWith(F("qr"))) {
|
||||||
|
renderQr(epdIndex, epdContent[epdIndex], updatePartial);
|
||||||
|
} else if (epdContent[epdIndex].length() > 5) {
|
||||||
|
renderText(epdIndex, epdContent[epdIndex], updatePartial);
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (epdContent[epdIndex].length() > 1) {
|
||||||
|
showChars(epdIndex, epdContent[epdIndex], updatePartial,
|
||||||
|
&FONT_MEDIUM);
|
||||||
|
} else {
|
||||||
|
showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial,
|
||||||
|
&FONT_BIG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xTaskNotifyGive(tasks[epdIndex]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void updateDisplay(void *pvParameters) noexcept {
|
||||||
|
const int epdIndex = *(int *)pvParameters;
|
||||||
|
delete (int *)pvParameters;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
// Wait for the task notification
|
||||||
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
|
||||||
|
|
||||||
for (uint i = 0; i < NUM_SCREENS; i++)
|
|
||||||
{
|
{
|
||||||
if (newEpdContent[i].compareTo(currentEpdContent[i]) != 0 || forceUpdate)
|
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
||||||
{
|
|
||||||
epdContent[i] = newEpdContent[i];
|
displays[epdIndex].init(0, false, 40);
|
||||||
UpdateDisplayTaskItem dispUpdate = {i};
|
|
||||||
xQueueSend(updateQueue, &dispUpdate, portMAX_DELAY);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
uint count = 0;
|
||||||
|
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10) {
|
||||||
void prepareDisplayUpdateTask(void *pvParameters)
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
{
|
count++;
|
||||||
UpdateDisplayTaskItem receivedItem;
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
// Wait for a work item to be available in the queue
|
|
||||||
if (xQueueReceive(updateQueue, &receivedItem, portMAX_DELAY))
|
|
||||||
{
|
|
||||||
uint epdIndex = receivedItem.dispNum;
|
|
||||||
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
|
|
||||||
// displays[epdIndex].init(0, false); // Little longer reset duration because of MCP
|
|
||||||
|
|
||||||
bool updatePartial = true;
|
|
||||||
|
|
||||||
if (strstr(epdContent[epdIndex].c_str(), "/") != NULL)
|
|
||||||
{
|
|
||||||
String top = epdContent[epdIndex].substring(0, epdContent[epdIndex].indexOf("/"));
|
|
||||||
String bottom = epdContent[epdIndex].substring(epdContent[epdIndex].indexOf("/") + 1);
|
|
||||||
splitText(epdIndex, top, bottom, updatePartial);
|
|
||||||
}
|
|
||||||
else if (epdContent[epdIndex].startsWith(F("qr")))
|
|
||||||
{
|
|
||||||
renderQr(epdIndex, epdContent[epdIndex], updatePartial);
|
|
||||||
}
|
|
||||||
else if (epdContent[epdIndex].length() > 5)
|
|
||||||
{
|
|
||||||
renderText(epdIndex, epdContent[epdIndex], updatePartial);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
|
|
||||||
if (epdContent[epdIndex].length() > 1)
|
|
||||||
{
|
|
||||||
showChars(epdIndex, epdContent[epdIndex], updatePartial, &FONT_MEDIUM);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
showDigit(epdIndex, epdContent[epdIndex].c_str()[0], updatePartial, &FONT_BIG);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
xTaskNotifyGive(tasks[epdIndex]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void updateDisplay(void *pvParameters) noexcept
|
bool updatePartial = true;
|
||||||
{
|
|
||||||
const int epdIndex = *(int *)pvParameters;
|
|
||||||
delete (int *)pvParameters;
|
|
||||||
|
|
||||||
for (;;)
|
// Full Refresh every x minutes
|
||||||
{
|
if (!lastFullRefresh[epdIndex] ||
|
||||||
// Wait for the task notification
|
(millis() - lastFullRefresh[epdIndex]) >
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
(preferences.getUInt("fullRefreshMin",
|
||||||
|
DEFAULT_MINUTES_FULL_REFRESH) *
|
||||||
std::lock_guard<std::mutex> lock(epdMutex[epdIndex]);
|
60 * 1000)) {
|
||||||
|
updatePartial = false;
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lockMcp(mcpMutex);
|
|
||||||
|
|
||||||
displays[epdIndex].init(0, false, 40);
|
|
||||||
}
|
|
||||||
uint count = 0;
|
|
||||||
while (EPD_BUSY[epdIndex].digitalRead() == HIGH || count < 10)
|
|
||||||
{
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool updatePartial = true;
|
|
||||||
|
|
||||||
// Full Refresh every x minutes
|
|
||||||
if (!lastFullRefresh[epdIndex] || (millis() - lastFullRefresh[epdIndex]) > (preferences.getUInt("fullRefreshMin", DEFAULT_MINUTES_FULL_REFRESH) * 60 * 1000))
|
|
||||||
{
|
|
||||||
updatePartial = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
char tries = 0;
|
|
||||||
while (tries < 3)
|
|
||||||
{
|
|
||||||
if (displays[epdIndex].displayWithReturn(updatePartial))
|
|
||||||
{
|
|
||||||
displays[epdIndex].powerOff();
|
|
||||||
currentEpdContent[epdIndex] = epdContent[epdIndex];
|
|
||||||
if (!updatePartial)
|
|
||||||
lastFullRefresh[epdIndex] = millis();
|
|
||||||
|
|
||||||
if (eventSourceTaskHandle != NULL)
|
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
tries++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void splitText(const uint dispNum, const String &top, const String &bottom, bool partial)
|
char tries = 0;
|
||||||
{
|
while (tries < 3) {
|
||||||
displays[dispNum].setRotation(2);
|
if (displays[epdIndex].displayWithReturn(updatePartial)) {
|
||||||
displays[dispNum].setFont(&FONT_SMALL);
|
displays[epdIndex].powerOff();
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
currentEpdContent[epdIndex] = epdContent[epdIndex];
|
||||||
|
if (!updatePartial)
|
||||||
|
lastFullRefresh[epdIndex] = millis();
|
||||||
|
|
||||||
// Top text
|
if (eventSourceTaskHandle != NULL)
|
||||||
int16_t ttbx, ttby;
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
uint16_t ttbw, ttbh;
|
|
||||||
displays[dispNum].getTextBounds(top, 0, 0, &ttbx, &ttby, &ttbw, &ttbh);
|
|
||||||
uint16_t tx = ((displays[dispNum].width() - ttbw) / 2) - ttbx;
|
|
||||||
uint16_t ty = ((displays[dispNum].height() - ttbh) / 2) - ttby - ttbh / 2 - 12;
|
|
||||||
|
|
||||||
// Bottom text
|
break;
|
||||||
int16_t tbbx, tbby;
|
}
|
||||||
uint16_t tbbw, tbbh;
|
|
||||||
displays[dispNum].getTextBounds(bottom, 0, 0, &tbbx, &tbby, &tbbw, &tbbh);
|
|
||||||
uint16_t bx = ((displays[dispNum].width() - tbbw) / 2) - tbbx;
|
|
||||||
uint16_t by = ((displays[dispNum].height() - tbbh) / 2) - tbby + tbbh / 2 + 12;
|
|
||||||
|
|
||||||
// Make separator as wide as the shortest text.
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
uint16_t lineWidth, lineX;
|
tries++;
|
||||||
if (tbbw < ttbh)
|
|
||||||
lineWidth = tbbw;
|
|
||||||
else
|
|
||||||
lineWidth = ttbw;
|
|
||||||
lineX = round((displays[dispNum].width() - lineWidth) / 2);
|
|
||||||
|
|
||||||
displays[dispNum].fillScreen(getBgColor());
|
|
||||||
displays[dispNum].setCursor(tx, ty);
|
|
||||||
displays[dispNum].print(top);
|
|
||||||
displays[dispNum].fillRoundRect(lineX, displays[dispNum].height() / 2 - 3, lineWidth, 6, 3, getFgColor());
|
|
||||||
displays[dispNum].setCursor(bx, by);
|
|
||||||
displays[dispNum].print(bottom);
|
|
||||||
}
|
|
||||||
|
|
||||||
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font)
|
|
||||||
{
|
|
||||||
String str(chr);
|
|
||||||
displays[dispNum].setRotation(2);
|
|
||||||
displays[dispNum].setFont(font);
|
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
|
||||||
int16_t tbx, tby;
|
|
||||||
uint16_t tbw, tbh;
|
|
||||||
displays[dispNum].getTextBounds(str, 0, 0, &tbx, &tby, &tbw, &tbh);
|
|
||||||
// center the bounding box by transposition of the origin:
|
|
||||||
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
|
||||||
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
|
||||||
displays[dispNum].fillScreen(getBgColor());
|
|
||||||
displays[dispNum].setCursor(x, y);
|
|
||||||
displays[dispNum].print(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
void showChars(const uint dispNum, const String &chars, bool partial, const GFXfont *font)
|
|
||||||
{
|
|
||||||
displays[dispNum].setRotation(2);
|
|
||||||
displays[dispNum].setFont(font);
|
|
||||||
displays[dispNum].setTextColor(getFgColor());
|
|
||||||
int16_t tbx, tby;
|
|
||||||
uint16_t tbw, tbh;
|
|
||||||
displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh);
|
|
||||||
// center the bounding box by transposition of the origin:
|
|
||||||
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
|
||||||
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
|
||||||
displays[dispNum].fillScreen(getBgColor());
|
|
||||||
displays[dispNum].setCursor(x, y);
|
|
||||||
displays[dispNum].print(chars);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getBgColor()
|
|
||||||
{
|
|
||||||
return bgColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getFgColor()
|
|
||||||
{
|
|
||||||
return fgColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setBgColor(int color)
|
|
||||||
{
|
|
||||||
bgColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setFgColor(int color)
|
|
||||||
{
|
|
||||||
fgColor = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<String, NUM_SCREENS> getCurrentEpdContent()
|
|
||||||
{
|
|
||||||
return currentEpdContent;
|
|
||||||
}
|
|
||||||
void renderText(const uint dispNum, const String &text, bool partial)
|
|
||||||
{
|
|
||||||
displays[dispNum].setRotation(2);
|
|
||||||
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
|
|
||||||
displays[dispNum].fillScreen(GxEPD_WHITE);
|
|
||||||
displays[dispNum].setTextColor(GxEPD_BLACK);
|
|
||||||
displays[dispNum].setCursor(0, 50);
|
|
||||||
|
|
||||||
std::stringstream ss;
|
|
||||||
ss.str(text.c_str());
|
|
||||||
|
|
||||||
std::string line;
|
|
||||||
|
|
||||||
while (std::getline(ss, line, '\n'))
|
|
||||||
{
|
|
||||||
if (line.rfind("*", 0) == 0)
|
|
||||||
{
|
|
||||||
line.erase(std::remove(line.begin(), line.end(), '*'), line.end());
|
|
||||||
|
|
||||||
displays[dispNum].setFont(&FreeSansBold9pt7b);
|
|
||||||
displays[dispNum].println(line.c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
displays[dispNum].setFont(&FreeSans9pt7b);
|
|
||||||
displays[dispNum].println(line.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderQr(const uint dispNum, const String &text, bool partial)
|
void splitText(const uint dispNum, const String &top, const String &bottom,
|
||||||
{
|
bool partial) {
|
||||||
|
displays[dispNum].setRotation(2);
|
||||||
|
displays[dispNum].setFont(&FONT_SMALL);
|
||||||
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
|
|
||||||
|
// Top text
|
||||||
|
int16_t ttbx, ttby;
|
||||||
|
uint16_t ttbw, ttbh;
|
||||||
|
displays[dispNum].getTextBounds(top, 0, 0, &ttbx, &ttby, &ttbw, &ttbh);
|
||||||
|
uint16_t tx = ((displays[dispNum].width() - ttbw) / 2) - ttbx;
|
||||||
|
uint16_t ty =
|
||||||
|
((displays[dispNum].height() - ttbh) / 2) - ttby - ttbh / 2 - 12;
|
||||||
|
|
||||||
|
// Bottom text
|
||||||
|
int16_t tbbx, tbby;
|
||||||
|
uint16_t tbbw, tbbh;
|
||||||
|
displays[dispNum].getTextBounds(bottom, 0, 0, &tbbx, &tbby, &tbbw, &tbbh);
|
||||||
|
uint16_t bx = ((displays[dispNum].width() - tbbw) / 2) - tbbx;
|
||||||
|
uint16_t by =
|
||||||
|
((displays[dispNum].height() - tbbh) / 2) - tbby + tbbh / 2 + 12;
|
||||||
|
|
||||||
|
// Make separator as wide as the shortest text.
|
||||||
|
uint16_t lineWidth, lineX;
|
||||||
|
if (tbbw < ttbh)
|
||||||
|
lineWidth = tbbw;
|
||||||
|
else
|
||||||
|
lineWidth = ttbw;
|
||||||
|
lineX = round((displays[dispNum].width() - lineWidth) / 2);
|
||||||
|
|
||||||
|
displays[dispNum].fillScreen(getBgColor());
|
||||||
|
displays[dispNum].setCursor(tx, ty);
|
||||||
|
displays[dispNum].print(top);
|
||||||
|
displays[dispNum].fillRoundRect(lineX, displays[dispNum].height() / 2 - 3,
|
||||||
|
lineWidth, 6, 3, getFgColor());
|
||||||
|
displays[dispNum].setCursor(bx, by);
|
||||||
|
displays[dispNum].print(bottom);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showDigit(const uint dispNum, char chr, bool partial,
|
||||||
|
const GFXfont *font) {
|
||||||
|
String str(chr);
|
||||||
|
displays[dispNum].setRotation(2);
|
||||||
|
displays[dispNum].setFont(font);
|
||||||
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
|
int16_t tbx, tby;
|
||||||
|
uint16_t tbw, tbh;
|
||||||
|
displays[dispNum].getTextBounds(str, 0, 0, &tbx, &tby, &tbw, &tbh);
|
||||||
|
// center the bounding box by transposition of the origin:
|
||||||
|
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
||||||
|
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
||||||
|
displays[dispNum].fillScreen(getBgColor());
|
||||||
|
displays[dispNum].setCursor(x, y);
|
||||||
|
displays[dispNum].print(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showChars(const uint dispNum, const String &chars, bool partial,
|
||||||
|
const GFXfont *font) {
|
||||||
|
displays[dispNum].setRotation(2);
|
||||||
|
displays[dispNum].setFont(font);
|
||||||
|
displays[dispNum].setTextColor(getFgColor());
|
||||||
|
int16_t tbx, tby;
|
||||||
|
uint16_t tbw, tbh;
|
||||||
|
displays[dispNum].getTextBounds(chars, 0, 0, &tbx, &tby, &tbw, &tbh);
|
||||||
|
// center the bounding box by transposition of the origin:
|
||||||
|
uint16_t x = ((displays[dispNum].width() - tbw) / 2) - tbx;
|
||||||
|
uint16_t y = ((displays[dispNum].height() - tbh) / 2) - tby;
|
||||||
|
displays[dispNum].fillScreen(getBgColor());
|
||||||
|
displays[dispNum].setCursor(x, y);
|
||||||
|
displays[dispNum].print(chars);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getBgColor() { return bgColor; }
|
||||||
|
|
||||||
|
int getFgColor() { return fgColor; }
|
||||||
|
|
||||||
|
void setBgColor(int color) { bgColor = color; }
|
||||||
|
|
||||||
|
void setFgColor(int color) { fgColor = color; }
|
||||||
|
|
||||||
|
std::array<String, NUM_SCREENS> getCurrentEpdContent() {
|
||||||
|
return currentEpdContent;
|
||||||
|
}
|
||||||
|
void renderText(const uint dispNum, const String &text, bool partial) {
|
||||||
|
displays[dispNum].setRotation(2);
|
||||||
|
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(),
|
||||||
|
displays[dispNum].height());
|
||||||
|
displays[dispNum].fillScreen(GxEPD_WHITE);
|
||||||
|
displays[dispNum].setTextColor(GxEPD_BLACK);
|
||||||
|
displays[dispNum].setCursor(0, 50);
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss.str(text.c_str());
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
while (std::getline(ss, line, '\n')) {
|
||||||
|
if (line.rfind("*", 0) == 0) {
|
||||||
|
line.erase(std::remove(line.begin(), line.end(), '*'), line.end());
|
||||||
|
|
||||||
|
displays[dispNum].setFont(&FreeSansBold9pt7b);
|
||||||
|
displays[dispNum].println(line.c_str());
|
||||||
|
} else {
|
||||||
|
displays[dispNum].setFont(&FreeSans9pt7b);
|
||||||
|
displays[dispNum].println(line.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void renderQr(const uint dispNum, const String &text, bool partial) {
|
||||||
#ifdef USE_QR
|
#ifdef USE_QR
|
||||||
|
|
||||||
uint8_t tempBuffer[800];
|
uint8_t tempBuffer[800];
|
||||||
bool ok = qrcodegen_encodeText(text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
bool ok = qrcodegen_encodeText(
|
||||||
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
|
text.substring(2).c_str(), tempBuffer, qrcode, qrcodegen_Ecc_LOW,
|
||||||
|
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
|
||||||
|
|
||||||
const int size = qrcodegen_getSize(qrcode);
|
const int size = qrcodegen_getSize(qrcode);
|
||||||
|
|
||||||
const int padding = floor(float(displays[dispNum].width() - (size * 4)) / 2);
|
const int padding = floor(float(displays[dispNum].width() - (size * 4)) / 2);
|
||||||
const int paddingY = floor(float(displays[dispNum].height() - (size * 4)) / 2);
|
const int paddingY =
|
||||||
displays[dispNum].setRotation(2);
|
floor(float(displays[dispNum].height() - (size * 4)) / 2);
|
||||||
|
displays[dispNum].setRotation(2);
|
||||||
|
|
||||||
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(), displays[dispNum].height());
|
displays[dispNum].setPartialWindow(0, 0, displays[dispNum].width(),
|
||||||
displays[dispNum].fillScreen(GxEPD_WHITE);
|
displays[dispNum].height());
|
||||||
const int border = 0;
|
displays[dispNum].fillScreen(GxEPD_WHITE);
|
||||||
|
const int border = 0;
|
||||||
|
|
||||||
for (int y = -border; y < size * 4 + border; y++)
|
for (int y = -border; y < size * 4 + border; y++) {
|
||||||
{
|
for (int x = -border; x < size * 4 + border; x++) {
|
||||||
for (int x = -border; x < size * 4 + border; x++)
|
displays[dispNum].drawPixel(
|
||||||
{
|
padding + x, paddingY + y,
|
||||||
displays[dispNum].drawPixel(padding + x, paddingY + y, qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4)) ? GxEPD_BLACK : GxEPD_WHITE);
|
qrcodegen_getModule(qrcode, floor(float(x) / 4), floor(float(y) / 4))
|
||||||
}
|
? GxEPD_BLACK
|
||||||
|
: GxEPD_WHITE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void waitUntilNoneBusy()
|
void waitUntilNoneBusy() {
|
||||||
{
|
for (int i = 0; i < NUM_SCREENS; i++) {
|
||||||
for (int i = 0; i < NUM_SCREENS; i++)
|
uint count = 0;
|
||||||
{
|
while (EPD_BUSY[i].digitalRead()) {
|
||||||
uint count = 0;
|
count++;
|
||||||
while (EPD_BUSY[i].digitalRead())
|
vTaskDelay(10);
|
||||||
{
|
if (count == 200) {
|
||||||
count++;
|
// displays[i].init(0, false);
|
||||||
vTaskDelay(10);
|
vTaskDelay(100);
|
||||||
if (count == 200)
|
} else if (count > 205) {
|
||||||
{
|
Serial.printf("Busy timeout %d", i);
|
||||||
// displays[i].init(0, false);
|
break;
|
||||||
vTaskDelay(100);
|
}
|
||||||
}
|
|
||||||
else if (count > 205)
|
|
||||||
{
|
|
||||||
Serial.printf("Busy timeout %d", i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,34 +1,35 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <GxEPD2_BW.h>
|
|
||||||
#include <native_pin.hpp>
|
|
||||||
#include <mcp23x17_pin.hpp>
|
|
||||||
#include "shared.hpp"
|
|
||||||
#include "config.hpp"
|
|
||||||
#include "fonts/fonts.hpp"
|
#include "fonts/fonts.hpp"
|
||||||
#include <Fonts/FreeSansBold9pt7b.h>
|
#include "lib/config.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Fonts/FreeSans9pt7b.h>
|
#include <Fonts/FreeSans9pt7b.h>
|
||||||
#include <regex>
|
#include <Fonts/FreeSansBold9pt7b.h>
|
||||||
|
#include <GxEPD2_BW.h>
|
||||||
|
#include <mcp23x17_pin.hpp>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
#include <native_pin.hpp>
|
||||||
|
#include <regex>
|
||||||
|
|
||||||
#ifdef USE_QR
|
#ifdef USE_QR
|
||||||
#include "qrcodegen.h"
|
#include "qrcodegen.h"
|
||||||
#endif
|
#endif
|
||||||
// extern TaskHandle_t epdTaskHandle;
|
// extern TaskHandle_t epdTaskHandle;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
char dispNum;
|
||||||
char dispNum;
|
|
||||||
} UpdateDisplayTaskItem;
|
} UpdateDisplayTaskItem;
|
||||||
|
|
||||||
void forceFullRefresh();
|
void forceFullRefresh();
|
||||||
void refreshFromMemory();
|
void refreshFromMemory();
|
||||||
void setupDisplays();
|
void setupDisplays();
|
||||||
|
|
||||||
void splitText(const uint dispNum, const String& top, const String& bottom, bool partial);
|
void splitText(const uint dispNum, const String &top, const String &bottom,
|
||||||
|
bool partial);
|
||||||
|
|
||||||
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
void showDigit(const uint dispNum, char chr, bool partial, const GFXfont *font);
|
||||||
void showChars(const uint dispNum, const String& chars, bool partial, const GFXfont *font);
|
void showChars(const uint dispNum, const String &chars, bool partial,
|
||||||
|
const GFXfont *font);
|
||||||
|
|
||||||
extern "C" void updateDisplay(void *pvParameters) noexcept;
|
extern "C" void updateDisplay(void *pvParameters) noexcept;
|
||||||
void updateDisplayAlt(int epdIndex);
|
void updateDisplayAlt(int epdIndex);
|
||||||
|
@ -39,10 +40,11 @@ int getFgColor();
|
||||||
void setBgColor(int color);
|
void setBgColor(int color);
|
||||||
void setFgColor(int color);
|
void setFgColor(int color);
|
||||||
|
|
||||||
void renderText(const uint dispNum, const String& text, bool partial);
|
void renderText(const uint dispNum, const String &text, bool partial);
|
||||||
void renderQr(const uint dispNum, const String& text, bool partial);
|
void renderQr(const uint dispNum, const String &text, bool partial);
|
||||||
|
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent, bool forceUpdate);
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent,
|
||||||
|
bool forceUpdate);
|
||||||
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent);
|
void setEpdContent(std::array<String, NUM_SCREENS> newEpdContent);
|
||||||
|
|
||||||
void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent);
|
void setEpdContent(std::array<std::string, NUM_SCREENS> newEpdContent);
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
|
|
||||||
namespace improv {
|
namespace improv {
|
||||||
|
|
||||||
ImprovCommand parse_improv_data(const std::vector<uint8_t> &data, bool check_checksum) {
|
ImprovCommand parse_improv_data(const std::vector<uint8_t> &data,
|
||||||
|
bool check_checksum) {
|
||||||
return parse_improv_data(data.data(), data.size(), check_checksum);
|
return parse_improv_data(data.data(), data.size(), check_checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImprovCommand parse_improv_data(const uint8_t *data, size_t length, bool check_checksum) {
|
ImprovCommand parse_improv_data(const uint8_t *data, size_t length,
|
||||||
|
bool check_checksum) {
|
||||||
ImprovCommand improv_command;
|
ImprovCommand improv_command;
|
||||||
Command command = (Command) data[0];
|
Command command = (Command)data[0];
|
||||||
uint8_t data_length = data[1];
|
uint8_t data_length = data[1];
|
||||||
|
|
||||||
if (data_length != length - 2 - check_checksum) {
|
if (data_length != length - 2 - check_checksum) {
|
||||||
|
@ -24,7 +26,7 @@ ImprovCommand parse_improv_data(const uint8_t *data, size_t length, bool check_c
|
||||||
calculated_checksum += data[i];
|
calculated_checksum += data[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((uint8_t) calculated_checksum != checksum) {
|
if ((uint8_t)calculated_checksum != checksum) {
|
||||||
improv_command.command = BAD_CHECKSUM;
|
improv_command.command = BAD_CHECKSUM;
|
||||||
return improv_command;
|
return improv_command;
|
||||||
}
|
}
|
||||||
|
@ -48,8 +50,10 @@ ImprovCommand parse_improv_data(const uint8_t *data, size_t length, bool check_c
|
||||||
return improv_command;
|
return improv_command;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_improv_serial_byte(size_t position, uint8_t byte, const uint8_t *buffer,
|
bool parse_improv_serial_byte(size_t position, uint8_t byte,
|
||||||
std::function<bool(ImprovCommand)> &&callback, std::function<void(Error)> &&on_error) {
|
const uint8_t *buffer,
|
||||||
|
std::function<bool(ImprovCommand)> &&callback,
|
||||||
|
std::function<void(Error)> &&on_error) {
|
||||||
if (position == 0)
|
if (position == 0)
|
||||||
return byte == 'I';
|
return byte == 'I';
|
||||||
if (position == 1)
|
if (position == 1)
|
||||||
|
@ -94,7 +98,9 @@ bool parse_improv_serial_byte(size_t position, uint8_t byte, const uint8_t *buff
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> build_rpc_response(Command command, const std::vector<std::string> &datum, bool add_checksum) {
|
std::vector<uint8_t> build_rpc_response(Command command,
|
||||||
|
const std::vector<std::string> &datum,
|
||||||
|
bool add_checksum) {
|
||||||
std::vector<uint8_t> out;
|
std::vector<uint8_t> out;
|
||||||
uint32_t length = 0;
|
uint32_t length = 0;
|
||||||
out.push_back(command);
|
out.push_back(command);
|
||||||
|
@ -118,7 +124,9 @@ std::vector<uint8_t> build_rpc_response(Command command, const std::vector<std::
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
std::vector<uint8_t> build_rpc_response(Command command, const std::vector<String> &datum, bool add_checksum) {
|
std::vector<uint8_t> build_rpc_response(Command command,
|
||||||
|
const std::vector<String> &datum,
|
||||||
|
bool add_checksum) {
|
||||||
std::vector<uint8_t> out;
|
std::vector<uint8_t> out;
|
||||||
uint32_t length = 0;
|
uint32_t length = 0;
|
||||||
out.push_back(command);
|
out.push_back(command);
|
||||||
|
@ -140,6 +148,6 @@ std::vector<uint8_t> build_rpc_response(Command command, const std::vector<Strin
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
#endif // ARDUINO
|
#endif // ARDUINO
|
||||||
|
|
||||||
} // namespace improv
|
} // namespace improv
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#endif // ARDUINO
|
#endif // ARDUINO
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
@ -14,9 +14,12 @@ namespace improv {
|
||||||
static const char *const SERVICE_UUID = "00467768-6228-2272-4663-277478268000";
|
static const char *const SERVICE_UUID = "00467768-6228-2272-4663-277478268000";
|
||||||
static const char *const STATUS_UUID = "00467768-6228-2272-4663-277478268001";
|
static const char *const STATUS_UUID = "00467768-6228-2272-4663-277478268001";
|
||||||
static const char *const ERROR_UUID = "00467768-6228-2272-4663-277478268002";
|
static const char *const ERROR_UUID = "00467768-6228-2272-4663-277478268002";
|
||||||
static const char *const RPC_COMMAND_UUID = "00467768-6228-2272-4663-277478268003";
|
static const char *const RPC_COMMAND_UUID =
|
||||||
static const char *const RPC_RESULT_UUID = "00467768-6228-2272-4663-277478268004";
|
"00467768-6228-2272-4663-277478268003";
|
||||||
static const char *const CAPABILITIES_UUID = "00467768-6228-2272-4663-277478268005";
|
static const char *const RPC_RESULT_UUID =
|
||||||
|
"00467768-6228-2272-4663-277478268004";
|
||||||
|
static const char *const CAPABILITIES_UUID =
|
||||||
|
"00467768-6228-2272-4663-277478268005";
|
||||||
|
|
||||||
enum Error : uint8_t {
|
enum Error : uint8_t {
|
||||||
ERROR_NONE = 0x00,
|
ERROR_NONE = 0x00,
|
||||||
|
@ -61,16 +64,23 @@ struct ImprovCommand {
|
||||||
std::string password;
|
std::string password;
|
||||||
};
|
};
|
||||||
|
|
||||||
ImprovCommand parse_improv_data(const std::vector<uint8_t> &data, bool check_checksum = true);
|
ImprovCommand parse_improv_data(const std::vector<uint8_t> &data,
|
||||||
ImprovCommand parse_improv_data(const uint8_t *data, size_t length, bool check_checksum = true);
|
bool check_checksum = true);
|
||||||
|
ImprovCommand parse_improv_data(const uint8_t *data, size_t length,
|
||||||
|
bool check_checksum = true);
|
||||||
|
|
||||||
bool parse_improv_serial_byte(size_t position, uint8_t byte, const uint8_t *buffer,
|
bool parse_improv_serial_byte(size_t position, uint8_t byte,
|
||||||
std::function<bool(ImprovCommand)> &&callback, std::function<void(Error)> &&on_error);
|
const uint8_t *buffer,
|
||||||
|
std::function<bool(ImprovCommand)> &&callback,
|
||||||
|
std::function<void(Error)> &&on_error);
|
||||||
|
|
||||||
std::vector<uint8_t> build_rpc_response(Command command, const std::vector<std::string> &datum,
|
std::vector<uint8_t> build_rpc_response(Command command,
|
||||||
|
const std::vector<std::string> &datum,
|
||||||
bool add_checksum = true);
|
bool add_checksum = true);
|
||||||
#ifdef ARDUINO
|
#ifdef ARDUINO
|
||||||
std::vector<uint8_t> build_rpc_response(Command command, const std::vector<String> &datum, bool add_checksum = true);
|
std::vector<uint8_t> build_rpc_response(Command command,
|
||||||
#endif // ARDUINO
|
const std::vector<String> &datum,
|
||||||
|
bool add_checksum = true);
|
||||||
|
#endif // ARDUINO
|
||||||
|
|
||||||
} // namespace improv
|
} // namespace improv
|
|
@ -5,375 +5,322 @@ QueueHandle_t ledTaskQueue = NULL;
|
||||||
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
|
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
|
||||||
uint ledTaskParams;
|
uint ledTaskParams;
|
||||||
|
|
||||||
void ledTask(void *parameter)
|
void ledTask(void *parameter) {
|
||||||
{
|
while (1) {
|
||||||
while (1)
|
if (ledTaskQueue != NULL) {
|
||||||
{
|
if (xQueueReceive(ledTaskQueue, &ledTaskParams, portMAX_DELAY) ==
|
||||||
if (ledTaskQueue != NULL)
|
pdPASS) {
|
||||||
{
|
uint32_t oldLights[NEOPIXEL_COUNT];
|
||||||
if (xQueueReceive(ledTaskQueue, &ledTaskParams, portMAX_DELAY) == pdPASS)
|
|
||||||
{
|
|
||||||
uint32_t oldLights[NEOPIXEL_COUNT];
|
|
||||||
|
|
||||||
// get current state
|
// get current state
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
{
|
oldLights[i] = pixels.getPixelColor(i);
|
||||||
oldLights[i] = pixels.getPixelColor(i);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
switch (ledTaskParams)
|
switch (ledTaskParams) {
|
||||||
{
|
case LED_POWER_TEST:
|
||||||
case LED_POWER_TEST:
|
ledRainbow(20);
|
||||||
ledRainbow(20);
|
pixels.clear();
|
||||||
pixels.clear();
|
break;
|
||||||
break;
|
case LED_EFFECT_WIFI_CONNECT_ERROR:
|
||||||
case LED_EFFECT_WIFI_CONNECT_ERROR:
|
blinkDelayTwoColor(100, 3, pixels.Color(8, 161, 236),
|
||||||
blinkDelayTwoColor(100, 3, pixels.Color(8, 161, 236), pixels.Color(255, 0, 0));
|
pixels.Color(255, 0, 0));
|
||||||
break;
|
break;
|
||||||
case LED_FLASH_ERROR:
|
case LED_FLASH_ERROR:
|
||||||
blinkDelayColor(250, 3, 255, 0, 0);
|
blinkDelayColor(250, 3, 255, 0, 0);
|
||||||
break;
|
break;
|
||||||
case LED_EFFECT_HEARTBEAT:
|
case LED_EFFECT_HEARTBEAT:
|
||||||
blinkDelayColor(150, 2, 0, 0, 255);
|
blinkDelayColor(150, 2, 0, 0, 255);
|
||||||
break;
|
break;
|
||||||
case LED_EFFECT_WIFI_CONNECT_SUCCESS:
|
case LED_EFFECT_WIFI_CONNECT_SUCCESS:
|
||||||
case LED_FLASH_SUCCESS:
|
case LED_FLASH_SUCCESS:
|
||||||
blinkDelayColor(150, 3, 0, 255, 0);
|
blinkDelayColor(150, 3, 0, 255, 0);
|
||||||
break;
|
break;
|
||||||
case LED_PROGRESS_100:
|
case LED_PROGRESS_100:
|
||||||
pixels.setPixelColor(0, pixels.Color(0, 255, 0));
|
pixels.setPixelColor(0, pixels.Color(0, 255, 0));
|
||||||
case LED_PROGRESS_75:
|
case LED_PROGRESS_75:
|
||||||
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
||||||
case LED_PROGRESS_50:
|
case LED_PROGRESS_50:
|
||||||
pixels.setPixelColor(2, pixels.Color(0, 255, 0));
|
pixels.setPixelColor(2, pixels.Color(0, 255, 0));
|
||||||
case LED_PROGRESS_25:
|
case LED_PROGRESS_25:
|
||||||
pixels.setPixelColor(3, pixels.Color(0, 255, 0));
|
pixels.setPixelColor(3, pixels.Color(0, 255, 0));
|
||||||
pixels.show();
|
pixels.show();
|
||||||
break;
|
break;
|
||||||
case LED_FLASH_UPDATE:
|
case LED_FLASH_UPDATE:
|
||||||
break;
|
break;
|
||||||
case LED_FLASH_BLOCK_NOTIFY:
|
case LED_FLASH_BLOCK_NOTIFY:
|
||||||
blinkDelayTwoColor(250, 3, pixels.Color(224, 67, 0), pixels.Color(8, 2, 0));
|
blinkDelayTwoColor(250, 3, pixels.Color(224, 67, 0),
|
||||||
break;
|
pixels.Color(8, 2, 0));
|
||||||
case LED_EFFECT_WIFI_WAIT_FOR_CONFIG:
|
break;
|
||||||
blinkDelayTwoColor(100, 1, pixels.Color(8, 161, 236), pixels.Color(156, 225, 240));
|
case LED_EFFECT_WIFI_WAIT_FOR_CONFIG:
|
||||||
break;
|
blinkDelayTwoColor(100, 1, pixels.Color(8, 161, 236),
|
||||||
case LED_EFFECT_WIFI_ERASE_SETTINGS:
|
pixels.Color(156, 225, 240));
|
||||||
blinkDelay(100, 3);
|
break;
|
||||||
break;
|
case LED_EFFECT_WIFI_ERASE_SETTINGS:
|
||||||
case LED_EFFECT_WIFI_CONNECTING:
|
blinkDelay(100, 3);
|
||||||
for (int i = NEOPIXEL_COUNT; i >= 0; i--)
|
break;
|
||||||
{
|
case LED_EFFECT_WIFI_CONNECTING:
|
||||||
for (int j = NEOPIXEL_COUNT; j >= 0; j--)
|
for (int i = NEOPIXEL_COUNT; i >= 0; i--) {
|
||||||
{
|
for (int j = NEOPIXEL_COUNT; j >= 0; j--) {
|
||||||
if (j == i)
|
if (j == i) {
|
||||||
{
|
pixels.setPixelColor(i, pixels.Color(16, 197, 236));
|
||||||
pixels.setPixelColor(i, pixels.Color(16, 197, 236));
|
} else {
|
||||||
}
|
pixels.setPixelColor(j, pixels.Color(0, 0, 0));
|
||||||
else
|
}
|
||||||
{
|
|
||||||
pixels.setPixelColor(j, pixels.Color(0, 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pixels.show();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(100));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case LED_EFFECT_PAUSE_TIMER:
|
|
||||||
for (int i = NEOPIXEL_COUNT; i >= 0; i--)
|
|
||||||
{
|
|
||||||
for (int j = NEOPIXEL_COUNT; j >= 0; j--)
|
|
||||||
{
|
|
||||||
uint32_t c = pixels.Color(0, 0, 0);
|
|
||||||
if (i == j)
|
|
||||||
c = pixels.Color(0, 255, 0);
|
|
||||||
pixels.setPixelColor(j, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
pixels.show();
|
|
||||||
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
|
||||||
pixels.show();
|
|
||||||
|
|
||||||
delay(900);
|
|
||||||
|
|
||||||
pixels.clear();
|
|
||||||
pixels.show();
|
|
||||||
break;
|
|
||||||
case LED_EFFECT_START_TIMER:
|
|
||||||
pixels.clear();
|
|
||||||
pixels.setPixelColor((NEOPIXEL_COUNT - 1), pixels.Color(255, 0, 0));
|
|
||||||
pixels.show();
|
|
||||||
|
|
||||||
delay(900);
|
|
||||||
|
|
||||||
for (int i = NEOPIXEL_COUNT; i--; i > 0)
|
|
||||||
{
|
|
||||||
|
|
||||||
for (int j = NEOPIXEL_COUNT; j--; j > 0)
|
|
||||||
{
|
|
||||||
uint32_t c = pixels.Color(0, 0, 0);
|
|
||||||
if (i == j)
|
|
||||||
c = pixels.Color(0, 255, 0);
|
|
||||||
|
|
||||||
pixels.setPixelColor(j, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
pixels.show();
|
|
||||||
|
|
||||||
delay(100);
|
|
||||||
}
|
|
||||||
|
|
||||||
pixels.clear();
|
|
||||||
pixels.show();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// revert to previous state unless power test
|
|
||||||
|
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, oldLights[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
pixels.show();
|
|
||||||
}
|
}
|
||||||
|
pixels.show();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case LED_EFFECT_PAUSE_TIMER:
|
||||||
|
for (int i = NEOPIXEL_COUNT; i >= 0; i--) {
|
||||||
|
for (int j = NEOPIXEL_COUNT; j >= 0; j--) {
|
||||||
|
uint32_t c = pixels.Color(0, 0, 0);
|
||||||
|
if (i == j)
|
||||||
|
c = pixels.Color(0, 255, 0);
|
||||||
|
pixels.setPixelColor(j, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels.show();
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||||
|
pixels.show();
|
||||||
|
|
||||||
|
delay(900);
|
||||||
|
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
break;
|
||||||
|
case LED_EFFECT_START_TIMER:
|
||||||
|
pixels.clear();
|
||||||
|
pixels.setPixelColor((NEOPIXEL_COUNT - 1), pixels.Color(255, 0, 0));
|
||||||
|
pixels.show();
|
||||||
|
|
||||||
|
delay(900);
|
||||||
|
|
||||||
|
for (int i = NEOPIXEL_COUNT; i--; i > 0) {
|
||||||
|
|
||||||
|
for (int j = NEOPIXEL_COUNT; j--; j > 0) {
|
||||||
|
uint32_t c = pixels.Color(0, 0, 0);
|
||||||
|
if (i == j)
|
||||||
|
c = pixels.Color(0, 255, 0);
|
||||||
|
|
||||||
|
pixels.setPixelColor(j, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels.show();
|
||||||
|
|
||||||
|
delay(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupLeds()
|
// revert to previous state unless power test
|
||||||
{
|
|
||||||
pixels.begin();
|
|
||||||
pixels.setBrightness(preferences.getUInt("ledBrightness", 128));
|
|
||||||
pixels.clear();
|
|
||||||
pixels.show();
|
|
||||||
setupLedTask();
|
|
||||||
if (preferences.getBool("ledTestOnPower", true))
|
|
||||||
{
|
|
||||||
while (!ledTaskQueue)
|
|
||||||
{
|
|
||||||
delay(1);
|
|
||||||
// wait until queue is available
|
|
||||||
}
|
|
||||||
queueLedEffect(LED_POWER_TEST);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupLedTask()
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
{
|
pixels.setPixelColor(i, oldLights[i]);
|
||||||
ledTaskQueue = xQueueCreate(5, sizeof(uint));
|
|
||||||
|
|
||||||
xTaskCreate(ledTask, "LedTask", 2048, NULL, tskIDLE_PRIORITY, &ledTaskHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void blinkDelay(int d, int times)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < times; j++)
|
|
||||||
{
|
|
||||||
|
|
||||||
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
|
||||||
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
|
||||||
pixels.setPixelColor(2, pixels.Color(255, 0, 0));
|
|
||||||
pixels.setPixelColor(3, pixels.Color(0, 255, 0));
|
|
||||||
pixels.show();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(d));
|
|
||||||
|
|
||||||
pixels.setPixelColor(0, pixels.Color(255, 255, 0));
|
|
||||||
pixels.setPixelColor(1, pixels.Color(0, 255, 255));
|
|
||||||
pixels.setPixelColor(2, pixels.Color(255, 255, 0));
|
|
||||||
pixels.setPixelColor(3, pixels.Color(0, 255, 255));
|
|
||||||
pixels.show();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(d));
|
|
||||||
}
|
|
||||||
pixels.clear();
|
|
||||||
pixels.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void blinkDelayColor(int d, int times, uint r, uint g, uint b)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < times; j++)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, pixels.Color(r, g, b));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pixels.show();
|
pixels.show();
|
||||||
vTaskDelay(pdMS_TO_TICKS(d));
|
}
|
||||||
|
|
||||||
pixels.clear();
|
|
||||||
pixels.show();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(d));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupLeds() {
|
||||||
|
pixels.begin();
|
||||||
|
pixels.setBrightness(preferences.getUInt("ledBrightness", 128));
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
setupLedTask();
|
||||||
|
if (preferences.getBool("ledTestOnPower", true)) {
|
||||||
|
while (!ledTaskQueue) {
|
||||||
|
delay(1);
|
||||||
|
// wait until queue is available
|
||||||
|
}
|
||||||
|
queueLedEffect(LED_POWER_TEST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupLedTask() {
|
||||||
|
ledTaskQueue = xQueueCreate(5, sizeof(uint));
|
||||||
|
|
||||||
|
xTaskCreate(ledTask, "LedTask", 2048, NULL, tskIDLE_PRIORITY, &ledTaskHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void blinkDelay(int d, int times) {
|
||||||
|
for (int j = 0; j < times; j++) {
|
||||||
|
|
||||||
|
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||||
|
pixels.setPixelColor(1, pixels.Color(0, 255, 0));
|
||||||
|
pixels.setPixelColor(2, pixels.Color(255, 0, 0));
|
||||||
|
pixels.setPixelColor(3, pixels.Color(0, 255, 0));
|
||||||
|
pixels.show();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(d));
|
||||||
|
|
||||||
|
pixels.setPixelColor(0, pixels.Color(255, 255, 0));
|
||||||
|
pixels.setPixelColor(1, pixels.Color(0, 255, 255));
|
||||||
|
pixels.setPixelColor(2, pixels.Color(255, 255, 0));
|
||||||
|
pixels.setPixelColor(3, pixels.Color(0, 255, 255));
|
||||||
|
pixels.show();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(d));
|
||||||
|
}
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void blinkDelayColor(int d, int times, uint r, uint g, uint b) {
|
||||||
|
for (int j = 0; j < times; j++) {
|
||||||
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
|
pixels.setPixelColor(i, pixels.Color(r, g, b));
|
||||||
|
}
|
||||||
|
|
||||||
|
pixels.show();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(d));
|
||||||
|
|
||||||
pixels.clear();
|
pixels.clear();
|
||||||
pixels.show();
|
pixels.show();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(d));
|
||||||
|
}
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2)
|
void blinkDelayTwoColor(int d, int times, uint32_t c1, uint32_t c2) {
|
||||||
{
|
for (int j = 0; j < times; j++) {
|
||||||
for (int j = 0; j < times; j++)
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
{
|
pixels.setPixelColor(i, c1);
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, c1);
|
|
||||||
}
|
|
||||||
pixels.show();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(d));
|
|
||||||
|
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, c2);
|
|
||||||
}
|
|
||||||
pixels.show();
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(d));
|
|
||||||
}
|
|
||||||
pixels.clear();
|
|
||||||
pixels.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearLeds()
|
|
||||||
{
|
|
||||||
preferences.putBool("ledStatus", false);
|
|
||||||
pixels.clear();
|
|
||||||
pixels.show();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLights(int r, int g, int b)
|
|
||||||
{
|
|
||||||
setLights(pixels.Color(r, g, b));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setLights(uint32_t color)
|
|
||||||
{
|
|
||||||
|
|
||||||
bool ledStatus = true;
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < NEOPIXEL_COUNT; i++)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(i, color);
|
|
||||||
}
|
}
|
||||||
pixels.show();
|
pixels.show();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(d));
|
||||||
|
|
||||||
if (color == pixels.Color(0, 0, 0))
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
{
|
pixels.setPixelColor(i, c2);
|
||||||
ledStatus = false;
|
|
||||||
} else {
|
|
||||||
saveLedState();
|
|
||||||
}
|
}
|
||||||
preferences.putBool("ledStatus", ledStatus);
|
pixels.show();
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(d));
|
||||||
|
}
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearLeds() {
|
||||||
|
preferences.putBool("ledStatus", false);
|
||||||
|
pixels.clear();
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setLights(int r, int g, int b) { setLights(pixels.Color(r, g, b)); }
|
||||||
|
|
||||||
|
void setLights(uint32_t color) {
|
||||||
|
|
||||||
|
bool ledStatus = true;
|
||||||
|
|
||||||
|
for (int i = 0; i < NEOPIXEL_COUNT; i++) {
|
||||||
|
pixels.setPixelColor(i, color);
|
||||||
|
}
|
||||||
|
pixels.show();
|
||||||
|
|
||||||
|
if (color == pixels.Color(0, 0, 0)) {
|
||||||
|
ledStatus = false;
|
||||||
|
} else {
|
||||||
|
saveLedState();
|
||||||
|
}
|
||||||
|
preferences.putBool("ledStatus", ledStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveLedState() {
|
void saveLedState() {
|
||||||
for (int i = 0; i < pixels.numPixels(); i++)
|
for (int i = 0; i < pixels.numPixels(); i++) {
|
||||||
{
|
int pixelColor = pixels.getPixelColor(i);
|
||||||
int pixelColor = pixels.getPixelColor(i);
|
char key[12];
|
||||||
char key[12];
|
snprintf(key, 12, "%s%d", "ledColor_", i);
|
||||||
snprintf(key, 12, "%s%d", "ledColor_", i);
|
preferences.putUInt(key, pixelColor);
|
||||||
preferences.putUInt(key, pixelColor);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void restoreLedState() {
|
void restoreLedState() {
|
||||||
for (int i = 0; i < pixels.numPixels(); i++)
|
for (int i = 0; i < pixels.numPixels(); i++) {
|
||||||
{
|
char key[12];
|
||||||
char key[12];
|
snprintf(key, 12, "%s%d", "ledColor_", i);
|
||||||
snprintf(key, 12, "%s%d", "ledColor_", i);
|
uint pixelColor = preferences.getUInt(key, pixels.Color(0, 0, 0));
|
||||||
uint pixelColor = preferences.getUInt(key, pixels.Color(0,0,0));
|
pixels.setPixelColor(i, pixelColor);
|
||||||
pixels.setPixelColor(i, pixelColor);
|
}
|
||||||
|
|
||||||
|
pixels.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueHandle_t getLedTaskQueue() { return ledTaskQueue; }
|
||||||
|
|
||||||
|
bool queueLedEffect(uint effect) {
|
||||||
|
if (ledTaskQueue == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint flashType = effect;
|
||||||
|
xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ledRainbow(int wait) {
|
||||||
|
// Hue of first pixel runs 5 complete loops through the color wheel.
|
||||||
|
// Color wheel has a range of 65536 but it's OK if we roll over, so
|
||||||
|
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
|
||||||
|
// means we'll make 5*65536/256 = 1280 passes through this loop:
|
||||||
|
for (long firstPixelHue = 0; firstPixelHue < 5 * 65536;
|
||||||
|
firstPixelHue += 256) {
|
||||||
|
// strip.rainbow() can take a single argument (first pixel hue) or
|
||||||
|
// optionally a few extras: number of rainbow repetitions (default 1),
|
||||||
|
// saturation and value (brightness) (both 0-255, similar to the
|
||||||
|
// ColorHSV() function, default 255), and a true/false flag for whether
|
||||||
|
// to apply gamma correction to provide 'truer' colors (default true).
|
||||||
|
pixels.rainbow(firstPixelHue);
|
||||||
|
// Above line is equivalent to:
|
||||||
|
// strip.rainbow(firstPixelHue, 1, 255, 255, true);
|
||||||
|
pixels.show(); // Update strip with new contents
|
||||||
|
delayMicroseconds(wait);
|
||||||
|
// vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ledTheaterChase(uint32_t color, int wait) {
|
||||||
|
for (int a = 0; a < 10; a++) { // Repeat 10 times...
|
||||||
|
for (int b = 0; b < 3; b++) { // 'b' counts from 0 to 2...
|
||||||
|
pixels.clear(); // Set all pixels in RAM to 0 (off)
|
||||||
|
// 'c' counts up from 'b' to end of strip in steps of 3...
|
||||||
|
for (int c = b; c < pixels.numPixels(); c += 3) {
|
||||||
|
pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color'
|
||||||
|
}
|
||||||
|
pixels.show(); // Update strip with new contents
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pixels.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QueueHandle_t getLedTaskQueue()
|
void ledTheaterChaseRainbow(int wait) {
|
||||||
{
|
int firstPixelHue = 0; // First pixel starts at red (hue 0)
|
||||||
return ledTaskQueue;
|
for (int a = 0; a < 30; a++) { // Repeat 30 times...
|
||||||
}
|
for (int b = 0; b < 3; b++) { // 'b' counts from 0 to 2...
|
||||||
|
pixels.clear(); // Set all pixels in RAM to 0 (off)
|
||||||
bool queueLedEffect(uint effect)
|
// 'c' counts up from 'b' to end of strip in increments of 3...
|
||||||
{
|
for (int c = b; c < pixels.numPixels(); c += 3) {
|
||||||
if (ledTaskQueue == NULL)
|
// hue of pixel 'c' is offset by an amount to make one full
|
||||||
{
|
// revolution of the color wheel (range 65536) along the length
|
||||||
return false;
|
// of the strip (strip.numPixels() steps):
|
||||||
|
int hue = firstPixelHue + c * 65536L / pixels.numPixels();
|
||||||
|
uint32_t color = pixels.gamma32(pixels.ColorHSV(hue)); // hue -> RGB
|
||||||
|
pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color'
|
||||||
|
}
|
||||||
|
pixels.show(); // Update strip with new contents
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment
|
||||||
|
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
|
||||||
}
|
}
|
||||||
|
}
|
||||||
uint flashType = effect;
|
|
||||||
xQueueSend(ledTaskQueue, &flashType, portMAX_DELAY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ledRainbow(int wait)
|
Adafruit_NeoPixel getPixels() { return pixels; }
|
||||||
{
|
|
||||||
// Hue of first pixel runs 5 complete loops through the color wheel.
|
|
||||||
// Color wheel has a range of 65536 but it's OK if we roll over, so
|
|
||||||
// just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
|
|
||||||
// means we'll make 5*65536/256 = 1280 passes through this loop:
|
|
||||||
for (long firstPixelHue = 0; firstPixelHue < 5 * 65536; firstPixelHue += 256)
|
|
||||||
{
|
|
||||||
// strip.rainbow() can take a single argument (first pixel hue) or
|
|
||||||
// optionally a few extras: number of rainbow repetitions (default 1),
|
|
||||||
// saturation and value (brightness) (both 0-255, similar to the
|
|
||||||
// ColorHSV() function, default 255), and a true/false flag for whether
|
|
||||||
// to apply gamma correction to provide 'truer' colors (default true).
|
|
||||||
pixels.rainbow(firstPixelHue);
|
|
||||||
// Above line is equivalent to:
|
|
||||||
// strip.rainbow(firstPixelHue, 1, 255, 255, true);
|
|
||||||
pixels.show(); // Update strip with new contents
|
|
||||||
delayMicroseconds(wait);
|
|
||||||
// vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ledTheaterChase(uint32_t color, int wait)
|
|
||||||
{
|
|
||||||
for (int a = 0; a < 10; a++)
|
|
||||||
{ // Repeat 10 times...
|
|
||||||
for (int b = 0; b < 3; b++)
|
|
||||||
{ // 'b' counts from 0 to 2...
|
|
||||||
pixels.clear(); // Set all pixels in RAM to 0 (off)
|
|
||||||
// 'c' counts up from 'b' to end of strip in steps of 3...
|
|
||||||
for (int c = b; c < pixels.numPixels(); c += 3)
|
|
||||||
{
|
|
||||||
pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color'
|
|
||||||
}
|
|
||||||
pixels.show(); // Update strip with new contents
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ledTheaterChaseRainbow(int wait)
|
|
||||||
{
|
|
||||||
int firstPixelHue = 0; // First pixel starts at red (hue 0)
|
|
||||||
for (int a = 0; a < 30; a++)
|
|
||||||
{ // Repeat 30 times...
|
|
||||||
for (int b = 0; b < 3; b++)
|
|
||||||
{ // 'b' counts from 0 to 2...
|
|
||||||
pixels.clear(); // Set all pixels in RAM to 0 (off)
|
|
||||||
// 'c' counts up from 'b' to end of strip in increments of 3...
|
|
||||||
for (int c = b; c < pixels.numPixels(); c += 3)
|
|
||||||
{
|
|
||||||
// hue of pixel 'c' is offset by an amount to make one full
|
|
||||||
// revolution of the color wheel (range 65536) along the length
|
|
||||||
// of the strip (strip.numPixels() steps):
|
|
||||||
int hue = firstPixelHue + c * 65536L / pixels.numPixels();
|
|
||||||
uint32_t color = pixels.gamma32(pixels.ColorHSV(hue)); // hue -> RGB
|
|
||||||
pixels.setPixelColor(c, color); // Set pixel 'c' to value 'color'
|
|
||||||
}
|
|
||||||
pixels.show(); // Update strip with new contents
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(wait)); // Pause for a moment
|
|
||||||
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Adafruit_NeoPixel getPixels()
|
|
||||||
{
|
|
||||||
return pixels;
|
|
||||||
}
|
|
|
@ -1,11 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include "lib/shared.hpp"
|
||||||
|
#include "lib/webserver.hpp"
|
||||||
#include <Adafruit_NeoPixel.h>
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
#include <Arduino.h>
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
#include "webserver.hpp"
|
|
||||||
#include "shared.hpp"
|
|
||||||
|
|
||||||
#ifndef NEOPIXEL_PIN
|
#ifndef NEOPIXEL_PIN
|
||||||
#define NEOPIXEL_PIN 34
|
#define NEOPIXEL_PIN 34
|
||||||
|
|
|
@ -2,10 +2,8 @@
|
||||||
|
|
||||||
TaskHandle_t taskOtaHandle = NULL;
|
TaskHandle_t taskOtaHandle = NULL;
|
||||||
|
|
||||||
void setupOTA()
|
void setupOTA() {
|
||||||
{
|
if (preferences.getBool("otaEnabled", true)) {
|
||||||
if (preferences.getBool("otaEnabled", true))
|
|
||||||
{
|
|
||||||
ArduinoOTA.onStart(onOTAStart);
|
ArduinoOTA.onStart(onOTAStart);
|
||||||
|
|
||||||
ArduinoOTA.onProgress(onOTAProgress);
|
ArduinoOTA.onProgress(onOTAProgress);
|
||||||
|
@ -16,39 +14,35 @@ void setupOTA()
|
||||||
ArduinoOTA.setMdnsEnabled(false);
|
ArduinoOTA.setMdnsEnabled(false);
|
||||||
ArduinoOTA.setRebootOnSuccess(false);
|
ArduinoOTA.setRebootOnSuccess(false);
|
||||||
ArduinoOTA.begin();
|
ArduinoOTA.begin();
|
||||||
//downloadUpdate();
|
// downloadUpdate();
|
||||||
|
|
||||||
xTaskCreate(handleOTATask, "handleOTA", 4096, NULL, tskIDLE_PRIORITY, &taskOtaHandle);
|
xTaskCreate(handleOTATask, "handleOTA", 4096, NULL, tskIDLE_PRIORITY,
|
||||||
|
&taskOtaHandle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onOTAProgress(unsigned int progress, unsigned int total)
|
void onOTAProgress(unsigned int progress, unsigned int total) {
|
||||||
{
|
|
||||||
uint percentage = progress / (total / 100);
|
uint percentage = progress / (total / 100);
|
||||||
pixels.fill(pixels.Color(0, 255, 0));
|
pixels.fill(pixels.Color(0, 255, 0));
|
||||||
if (percentage < 100)
|
if (percentage < 100) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
|
pixels.setPixelColor(0, pixels.Color(0, 0, 0));
|
||||||
}
|
}
|
||||||
if (percentage < 75)
|
if (percentage < 75) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(1, pixels.Color(0, 0, 0));
|
pixels.setPixelColor(1, pixels.Color(0, 0, 0));
|
||||||
}
|
}
|
||||||
if (percentage < 50)
|
if (percentage < 50) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(2, pixels.Color(0, 0, 0));
|
pixels.setPixelColor(2, pixels.Color(0, 0, 0));
|
||||||
}
|
}
|
||||||
if (percentage < 25)
|
if (percentage < 25) {
|
||||||
{
|
|
||||||
pixels.setPixelColor(3, pixels.Color(0, 0, 0));
|
pixels.setPixelColor(3, pixels.Color(0, 0, 0));
|
||||||
}
|
}
|
||||||
pixels.show();
|
pixels.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onOTAStart()
|
void onOTAStart() {
|
||||||
{
|
|
||||||
forceFullRefresh();
|
forceFullRefresh();
|
||||||
std::array<String, NUM_SCREENS> epdContent = {"U", "P", "D", "A", "T", "E", "!"};
|
std::array<String, NUM_SCREENS> epdContent = {"U", "P", "D", "A",
|
||||||
|
"T", "E", "!"};
|
||||||
setEpdContent(epdContent);
|
setEpdContent(epdContent);
|
||||||
// Stop all timers
|
// Stop all timers
|
||||||
esp_timer_stop(screenRotateTimer);
|
esp_timer_stop(screenRotateTimer);
|
||||||
|
@ -68,17 +62,14 @@ void onOTAStart()
|
||||||
stopPriceNotify();
|
stopPriceNotify();
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleOTATask(void *parameter)
|
void handleOTATask(void *parameter) {
|
||||||
{
|
for (;;) {
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
ArduinoOTA.handle(); // Allow OTA updates to occur
|
ArduinoOTA.handle(); // Allow OTA updates to occur
|
||||||
vTaskDelay(pdMS_TO_TICKS(2500));
|
vTaskDelay(pdMS_TO_TICKS(2500));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void downloadUpdate()
|
void downloadUpdate() {
|
||||||
{
|
|
||||||
WiFiClientSecure client;
|
WiFiClientSecure client;
|
||||||
client.setInsecure();
|
client.setInsecure();
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
|
@ -87,12 +78,12 @@ void downloadUpdate()
|
||||||
// Send HTTP request to CoinGecko API
|
// Send HTTP request to CoinGecko API
|
||||||
http.useHTTP10(true);
|
http.useHTTP10(true);
|
||||||
|
|
||||||
http.begin(client, "https://api.github.com/repos/btclock/btclock_v3/releases/latest");
|
http.begin(client,
|
||||||
|
"https://api.github.com/repos/btclock/btclock_v3/releases/latest");
|
||||||
int httpCode = http.GET();
|
int httpCode = http.GET();
|
||||||
|
|
||||||
if (httpCode == 200)
|
if (httpCode == 200) {
|
||||||
{
|
// WiFiClient * stream = http->getStreamPtr();
|
||||||
// WiFiClient * stream = http->getStreamPtr();
|
|
||||||
|
|
||||||
StaticJsonDocument<64> filter;
|
StaticJsonDocument<64> filter;
|
||||||
|
|
||||||
|
@ -102,18 +93,17 @@ void downloadUpdate()
|
||||||
|
|
||||||
SpiRamJsonDocument doc(1536);
|
SpiRamJsonDocument doc(1536);
|
||||||
|
|
||||||
DeserializationError error = deserializeJson(doc, http.getStream(), DeserializationOption::Filter(filter));
|
DeserializationError error = deserializeJson(
|
||||||
|
doc, http.getStream(), DeserializationOption::Filter(filter));
|
||||||
|
|
||||||
if (error)
|
if (error) {
|
||||||
{
|
|
||||||
Serial.print("deserializeJson() failed: ");
|
Serial.print("deserializeJson() failed: ");
|
||||||
Serial.println(error.c_str());
|
Serial.println(error.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String downloadUrl;
|
String downloadUrl;
|
||||||
for (JsonObject asset : doc["assets"].as<JsonArray>())
|
for (JsonObject asset : doc["assets"].as<JsonArray>()) {
|
||||||
{
|
|
||||||
if (asset["name"].as<String>().compareTo("firmware.bin") == 0) {
|
if (asset["name"].as<String>().compareTo("firmware.bin") == 0) {
|
||||||
downloadUrl = asset["browser_download_url"].as<String>();
|
downloadUrl = asset["browser_download_url"].as<String>();
|
||||||
break;
|
break;
|
||||||
|
@ -122,8 +112,6 @@ void downloadUpdate()
|
||||||
|
|
||||||
Serial.printf("Download update from %s", downloadUrl);
|
Serial.printf("Download update from %s", downloadUrl);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// esp_http_client_config_t config = {
|
// esp_http_client_config_t config = {
|
||||||
// .url = CONFIG_FIRMWARE_UPGRADE_URL,
|
// .url = CONFIG_FIRMWARE_UPGRADE_URL,
|
||||||
// };
|
// };
|
||||||
|
@ -138,8 +126,7 @@ void downloadUpdate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void onOTAError(ota_error_t error)
|
void onOTAError(ota_error_t error) {
|
||||||
{
|
|
||||||
Serial.println("\nOTA update error, restarting");
|
Serial.println("\nOTA update error, restarting");
|
||||||
Wire.end();
|
Wire.end();
|
||||||
SPI.end();
|
SPI.end();
|
||||||
|
@ -147,8 +134,7 @@ void onOTAError(ota_error_t error)
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
void onOTAComplete()
|
void onOTAComplete() {
|
||||||
{
|
|
||||||
Serial.println("\nOTA update finished");
|
Serial.println("\nOTA update finished");
|
||||||
Wire.end();
|
Wire.end();
|
||||||
SPI.end();
|
SPI.end();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
#include "lib/config.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ArduinoOTA.h>
|
#include <ArduinoOTA.h>
|
||||||
#include "config.hpp"
|
|
||||||
#include "shared.hpp"
|
|
||||||
|
|
||||||
void setupOTA();
|
void setupOTA();
|
||||||
void onOTAStart();
|
void onOTAStart();
|
||||||
|
|
|
@ -1,60 +1,56 @@
|
||||||
#include "price_fetch.hpp"
|
#include "price_fetch.hpp"
|
||||||
|
|
||||||
const PROGMEM char *cgApiUrl = "https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd%2Ceur";
|
const PROGMEM char *cgApiUrl = "https://api.coingecko.com/api/v3/simple/"
|
||||||
|
"price?ids=bitcoin&vs_currencies=usd%2Ceur";
|
||||||
|
|
||||||
TaskHandle_t priceFetchTaskHandle;
|
TaskHandle_t priceFetchTaskHandle;
|
||||||
|
|
||||||
void taskPriceFetch(void *pvParameters)
|
void taskPriceFetch(void *pvParameters) {
|
||||||
{
|
WiFiClientSecure *client = new WiFiClientSecure;
|
||||||
WiFiClientSecure *client = new WiFiClientSecure;
|
client->setInsecure();
|
||||||
client->setInsecure();
|
for (;;) {
|
||||||
for (;;)
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
{
|
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
|
||||||
|
|
||||||
HTTPClient *http = new HTTPClient();
|
HTTPClient *http = new HTTPClient();
|
||||||
http->setUserAgent(USER_AGENT);
|
http->setUserAgent(USER_AGENT);
|
||||||
|
|
||||||
// Send HTTP request to CoinGecko API
|
// Send HTTP request to CoinGecko API
|
||||||
http->begin(*client, cgApiUrl);
|
http->begin(*client, cgApiUrl);
|
||||||
|
|
||||||
int httpCode = http->GET();
|
int httpCode = http->GET();
|
||||||
|
|
||||||
// Parse JSON response and extract average price
|
// Parse JSON response and extract average price
|
||||||
uint usdPrice, eurPrice;
|
uint usdPrice, eurPrice;
|
||||||
if (httpCode == 200)
|
if (httpCode == 200) {
|
||||||
{
|
String payload = http->getString();
|
||||||
String payload = http->getString();
|
StaticJsonDocument<96> doc;
|
||||||
StaticJsonDocument<96> doc;
|
deserializeJson(doc, payload);
|
||||||
deserializeJson(doc, payload);
|
// usdPrice = doc["bitcoin"]["usd"];
|
||||||
// usdPrice = doc["bitcoin"]["usd"];
|
eurPrice = doc["bitcoin"]["eur"].as<uint>();
|
||||||
eurPrice = doc["bitcoin"]["eur"].as<uint>();
|
|
||||||
|
|
||||||
setPrice(eurPrice);
|
setPrice(eurPrice);
|
||||||
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME || getCurrentScreen() == SCREEN_MARKET_CAP))
|
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER ||
|
||||||
{
|
getCurrentScreen() == SCREEN_MSCW_TIME ||
|
||||||
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
getCurrentScreen() == SCREEN_MARKET_CAP)) {
|
||||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||||
}
|
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
preferences.putUInt("lastPrice", eurPrice);
|
preferences.putUInt("lastPrice", eurPrice);
|
||||||
}
|
} else {
|
||||||
else
|
Serial.print(
|
||||||
{
|
F("Error retrieving BTC/USD price (CoinGecko). HTTP status code: "));
|
||||||
Serial.print(F("Error retrieving BTC/USD price (CoinGecko). HTTP status code: "));
|
Serial.println(httpCode);
|
||||||
Serial.println(httpCode);
|
if (httpCode == -1) {
|
||||||
if (httpCode == -1)
|
WiFi.reconnect();
|
||||||
{
|
}
|
||||||
WiFi.reconnect();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupPriceFetchTask()
|
void setupPriceFetchTask() {
|
||||||
{
|
xTaskCreate(taskPriceFetch, "priceFetch", (6 * 1024), NULL, tskIDLE_PRIORITY,
|
||||||
xTaskCreate(taskPriceFetch, "priceFetch", (6*1024), NULL, tskIDLE_PRIORITY, &priceFetchTaskHandle);
|
&priceFetchTaskHandle);
|
||||||
|
|
||||||
xTaskNotifyGive(priceFetchTaskHandle);
|
|
||||||
|
|
||||||
|
xTaskNotifyGive(priceFetchTaskHandle);
|
||||||
}
|
}
|
|
@ -1,7 +1,7 @@
|
||||||
|
#include "lib/config.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <HTTPClient.h>
|
#include <HTTPClient.h>
|
||||||
#include "config.hpp"
|
|
||||||
#include "shared.hpp"
|
|
||||||
|
|
||||||
extern TaskHandle_t priceFetchTaskHandle;
|
extern TaskHandle_t priceFetchTaskHandle;
|
||||||
|
|
||||||
|
|
|
@ -38,86 +38,82 @@ esp_websocket_client_handle_t clientPrice = NULL;
|
||||||
uint currentPrice = 30000;
|
uint currentPrice = 30000;
|
||||||
unsigned long int lastPriceUpdate;
|
unsigned long int lastPriceUpdate;
|
||||||
|
|
||||||
void setupPriceNotify()
|
void setupPriceNotify() {
|
||||||
{
|
// currentPrice = preferences.get("lastPrice", 30000);
|
||||||
// currentPrice = preferences.get("lastPrice", 30000);
|
|
||||||
|
|
||||||
esp_websocket_client_config_t config = {
|
esp_websocket_client_config_t config = {.uri = wsServerPrice,
|
||||||
.uri = wsServerPrice,
|
// .task_stack = (7*1024),
|
||||||
// .task_stack = (7*1024),
|
// .cert_pem = coinCapWsCert,
|
||||||
// .cert_pem = coinCapWsCert,
|
.user_agent = USER_AGENT};
|
||||||
.user_agent = USER_AGENT
|
|
||||||
};
|
|
||||||
|
|
||||||
clientPrice = esp_websocket_client_init(&config);
|
clientPrice = esp_websocket_client_init(&config);
|
||||||
esp_websocket_register_events(clientPrice, WEBSOCKET_EVENT_ANY, onWebsocketPriceEvent, clientPrice);
|
esp_websocket_register_events(clientPrice, WEBSOCKET_EVENT_ANY,
|
||||||
esp_websocket_client_start(clientPrice);
|
onWebsocketPriceEvent, clientPrice);
|
||||||
|
esp_websocket_client_start(clientPrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base,
|
||||||
{
|
int32_t event_id, void *event_data) {
|
||||||
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
esp_websocket_event_data_t *data = (esp_websocket_event_data_t *)event_data;
|
||||||
|
|
||||||
switch (event_id)
|
switch (event_id) {
|
||||||
{
|
case WEBSOCKET_EVENT_CONNECTED:
|
||||||
case WEBSOCKET_EVENT_CONNECTED:
|
Serial.println(F("Connected to CoinCap.io WebSocket"));
|
||||||
Serial.println(F("Connected to CoinCap.io WebSocket"));
|
break;
|
||||||
break;
|
case WEBSOCKET_EVENT_DATA:
|
||||||
case WEBSOCKET_EVENT_DATA:
|
onWebsocketPriceMessage(data);
|
||||||
onWebsocketPriceMessage(data);
|
break;
|
||||||
break;
|
case WEBSOCKET_EVENT_ERROR:
|
||||||
case WEBSOCKET_EVENT_ERROR:
|
Serial.println(F("Price WS Connnection error"));
|
||||||
Serial.println(F("Price WS Connnection error"));
|
break;
|
||||||
break;
|
case WEBSOCKET_EVENT_DISCONNECTED:
|
||||||
case WEBSOCKET_EVENT_DISCONNECTED:
|
Serial.println(F("Price WS Connnection Closed"));
|
||||||
Serial.println(F("Price WS Connnection Closed"));
|
break;
|
||||||
break;
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data)
|
void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data) {
|
||||||
{
|
SpiRamJsonDocument doc(event_data->data_len);
|
||||||
SpiRamJsonDocument doc(event_data->data_len);
|
|
||||||
|
|
||||||
deserializeJson(doc, (char *)event_data->data_ptr);
|
deserializeJson(doc, (char *)event_data->data_ptr);
|
||||||
|
|
||||||
if (doc.containsKey("bitcoin")) {
|
if (doc.containsKey("bitcoin")) {
|
||||||
if (currentPrice != doc["bitcoin"].as<long>()) {
|
if (currentPrice != doc["bitcoin"].as<long>()) {
|
||||||
|
|
||||||
uint minSecPriceUpd = preferences.getUInt("minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE);
|
uint minSecPriceUpd = preferences.getUInt(
|
||||||
uint currentTime = esp_timer_get_time() / 1000000;
|
"minSecPriceUpd", DEFAULT_SECONDS_BETWEEN_PRICE_UPDATE);
|
||||||
|
uint currentTime = esp_timer_get_time() / 1000000;
|
||||||
|
|
||||||
if (lastPriceUpdate == 0 || (currentTime - lastPriceUpdate) > minSecPriceUpd) {
|
if (lastPriceUpdate == 0 ||
|
||||||
// const unsigned long oldPrice = currentPrice;
|
(currentTime - lastPriceUpdate) > minSecPriceUpd) {
|
||||||
currentPrice = doc["bitcoin"].as<uint>();
|
// const unsigned long oldPrice = currentPrice;
|
||||||
preferences.putUInt("lastPrice", currentPrice);
|
currentPrice = doc["bitcoin"].as<uint>();
|
||||||
lastPriceUpdate = currentTime;
|
preferences.putUInt("lastPrice", currentPrice);
|
||||||
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
lastPriceUpdate = currentTime;
|
||||||
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER || getCurrentScreen() == SCREEN_MSCW_TIME || getCurrentScreen() == SCREEN_MARKET_CAP)) {
|
// if (abs((int)(oldPrice-currentPrice)) > round(0.0015*oldPrice)) {
|
||||||
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
if (workQueue != nullptr && (getCurrentScreen() == SCREEN_BTC_TICKER ||
|
||||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
getCurrentScreen() == SCREEN_MSCW_TIME ||
|
||||||
}
|
getCurrentScreen() == SCREEN_MARKET_CAP)) {
|
||||||
//}
|
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||||
}
|
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getPrice() {
|
uint getPrice() { return currentPrice; }
|
||||||
return currentPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPrice(uint newPrice) {
|
void setPrice(uint newPrice) { currentPrice = newPrice; }
|
||||||
currentPrice = newPrice;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isPriceNotifyConnected() {
|
bool isPriceNotifyConnected() {
|
||||||
if (clientPrice == NULL)
|
if (clientPrice == NULL)
|
||||||
return false;
|
return false;
|
||||||
return esp_websocket_client_is_connected(clientPrice);
|
return esp_websocket_client_is_connected(clientPrice);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stopPriceNotify() {
|
void stopPriceNotify() {
|
||||||
esp_websocket_client_stop(clientPrice);
|
esp_websocket_client_stop(clientPrice);
|
||||||
esp_websocket_client_destroy(clientPrice);
|
esp_websocket_client_destroy(clientPrice);
|
||||||
}
|
}
|
|
@ -1,18 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "esp_websocket_client.h"
|
#include <esp_websocket_client.h>
|
||||||
#include "screen_handler.hpp"
|
#include "lib/screen_handler.hpp"
|
||||||
|
|
||||||
//using namespace websockets;
|
// using namespace websockets;
|
||||||
|
|
||||||
void setupPriceNotify();
|
void setupPriceNotify();
|
||||||
|
|
||||||
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data);
|
void onWebsocketPriceEvent(void *handler_args, esp_event_base_t base,
|
||||||
void onWebsocketPriceMessage(esp_websocket_event_data_t* event_data);
|
int32_t event_id, void *event_data);
|
||||||
|
void onWebsocketPriceMessage(esp_websocket_event_data_t *event_data);
|
||||||
|
|
||||||
uint getPrice();
|
uint getPrice();
|
||||||
void setPrice(uint newPrice);
|
void setPrice(uint newPrice);
|
||||||
|
|
|
@ -8,7 +8,8 @@ TaskHandle_t workerTaskHandle;
|
||||||
esp_timer_handle_t screenRotateTimer;
|
esp_timer_handle_t screenRotateTimer;
|
||||||
esp_timer_handle_t minuteTimer;
|
esp_timer_handle_t minuteTimer;
|
||||||
|
|
||||||
std::array<std::string, NUM_SCREENS> taskEpdContent = {"", "", "", "", "", "", ""};
|
std::array<std::string, NUM_SCREENS> taskEpdContent = {"", "", "", "",
|
||||||
|
"", "", ""};
|
||||||
std::string priceString;
|
std::string priceString;
|
||||||
|
|
||||||
// typedef enum
|
// typedef enum
|
||||||
|
@ -29,327 +30,280 @@ QueueHandle_t workQueue = NULL;
|
||||||
|
|
||||||
uint currentScreen;
|
uint currentScreen;
|
||||||
|
|
||||||
void workerTask(void *pvParameters)
|
void workerTask(void *pvParameters) {
|
||||||
{
|
WorkItem receivedItem;
|
||||||
WorkItem receivedItem;
|
|
||||||
|
|
||||||
while (1)
|
while (1) {
|
||||||
{
|
// Wait for a work item to be available in the queue
|
||||||
// Wait for a work item to be available in the queue
|
if (xQueueReceive(workQueue, &receivedItem, portMAX_DELAY)) {
|
||||||
if (xQueueReceive(workQueue, &receivedItem, portMAX_DELAY))
|
uint firstIndex = 0;
|
||||||
{
|
|
||||||
uint firstIndex = 0;
|
|
||||||
|
|
||||||
// Process the work item based on its type
|
// Process the work item based on its type
|
||||||
switch (receivedItem.type)
|
switch (receivedItem.type) {
|
||||||
{
|
case TASK_PRICE_UPDATE: {
|
||||||
case TASK_PRICE_UPDATE:
|
uint price = getPrice();
|
||||||
{
|
char priceSymbol = '$';
|
||||||
uint price = getPrice();
|
if (preferences.getBool("fetchEurPrice", false)) {
|
||||||
char priceSymbol = '$';
|
priceSymbol = '[';
|
||||||
if (preferences.getBool("fetchEurPrice", false))
|
|
||||||
{
|
|
||||||
priceSymbol = '[';
|
|
||||||
}
|
|
||||||
if (getCurrentScreen() == SCREEN_BTC_TICKER)
|
|
||||||
{
|
|
||||||
taskEpdContent = parsePriceData(price, priceSymbol);
|
|
||||||
}
|
|
||||||
else if (getCurrentScreen() == SCREEN_MSCW_TIME)
|
|
||||||
{
|
|
||||||
taskEpdContent = parseSatsPerCurrency(price, priceSymbol);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
taskEpdContent = parseMarketCap(getBlockHeight(), price, priceSymbol, preferences.getBool("mcapBigChar", true));
|
|
||||||
}
|
|
||||||
|
|
||||||
setEpdContent(taskEpdContent);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TASK_BLOCK_UPDATE:
|
|
||||||
{
|
|
||||||
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN)
|
|
||||||
{
|
|
||||||
taskEpdContent = parseBlockHeight(getBlockHeight());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
taskEpdContent = parseHalvingCountdown(getBlockHeight());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getCurrentScreen() == SCREEN_HALVING_COUNTDOWN || getCurrentScreen() == SCREEN_BLOCK_HEIGHT)
|
|
||||||
{
|
|
||||||
setEpdContent(taskEpdContent);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TASK_TIME_UPDATE:
|
|
||||||
{
|
|
||||||
if (getCurrentScreen() == SCREEN_TIME)
|
|
||||||
{
|
|
||||||
time_t currentTime;
|
|
||||||
struct tm timeinfo;
|
|
||||||
time(¤tTime);
|
|
||||||
localtime_r(¤tTime, &timeinfo);
|
|
||||||
std::string timeString;
|
|
||||||
|
|
||||||
String minute = String(timeinfo.tm_min);
|
|
||||||
if (minute.length() < 2)
|
|
||||||
{
|
|
||||||
minute = "0" + minute;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeString = std::to_string(timeinfo.tm_hour) + ":" + minute.c_str();
|
|
||||||
timeString.insert(timeString.begin(), NUM_SCREENS - timeString.length(), ' ');
|
|
||||||
taskEpdContent[0] = std::to_string(timeinfo.tm_mday) + "/" + std::to_string(timeinfo.tm_mon + 1);
|
|
||||||
|
|
||||||
for (uint i = 1; i < NUM_SCREENS; i++)
|
|
||||||
{
|
|
||||||
taskEpdContent[i] = timeString[i];
|
|
||||||
}
|
|
||||||
setEpdContent(taskEpdContent);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// Add more cases for additional task types
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
if (getCurrentScreen() == SCREEN_BTC_TICKER) {
|
||||||
}
|
taskEpdContent = parsePriceData(price, priceSymbol);
|
||||||
|
} else if (getCurrentScreen() == SCREEN_MSCW_TIME) {
|
||||||
void taskScreenRotate(void *pvParameters)
|
taskEpdContent = parseSatsPerCurrency(price, priceSymbol);
|
||||||
{
|
} else {
|
||||||
for (;;)
|
taskEpdContent =
|
||||||
{
|
parseMarketCap(getBlockHeight(), price, priceSymbol,
|
||||||
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
preferences.getBool("mcapBigChar", true));
|
||||||
|
|
||||||
int nextScreen = (currentScreen + 1) % SCREEN_COUNT;
|
|
||||||
String key = "screen" + String(nextScreen) + "Visible";
|
|
||||||
|
|
||||||
while (!preferences.getBool(key.c_str(), true))
|
|
||||||
{
|
|
||||||
nextScreen = (nextScreen + 1) % SCREEN_COUNT;
|
|
||||||
key = "screen" + String(nextScreen) + "Visible";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentScreen(nextScreen);
|
setEpdContent(taskEpdContent);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TASK_BLOCK_UPDATE: {
|
||||||
|
if (getCurrentScreen() != SCREEN_HALVING_COUNTDOWN) {
|
||||||
|
taskEpdContent = parseBlockHeight(getBlockHeight());
|
||||||
|
} else {
|
||||||
|
taskEpdContent = parseHalvingCountdown(getBlockHeight());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getCurrentScreen() == SCREEN_HALVING_COUNTDOWN ||
|
||||||
|
getCurrentScreen() == SCREEN_BLOCK_HEIGHT) {
|
||||||
|
setEpdContent(taskEpdContent);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TASK_TIME_UPDATE: {
|
||||||
|
if (getCurrentScreen() == SCREEN_TIME) {
|
||||||
|
time_t currentTime;
|
||||||
|
struct tm timeinfo;
|
||||||
|
time(¤tTime);
|
||||||
|
localtime_r(¤tTime, &timeinfo);
|
||||||
|
std::string timeString;
|
||||||
|
|
||||||
|
String minute = String(timeinfo.tm_min);
|
||||||
|
if (minute.length() < 2) {
|
||||||
|
minute = "0" + minute;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeString = std::to_string(timeinfo.tm_hour) + ":" + minute.c_str();
|
||||||
|
timeString.insert(timeString.begin(),
|
||||||
|
NUM_SCREENS - timeString.length(), ' ');
|
||||||
|
taskEpdContent[0] = std::to_string(timeinfo.tm_mday) + "/" +
|
||||||
|
std::to_string(timeinfo.tm_mon + 1);
|
||||||
|
|
||||||
|
for (uint i = 1; i < NUM_SCREENS; i++) {
|
||||||
|
taskEpdContent[i] = timeString[i];
|
||||||
|
}
|
||||||
|
setEpdContent(taskEpdContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Add more cases for additional task types
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR minuteTimerISR(void *arg)
|
void taskScreenRotate(void *pvParameters) {
|
||||||
{
|
for (;;) {
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
|
||||||
// vTaskNotifyGiveFromISR(timeUpdateTaskHandle, &xHigherPriorityTaskWoken);
|
|
||||||
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
int nextScreen = (currentScreen + 1) % SCREEN_COUNT;
|
||||||
xQueueSendFromISR(workQueue, &timeUpdate, &xHigherPriorityTaskWoken);
|
String key = "screen" + String(nextScreen) + "Visible";
|
||||||
if (priceFetchTaskHandle != NULL)
|
|
||||||
{
|
while (!preferences.getBool(key.c_str(), true)) {
|
||||||
vTaskNotifyGiveFromISR(priceFetchTaskHandle, &xHigherPriorityTaskWoken);
|
nextScreen = (nextScreen + 1) % SCREEN_COUNT;
|
||||||
}
|
key = "screen" + String(nextScreen) + "Visible";
|
||||||
if (xHigherPriorityTaskWoken == pdTRUE)
|
|
||||||
{
|
|
||||||
portYIELD_FROM_ISR();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setCurrentScreen(nextScreen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRAM_ATTR screenRotateTimerISR(void *arg)
|
void IRAM_ATTR minuteTimerISR(void *arg) {
|
||||||
{
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
// vTaskNotifyGiveFromISR(timeUpdateTaskHandle, &xHigherPriorityTaskWoken);
|
||||||
vTaskNotifyGiveFromISR(taskScreenRotateTaskHandle, &xHigherPriorityTaskWoken);
|
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||||
if (xHigherPriorityTaskWoken == pdTRUE)
|
xQueueSendFromISR(workQueue, &timeUpdate, &xHigherPriorityTaskWoken);
|
||||||
{
|
if (priceFetchTaskHandle != NULL) {
|
||||||
portYIELD_FROM_ISR();
|
vTaskNotifyGiveFromISR(priceFetchTaskHandle, &xHigherPriorityTaskWoken);
|
||||||
}
|
}
|
||||||
|
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTasks()
|
void IRAM_ATTR screenRotateTimerISR(void *arg) {
|
||||||
{
|
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
|
||||||
workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem));
|
vTaskNotifyGiveFromISR(taskScreenRotateTaskHandle, &xHigherPriorityTaskWoken);
|
||||||
|
if (xHigherPriorityTaskWoken == pdTRUE) {
|
||||||
// xTaskCreate(taskPriceUpdate, "updatePrice", 1024, NULL, tskIDLE_PRIORITY, &priceUpdateTaskHandle);
|
portYIELD_FROM_ISR();
|
||||||
// xTaskCreate(taskBlockUpdate, "updateBlock", 1024, NULL, tskIDLE_PRIORITY, &blockUpdateTaskHandle);
|
}
|
||||||
// xTaskCreate(taskTimeUpdate, "updateTime", 1024, NULL, tskIDLE_PRIORITY, &timeUpdateTaskHandle);
|
|
||||||
xTaskCreate(workerTask, "workerTask", 4096, NULL, tskIDLE_PRIORITY, &workerTaskHandle);
|
|
||||||
|
|
||||||
xTaskCreate(taskScreenRotate, "rotateScreen", 2048, NULL, tskIDLE_PRIORITY, &taskScreenRotateTaskHandle);
|
|
||||||
|
|
||||||
waitUntilNoneBusy();
|
|
||||||
setCurrentScreen(preferences.getUInt("currentScreen", 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupTimeUpdateTimer(void *pvParameters)
|
void setupTasks() {
|
||||||
{
|
workQueue = xQueueCreate(WORK_QUEUE_SIZE, sizeof(WorkItem));
|
||||||
const esp_timer_create_args_t minuteTimerConfig = {
|
|
||||||
.callback = &minuteTimerISR,
|
|
||||||
.name = "minute_timer"};
|
|
||||||
|
|
||||||
esp_timer_create(&minuteTimerConfig, &minuteTimer);
|
// xTaskCreate(taskPriceUpdate, "updatePrice", 1024, NULL, tskIDLE_PRIORITY,
|
||||||
|
// &priceUpdateTaskHandle); xTaskCreate(taskBlockUpdate, "updateBlock", 1024,
|
||||||
|
// NULL, tskIDLE_PRIORITY, &blockUpdateTaskHandle);
|
||||||
|
// xTaskCreate(taskTimeUpdate, "updateTime", 1024, NULL, tskIDLE_PRIORITY,
|
||||||
|
// &timeUpdateTaskHandle);
|
||||||
|
xTaskCreate(workerTask, "workerTask", 4096, NULL, tskIDLE_PRIORITY,
|
||||||
|
&workerTaskHandle);
|
||||||
|
|
||||||
time_t currentTime;
|
xTaskCreate(taskScreenRotate, "rotateScreen", 2048, NULL, tskIDLE_PRIORITY,
|
||||||
struct tm timeinfo;
|
&taskScreenRotateTaskHandle);
|
||||||
time(¤tTime);
|
|
||||||
localtime_r(¤tTime, &timeinfo);
|
|
||||||
uint32_t secondsUntilNextMinute = 60 - timeinfo.tm_sec;
|
|
||||||
|
|
||||||
if (secondsUntilNextMinute > 0)
|
waitUntilNoneBusy();
|
||||||
vTaskDelay(pdMS_TO_TICKS((secondsUntilNextMinute * 1000)));
|
setCurrentScreen(preferences.getUInt("currentScreen", 0));
|
||||||
|
}
|
||||||
|
|
||||||
esp_timer_start_periodic(minuteTimer, usPerMinute);
|
void setupTimeUpdateTimer(void *pvParameters) {
|
||||||
|
const esp_timer_create_args_t minuteTimerConfig = {
|
||||||
|
.callback = &minuteTimerISR, .name = "minute_timer"};
|
||||||
|
|
||||||
|
esp_timer_create(&minuteTimerConfig, &minuteTimer);
|
||||||
|
|
||||||
|
time_t currentTime;
|
||||||
|
struct tm timeinfo;
|
||||||
|
time(¤tTime);
|
||||||
|
localtime_r(¤tTime, &timeinfo);
|
||||||
|
uint32_t secondsUntilNextMinute = 60 - timeinfo.tm_sec;
|
||||||
|
|
||||||
|
if (secondsUntilNextMinute > 0)
|
||||||
|
vTaskDelay(pdMS_TO_TICKS((secondsUntilNextMinute * 1000)));
|
||||||
|
|
||||||
|
esp_timer_start_periodic(minuteTimer, usPerMinute);
|
||||||
|
|
||||||
|
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
||||||
|
// xTaskNotifyGive(timeUpdateTaskHandle);
|
||||||
|
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setupScreenRotateTimer(void *pvParameters) {
|
||||||
|
const esp_timer_create_args_t screenRotateTimerConfig = {
|
||||||
|
.callback = &screenRotateTimerISR, .name = "screen_rotate_timer"};
|
||||||
|
|
||||||
|
esp_timer_create(&screenRotateTimerConfig, &screenRotateTimer);
|
||||||
|
|
||||||
|
if (preferences.getBool("timerActive", true)) {
|
||||||
|
esp_timer_start_periodic(screenRotateTimer,
|
||||||
|
getTimerSeconds() * usPerSecond);
|
||||||
|
}
|
||||||
|
|
||||||
|
vTaskDelete(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint getTimerSeconds() { return preferences.getUInt("timerSeconds", 1800); }
|
||||||
|
|
||||||
|
bool isTimerActive() { return esp_timer_is_active(screenRotateTimer); }
|
||||||
|
|
||||||
|
void setTimerActive(bool status) {
|
||||||
|
if (status) {
|
||||||
|
esp_timer_start_periodic(screenRotateTimer,
|
||||||
|
getTimerSeconds() * usPerSecond);
|
||||||
|
queueLedEffect(LED_EFFECT_START_TIMER);
|
||||||
|
preferences.putBool("timerActive", true);
|
||||||
|
} else {
|
||||||
|
esp_timer_stop(screenRotateTimer);
|
||||||
|
queueLedEffect(LED_EFFECT_PAUSE_TIMER);
|
||||||
|
preferences.putBool("timerActive", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (eventSourceTaskHandle != NULL)
|
||||||
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleTimerActive() { setTimerActive(!isTimerActive()); }
|
||||||
|
|
||||||
|
uint getCurrentScreen() { return currentScreen; }
|
||||||
|
|
||||||
|
void setCurrentScreen(uint newScreen) {
|
||||||
|
if (newScreen != SCREEN_CUSTOM) {
|
||||||
|
preferences.putUInt("currentScreen", newScreen);
|
||||||
|
}
|
||||||
|
|
||||||
|
currentScreen = newScreen;
|
||||||
|
|
||||||
|
switch (currentScreen) {
|
||||||
|
case SCREEN_TIME: {
|
||||||
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
||||||
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
||||||
// xTaskNotifyGive(timeUpdateTaskHandle);
|
// xTaskNotifyGive(timeUpdateTaskHandle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCREEN_HALVING_COUNTDOWN:
|
||||||
|
case SCREEN_BLOCK_HEIGHT: {
|
||||||
|
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
||||||
|
// xTaskNotifyGive(blockUpdateTaskHandle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SCREEN_MARKET_CAP:
|
||||||
|
case SCREEN_MSCW_TIME:
|
||||||
|
case SCREEN_BTC_TICKER: {
|
||||||
|
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
||||||
|
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
||||||
|
// xTaskNotifyGive(priceUpdateTaskHandle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
if (eventSourceTaskHandle != NULL)
|
||||||
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setupScreenRotateTimer(void *pvParameters)
|
void nextScreen() {
|
||||||
{
|
int newCurrentScreen = (getCurrentScreen() + 1) % SCREEN_COUNT;
|
||||||
const esp_timer_create_args_t screenRotateTimerConfig = {
|
String key = "screen" + String(newCurrentScreen) + "Visible";
|
||||||
.callback = &screenRotateTimerISR,
|
|
||||||
.name = "screen_rotate_timer"};
|
|
||||||
|
|
||||||
esp_timer_create(&screenRotateTimerConfig, &screenRotateTimer);
|
while (!preferences.getBool(key.c_str(), true)) {
|
||||||
|
newCurrentScreen = (newCurrentScreen + 1) % SCREEN_COUNT;
|
||||||
if (preferences.getBool("timerActive", true))
|
key = "screen" + String(newCurrentScreen) + "Visible";
|
||||||
{
|
}
|
||||||
esp_timer_start_periodic(screenRotateTimer, getTimerSeconds() * usPerSecond);
|
setCurrentScreen(newCurrentScreen);
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelete(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint getTimerSeconds()
|
void previousScreen() {
|
||||||
{
|
|
||||||
return preferences.getUInt("timerSeconds", 1800);
|
int newCurrentScreen = modulo(getCurrentScreen() - 1, SCREEN_COUNT);
|
||||||
|
String key = "screen" + String(newCurrentScreen) + "Visible";
|
||||||
|
|
||||||
|
while (!preferences.getBool(key.c_str(), true)) {
|
||||||
|
newCurrentScreen = modulo(newCurrentScreen - 1, SCREEN_COUNT);
|
||||||
|
key = "screen" + String(newCurrentScreen) + "Visible";
|
||||||
|
}
|
||||||
|
setCurrentScreen(newCurrentScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTimerActive()
|
void showSystemStatusScreen() {
|
||||||
{
|
std::array<String, NUM_SCREENS> sysStatusEpdContent = {"", "", "", "",
|
||||||
return esp_timer_is_active(screenRotateTimer);
|
"", "", ""};
|
||||||
}
|
|
||||||
|
|
||||||
void setTimerActive(bool status)
|
String ipAddr = WiFi.localIP().toString();
|
||||||
{
|
String subNet = WiFi.subnetMask().toString();
|
||||||
if (status)
|
|
||||||
{
|
|
||||||
esp_timer_start_periodic(screenRotateTimer, getTimerSeconds() * usPerSecond);
|
|
||||||
queueLedEffect(LED_EFFECT_START_TIMER);
|
|
||||||
preferences.putBool("timerActive", true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
esp_timer_stop(screenRotateTimer);
|
|
||||||
queueLedEffect(LED_EFFECT_PAUSE_TIMER);
|
|
||||||
preferences.putBool("timerActive", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventSourceTaskHandle != NULL)
|
sysStatusEpdContent[0] = "IP/Subnet";
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void toggleTimerActive()
|
int ipAddrPos = 0;
|
||||||
{
|
int subnetPos = 0;
|
||||||
setTimerActive(!isTimerActive());
|
for (int i = 0; i < 4; i++) {
|
||||||
}
|
sysStatusEpdContent[1 + i] = ipAddr.substring(0, ipAddr.indexOf('.')) +
|
||||||
|
"/" + subNet.substring(0, subNet.indexOf('.'));
|
||||||
|
ipAddrPos = ipAddr.indexOf('.') + 1;
|
||||||
|
subnetPos = subNet.indexOf('.') + 1;
|
||||||
|
ipAddr = ipAddr.substring(ipAddrPos);
|
||||||
|
subNet = subNet.substring(subnetPos);
|
||||||
|
}
|
||||||
|
sysStatusEpdContent[NUM_SCREENS - 2] = "RAM/Status";
|
||||||
|
|
||||||
uint getCurrentScreen()
|
sysStatusEpdContent[NUM_SCREENS - 1] =
|
||||||
{
|
String((int)round(ESP.getFreeHeap() / 1024)) + "/" +
|
||||||
return currentScreen;
|
(int)round(ESP.getHeapSize() / 1024);
|
||||||
}
|
setCurrentScreen(SCREEN_CUSTOM);
|
||||||
|
setEpdContent(sysStatusEpdContent);
|
||||||
void setCurrentScreen(uint newScreen)
|
|
||||||
{
|
|
||||||
if (newScreen != SCREEN_CUSTOM)
|
|
||||||
{
|
|
||||||
preferences.putUInt("currentScreen", newScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
currentScreen = newScreen;
|
|
||||||
|
|
||||||
switch (currentScreen)
|
|
||||||
{
|
|
||||||
case SCREEN_TIME:
|
|
||||||
{
|
|
||||||
WorkItem timeUpdate = {TASK_TIME_UPDATE, 0};
|
|
||||||
xQueueSend(workQueue, &timeUpdate, portMAX_DELAY);
|
|
||||||
// xTaskNotifyGive(timeUpdateTaskHandle);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SCREEN_HALVING_COUNTDOWN:
|
|
||||||
case SCREEN_BLOCK_HEIGHT:
|
|
||||||
{
|
|
||||||
WorkItem blockUpdate = {TASK_BLOCK_UPDATE, 0};
|
|
||||||
xQueueSend(workQueue, &blockUpdate, portMAX_DELAY);
|
|
||||||
// xTaskNotifyGive(blockUpdateTaskHandle);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SCREEN_MARKET_CAP:
|
|
||||||
case SCREEN_MSCW_TIME:
|
|
||||||
case SCREEN_BTC_TICKER:
|
|
||||||
{
|
|
||||||
WorkItem priceUpdate = {TASK_PRICE_UPDATE, 0};
|
|
||||||
xQueueSend(workQueue, &priceUpdate, portMAX_DELAY);
|
|
||||||
// xTaskNotifyGive(priceUpdateTaskHandle);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (eventSourceTaskHandle != NULL)
|
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void nextScreen()
|
|
||||||
{
|
|
||||||
int newCurrentScreen = (getCurrentScreen() + 1) % SCREEN_COUNT;
|
|
||||||
String key = "screen" + String(newCurrentScreen) + "Visible";
|
|
||||||
|
|
||||||
while (!preferences.getBool(key.c_str(), true))
|
|
||||||
{
|
|
||||||
newCurrentScreen = (newCurrentScreen + 1) % SCREEN_COUNT;
|
|
||||||
key = "screen" + String(newCurrentScreen) + "Visible";
|
|
||||||
}
|
|
||||||
setCurrentScreen(newCurrentScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void previousScreen()
|
|
||||||
{
|
|
||||||
|
|
||||||
int newCurrentScreen = modulo(getCurrentScreen() - 1, SCREEN_COUNT);
|
|
||||||
String key = "screen" + String(newCurrentScreen) + "Visible";
|
|
||||||
|
|
||||||
while (!preferences.getBool(key.c_str(), true))
|
|
||||||
{
|
|
||||||
newCurrentScreen = modulo(newCurrentScreen - 1, SCREEN_COUNT);
|
|
||||||
key = "screen" + String(newCurrentScreen) + "Visible";
|
|
||||||
}
|
|
||||||
setCurrentScreen(newCurrentScreen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void showSystemStatusScreen()
|
|
||||||
{
|
|
||||||
std::array<String, NUM_SCREENS> sysStatusEpdContent = {"", "", "", "", "", "", ""};
|
|
||||||
|
|
||||||
String ipAddr = WiFi.localIP().toString();
|
|
||||||
String subNet = WiFi.subnetMask().toString();
|
|
||||||
|
|
||||||
sysStatusEpdContent[0] = "IP/Subnet";
|
|
||||||
|
|
||||||
int ipAddrPos = 0;
|
|
||||||
int subnetPos = 0;
|
|
||||||
for (int i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
sysStatusEpdContent[1 + i] = ipAddr.substring(0, ipAddr.indexOf('.')) + "/" + subNet.substring(0, subNet.indexOf('.'));
|
|
||||||
ipAddrPos = ipAddr.indexOf('.') + 1;
|
|
||||||
subnetPos = subNet.indexOf('.') + 1;
|
|
||||||
ipAddr = ipAddr.substring(ipAddrPos);
|
|
||||||
subNet = subNet.substring(subnetPos);
|
|
||||||
}
|
|
||||||
sysStatusEpdContent[NUM_SCREENS - 2] = "RAM/Status";
|
|
||||||
|
|
||||||
sysStatusEpdContent[NUM_SCREENS - 1] = String((int)round(ESP.getFreeHeap() / 1024)) + "/" + (int)round(ESP.getHeapSize() / 1024);
|
|
||||||
setCurrentScreen(SCREEN_CUSTOM);
|
|
||||||
setEpdContent(sysStatusEpdContent);
|
|
||||||
}
|
}
|
|
@ -2,13 +2,13 @@
|
||||||
|
|
||||||
#include <esp_timer.h>
|
#include <esp_timer.h>
|
||||||
|
|
||||||
|
#include <data_handler.hpp>
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
#include <data_handler.hpp>
|
|
||||||
|
|
||||||
#include "price_fetch.hpp"
|
|
||||||
#include "shared.hpp"
|
|
||||||
#include "lib/epd.hpp"
|
#include "lib/epd.hpp"
|
||||||
|
#include "lib/price_fetch.hpp"
|
||||||
|
#include "lib/shared.hpp"
|
||||||
|
|
||||||
// extern TaskHandle_t priceUpdateTaskHandle;
|
// extern TaskHandle_t priceUpdateTaskHandle;
|
||||||
// extern TaskHandle_t blockUpdateTaskHandle;
|
// extern TaskHandle_t blockUpdateTaskHandle;
|
||||||
|
@ -21,17 +21,15 @@ extern esp_timer_handle_t minuteTimer;
|
||||||
|
|
||||||
extern QueueHandle_t workQueue;
|
extern QueueHandle_t workQueue;
|
||||||
|
|
||||||
typedef enum
|
typedef enum {
|
||||||
{
|
TASK_PRICE_UPDATE,
|
||||||
TASK_PRICE_UPDATE,
|
TASK_BLOCK_UPDATE,
|
||||||
TASK_BLOCK_UPDATE,
|
TASK_TIME_UPDATE
|
||||||
TASK_TIME_UPDATE
|
|
||||||
} TaskType;
|
} TaskType;
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
TaskType type;
|
||||||
TaskType type;
|
char data;
|
||||||
char data;
|
|
||||||
} WorkItem;
|
} WorkItem;
|
||||||
|
|
||||||
void workerTask(void *pvParameters);
|
void workerTask(void *pvParameters);
|
||||||
|
@ -45,8 +43,8 @@ void showSystemStatusScreen();
|
||||||
void setupTimeUpdateTimer(void *pvParameters);
|
void setupTimeUpdateTimer(void *pvParameters);
|
||||||
void setupScreenRotateTimer(void *pvParameters);
|
void setupScreenRotateTimer(void *pvParameters);
|
||||||
|
|
||||||
void IRAM_ATTR minuteTimerISR(void* arg);
|
void IRAM_ATTR minuteTimerISR(void *arg);
|
||||||
void IRAM_ATTR screenRotateTimerISR(void* arg);
|
void IRAM_ATTR screenRotateTimerISR(void *arg);
|
||||||
|
|
||||||
// void taskPriceUpdate(void *pvParameters);
|
// void taskPriceUpdate(void *pvParameters);
|
||||||
// void taskBlockUpdate(void *pvParameters);
|
// void taskBlockUpdate(void *pvParameters);
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <freertos/FreeRTOS.h>
|
|
||||||
#include <freertos/task.h>
|
|
||||||
#include <Adafruit_MCP23X17.h>
|
#include <Adafruit_MCP23X17.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include <Preferences.h>
|
#include <Preferences.h>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
#include <freertos/task.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include "utils.hpp"
|
#include <utils.hpp>
|
||||||
|
|
||||||
extern Adafruit_MCP23X17 mcp1;
|
extern Adafruit_MCP23X17 mcp1;
|
||||||
#ifdef IS_BTCLOCK_S3
|
#ifdef IS_BTCLOCK_S3
|
||||||
|
@ -26,23 +26,22 @@ const PROGMEM int SCREEN_MARKET_CAP = 5;
|
||||||
const PROGMEM int SCREEN_COUNTDOWN = 98;
|
const PROGMEM int SCREEN_COUNTDOWN = 98;
|
||||||
const PROGMEM int SCREEN_CUSTOM = 99;
|
const PROGMEM int SCREEN_CUSTOM = 99;
|
||||||
const int SCREEN_COUNT = 6;
|
const int SCREEN_COUNT = 6;
|
||||||
const PROGMEM int screens[SCREEN_COUNT] = { SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER, SCREEN_TIME, SCREEN_HALVING_COUNTDOWN, SCREEN_MARKET_CAP };
|
const PROGMEM int screens[SCREEN_COUNT] = {
|
||||||
|
SCREEN_BLOCK_HEIGHT, SCREEN_MSCW_TIME, SCREEN_BTC_TICKER,
|
||||||
|
SCREEN_TIME, SCREEN_HALVING_COUNTDOWN, SCREEN_MARKET_CAP};
|
||||||
const int usPerSecond = 1000000;
|
const int usPerSecond = 1000000;
|
||||||
const int usPerMinute = 60 * usPerSecond;
|
const int usPerMinute = 60 * usPerSecond;
|
||||||
|
|
||||||
struct SpiRamAllocator {
|
struct SpiRamAllocator {
|
||||||
void* allocate(size_t size) {
|
void *allocate(size_t size) {
|
||||||
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
|
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM);
|
||||||
}
|
}
|
||||||
|
|
||||||
void deallocate(void* pointer) {
|
void deallocate(void *pointer) { heap_caps_free(pointer); }
|
||||||
heap_caps_free(pointer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void* reallocate(void* ptr, size_t new_size) {
|
void *reallocate(void *ptr, size_t new_size) {
|
||||||
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
|
return heap_caps_realloc(ptr, new_size, MALLOC_CAP_SPIRAM);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using SpiRamJsonDocument = BasicJsonDocument<SpiRamAllocator>;
|
using SpiRamJsonDocument = BasicJsonDocument<SpiRamAllocator>;
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,4 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "WebServer.h"
|
#include "WebServer.h"
|
||||||
#include "ESPAsyncWebServer.h"
|
#include "ESPAsyncWebServer.h"
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
@ -7,10 +8,19 @@
|
||||||
#include "AsyncJson.h"
|
#include "AsyncJson.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
// #include "AsyncJson.h"
|
||||||
|
// #include "ESPAsyncWebServer.h"
|
||||||
|
// #include "WebServer.h"
|
||||||
|
// #include <ArduinoJson.h>
|
||||||
|
// #include <ESPmDNS.h>
|
||||||
|
// #include <LittleFS.h>
|
||||||
|
// #include <iostream>
|
||||||
|
|
||||||
#include "lib/block_notify.hpp"
|
#include "lib/block_notify.hpp"
|
||||||
|
#include "lib/led_handler.hpp"
|
||||||
#include "lib/price_notify.hpp"
|
#include "lib/price_notify.hpp"
|
||||||
#include "lib/screen_handler.hpp"
|
#include "lib/screen_handler.hpp"
|
||||||
#include "lib/led_handler.hpp"
|
|
||||||
|
|
||||||
#include "webserver/OneParamRewrite.hpp"
|
#include "webserver/OneParamRewrite.hpp"
|
||||||
|
|
||||||
|
@ -40,7 +50,6 @@ void onApiLightsOff(AsyncWebServerRequest *request);
|
||||||
void onApiLightsSetColor(AsyncWebServerRequest *request);
|
void onApiLightsSetColor(AsyncWebServerRequest *request);
|
||||||
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json);
|
void onApiLightsSetJson(AsyncWebServerRequest *request, JsonVariant &json);
|
||||||
|
|
||||||
|
|
||||||
void onApiRestart(AsyncWebServerRequest *request);
|
void onApiRestart(AsyncWebServerRequest *request);
|
||||||
|
|
||||||
void onIndex(AsyncWebServerRequest *request);
|
void onIndex(AsyncWebServerRequest *request);
|
||||||
|
|
|
@ -1,43 +1,31 @@
|
||||||
#include "OneParamRewrite.hpp"
|
#include "OneParamRewrite.hpp"
|
||||||
|
|
||||||
OneParamRewrite::OneParamRewrite(const char *from, const char *to)
|
OneParamRewrite::OneParamRewrite(const char *from, const char *to)
|
||||||
: AsyncWebRewrite(from, to)
|
: AsyncWebRewrite(from, to) {
|
||||||
{
|
|
||||||
|
|
||||||
_paramIndex = _from.indexOf('{');
|
_paramIndex = _from.indexOf('{');
|
||||||
|
|
||||||
if (_paramIndex >= 0 && _from.endsWith("}"))
|
if (_paramIndex >= 0 && _from.endsWith("}")) {
|
||||||
{
|
_urlPrefix = _from.substring(0, _paramIndex);
|
||||||
_urlPrefix = _from.substring(0, _paramIndex);
|
int index = _params.indexOf('{');
|
||||||
int index = _params.indexOf('{');
|
if (index >= 0) {
|
||||||
if (index >= 0)
|
_params = _params.substring(0, index);
|
||||||
{
|
|
||||||
_params = _params.substring(0, index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
} else {
|
||||||
{
|
_urlPrefix = _from;
|
||||||
_urlPrefix = _from;
|
}
|
||||||
}
|
_paramsBackup = _params;
|
||||||
_paramsBackup = _params;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OneParamRewrite::match(AsyncWebServerRequest *request)
|
bool OneParamRewrite::match(AsyncWebServerRequest *request) {
|
||||||
{
|
if (request->url().startsWith(_urlPrefix)) {
|
||||||
if (request->url().startsWith(_urlPrefix))
|
if (_paramIndex >= 0) {
|
||||||
{
|
_params = _paramsBackup + request->url().substring(_paramIndex);
|
||||||
if (_paramIndex >= 0)
|
} else {
|
||||||
{
|
_params = _paramsBackup;
|
||||||
_params = _paramsBackup + request->url().substring(_paramIndex);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_params = _paramsBackup;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,14 +2,13 @@
|
||||||
|
|
||||||
#include "ESPAsyncWebServer.h"
|
#include "ESPAsyncWebServer.h"
|
||||||
|
|
||||||
class OneParamRewrite : public AsyncWebRewrite
|
class OneParamRewrite : public AsyncWebRewrite {
|
||||||
{
|
|
||||||
protected:
|
protected:
|
||||||
String _urlPrefix;
|
String _urlPrefix;
|
||||||
int _paramIndex;
|
int _paramIndex;
|
||||||
String _paramsBackup;
|
String _paramsBackup;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OneParamRewrite(const char *from, const char *to);
|
OneParamRewrite(const char *from, const char *to);
|
||||||
bool match(AsyncWebServerRequest *request) override;
|
bool match(AsyncWebServerRequest *request) override;
|
||||||
};
|
};
|
82
src/main.cpp
82
src/main.cpp
|
@ -1,50 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2023 Djuri Baars
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <WiFiManager.h>
|
#include <WiFiManager.h>
|
||||||
#define WEBSERVER_H
|
#define WEBSERVER_H
|
||||||
#include "ESPAsyncWebServer.h"
|
#include "ESPAsyncWebServer.h"
|
||||||
|
|
||||||
#include "lib/config.hpp"
|
#include "lib/config.hpp"
|
||||||
|
|
||||||
//char ptrTaskList[400];
|
|
||||||
|
|
||||||
uint wifiLostConnection;
|
uint wifiLostConnection;
|
||||||
|
|
||||||
extern "C" void app_main()
|
extern "C" void app_main() {
|
||||||
{
|
initArduino();
|
||||||
initArduino();
|
|
||||||
|
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
while (true)
|
while (true) {
|
||||||
{
|
// vTaskList(ptrTaskList);
|
||||||
// vTaskList(ptrTaskList);
|
// Serial.println(F("**********************************"));
|
||||||
// Serial.println(F("**********************************"));
|
// Serial.println(F("Task State Prio Stack Num"));
|
||||||
// Serial.println(F("Task State Prio Stack Num"));
|
// Serial.println(F("**********************************"));
|
||||||
// Serial.println(F("**********************************"));
|
// Serial.print(ptrTaskList);
|
||||||
// Serial.print(ptrTaskList);
|
// Serial.println(F("**********************************"));
|
||||||
// Serial.println(F("**********************************"));
|
if (eventSourceTaskHandle != NULL)
|
||||||
if (eventSourceTaskHandle != NULL)
|
xTaskNotifyGive(eventSourceTaskHandle);
|
||||||
xTaskNotifyGive(eventSourceTaskHandle);
|
|
||||||
|
|
||||||
if (!WiFi.isConnected()) {
|
if (!WiFi.isConnected()) {
|
||||||
if (!wifiLostConnection) {
|
if (!wifiLostConnection) {
|
||||||
wifiLostConnection = esp_timer_get_time() / 1000000;
|
wifiLostConnection = esp_timer_get_time() / 1000000;
|
||||||
Serial.println("Lost WiFi connection, trying to reconnect...");
|
Serial.println("Lost WiFi connection, trying to reconnect...");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (((esp_timer_get_time() / 1000000) - wifiLostConnection) > 600) {
|
if (((esp_timer_get_time() / 1000000) - wifiLostConnection) > 600) {
|
||||||
Serial.println("Still no connection after 10 minutes, restarting...");
|
Serial.println("Still no connection after 10 minutes, restarting...");
|
||||||
delay(2000);
|
delay(2000);
|
||||||
ESP.restart();
|
ESP.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFi.begin();
|
WiFi.begin();
|
||||||
} else if (wifiLostConnection) {
|
} else if (wifiLostConnection) {
|
||||||
wifiLostConnection = 0;
|
wifiLostConnection = 0;
|
||||||
Serial.println("Connection restored, reset timer.");
|
Serial.println("Connection restored, reset timer.");
|
||||||
}
|
|
||||||
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(5000));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vTaskDelay(pdMS_TO_TICKS(5000));
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue