Implemented basic home screen

Refactored settings and global state to reduce overhead
Consolidated configuration into class constants
(I really didn't like all the shouting in the code :-))
This commit is contained in:
Mark van Renswoude 2020-01-30 10:28:01 +01:00
parent 72fd1af579
commit 5d013b4273
28 changed files with 1240 additions and 227 deletions

21
doc/testscript.md Normal file
View File

@ -0,0 +1,21 @@
# Testscript
As I really do not want to explain to my employer how I broke my desk, this document describes the intended behaviour of the software in various scenarios, focusing on the safety guards.
## Startup
1. Height sensor must report at least 3 values within 5mm of each other in 500 ms intervals to be considered stable.
1. If the EEPROM has not been initialized yet, the height offset setup screen must be displayed.
1. Otherwise, the home screen must be displayed.
## Home
## Moving
1. If the height sensor does not report a valid value for 100ms the move must be aborted and the move error screen shown.
### Move error screen
1. This screen can only be closed if the height sensor is considered stable, as described in the startup sequence.
1. Pressing any button will close this screen and return to the Home screen.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,480 @@
const uint8_t FreeSansBold18pt7bBitmaps[] PROGMEM = {
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE7, 0x39, 0xCE, 0x73, 0x80,
0x0F, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0xC7, 0xFE, 0x3F, 0xF1, 0xFF, 0x8F,
0xFC, 0x7D, 0xC1, 0xCE, 0x0E, 0x70, 0x70, 0x03, 0xC3, 0x80, 0x3C, 0x78,
0x03, 0xC7, 0x80, 0x38, 0x78, 0x07, 0x87, 0x07, 0xFF, 0xFF, 0x7F, 0xFF,
0xF7, 0xFF, 0xFF, 0x7F, 0xFF, 0xF0, 0xF0, 0xE0, 0x0F, 0x0E, 0x00, 0xF1,
0xE0, 0x0F, 0x1E, 0x00, 0xE1, 0xE0, 0xFF, 0xFF, 0xCF, 0xFF, 0xFC, 0xFF,
0xFF, 0xCF, 0xFF, 0xFC, 0x1C, 0x3C, 0x03, 0xC3, 0x80, 0x3C, 0x78, 0x03,
0xC7, 0x80, 0x38, 0x78, 0x03, 0x87, 0x80, 0x00, 0x60, 0x00, 0x7F, 0x80,
0x3F, 0xFC, 0x0F, 0xFF, 0xC3, 0xFF, 0xFC, 0xFC, 0xDF, 0x9F, 0x19, 0xFB,
0xC3, 0x1F, 0x78, 0x63, 0xEF, 0x8C, 0x01, 0xFD, 0x80, 0x1F, 0xF0, 0x01,
0xFF, 0xC0, 0x1F, 0xFE, 0x00, 0x7F, 0xE0, 0x03, 0xFE, 0x00, 0x67, 0xE0,
0x0C, 0x7F, 0xE1, 0x8F, 0xFC, 0x31, 0xFF, 0xC6, 0x3E, 0xFC, 0xDF, 0x9F,
0xFF, 0xF1, 0xFF, 0xFC, 0x0F, 0xFF, 0x00, 0x7F, 0x80, 0x01, 0x80, 0x00,
0x30, 0x00, 0x06, 0x00, 0x0F, 0x00, 0x1C, 0x01, 0xFE, 0x00, 0xE0, 0x1F,
0xF8, 0x0E, 0x00, 0xFF, 0xC0, 0x70, 0x0F, 0x0F, 0x07, 0x00, 0x70, 0x38,
0x38, 0x03, 0x81, 0xC3, 0x80, 0x1C, 0x0E, 0x3C, 0x00, 0xF0, 0xF1, 0xC0,
0x03, 0xFF, 0x1C, 0x00, 0x1F, 0xF8, 0xE0, 0x00, 0x7F, 0x8E, 0x00, 0x00,
0xF0, 0x70, 0xF8, 0x00, 0x07, 0x1F, 0xF0, 0x00, 0x39, 0xFF, 0xC0, 0x03,
0x8F, 0xFE, 0x00, 0x1C, 0xF0, 0x78, 0x01, 0xC7, 0x01, 0xC0, 0x0C, 0x38,
0x0E, 0x00, 0xE1, 0xC0, 0x70, 0x06, 0x0F, 0x07, 0x80, 0x70, 0x3F, 0xF8,
0x07, 0x01, 0xFF, 0xC0, 0x38, 0x07, 0xFC, 0x03, 0x80, 0x0F, 0x80, 0x01,
0xF0, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x1F, 0x1E,
0x00, 0x7C, 0x78, 0x01, 0xF1, 0xE0, 0x07, 0xE7, 0x80, 0x0F, 0xBC, 0x00,
0x1F, 0xE0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x1F, 0xF0, 0xF0, 0xFF,
0xE3, 0xC7, 0xE7, 0xCF, 0x3F, 0x0F, 0xF8, 0xF8, 0x3F, 0xE3, 0xE0, 0x7F,
0x8F, 0x80, 0xFC, 0x3F, 0x03, 0xF0, 0x7E, 0x3F, 0xE1, 0xFF, 0xFF, 0x83,
0xFF, 0xFF, 0x07, 0xFE, 0x7E, 0x07, 0xF0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFD,
0xCE, 0x70, 0x07, 0x87, 0x83, 0xC3, 0xC1, 0xE1, 0xE0, 0xF0, 0x78, 0x78,
0x3C, 0x1E, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E,
0x0F, 0x03, 0x81, 0xE0, 0xF0, 0x78, 0x1E, 0x0F, 0x03, 0x81, 0xE0, 0x70,
0x3C, 0x0E, 0x07, 0x80, 0xF0, 0x38, 0x1E, 0x07, 0x83, 0xC0, 0xF0, 0x78,
0x3C, 0x0F, 0x07, 0x83, 0xC0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
0xC1, 0xE0, 0xF0, 0x78, 0x78, 0x3C, 0x1E, 0x0F, 0x0F, 0x07, 0x87, 0x83,
0xC1, 0xC1, 0xE0, 0xE0, 0xF0, 0x00, 0x06, 0x00, 0x60, 0x06, 0x07, 0x6E,
0x7F, 0xE3, 0xFC, 0x0F, 0x01, 0xF8, 0x1F, 0x83, 0x9C, 0x10, 0x80, 0x03,
0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x03, 0xC0, 0x03,
0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0x8C, 0x63,
0x37, 0xB0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0x80, 0x01,
0x81, 0xC0, 0xC0, 0x60, 0x70, 0x38, 0x18, 0x0C, 0x0E, 0x06, 0x03, 0x01,
0x81, 0xC0, 0xC0, 0x60, 0x30, 0x38, 0x18, 0x0C, 0x0E, 0x07, 0x03, 0x01,
0x81, 0xC0, 0xC0, 0x00, 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0xFF, 0x87, 0xFF,
0xC7, 0xE3, 0xF3, 0xE0, 0xF9, 0xF0, 0x7D, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC,
0x07, 0xFE, 0x03, 0xFF, 0x01, 0xFF, 0x80, 0xFF, 0xC0, 0x7F, 0xE0, 0x3F,
0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xDF, 0x07, 0xCF, 0x83, 0xE7, 0xE3,
0xF1, 0xFF, 0xF0, 0xFF, 0xF8, 0x3F, 0xF8, 0x07, 0xF0, 0x00, 0x01, 0xC0,
0xF0, 0x3C, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xC1, 0xF0, 0x7C,
0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07,
0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC0, 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0xFF,
0x8F, 0xFF, 0xE7, 0xE3, 0xF7, 0xE0, 0xFF, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8,
0x0F, 0x80, 0x07, 0xC0, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xF0, 0x03, 0xF0,
0x07, 0xF0, 0x07, 0xF0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xC0, 0x07, 0xC0,
0x03, 0xE0, 0x03, 0xFF, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0x7F, 0xFF, 0x80,
0x07, 0xE0, 0x0F, 0xFC, 0x0F, 0xFF, 0x0F, 0xFF, 0xCF, 0xC3, 0xF7, 0xC0,
0xFB, 0xE0, 0x7D, 0xF0, 0x3E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x0F, 0x80,
0x3F, 0x80, 0x1F, 0xC0, 0x0F, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F,
0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x83, 0xF7, 0xC3, 0xF3, 0xFF, 0xF8, 0xFF,
0xF8, 0x3F, 0xF8, 0x07, 0xF0, 0x00, 0x00, 0xFC, 0x00, 0xFC, 0x01, 0xFC,
0x01, 0xFC, 0x03, 0xFC, 0x07, 0x7C, 0x07, 0x7C, 0x0E, 0x7C, 0x0E, 0x7C,
0x1C, 0x7C, 0x18, 0x7C, 0x38, 0x7C, 0x70, 0x7C, 0x60, 0x7C, 0xE0, 0x7C,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7C, 0x00, 0x7C,
0x00, 0x7C, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x7C, 0x1F, 0xFF, 0x0F, 0xFF,
0x8F, 0xFF, 0xC7, 0xFF, 0xE3, 0xC0, 0x01, 0xE0, 0x00, 0xE0, 0x00, 0x70,
0x00, 0x79, 0xF0, 0x3F, 0xFE, 0x1F, 0xFF, 0x8F, 0xFF, 0xE7, 0xC3, 0xF0,
0x00, 0xFC, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xFE, 0x03,
0xFF, 0x03, 0xFF, 0xC3, 0xF3, 0xFF, 0xF1, 0xFF, 0xF8, 0x3F, 0xF0, 0x07,
0xE0, 0x00, 0x03, 0xF8, 0x03, 0xFF, 0x81, 0xFF, 0xF0, 0xFF, 0xFE, 0x3E,
0x1F, 0x9F, 0x03, 0xE7, 0xC0, 0x03, 0xE0, 0x00, 0xF8, 0xF8, 0x3E, 0xFF,
0x8F, 0xFF, 0xF3, 0xFF, 0xFE, 0xFE, 0x1F, 0xBF, 0x03, 0xFF, 0x80, 0x7F,
0xE0, 0x1F, 0xF8, 0x07, 0xFE, 0x01, 0xF7, 0x80, 0x7D, 0xF0, 0x3E, 0x7E,
0x1F, 0x8F, 0xFF, 0xC1, 0xFF, 0xF0, 0x3F, 0xF0, 0x03, 0xF0, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xF0, 0x00, 0xF8,
0x00, 0xF8, 0x00, 0x78, 0x00, 0x7C, 0x00, 0x3C, 0x00, 0x3E, 0x00, 0x1E,
0x00, 0x1F, 0x00, 0x0F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xC0, 0x03,
0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x78, 0x00, 0x7C, 0x00, 0x3E, 0x00,
0x1F, 0x00, 0x0F, 0x80, 0x00, 0x07, 0xE0, 0x07, 0xFC, 0x0F, 0xFF, 0x07,
0xFF, 0xC7, 0xC3, 0xF3, 0xC0, 0xF9, 0xE0, 0x3C, 0xF0, 0x1E, 0x78, 0x1F,
0x1E, 0x1F, 0x07, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0xE3, 0xF1, 0xF9, 0xF0,
0x7D, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x83, 0xF7,
0xC3, 0xF3, 0xFF, 0xF8, 0xFF, 0xF8, 0x3F, 0xF8, 0x07, 0xF0, 0x00, 0x07,
0xE0, 0x0F, 0xFC, 0x0F, 0xFF, 0x0F, 0xFF, 0xC7, 0xE3, 0xF7, 0xE0, 0xFB,
0xE0, 0x3D, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x83,
0xF7, 0xE3, 0xFB, 0xFF, 0xFC, 0xFF, 0xFE, 0x3F, 0xDF, 0x07, 0xCF, 0x80,
0x07, 0x80, 0x03, 0xDF, 0x03, 0xE7, 0xC3, 0xE3, 0xFF, 0xF0, 0xFF, 0xF0,
0x3F, 0xF0, 0x07, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00,
0x00, 0x7F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x00, 0x00,
0x00, 0x7F, 0xFF, 0xFF, 0xC6, 0x33, 0x9B, 0xD8, 0x00, 0x00, 0xC0, 0x00,
0xF0, 0x01, 0xFC, 0x03, 0xFF, 0x03, 0xFF, 0x07, 0xFE, 0x0F, 0xFC, 0x03,
0xF8, 0x00, 0xF0, 0x00, 0x3F, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x07,
0xFF, 0x00, 0x3F, 0xF0, 0x01, 0xFC, 0x00, 0x1F, 0x00, 0x00, 0xC0, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xC0, 0x00, 0x3C, 0x00, 0x0F, 0xE0, 0x03, 0xFF, 0x00, 0x3F, 0xF0,
0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0x00, 0x03, 0xC0, 0x07, 0xF0,
0x0F, 0xFC, 0x1F, 0xF8, 0x3F, 0xF8, 0x3F, 0xF0, 0x0F, 0xE0, 0x03, 0xC0,
0x00, 0xC0, 0x00, 0x00, 0x07, 0xF0, 0x07, 0xFF, 0x03, 0xFF, 0xF1, 0xFF,
0xFC, 0x7E, 0x3F, 0xBF, 0x03, 0xFF, 0x80, 0x7F, 0xE0, 0x1F, 0xF8, 0x07,
0xC0, 0x03, 0xF0, 0x01, 0xFC, 0x00, 0xFE, 0x00, 0x7F, 0x00, 0x3F, 0x80,
0x1F, 0xC0, 0x07, 0xC0, 0x03, 0xE0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0,
0x00, 0xF8, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0xC0, 0x01, 0xF8, 0x07, 0xF0, 0x03, 0xE0, 0x01, 0xF8, 0x07,
0x80, 0x00, 0x7C, 0x0F, 0x00, 0x00, 0x3C, 0x1E, 0x03, 0xE3, 0x9E, 0x3C,
0x0F, 0xF7, 0x8E, 0x38, 0x1F, 0xFF, 0x0E, 0x78, 0x3E, 0x1F, 0x07, 0x70,
0x38, 0x0F, 0x07, 0x70, 0x78, 0x0F, 0x07, 0xE0, 0x70, 0x0E, 0x07, 0xE0,
0x70, 0x0E, 0x07, 0xE0, 0xE0, 0x0E, 0x07, 0xE0, 0xE0, 0x1E, 0x0F, 0xE0,
0xE0, 0x1C, 0x0E, 0xE0, 0xE0, 0x3C, 0x1E, 0xE0, 0xF0, 0x3C, 0x3C, 0xF0,
0xF0, 0xFC, 0x7C, 0x70, 0x7F, 0xFF, 0xF8, 0x78, 0x3F, 0xCF, 0xF0, 0x3C,
0x1F, 0x07, 0xC0, 0x3E, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x0F,
0xC0, 0x01, 0x00, 0x07, 0xF0, 0x0F, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7F,
0x00, 0x00, 0x7F, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x80, 0x01, 0xFF,
0x80, 0x01, 0xFF, 0x80, 0x01, 0xF7, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xE7,
0xC0, 0x03, 0xE3, 0xE0, 0x07, 0xC3, 0xE0, 0x07, 0xC3, 0xE0, 0x07, 0xC1,
0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0xFF, 0xF8, 0x1F, 0xFF,
0xF8, 0x1F, 0xFF, 0xFC, 0x1F, 0xFF, 0xFC, 0x3E, 0x00, 0x7C, 0x3E, 0x00,
0x7E, 0x3E, 0x00, 0x3E, 0x7C, 0x00, 0x3E, 0x7C, 0x00, 0x3F, 0x7C, 0x00,
0x1F, 0xFF, 0xFC, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0x8F, 0xFF, 0xFC, 0xF8,
0x07, 0xEF, 0x80, 0x3E, 0xF8, 0x03, 0xEF, 0x80, 0x3E, 0xF8, 0x03, 0xEF,
0x80, 0x3E, 0xF8, 0x07, 0xCF, 0xFF, 0xF8, 0xFF, 0xFF, 0x0F, 0xFF, 0xF8,
0xFF, 0xFF, 0xCF, 0x80, 0x7E, 0xF8, 0x01, 0xEF, 0x80, 0x1F, 0xF8, 0x01,
0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x3E, 0xFF, 0xFF, 0xEF, 0xFF,
0xFC, 0xFF, 0xFF, 0x8F, 0xFF, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xFF, 0x80,
0x3F, 0xFF, 0xC0, 0xFF, 0xFF, 0xC3, 0xF8, 0x1F, 0x87, 0xE0, 0x1F, 0x9F,
0x80, 0x1F, 0x3E, 0x00, 0x1F, 0x7C, 0x00, 0x3F, 0xF0, 0x00, 0x03, 0xE0,
0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00,
0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00, 0x7D, 0xF0, 0x00,
0xFB, 0xF0, 0x03, 0xF3, 0xF0, 0x0F, 0xC7, 0xF0, 0x3F, 0x87, 0xFF, 0xFE,
0x07, 0xFF, 0xF8, 0x03, 0xFF, 0xC0, 0x01, 0xFE, 0x00, 0xFF, 0xFC, 0x07,
0xFF, 0xF8, 0x3F, 0xFF, 0xE1, 0xFF, 0xFF, 0x8F, 0x80, 0xFE, 0x7C, 0x01,
0xF3, 0xE0, 0x07, 0xDF, 0x00, 0x3E, 0xF8, 0x01, 0xF7, 0xC0, 0x07, 0xFE,
0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x0F, 0xFC, 0x00, 0x7F, 0xE0, 0x03,
0xFF, 0x00, 0x1F, 0xF8, 0x00, 0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0x7D, 0xF0,
0x03, 0xEF, 0x80, 0x3E, 0x7C, 0x07, 0xF3, 0xFF, 0xFF, 0x1F, 0xFF, 0xF0,
0xFF, 0xFF, 0x07, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xDF, 0xFF, 0xFB, 0xFF,
0xFF, 0x7F, 0xFF, 0xEF, 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0,
0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7F, 0xFF, 0xCF, 0xFF,
0xF9, 0xFF, 0xFF, 0x3F, 0xFF, 0xE7, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00,
0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x3F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xC0, 0x03, 0xE0, 0x01, 0xF0,
0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F, 0xFF, 0xEF, 0xFF, 0xF7,
0xFF, 0xFB, 0xFF, 0xFD, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00,
0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xE0, 0x01, 0xF0, 0x00, 0xF8,
0x00, 0x7C, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x03, 0xFF, 0xE0, 0x07, 0xFF,
0xF8, 0x0F, 0xFF, 0xFC, 0x1F, 0xC0, 0xFE, 0x3F, 0x00, 0x7E, 0x7E, 0x00,
0x3F, 0x7C, 0x00, 0x1F, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x00,
0x00, 0xF8, 0x00, 0x00, 0xF8, 0x03, 0xFF, 0xF8, 0x03, 0xFF, 0xF8, 0x03,
0xFF, 0xF8, 0x03, 0xFF, 0xFC, 0x00, 0x0F, 0x7C, 0x00, 0x1F, 0x7C, 0x00,
0x1F, 0x7E, 0x00, 0x3F, 0x3F, 0x00, 0x7F, 0x1F, 0xC1, 0xFF, 0x0F, 0xFF,
0xFF, 0x07, 0xFF, 0xE7, 0x03, 0xFF, 0xC7, 0x00, 0xFF, 0x07, 0xF8, 0x01,
0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80,
0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x01, 0xFF,
0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F,
0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01,
0xFF, 0x80, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0x00, 0x1F,
0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F,
0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F,
0x00, 0x1F, 0x00, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F,
0xF8, 0x1F, 0xFC, 0x3F, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, 0x07, 0xE0,
0xF8, 0x01, 0xFB, 0xE0, 0x0F, 0xCF, 0x80, 0x7E, 0x3E, 0x03, 0xF0, 0xF8,
0x1F, 0x83, 0xE0, 0xFC, 0x0F, 0x87, 0xE0, 0x3E, 0x3F, 0x00, 0xF8, 0xF8,
0x03, 0xE7, 0xE0, 0x0F, 0xBF, 0x00, 0x3F, 0xF8, 0x00, 0xFF, 0xF0, 0x03,
0xFF, 0xE0, 0x0F, 0xFF, 0x80, 0x3F, 0xBF, 0x00, 0xFC, 0x7E, 0x03, 0xE0,
0xFC, 0x0F, 0x81, 0xF8, 0x3E, 0x07, 0xE0, 0xF8, 0x0F, 0xC3, 0xE0, 0x1F,
0x8F, 0x80, 0x7F, 0x3E, 0x00, 0xFC, 0xF8, 0x01, 0xFB, 0xE0, 0x03, 0xF0,
0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0,
0x03, 0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F,
0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00,
0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0x00, 0xFF, 0xFF,
0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0x81, 0xFF, 0xFF,
0x81, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0x81, 0xFF, 0xFB, 0xC3, 0xDF, 0xFB,
0xC3, 0xDF, 0xFB, 0xC3, 0xDF, 0xFB, 0xC3, 0xDF, 0xF9, 0xC7, 0xDF, 0xF9,
0xE7, 0x9F, 0xF9, 0xE7, 0x9F, 0xF9, 0xE7, 0x9F, 0xF9, 0xE7, 0x9F, 0xF8,
0xFF, 0x1F, 0xF8, 0xFF, 0x1F, 0xF8, 0xFF, 0x1F, 0xF8, 0xFF, 0x1F, 0xF8,
0x7F, 0x1F, 0xF8, 0x7E, 0x1F, 0xF8, 0x7E, 0x1F, 0xF8, 0x7E, 0x1F, 0xF8,
0x3E, 0x1F, 0xF8, 0x01, 0xFF, 0xC0, 0x1F, 0xFE, 0x01, 0xFF, 0xE0, 0x1F,
0xFF, 0x01, 0xFF, 0xF0, 0x1F, 0xFF, 0x81, 0xFF, 0xF8, 0x1F, 0xFF, 0xC1,
0xFF, 0xBC, 0x1F, 0xFB, 0xE1, 0xFF, 0x9F, 0x1F, 0xF9, 0xF1, 0xFF, 0x8F,
0x9F, 0xF8, 0x79, 0xFF, 0x87, 0xDF, 0xF8, 0x3D, 0xFF, 0x83, 0xFF, 0xF8,
0x1F, 0xFF, 0x81, 0xFF, 0xF8, 0x0F, 0xFF, 0x80, 0xFF, 0xF8, 0x07, 0xFF,
0x80, 0x3F, 0xF8, 0x03, 0xFF, 0x80, 0x1F, 0x00, 0x7F, 0x00, 0x01, 0xFF,
0xF0, 0x01, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0x01, 0xFC, 0x1F, 0xC1, 0xF8,
0x03, 0xF1, 0xF8, 0x00, 0xFC, 0xF8, 0x00, 0x3E, 0x7C, 0x00, 0x1F, 0x7C,
0x00, 0x07, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x00, 0xFF,
0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x3F, 0xF0, 0x00, 0x1F, 0xF8, 0x00, 0x0F,
0xBE, 0x00, 0x0F, 0x9F, 0x00, 0x07, 0xCF, 0xC0, 0x07, 0xE3, 0xF0, 0x07,
0xE0, 0xFE, 0x0F, 0xE0, 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xE0, 0x03, 0xFF,
0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFF, 0xFC, 0x1F, 0xFF, 0xE3, 0xFF, 0xFE,
0x7F, 0xFF, 0xEF, 0x80, 0xFF, 0xF0, 0x0F, 0xFE, 0x00, 0xFF, 0xC0, 0x1F,
0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x1F, 0xFC, 0x07, 0xEF, 0xFF, 0xFD,
0xFF, 0xFF, 0x3F, 0xFF, 0xC7, 0xFF, 0xE0, 0xF8, 0x00, 0x1F, 0x00, 0x03,
0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07,
0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x01, 0xFF,
0xF0, 0x01, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0x01, 0xFC, 0x1F, 0xC1, 0xF8,
0x03, 0xF1, 0xF8, 0x00, 0xFC, 0xF8, 0x00, 0x3E, 0x7C, 0x00, 0x1F, 0x7C,
0x00, 0x07, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x00, 0xFF,
0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x3F, 0xF0, 0x00, 0x1F, 0xF8, 0x01, 0x0F,
0xBE, 0x01, 0xCF, 0x9F, 0x01, 0xFF, 0xCF, 0xC0, 0x7F, 0xE3, 0xF0, 0x1F,
0xE0, 0xFE, 0x0F, 0xF0, 0x7F, 0xFF, 0xF8, 0x0F, 0xFF, 0xFE, 0x03, 0xFF,
0xEF, 0x80, 0x3F, 0xC3, 0x80, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x07, 0xFF,
0xFE, 0x3F, 0xFF, 0xF9, 0xFF, 0xFF, 0xCF, 0x80, 0x3F, 0x7C, 0x00, 0xFB,
0xE0, 0x07, 0xDF, 0x00, 0x3E, 0xF8, 0x01, 0xF7, 0xC0, 0x0F, 0x3E, 0x00,
0xF9, 0xFF, 0xFF, 0x8F, 0xFF, 0xF8, 0x7F, 0xFF, 0xC3, 0xFF, 0xFF, 0x1F,
0x00, 0xFC, 0xF8, 0x03, 0xE7, 0xC0, 0x1F, 0x3E, 0x00, 0xF9, 0xF0, 0x07,
0xCF, 0x80, 0x3E, 0x7C, 0x01, 0xF3, 0xE0, 0x0F, 0x9F, 0x00, 0x7C, 0xF8,
0x03, 0xF7, 0xC0, 0x0F, 0xC0, 0x07, 0xF8, 0x01, 0xFF, 0xF0, 0x3F, 0xFF,
0x87, 0xFF, 0xFC, 0x7E, 0x0F, 0xCF, 0xC0, 0x7E, 0xF8, 0x03, 0xEF, 0x80,
0x3E, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0xFF, 0x00, 0x07, 0xFF, 0xC0, 0x3F,
0xFF, 0x81, 0xFF, 0xFC, 0x03, 0xFF, 0xE0, 0x01, 0xFF, 0x00, 0x03, 0xF0,
0x00, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xFC, 0x03, 0xFF, 0xE0, 0x7E,
0x7F, 0xFF, 0xE3, 0xFF, 0xFC, 0x1F, 0xFF, 0x00, 0x3F, 0xC0, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x1F, 0x00, 0x03, 0xE0,
0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0,
0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80,
0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00,
0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00,
0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01,
0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80,
0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8,
0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF, 0x80, 0x1F, 0xF8, 0x01, 0xFF,
0x80, 0x1F, 0x7C, 0x03, 0xE7, 0xE0, 0x7E, 0x3F, 0xFF, 0xC3, 0xFF, 0xFC,
0x0F, 0xFF, 0x00, 0x3F, 0xC0, 0xF8, 0x00, 0xFB, 0xE0, 0x03, 0xE7, 0xC0,
0x1F, 0x9F, 0x00, 0x7C, 0x7C, 0x01, 0xF0, 0xF8, 0x07, 0xC3, 0xE0, 0x3E,
0x0F, 0x80, 0xF8, 0x1E, 0x03, 0xE0, 0x7C, 0x1F, 0x01, 0xF0, 0x7C, 0x03,
0xC1, 0xF0, 0x0F, 0x87, 0x80, 0x3E, 0x3E, 0x00, 0xF8, 0xF8, 0x01, 0xE3,
0xC0, 0x07, 0xCF, 0x00, 0x1F, 0x7C, 0x00, 0x3D, 0xE0, 0x00, 0xFF, 0x80,
0x03, 0xFE, 0x00, 0x07, 0xF0, 0x00, 0x1F, 0xC0, 0x00, 0x7F, 0x00, 0x00,
0xF8, 0x00, 0x03, 0xE0, 0x00, 0xF8, 0x07, 0xC0, 0x3F, 0xF8, 0x07, 0xE0,
0x3E, 0xFC, 0x07, 0xE0, 0x3E, 0x7C, 0x0F, 0xE0, 0x3E, 0x7C, 0x0F, 0xE0,
0x7E, 0x7C, 0x0F, 0xE0, 0x7C, 0x7C, 0x0F, 0xF0, 0x7C, 0x3E, 0x0F, 0xF0,
0x7C, 0x3E, 0x1E, 0xF0, 0x78, 0x3E, 0x1E, 0x70, 0xF8, 0x1E, 0x1E, 0x70,
0xF8, 0x1E, 0x1E, 0x78, 0xF8, 0x1F, 0x1E, 0x78, 0xF0, 0x1F, 0x3C, 0x78,
0xF0, 0x0F, 0x3C, 0x39, 0xF0, 0x0F, 0x3C, 0x3D, 0xF0, 0x0F, 0x3C, 0x3D,
0xE0, 0x0F, 0xBC, 0x3D, 0xE0, 0x07, 0xF8, 0x3D, 0xE0, 0x07, 0xF8, 0x1F,
0xE0, 0x07, 0xF8, 0x1F, 0xC0, 0x03, 0xF8, 0x1F, 0xC0, 0x03, 0xF8, 0x1F,
0xC0, 0x03, 0xF0, 0x0F, 0x80, 0x03, 0xF0, 0x0F, 0x80, 0x01, 0xF0, 0x0F,
0x80, 0xFE, 0x01, 0xF9, 0xF8, 0x07, 0xE3, 0xF0, 0x3F, 0x0F, 0xC0, 0xF8,
0x1F, 0x87, 0xE0, 0x7E, 0x3F, 0x00, 0xFC, 0xFC, 0x01, 0xF7, 0xE0, 0x07,
0xFF, 0x00, 0x0F, 0xFC, 0x00, 0x3F, 0xE0, 0x00, 0x7F, 0x00, 0x00, 0xFC,
0x00, 0x07, 0xF0, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x80, 0x03, 0xFF, 0x00,
0x1F, 0x7E, 0x00, 0xFC, 0xF8, 0x03, 0xE3, 0xF0, 0x1F, 0x87, 0xC0, 0x7C,
0x1F, 0x83, 0xF0, 0x3F, 0x1F, 0x80, 0xFC, 0x7E, 0x01, 0xFB, 0xF0, 0x07,
0xF0, 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0x9F, 0x00, 0xFC, 0xFC, 0x07, 0xC3,
0xE0, 0x7E, 0x1F, 0x83, 0xE0, 0x7C, 0x1F, 0x03, 0xF1, 0xF0, 0x0F, 0x8F,
0x80, 0x7E, 0xF8, 0x01, 0xF7, 0xC0, 0x0F, 0xFC, 0x00, 0x3F, 0xE0, 0x00,
0xFE, 0x00, 0x07, 0xF0, 0x00, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x07, 0xC0,
0x00, 0x3E, 0x00, 0x01, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0x7C, 0x00, 0x03,
0xE0, 0x00, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x07, 0xC0, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x7E, 0x00, 0x1F,
0x80, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF8,
0x00, 0x7E, 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x01, 0xFC, 0x00, 0x3F, 0x00,
0x0F, 0xC0, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x01,
0xFC, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x38, 0x06,
0x01, 0x80, 0x70, 0x0C, 0x03, 0x00, 0xE0, 0x18, 0x06, 0x01, 0xC0, 0x30,
0x0C, 0x03, 0x00, 0xE0, 0x18, 0x06, 0x01, 0xC0, 0x30, 0x0C, 0x03, 0x80,
0x60, 0x18, 0x07, 0x01, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x1F,
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0xFF, 0xFF,
0xFF, 0xFF, 0x03, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x0F, 0xF0, 0x0F, 0xF0,
0x0F, 0x78, 0x1E, 0x78, 0x1E, 0x78, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x1E,
0x78, 0x1E, 0x78, 0x1E, 0x70, 0x0F, 0xF0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0x07, 0xF8, 0x07,
0xFF, 0x83, 0xFF, 0xF1, 0xFF, 0xFE, 0x7C, 0x1F, 0xBE, 0x03, 0xE0, 0x00,
0xF8, 0x01, 0xFE, 0x0F, 0xFF, 0x8F, 0xFF, 0xE7, 0xF8, 0xFB, 0xF0, 0x3E,
0xF8, 0x0F, 0xBE, 0x07, 0xEF, 0xC3, 0xFB, 0xFF, 0xFE, 0x7F, 0xFF, 0x8F,
0xFB, 0xF1, 0xF8, 0xFC, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0,
0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE7, 0xE0, 0xFB, 0xFC,
0x3F, 0xFF, 0xCF, 0xFF, 0xF3, 0xF8, 0x7E, 0xFC, 0x0F, 0xBF, 0x03, 0xFF,
0x80, 0x7F, 0xE0, 0x1F, 0xF8, 0x07, 0xFE, 0x01, 0xFF, 0x80, 0x7F, 0xF0,
0x3F, 0xFC, 0x0F, 0xBF, 0x87, 0xEF, 0xFF, 0xF3, 0xFF, 0xFC, 0xFB, 0xFC,
0x3E, 0x7E, 0x00, 0x03, 0xF0, 0x07, 0xFE, 0x0F, 0xFF, 0x87, 0xFF, 0xE7,
0xE1, 0xFB, 0xE0, 0x7F, 0xE0, 0x3F, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00,
0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0xFB, 0xE0, 0x7D, 0xF8, 0x7E, 0x7F,
0xFE, 0x3F, 0xFE, 0x0F, 0xFE, 0x00, 0xFC, 0x00, 0x00, 0x03, 0xE0, 0x00,
0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00,
0xF8, 0x1F, 0x1F, 0x0F, 0xFB, 0xE3, 0xFF, 0xFC, 0xFF, 0xFF, 0xBF, 0x8F,
0xF7, 0xC0, 0x7F, 0xF8, 0x0F, 0xFE, 0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03,
0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFE, 0x03, 0xF7, 0xC0, 0x7E, 0xFC, 0x3F,
0xCF, 0xFF, 0xF8, 0xFF, 0xFF, 0x0F, 0xFB, 0xE0, 0xFC, 0x7C, 0x07, 0xE0,
0x07, 0xFE, 0x03, 0xFF, 0xE0, 0xFF, 0xF8, 0x7E, 0x1F, 0x1F, 0x03, 0xCF,
0x80, 0xFB, 0xE0, 0x1E, 0xFF, 0xFF, 0xBF, 0xFF, 0xEF, 0xFF, 0xFB, 0xE0,
0x00, 0xF8, 0x00, 0x3F, 0x03, 0xE7, 0xE1, 0xF9, 0xFF, 0xFC, 0x3F, 0xFE,
0x07, 0xFF, 0x00, 0x7F, 0x00, 0x0F, 0xC7, 0xF3, 0xFC, 0xFF, 0x3E, 0x0F,
0x83, 0xE3, 0xFE, 0xFF, 0xBF, 0xE3, 0xE0, 0xF8, 0x3E, 0x0F, 0x83, 0xE0,
0xF8, 0x3E, 0x0F, 0x83, 0xE0, 0xF8, 0x3E, 0x0F, 0x83, 0xE0, 0xF8, 0x3E,
0x0F, 0x80, 0x07, 0xC7, 0xC3, 0xFD, 0xF3, 0xFF, 0xFC, 0xFF, 0xFF, 0x7E,
0x1F, 0xDF, 0x03, 0xFF, 0xC0, 0xFF, 0xE0, 0x1F, 0xF8, 0x07, 0xFE, 0x01,
0xFF, 0x80, 0x7F, 0xE0, 0x1F, 0xFC, 0x0F, 0xDF, 0x03, 0xF7, 0xE1, 0xFD,
0xFF, 0xFF, 0x3F, 0xFF, 0xC7, 0xFD, 0xF0, 0x7C, 0x7C, 0x00, 0x1F, 0x00,
0x07, 0xFF, 0x03, 0xF7, 0xE1, 0xF9, 0xFF, 0xFC, 0x3F, 0xFE, 0x01, 0xFE,
0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07,
0xC0, 0x03, 0xE0, 0x01, 0xF1, 0xF0, 0xFB, 0xFE, 0x7F, 0xFF, 0xBF, 0xFF,
0xDF, 0xC3, 0xFF, 0xC0, 0xFF, 0xC0, 0x7F, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8,
0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x01, 0xFF, 0x80, 0xFF, 0xC0, 0x7F,
0xE0, 0x3F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xC0, 0xFF, 0xFF, 0xF0,
0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xC0, 0x3E, 0x7C, 0xF9, 0xF0, 0x00, 0x00, 0x1F, 0x3E, 0x7C, 0xF9,
0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E,
0x7C, 0xF9, 0xF3, 0xFF, 0xFF, 0xFE, 0xF8, 0xF8, 0x00, 0x7C, 0x00, 0x3E,
0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xE0, 0x01, 0xF0, 0x3E,
0xF8, 0x3E, 0x7C, 0x3F, 0x3E, 0x3F, 0x1F, 0x3F, 0x0F, 0x9F, 0x07, 0xDF,
0x03, 0xFF, 0x81, 0xFF, 0xC0, 0xFF, 0xF0, 0x7F, 0xF8, 0x3F, 0x7E, 0x1F,
0x1F, 0x0F, 0x87, 0xC7, 0xC3, 0xF3, 0xE0, 0xF9, 0xF0, 0x7E, 0xF8, 0x1F,
0x7C, 0x0F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xF8, 0xF8, 0x3F, 0x1F,
0x7F, 0x9F, 0xF3, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xC3, 0xF8,
0x7F, 0xF8, 0x3F, 0x07, 0xFE, 0x07, 0xC0, 0xFF, 0xC0, 0xF8, 0x1F, 0xF8,
0x1F, 0x03, 0xFF, 0x03, 0xE0, 0x7F, 0xE0, 0x7C, 0x0F, 0xFC, 0x0F, 0x81,
0xFF, 0x81, 0xF0, 0x3F, 0xF0, 0x3E, 0x07, 0xFE, 0x07, 0xC0, 0xFF, 0xC0,
0xF8, 0x1F, 0xF8, 0x1F, 0x03, 0xFF, 0x03, 0xE0, 0x7F, 0xE0, 0x7C, 0x0F,
0x80, 0xF8, 0xF8, 0x7D, 0xFF, 0x3F, 0xFF, 0xDF, 0xFF, 0xEF, 0xE1, 0xFF,
0xE0, 0x7F, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03,
0xFF, 0x01, 0xFF, 0x80, 0xFF, 0xC0, 0x7F, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8,
0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xE0, 0x03, 0xF8, 0x01, 0xFF, 0xC0, 0x7F,
0xFC, 0x1F, 0xFF, 0xC7, 0xF0, 0xFC, 0xF8, 0x0F, 0xBF, 0x01, 0xFF, 0xC0,
0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0xC0,
0x7E, 0xF8, 0x0F, 0x9F, 0x87, 0xF1, 0xFF, 0xFC, 0x1F, 0xFF, 0x01, 0xFF,
0xC0, 0x0F, 0xE0, 0x00, 0xF8, 0xF8, 0x3E, 0xFF, 0x8F, 0xFF, 0xF3, 0xFF,
0xFC, 0xFE, 0x1F, 0xBF, 0x03, 0xEF, 0xC0, 0xFF, 0xE0, 0x1F, 0xF8, 0x07,
0xFE, 0x01, 0xFF, 0x80, 0x7F, 0xE0, 0x1F, 0xFC, 0x0F, 0xFF, 0x03, 0xEF,
0xE1, 0xFB, 0xFF, 0xFC, 0xFF, 0xFF, 0x3E, 0xFF, 0x0F, 0x8F, 0x83, 0xE0,
0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00,
0x3E, 0x00, 0x00, 0x07, 0xE3, 0xE1, 0xFF, 0x7C, 0x7F, 0xFF, 0x9F, 0xFF,
0xF7, 0xF1, 0xFE, 0xF8, 0x0F, 0xFF, 0x01, 0xFF, 0xC0, 0x1F, 0xF8, 0x03,
0xFF, 0x00, 0x7F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF, 0xC0, 0x7E, 0xF8, 0x0F,
0xDF, 0x83, 0xF9, 0xFF, 0xFF, 0x3F, 0xFF, 0xE1, 0xFF, 0x7C, 0x1F, 0x8F,
0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F,
0x00, 0x03, 0xE0, 0x00, 0x7C, 0xF8, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xE1,
0xF8, 0x3E, 0x07, 0xC0, 0xF8, 0x1F, 0x03, 0xE0, 0x7C, 0x0F, 0x81, 0xF0,
0x3E, 0x07, 0xC0, 0xF8, 0x1F, 0x03, 0xE0, 0x00, 0x07, 0xF0, 0x0F, 0xFE,
0x0F, 0xFF, 0x87, 0xFF, 0xE7, 0xE1, 0xF3, 0xE0, 0x79, 0xF8, 0x00, 0xFF,
0x80, 0x3F, 0xFC, 0x1F, 0xFF, 0x83, 0xFF, 0xC0, 0x3F, 0xF0, 0x01, 0xFF,
0xC0, 0x7D, 0xF0, 0x7E, 0xFF, 0xFE, 0x3F, 0xFF, 0x0F, 0xFF, 0x01, 0xFE,
0x00, 0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE7, 0xFF, 0xFF, 0xFF, 0x3E, 0x1F,
0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xF3,
0xF8, 0xFC, 0x3E, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x01, 0xFF,
0x80, 0xFF, 0xC0, 0x7F, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07,
0xFE, 0x03, 0xFF, 0x01, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xF0, 0xFF, 0xFF,
0xFF, 0x7F, 0xFF, 0x9F, 0xF7, 0xC7, 0xE3, 0xE0, 0x7C, 0x07, 0xCF, 0x80,
0xF9, 0xF0, 0x1F, 0x1F, 0x07, 0xC3, 0xE0, 0xF8, 0x7C, 0x1F, 0x07, 0x83,
0xC0, 0xF8, 0xF8, 0x1F, 0x1F, 0x01, 0xE3, 0xC0, 0x3E, 0x78, 0x07, 0xDF,
0x00, 0x7B, 0xC0, 0x0F, 0xF8, 0x01, 0xFF, 0x00, 0x1F, 0xC0, 0x03, 0xF8,
0x00, 0x7F, 0x00, 0x07, 0xC0, 0x00, 0xFC, 0x1F, 0x03, 0xEF, 0x83, 0xE0,
0x7D, 0xF0, 0x7E, 0x1F, 0x3E, 0x0F, 0xC3, 0xE3, 0xC3, 0xF8, 0x7C, 0x7C,
0x7F, 0x0F, 0x0F, 0x8F, 0xF3, 0xE1, 0xF1, 0xDE, 0x7C, 0x1E, 0x7B, 0xCF,
0x83, 0xEF, 0x39, 0xE0, 0x7D, 0xE7, 0x3C, 0x07, 0xB8, 0xFF, 0x80, 0xF7,
0x1F, 0xE0, 0x1F, 0xE3, 0xFC, 0x03, 0xFC, 0x3F, 0x80, 0x3F, 0x07, 0xF0,
0x07, 0xE0, 0xFC, 0x00, 0xFC, 0x1F, 0x80, 0x0F, 0x83, 0xF0, 0x00, 0xFC,
0x1F, 0x9F, 0x07, 0xE7, 0xE3, 0xF0, 0xF8, 0xF8, 0x1F, 0x7E, 0x07, 0xDF,
0x00, 0xFF, 0x80, 0x1F, 0xE0, 0x07, 0xF0, 0x00, 0xF8, 0x00, 0x7F, 0x00,
0x3F, 0xE0, 0x0F, 0xF8, 0x07, 0xDF, 0x03, 0xF7, 0xE0, 0xF8, 0xF8, 0x7E,
0x3F, 0x1F, 0x07, 0xEF, 0xC0, 0xF8, 0x7C, 0x03, 0xEF, 0x80, 0xF9, 0xF8,
0x1F, 0x1F, 0x03, 0xE3, 0xE0, 0xF8, 0x7C, 0x1F, 0x07, 0xC3, 0xE0, 0xF8,
0x78, 0x0F, 0x1F, 0x01, 0xF3, 0xC0, 0x3E, 0x78, 0x03, 0xDF, 0x00, 0x7F,
0xC0, 0x0F, 0xF8, 0x00, 0xFF, 0x00, 0x1F, 0xC0, 0x01, 0xF8, 0x00, 0x3F,
0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1E, 0x00, 0x07, 0xC0, 0x07, 0xF8,
0x00, 0xFE, 0x00, 0x1F, 0x80, 0x03, 0xE0, 0x00, 0x7F, 0xFE, 0x7F, 0xFE,
0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0,
0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00,
0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x87,
0xC7, 0xE3, 0xF1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1,
0xE0, 0xF0, 0xF9, 0xF8, 0xF0, 0x7E, 0x0F, 0x83, 0xC1, 0xE0, 0xF0, 0x78,
0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xFC, 0x7E, 0x1F, 0x07, 0x80,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE0, 0xF0, 0x7C, 0x3E, 0x1F, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E,
0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x1F, 0x83, 0xC7, 0xE7, 0xC3,
0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC7, 0xE3, 0xE1,
0xF0, 0xF0, 0x00, 0x3C, 0x00, 0xFE, 0x0F, 0xFE, 0x1E, 0x1F, 0xFC, 0x0F,
0xC0, 0x0F, 0x00};
const GFXglyph FreeSansBold18pt7bGlyphs[] PROGMEM = {
{0, 0, 0, 10, 0, 1}, // 0x20 ' '
{0, 5, 25, 12, 4, -24}, // 0x21 '!'
{16, 13, 9, 17, 2, -25}, // 0x22 '"'
{31, 20, 24, 19, 0, -23}, // 0x23 '#'
{91, 19, 29, 19, 0, -25}, // 0x24 '$'
{160, 29, 25, 31, 1, -24}, // 0x25 '%'
{251, 22, 25, 25, 2, -24}, // 0x26 '&'
{320, 5, 9, 9, 2, -25}, // 0x27 '''
{326, 9, 33, 12, 1, -25}, // 0x28 '('
{364, 9, 33, 12, 1, -25}, // 0x29 ')'
{402, 12, 11, 14, 0, -25}, // 0x2A '*'
{419, 16, 16, 20, 2, -15}, // 0x2B '+'
{451, 5, 11, 9, 2, -4}, // 0x2C ','
{458, 9, 4, 12, 1, -10}, // 0x2D '-'
{463, 5, 5, 9, 2, -4}, // 0x2E '.'
{467, 9, 25, 10, 0, -24}, // 0x2F '/'
{496, 17, 25, 19, 1, -24}, // 0x30 '0'
{550, 10, 25, 19, 3, -24}, // 0x31 '1'
{582, 17, 25, 19, 1, -24}, // 0x32 '2'
{636, 17, 25, 19, 1, -24}, // 0x33 '3'
{690, 16, 25, 19, 2, -24}, // 0x34 '4'
{740, 17, 25, 19, 1, -24}, // 0x35 '5'
{794, 18, 25, 19, 1, -24}, // 0x36 '6'
{851, 17, 25, 19, 1, -24}, // 0x37 '7'
{905, 17, 25, 19, 1, -24}, // 0x38 '8'
{959, 17, 25, 19, 1, -24}, // 0x39 '9'
{1013, 5, 18, 9, 2, -17}, // 0x3A ':'
{1025, 5, 24, 9, 2, -17}, // 0x3B ';'
{1040, 18, 17, 20, 1, -16}, // 0x3C '<'
{1079, 17, 12, 20, 2, -13}, // 0x3D '='
{1105, 18, 17, 20, 1, -16}, // 0x3E '>'
{1144, 18, 26, 21, 2, -25}, // 0x3F '?'
{1203, 32, 31, 34, 1, -25}, // 0x40 '@'
{1327, 24, 26, 24, 0, -25}, // 0x41 'A'
{1405, 20, 26, 25, 3, -25}, // 0x42 'B'
{1470, 23, 26, 25, 1, -25}, // 0x43 'C'
{1545, 21, 26, 25, 3, -25}, // 0x44 'D'
{1614, 19, 26, 23, 3, -25}, // 0x45 'E'
{1676, 17, 26, 22, 3, -25}, // 0x46 'F'
{1732, 24, 26, 27, 1, -25}, // 0x47 'G'
{1810, 20, 26, 26, 3, -25}, // 0x48 'H'
{1875, 5, 26, 11, 3, -25}, // 0x49 'I'
{1892, 16, 26, 20, 1, -25}, // 0x4A 'J'
{1944, 22, 26, 25, 3, -25}, // 0x4B 'K'
{2016, 17, 26, 22, 3, -25}, // 0x4C 'L'
{2072, 24, 26, 30, 3, -25}, // 0x4D 'M'
{2150, 20, 26, 26, 3, -25}, // 0x4E 'N'
{2215, 25, 26, 27, 1, -25}, // 0x4F 'O'
{2297, 19, 26, 24, 3, -25}, // 0x50 'P'
{2359, 25, 27, 27, 1, -25}, // 0x51 'Q'
{2444, 21, 26, 25, 3, -25}, // 0x52 'R'
{2513, 20, 26, 24, 2, -25}, // 0x53 'S'
{2578, 19, 26, 23, 2, -25}, // 0x54 'T'
{2640, 20, 26, 26, 3, -25}, // 0x55 'U'
{2705, 22, 26, 23, 1, -25}, // 0x56 'V'
{2777, 32, 26, 34, 1, -25}, // 0x57 'W'
{2881, 22, 26, 24, 1, -25}, // 0x58 'X'
{2953, 21, 26, 22, 1, -25}, // 0x59 'Y'
{3022, 19, 26, 21, 1, -25}, // 0x5A 'Z'
{3084, 8, 33, 12, 2, -25}, // 0x5B '['
{3117, 10, 25, 10, 0, -24}, // 0x5C '\'
{3149, 8, 33, 12, 1, -25}, // 0x5D ']'
{3182, 16, 15, 20, 2, -23}, // 0x5E '^'
{3212, 21, 3, 19, -1, 5}, // 0x5F '_'
{3220, 7, 5, 9, 1, -25}, // 0x60 '`'
{3225, 18, 19, 20, 1, -18}, // 0x61 'a'
{3268, 18, 26, 22, 2, -25}, // 0x62 'b'
{3327, 17, 19, 20, 1, -18}, // 0x63 'c'
{3368, 19, 26, 22, 1, -25}, // 0x64 'd'
{3430, 18, 19, 20, 1, -18}, // 0x65 'e'
{3473, 10, 26, 12, 1, -25}, // 0x66 'f'
{3506, 18, 26, 21, 1, -18}, // 0x67 'g'
{3565, 17, 26, 21, 2, -25}, // 0x68 'h'
{3621, 5, 26, 10, 2, -25}, // 0x69 'i'
{3638, 7, 33, 10, 0, -25}, // 0x6A 'j'
{3667, 17, 26, 20, 2, -25}, // 0x6B 'k'
{3723, 5, 26, 9, 2, -25}, // 0x6C 'l'
{3740, 27, 19, 31, 2, -18}, // 0x6D 'm'
{3805, 17, 19, 21, 2, -18}, // 0x6E 'n'
{3846, 19, 19, 21, 1, -18}, // 0x6F 'o'
{3892, 18, 26, 22, 2, -18}, // 0x70 'p'
{3951, 19, 26, 22, 1, -18}, // 0x71 'q'
{4013, 11, 19, 14, 2, -18}, // 0x72 'r'
{4040, 17, 19, 19, 1, -18}, // 0x73 's'
{4081, 9, 23, 12, 1, -22}, // 0x74 't'
{4107, 17, 19, 21, 2, -18}, // 0x75 'u'
{4148, 19, 19, 19, 0, -18}, // 0x76 'v'
{4194, 27, 19, 27, 0, -18}, // 0x77 'w'
{4259, 18, 19, 19, 1, -18}, // 0x78 'x'
{4302, 19, 26, 19, 0, -18}, // 0x79 'y'
{4364, 16, 19, 18, 1, -18}, // 0x7A 'z'
{4402, 9, 33, 14, 1, -25}, // 0x7B '{'
{4440, 3, 33, 10, 4, -25}, // 0x7C '|'
{4453, 9, 33, 14, 3, -25}, // 0x7D '}'
{4491, 15, 6, 18, 1, -10}}; // 0x7E '~'
const GFXfont FreeSansBold18pt7b PROGMEM = {
(uint8_t *)FreeSansBold18pt7bBitmaps, (GFXglyph *)FreeSansBold18pt7bGlyphs,
0x20, 0x7E, 42};
// Approx. 5175 bytes

View File

@ -0,0 +1,181 @@
/*
Generated by AdafruitGFXFontToBitmap
https: //github.com/MvRens/AdafruitGFXFontTools
Source: FreeSansBold18pt7b.h
Filter: [0-9\.mSTOPMenu]
*/
const uint8_t FreeSansBold18pt7bTrimmedBitmaps[] PROGMEM = {
0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0xFF, 0x87, 0xFF,
0xC7, 0xE3, 0xF3, 0xE0, 0xF9, 0xF0, 0x7D, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC,
0x07, 0xFE, 0x03, 0xFF, 0x01, 0xFF, 0x80, 0xFF, 0xC0, 0x7F, 0xE0, 0x3F,
0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xDF, 0x07, 0xCF, 0x83, 0xE7, 0xE3,
0xF1, 0xFF, 0xF0, 0xFF, 0xF8, 0x3F, 0xF8, 0x07, 0xF0, 0x00, 0x01, 0xC0,
0xF0, 0x3C, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xC1, 0xF0, 0x7C,
0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07,
0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC0, 0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0xFF,
0x8F, 0xFF, 0xE7, 0xE3, 0xF7, 0xE0, 0xFF, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8,
0x0F, 0x80, 0x07, 0xC0, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xF0, 0x03, 0xF0,
0x07, 0xF0, 0x07, 0xF0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xC0, 0x07, 0xC0,
0x03, 0xE0, 0x03, 0xFF, 0xFD, 0xFF, 0xFE, 0xFF, 0xFF, 0x7F, 0xFF, 0x80,
0x07, 0xE0, 0x0F, 0xFC, 0x0F, 0xFF, 0x0F, 0xFF, 0xCF, 0xC3, 0xF7, 0xC0,
0xFB, 0xE0, 0x7D, 0xF0, 0x3E, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x0F, 0x80,
0x3F, 0x80, 0x1F, 0xC0, 0x0F, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F,
0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x83, 0xF7, 0xC3, 0xF3, 0xFF, 0xF8, 0xFF,
0xF8, 0x3F, 0xF8, 0x07, 0xF0, 0x00, 0x00, 0xFC, 0x00, 0xFC, 0x01, 0xFC,
0x01, 0xFC, 0x03, 0xFC, 0x07, 0x7C, 0x07, 0x7C, 0x0E, 0x7C, 0x0E, 0x7C,
0x1C, 0x7C, 0x18, 0x7C, 0x38, 0x7C, 0x70, 0x7C, 0x60, 0x7C, 0xE0, 0x7C,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7C, 0x00, 0x7C,
0x00, 0x7C, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x7C, 0x1F, 0xFF, 0x0F, 0xFF,
0x8F, 0xFF, 0xC7, 0xFF, 0xE3, 0xC0, 0x01, 0xE0, 0x00, 0xE0, 0x00, 0x70,
0x00, 0x79, 0xF0, 0x3F, 0xFE, 0x1F, 0xFF, 0x8F, 0xFF, 0xE7, 0xC3, 0xF0,
0x00, 0xFC, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xFE, 0x03,
0xFF, 0x03, 0xFF, 0xC3, 0xF3, 0xFF, 0xF1, 0xFF, 0xF8, 0x3F, 0xF0, 0x07,
0xE0, 0x00, 0x03, 0xF8, 0x03, 0xFF, 0x81, 0xFF, 0xF0, 0xFF, 0xFE, 0x3E,
0x1F, 0x9F, 0x03, 0xE7, 0xC0, 0x03, 0xE0, 0x00, 0xF8, 0xF8, 0x3E, 0xFF,
0x8F, 0xFF, 0xF3, 0xFF, 0xFE, 0xFE, 0x1F, 0xBF, 0x03, 0xFF, 0x80, 0x7F,
0xE0, 0x1F, 0xF8, 0x07, 0xFE, 0x01, 0xF7, 0x80, 0x7D, 0xF0, 0x3E, 0x7E,
0x1F, 0x8F, 0xFF, 0xC1, 0xFF, 0xF0, 0x3F, 0xF0, 0x03, 0xF0, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xF0, 0x00, 0xF8,
0x00, 0xF8, 0x00, 0x78, 0x00, 0x7C, 0x00, 0x3C, 0x00, 0x3E, 0x00, 0x1E,
0x00, 0x1F, 0x00, 0x0F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xC0, 0x03,
0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x78, 0x00, 0x7C, 0x00, 0x3E, 0x00,
0x1F, 0x00, 0x0F, 0x80, 0x00, 0x07, 0xE0, 0x07, 0xFC, 0x0F, 0xFF, 0x07,
0xFF, 0xC7, 0xC3, 0xF3, 0xC0, 0xF9, 0xE0, 0x3C, 0xF0, 0x1E, 0x78, 0x1F,
0x1E, 0x1F, 0x07, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0xE3, 0xF1, 0xF9, 0xF0,
0x7D, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x83, 0xF7,
0xC3, 0xF3, 0xFF, 0xF8, 0xFF, 0xF8, 0x3F, 0xF8, 0x07, 0xF0, 0x00, 0x07,
0xE0, 0x0F, 0xFC, 0x0F, 0xFF, 0x0F, 0xFF, 0xC7, 0xE3, 0xF7, 0xE0, 0xFB,
0xE0, 0x3D, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x83,
0xF7, 0xE3, 0xFB, 0xFF, 0xFC, 0xFF, 0xFE, 0x3F, 0xDF, 0x07, 0xCF, 0x80,
0x07, 0x80, 0x03, 0xDF, 0x03, 0xE7, 0xC3, 0xE3, 0xFF, 0xF0, 0xFF, 0xF0,
0x3F, 0xF0, 0x07, 0xE0, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
0x00, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0x81, 0xFF, 0xFF,
0x81, 0xFF, 0xFF, 0x81, 0xFF, 0xFB, 0xC3, 0xDF, 0xFB, 0xC3, 0xDF, 0xFB,
0xC3, 0xDF, 0xFB, 0xC3, 0xDF, 0xF9, 0xC7, 0xDF, 0xF9, 0xE7, 0x9F, 0xF9,
0xE7, 0x9F, 0xF9, 0xE7, 0x9F, 0xF9, 0xE7, 0x9F, 0xF8, 0xFF, 0x1F, 0xF8,
0xFF, 0x1F, 0xF8, 0xFF, 0x1F, 0xF8, 0xFF, 0x1F, 0xF8, 0x7F, 0x1F, 0xF8,
0x7E, 0x1F, 0xF8, 0x7E, 0x1F, 0xF8, 0x7E, 0x1F, 0xF8, 0x3E, 0x1F, 0x00,
0x7F, 0x00, 0x01, 0xFF, 0xF0, 0x01, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0x01,
0xFC, 0x1F, 0xC1, 0xF8, 0x03, 0xF1, 0xF8, 0x00, 0xFC, 0xF8, 0x00, 0x3E,
0x7C, 0x00, 0x1F, 0x7C, 0x00, 0x07, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x01,
0xFF, 0x80, 0x00, 0xFF, 0xC0, 0x00, 0x7F, 0xE0, 0x00, 0x3F, 0xF0, 0x00,
0x1F, 0xF8, 0x00, 0x0F, 0xBE, 0x00, 0x0F, 0x9F, 0x00, 0x07, 0xCF, 0xC0,
0x07, 0xE3, 0xF0, 0x07, 0xE0, 0xFE, 0x0F, 0xE0, 0x7F, 0xFF, 0xE0, 0x0F,
0xFF, 0xE0, 0x03, 0xFF, 0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFF, 0xFC, 0x1F,
0xFF, 0xE3, 0xFF, 0xFE, 0x7F, 0xFF, 0xEF, 0x80, 0xFF, 0xF0, 0x0F, 0xFE,
0x00, 0xFF, 0xC0, 0x1F, 0xF8, 0x03, 0xFF, 0x00, 0x7F, 0xE0, 0x1F, 0xFC,
0x07, 0xEF, 0xFF, 0xFD, 0xFF, 0xFF, 0x3F, 0xFF, 0xC7, 0xFF, 0xE0, 0xF8,
0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0,
0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x00, 0x07,
0xF8, 0x01, 0xFF, 0xF0, 0x3F, 0xFF, 0x87, 0xFF, 0xFC, 0x7E, 0x0F, 0xCF,
0xC0, 0x7E, 0xF8, 0x03, 0xEF, 0x80, 0x3E, 0xF8, 0x00, 0x0F, 0xC0, 0x00,
0xFF, 0x00, 0x07, 0xFF, 0xC0, 0x3F, 0xFF, 0x81, 0xFF, 0xFC, 0x03, 0xFF,
0xE0, 0x01, 0xFF, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0xF8, 0x01, 0xFF, 0x80,
0x1F, 0xFC, 0x03, 0xFF, 0xE0, 0x7E, 0x7F, 0xFF, 0xE3, 0xFF, 0xFC, 0x1F,
0xFF, 0x00, 0x3F, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01,
0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03,
0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07,
0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F,
0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xE0, 0x07, 0xFE, 0x03, 0xFF,
0xE0, 0xFF, 0xF8, 0x7E, 0x1F, 0x1F, 0x03, 0xCF, 0x80, 0xFB, 0xE0, 0x1E,
0xFF, 0xFF, 0xBF, 0xFF, 0xEF, 0xFF, 0xFB, 0xE0, 0x00, 0xF8, 0x00, 0x3F,
0x03, 0xE7, 0xE1, 0xF9, 0xFF, 0xFC, 0x3F, 0xFE, 0x07, 0xFF, 0x00, 0x7F,
0x00, 0xF8, 0xF8, 0x3F, 0x1F, 0x7F, 0x9F, 0xF3, 0xFF, 0xFF, 0xFF, 0x7F,
0xFF, 0xFF, 0xFF, 0xC3, 0xF8, 0x7F, 0xF8, 0x3F, 0x07, 0xFE, 0x07, 0xC0,
0xFF, 0xC0, 0xF8, 0x1F, 0xF8, 0x1F, 0x03, 0xFF, 0x03, 0xE0, 0x7F, 0xE0,
0x7C, 0x0F, 0xFC, 0x0F, 0x81, 0xFF, 0x81, 0xF0, 0x3F, 0xF0, 0x3E, 0x07,
0xFE, 0x07, 0xC0, 0xFF, 0xC0, 0xF8, 0x1F, 0xF8, 0x1F, 0x03, 0xFF, 0x03,
0xE0, 0x7F, 0xE0, 0x7C, 0x0F, 0x80, 0xF8, 0xF8, 0x7D, 0xFF, 0x3F, 0xFF,
0xDF, 0xFF, 0xEF, 0xE1, 0xFF, 0xE0, 0x7F, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8,
0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x01, 0xFF, 0x80, 0xFF, 0xC0, 0x7F,
0xE0, 0x3F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xE0, 0xF8,
0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x01, 0xFF, 0x80, 0xFF, 0xC0, 0x7F,
0xE0, 0x3F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x01,
0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x9F,
0xF7, 0xC7, 0xE3, 0xE0 };
const GFXglyph FreeSansBold18pt7bTrimmedGlyphs[] PROGMEM = {
{ 0, 5, 5, 9, 2, -4 }, // 0x2E '.'
{ 0, 0, 0, 0, 0, 0 }, // 0x2F '/'
{ 4, 17, 25, 19, 1, -24 }, // 0x30 '0'
{ 58, 10, 25, 19, 3, -24 }, // 0x31 '1'
{ 90, 17, 25, 19, 1, -24 }, // 0x32 '2'
{ 144, 17, 25, 19, 1, -24 }, // 0x33 '3'
{ 198, 16, 25, 19, 2, -24 }, // 0x34 '4'
{ 248, 17, 25, 19, 1, -24 }, // 0x35 '5'
{ 302, 18, 25, 19, 1, -24 }, // 0x36 '6'
{ 359, 17, 25, 19, 1, -24 }, // 0x37 '7'
{ 413, 17, 25, 19, 1, -24 }, // 0x38 '8'
{ 467, 17, 25, 19, 1, -24 }, // 0x39 '9'
{ 0, 0, 0, 0, 0, 0 }, // 0x3A ':'
{ 0, 0, 0, 0, 0, 0 }, // 0x3B ';'
{ 0, 0, 0, 0, 0, 0 }, // 0x3C '<'
{ 0, 0, 0, 0, 0, 0 }, // 0x3D '='
{ 0, 0, 0, 0, 0, 0 }, // 0x3E '>'
{ 0, 0, 0, 0, 0, 0 }, // 0x3F '?'
{ 0, 0, 0, 0, 0, 0 }, // 0x40 '@'
{ 0, 0, 0, 0, 0, 0 }, // 0x41 'A'
{ 0, 0, 0, 0, 0, 0 }, // 0x42 'B'
{ 0, 0, 0, 0, 0, 0 }, // 0x43 'C'
{ 0, 0, 0, 0, 0, 0 }, // 0x44 'D'
{ 0, 0, 0, 0, 0, 0 }, // 0x45 'E'
{ 0, 0, 0, 0, 0, 0 }, // 0x46 'F'
{ 0, 0, 0, 0, 0, 0 }, // 0x47 'G'
{ 0, 0, 0, 0, 0, 0 }, // 0x48 'H'
{ 0, 0, 0, 0, 0, 0 }, // 0x49 'I'
{ 0, 0, 0, 0, 0, 0 }, // 0x4A 'J'
{ 0, 0, 0, 0, 0, 0 }, // 0x4B 'K'
{ 0, 0, 0, 0, 0, 0 }, // 0x4C 'L'
{ 521, 24, 26, 30, 3, -25 }, // 0x4D 'M'
{ 0, 0, 0, 0, 0, 0 }, // 0x4E 'N'
{ 599, 25, 26, 27, 1, -25 }, // 0x4F 'O'
{ 681, 19, 26, 24, 3, -25 }, // 0x50 'P'
{ 0, 0, 0, 0, 0, 0 }, // 0x51 'Q'
{ 0, 0, 0, 0, 0, 0 }, // 0x52 'R'
{ 743, 20, 26, 24, 2, -25 }, // 0x53 'S'
{ 808, 19, 26, 23, 2, -25 }, // 0x54 'T'
{ 0, 0, 0, 0, 0, 0 }, // 0x55 'U'
{ 0, 0, 0, 0, 0, 0 }, // 0x56 'V'
{ 0, 0, 0, 0, 0, 0 }, // 0x57 'W'
{ 0, 0, 0, 0, 0, 0 }, // 0x58 'X'
{ 0, 0, 0, 0, 0, 0 }, // 0x59 'Y'
{ 0, 0, 0, 0, 0, 0 }, // 0x5A 'Z'
{ 0, 0, 0, 0, 0, 0 }, // 0x5B '['
{ 0, 0, 0, 0, 0, 0 }, // 0x5C '\'
{ 0, 0, 0, 0, 0, 0 }, // 0x5D ']'
{ 0, 0, 0, 0, 0, 0 }, // 0x5E '^'
{ 0, 0, 0, 0, 0, 0 }, // 0x5F '_'
{ 0, 0, 0, 0, 0, 0 }, // 0x60 '`'
{ 0, 0, 0, 0, 0, 0 }, // 0x61 'a'
{ 0, 0, 0, 0, 0, 0 }, // 0x62 'b'
{ 0, 0, 0, 0, 0, 0 }, // 0x63 'c'
{ 0, 0, 0, 0, 0, 0 }, // 0x64 'd'
{ 870, 18, 19, 20, 1, -18 }, // 0x65 'e'
{ 0, 0, 0, 0, 0, 0 }, // 0x66 'f'
{ 0, 0, 0, 0, 0, 0 }, // 0x67 'g'
{ 0, 0, 0, 0, 0, 0 }, // 0x68 'h'
{ 0, 0, 0, 0, 0, 0 }, // 0x69 'i'
{ 0, 0, 0, 0, 0, 0 }, // 0x6A 'j'
{ 0, 0, 0, 0, 0, 0 }, // 0x6B 'k'
{ 0, 0, 0, 0, 0, 0 }, // 0x6C 'l'
{ 913, 27, 19, 31, 2, -18 }, // 0x6D 'm'
{ 978, 17, 19, 21, 2, -18 }, // 0x6E 'n'
{ 0, 0, 0, 0, 0, 0 }, // 0x6F 'o'
{ 0, 0, 0, 0, 0, 0 }, // 0x70 'p'
{ 0, 0, 0, 0, 0, 0 }, // 0x71 'q'
{ 0, 0, 0, 0, 0, 0 }, // 0x72 'r'
{ 0, 0, 0, 0, 0, 0 }, // 0x73 's'
{ 0, 0, 0, 0, 0, 0 }, // 0x74 't'
{ 1019, 17, 19, 21, 2, -18 } }; // 0x75 'u'
const GFXfont FreeSansBold18pt7bTrimmed PROGMEM = {
(uint8_t *)FreeSansBold18pt7bTrimmedBitmaps,
(GFXglyph *)FreeSansBold18pt7bTrimmedGlyphs,
0x2E, 0x75, 42 };
// Approx. 1571 bytes

7
src/fonts/trim.bat Normal file
View File

@ -0,0 +1,7 @@
@Echo Off
REM It is a nuisance to keep the filter up-to-date with whatever is printed
REM in the actual source, but the space savings are worth it.
AdafruitGFXFontTrim [0-9\.mSTOPMenu] FreeSansBold18pt7b.h
pause

View File

@ -1,23 +0,0 @@
#ifndef __colors
#define __colors
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
#define COLOR_INITSEQ_BACKGROUND BLACK
#define COLOR_INITSEQ_TITLE YELLOW
#define COLOR_INITSEQ_ITEMS WHITE
#define COLOR_INITSEQ_SUCCESS GREEN
#define COLOR_INITSEQ_ERROR RED
#define COLOR_MENU_BACKGROUND BLACK
#endif

102
src/include/config.h Normal file
View File

@ -0,0 +1,102 @@
#ifndef __config
#define __config
// The default color set provided by Adafruit
#define BLACK 0x0000
#define BLUE 0x001F
#define RED 0xF800
#define GREEN 0x07E0
#define CYAN 0x07FF
#define MAGENTA 0xF81F
#define YELLOW 0xFFE0
#define WHITE 0xFFFF
/*
TODO make constants for these values once they are used
#define STOP_RED 0xF9A6
#define MOVING_ORANGE 0xF443
#define MOVING_ORANGE_LIGHT 0xFD8C
*/
class Config
{
public:
/*
Display
Settings for an ST7789 based 240x240 pixel LCD.
Note that all screen class implementations are only tested against
this resolution, changing it may have unexpected results.
*/
static const uint8_t DisplayWidth = 240;
static const uint8_t DisplayHeight = 240;
static const uint8_t DisplayRotation = 2;
// Control pins. Data is sent over the hardware SPI pins.
static const uint8_t DisplayPortCS = 10;
static const uint8_t DisplayPortRST = 9;
static const uint8_t DisplayPortDC = 8;
static const uint8_t DisplayPortBL = 7;
/*
Height sensor
Settings for a VL53L0X time-of-flight sensor.
*/
static const uint8_t HeightSensorI2CAddress = 0x29;
// Values above this will be disregarded as invalid
static const uint16_t HeightMeasurementMax = 1500;
// How much the measurements can change to still be considered "stable"
static const uint8_t HeightMeasurementDeltaStable = 5;
// How far in advance to stop the motor
static const uint8_t HeightMeasurementDeltaStop = 0;
// How far off we can be from the target height to still be considered on target
static const uint8_t HeightMeasurementDeltaOnTarget = 5;
// How long we allow invalid measurements until the move operation is aborted
static const uint8_t HeightMeasurementAbortTimeout = 100;
/*
Colors
*/
// A useful RGB565 calculator: http://www.rinkydinkelectronics.com/calc_rgb565.php
static const uint16_t ColorInitSeqBackground = BLACK;
static const uint16_t ColorInitSeqTitle = YELLOW;
static const uint16_t ColorInitSeqItems = WHITE;
static const uint16_t ColorInitSeqSuccess = GREEN;
static const uint16_t ColorInitSeqError = RED;
static const uint16_t ColorMenuBackground = BLACK;
static const uint16_t ColorPresetText = 0x9492; // Light gray
static const uint16_t ColorPresetBackground = BLACK;
static const uint16_t ColorPresetNumber = 0x528A; // Dark gray
static const uint16_t ColorPresetSelectedText = WHITE;
static const uint16_t ColorPresetSelectedBackground = 0x2BE7; // Soft green
static const uint16_t ColorPresetSelectedNumber = 0x556B; // Slightly lighter green
};
#endif

View File

@ -1,15 +0,0 @@
#ifndef __ports
#define __ports
// Settings for an ST7789 based 240x240 pixel LCD.
#define DISPLAY_WIDTH 240
#define DISPLAY_HEIGHT 240
#define DISPLAY_ROTATION 2
// Control pins. Data is sent over the hardware SPI pins.
#define DISPLAY_PORT_CS 10
#define DISPLAY_PORT_RST 9
#define DISPLAY_PORT_DC 8
#define DISPLAY_PORT_BL 7
#endif

View File

@ -1,6 +0,0 @@
#ifndef __heightsensor
#define __heightsensor
#define HEIGHTSENSOR_I2C_ADDRESS 0x29
#endif

View File

@ -1,10 +0,0 @@
#ifndef __limits
#define __limits
// Values above this will be disregarded as invalid
#define HeightMeasurementMax 1500
// How much the measurements can change to still be considered "stable"
#define HeightMeasurementStableDelta 5
#endif

22
src/lib/motor.cpp Normal file
View File

@ -0,0 +1,22 @@
#include "./motor.h"
void motorStart(MotorDirection direction)
{
// TODO
}
void motorStop()
{
// TODO
}
bool motorIsOverCurrent()
{
// TODO
return false;
}

16
src/lib/motor.h Normal file
View File

@ -0,0 +1,16 @@
#ifndef __motor
#define __motor
enum class MotorDirection
{
Up = 0,
Down = 1
};
extern void motorStart(MotorDirection direction);
extern void motorStop();
extern bool motorIsOverCurrent();
#endif

View File

@ -1,41 +0,0 @@
#include "./persist.h"
#include <EEPROM.h>
bool Persist::init()
{
PersistHeader header;
EEPROM.get(0, header);
if (header.identifier == PersistIdentifier)
{
if (header.version >= 1)
this->readHeights();
return true;
}
return false;
}
void Persist::readHeights()
{
EEPROM.get(PersistHeightsAddress, this->heights);
}
void Persist::writeHeights()
{
EEPROM.put(PersistHeightsAddress, this->heights);
}
void Persist::setHeightOffset(uint8_t newValue)
{
if (newValue == this->heights.offset)
return;
this->heights.offset = newValue;
this->writeHeights();
}

View File

@ -1,49 +0,0 @@
#ifndef __persist
#define __persist
#include <stdint.h>
#include <string.h>
#define PersistIdentifier 0x42
#define PersistVersion1 1
struct PersistHeader
{
uint8_t identifier;
uint8_t version;
};
#define PersistHeightsAddress sizeof(PersistHeader)
struct PersistHeights
{
uint8_t offset;
uint16_t setting[2];
};
class Persist
{
public:
Persist()
{
memset(&this->heights, 0, sizeof(PersistHeights));
}
bool init();
// How many centimeters up the reflective surface is from the ground
uint8_t getHeightOffset() { return this->heights.offset; }
void setHeightOffset(uint8_t newValue);
private:
void readHeights();
void writeHeights();
PersistHeights heights;
};
#endif

View File

@ -2,19 +2,13 @@
#define __screen #define __screen
#include <Adafruit_GFX.h> #include <Adafruit_GFX.h>
#include "include/display.h" #include "include/config.h"
#if DISPLAY_WIDTH != 240 || DISPLAY_HEIGHT != 240
#error "The menu assumes a display pixel size of 240x240"
#endif
class ScreenManager; class ScreenManager;
enum Button enum class Button
{ {
Up = 0, Up = 0,
Menu = 1, Menu = 1,
@ -49,16 +43,14 @@ class BaseScreen
class ScreenManager class ScreenManager
{ {
public: public:
ScreenManager(Adafruit_GFX* display, uint32_t* currentTime) ScreenManager(Adafruit_GFX* display)
{ {
this->display = display; this->display = display;
this->currentTime = currentTime;
} }
inline void tick() { this->getCurrentScreen()->onTick(); } inline void tick() { this->getCurrentScreen()->onTick(); }
inline BaseScreen* getCurrentScreen() { return this->currentScreen; } inline BaseScreen* getCurrentScreen() { return this->currentScreen; }
inline uint32_t getCurrentTime() { return *this->currentTime; }
inline Adafruit_GFX* getDisplay() { return this->display; } inline Adafruit_GFX* getDisplay() { return this->display; }
@ -76,7 +68,6 @@ class ScreenManager
private: private:
Adafruit_GFX* display; Adafruit_GFX* display;
uint32_t* currentTime;
BaseScreen* currentScreen = nullptr; BaseScreen* currentScreen = nullptr;
}; };

View File

@ -1,17 +1,52 @@
#include "./home.h" #include "./home.h"
#include <Fonts/FreeSansBold18pt7b.h> #include "fonts/FreeSansBold18pt7b.trimmed.h"
#include "include/colors.h" #include "include/config.h"
#include "lib/settings.h"
#define HOME_FONT_BASELINE 25
#define HOME_FONT_HEIGHT 42
#define HOME_MOVING_REFRESHRATE 250
#define PRESET_MARGIN 7
// HOME_FONT_BASELINE is not a mistake, as there are no characters used which
// go below the baseline.
#define PRESET_LINEHEIGHT (HOME_FONT_BASELINE + (2 * PRESET_MARGIN))
// TODO move to shared file
// Formats a height value as "0.00m" (always exactly 5 characters long).
// Buffer must be at least 5 bytes long. No null character is added.
void getDisplayHeight(char* buffer, uint8_t value)
{
if (value > 99)
buffer[0] = '0' + ((value / 100) % 10);
else
buffer[0] = '0';
buffer[1] = '.';
buffer[2] = '0' + ((value / 10) % 10);
buffer[3] = '0' + (value % 10);
buffer[4] = 'm';
}
void HomeScreen::onShow() void HomeScreen::onShow()
{ {
this->showTime = State.CurrentTime;
auto display = this->getDisplay(); auto display = this->getDisplay();
display->setFont(&FreeSansBold18pt7b); display->setFont(&FreeSansBold18pt7bTrimmed);
display->fillScreen(COLOR_MENU_BACKGROUND); display->fillScreen(Config::ColorMenuBackground);
display->setCursor(0, 25);
display->print("Hello world!"); this->drawPreset1();
this->drawMenu();
this->drawPreset2();
// TODO if the height does not match either preset, display the actual height
} }
@ -21,5 +56,71 @@ void HomeScreen::onButton(Button button)
void HomeScreen::onTick() void HomeScreen::onTick()
{
// TODO turn off screen after timeout
//if (State.CurrentTime )
}
void HomeScreen::drawPreset1()
{
this->drawPreset(1, 0, Settings.Height.Preset[0]);
}
void HomeScreen::drawPreset2()
{
this->drawPreset(2, Config::DisplayHeight - PRESET_LINEHEIGHT, Settings.Height.Preset[1]);
}
void HomeScreen::drawPreset(uint8_t number, uint8_t y, uint8_t value)
{
auto display = this->getDisplay();
uint16_t numberColor;
uint16_t textColor;
uint16_t backgroundColor;
// An exact comparison is enough here, the movement code takes care of that if it's "close enough"
if (value == State.CurrentHeight)
{
textColor = Config::ColorPresetSelectedText;
numberColor = Config::ColorPresetSelectedNumber;
backgroundColor = Config::ColorPresetSelectedBackground;
}
else
{
textColor = Config::ColorPresetText;
numberColor = Config::ColorPresetNumber;
backgroundColor = Config::ColorPresetBackground;
}
display->fillRect(0, y, Config::DisplayWidth, PRESET_LINEHEIGHT, backgroundColor);
display->setCursor(0, y + HOME_FONT_BASELINE + PRESET_MARGIN);
display->setTextColor(numberColor);
display->print("P");
display->print(number);
char textValue[6];
getDisplayHeight(&textValue[0], value);
textValue[5] = 0;
// Calculate the center position
int16_t textX;
int16_t textY;
uint16_t textW;
uint16_t textH;
display->getTextBounds(&textValue[0], 0, 0, &textX, &textY, &textW, &textH);
textX = (Config::DisplayWidth - textW) / 2;
display->setCursor(textX, y + HOME_FONT_BASELINE + PRESET_MARGIN);
display->setTextColor(textColor);
display->print(textValue);
}
void HomeScreen::drawMenu()
{ {
} }

View File

@ -2,6 +2,7 @@
#define __screen_home #define __screen_home
#include "../screen.h" #include "../screen.h"
#include "../state.h"
/* /*
@ -16,6 +17,14 @@ class HomeScreen : public BaseScreen
void onShow(); void onShow();
void onButton(Button button); void onButton(Button button);
void onTick(); void onTick();
private:
uint32_t showTime;
void drawPreset1();
void drawPreset2();
void drawPreset(uint8_t number, uint8_t y, uint8_t value);
void drawMenu();
}; };
#endif #endif

48
src/lib/screen/move.cpp Normal file
View File

@ -0,0 +1,48 @@
#include "./move.h"
#include "./home.h"
#include "fonts/FreeSansBold18pt7b.trimmed.h"
#include "include/config.h"
#include "lib/settings.h"
#define MOVE_FONT_BASELINE 25
#define MOVE_FONT_HEIGHT 42
#define MOVE_REFRESHRATE 250
void MoveScreen::onShow()
{
auto display = this->getDisplay();
display->setFont(&FreeSansBold18pt7bTrimmed);
display->fillScreen(Config::ColorMenuBackground);
// TODO draw current and target height
}
void MoveScreen::onButton(Button button)
{
// TODO stop the motor
this->getScreenManager()->show<HomeScreen>();
}
void MoveScreen::onTick()
{
if (State.MoveDirection != Direction::None)
{
this->getScreenManager()->show<HomeScreen>();
return;
}
// Don't update every tick, it takes a significant amount of time
// and monitoring the current height is more important.
// TODO should we also stop updating when we're approaching the target height or is that overkill?
if (State.CurrentTime - this->lastRefresh >= MOVE_REFRESHRATE)
{
this->lastRefresh = State.CurrentTime;
}
}

25
src/lib/screen/move.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef __screen_move
#define __screen_move
#include "../screen.h"
#include "../state.h"
/*
* Move screen
* Shows the current and target height
*/
class MoveScreen : public BaseScreen
{
public:
MoveScreen(ScreenManager* screenManager) : BaseScreen(screenManager) { }
void onShow();
void onButton(Button button);
void onTick();
private:
uint32_t lastRefresh;
};
#endif

52
src/lib/settings.cpp Normal file
View File

@ -0,0 +1,52 @@
#include "./settings.h"
#include <EEPROM.h>
#define SettingsIdentifier 0x42
#define SettingsVersion1 1
SettingsContainer Settings;
struct SettingsHeader
{
uint8_t identifier;
uint8_t version;
};
#define SettingsHeightsAddress sizeof(SettingsHeader)
// Forward declarations
void readHeights();
bool readSettings()
{
memset(&Settings, 0, sizeof(SettingsContainer));
SettingsHeader header;
EEPROM.get(0, header);
if (header.identifier == SettingsIdentifier)
{
if (header.version >= 1)
readHeights();
return true;
}
return false;
}
void readHeights()
{
EEPROM.get(SettingsHeightsAddress, Settings.Height);
}
void writeSettingsHeights()
{
EEPROM.put(SettingsHeightsAddress, Settings.Height);
}

25
src/lib/settings.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef __settings
#define __settings
#include <stdint.h>
#include <string.h>
struct SettingsHeights
{
uint8_t Offset;
uint16_t Preset[2];
};
struct SettingsContainer
{
SettingsHeights Height;
};
extern bool readSettings();
extern void writeSettingsHeights();
extern SettingsContainer Settings;
#endif

View File

@ -1,16 +1,3 @@
#include "state.h" #include "state.h"
uint16_t currentHeight = 0; StateContainer State;
uint16_t getCurrentHeight()
{
return currentHeight;
}
void setCurrentHeight(uint16_t value)
{
currentHeight = value;
}

View File

@ -3,7 +3,23 @@
#include "stdint.h" #include "stdint.h"
uint16_t getCurrentHeight(); enum class Direction
void setCurrentHeight(uint16_t value); {
None = 0,
Up = 1,
Down = 2
};
struct StateContainer
{
uint32_t CurrentTime;
uint16_t CurrentHeight;
Direction MoveDirection;
uint16_t MoveTarget;
};
extern StateContainer State;
#endif #endif

View File

@ -89,7 +89,7 @@ bool VL53L0X::getSingleRangingMeasurement(VL53L0X_RangingMeasurementData_t *data
} }
bool VL53L0X::getSingleRangingMeasurement(uint16_t* distanceMillimeters, VL53L0X_Error* error) bool VL53L0X::getSingleRangingMeasurement(uint16_t* distanceMillimeters, VL53L0X_Error* error, uint16_t maxValidHeight)
{ {
VL53L0X_RangingMeasurementData_t data; VL53L0X_RangingMeasurementData_t data;
auto result = this->getSingleRangingMeasurement(&data, error); auto result = this->getSingleRangingMeasurement(&data, error);
@ -97,5 +97,5 @@ bool VL53L0X::getSingleRangingMeasurement(uint16_t* distanceMillimeters, VL53L0X
if (result) if (result)
*distanceMillimeters = data.RangeMilliMeter; *distanceMillimeters = data.RangeMilliMeter;
return result; return result && data.RangeMilliMeter <= maxValidHeight;
} }

View File

@ -44,7 +44,7 @@ class VL53L0X
bool init(uint8_t address, VL53L0XResult* result); bool init(uint8_t address, VL53L0XResult* result);
bool setMeasurementTimingBudget(uint32_t budget_us, VL53L0X_Error* error); bool setMeasurementTimingBudget(uint32_t budget_us, VL53L0X_Error* error);
bool getSingleRangingMeasurement(VL53L0X_RangingMeasurementData_t* data, VL53L0X_Error* error); bool getSingleRangingMeasurement(VL53L0X_RangingMeasurementData_t* data, VL53L0X_Error* error);
bool getSingleRangingMeasurement(uint16_t* distanceMillimeters, VL53L0X_Error* error); bool getSingleRangingMeasurement(uint16_t* distanceMillimeters, VL53L0X_Error* error, uint16_t maxValidHeight);
private: private:
VL53L0X_Dev_t device; VL53L0X_Dev_t device;

View File

@ -3,44 +3,43 @@
#include <Adafruit_GFX.h> #include <Adafruit_GFX.h>
#include <Adafruit_ST7789.h> #include <Adafruit_ST7789.h>
#include "./include/display.h" #include "./include/config.h"
#include "./include/heightsensor.h"
#include "./include/colors.h"
#include "./lib/debug.h" #include "./lib/debug.h"
#include "./lib/persist.h" #include "./lib/settings.h"
#include "./lib/screen.h" #include "./lib/screen.h"
#include "./lib/vl53l0x.h" #include "./lib/vl53l0x.h"
#include "./lib/limits.h"
#include "./lib/state.h" #include "./lib/state.h"
#include "./lib/motor.h"
#include "./lib/screen/home.h" #include "./lib/screen/home.h"
enum class InitSequenceStep
{
EEPROM = 0,
HeightSensorInit = 1,
HeightSensorBudget = 2,
HeightSensorTest = 3,
Last = HeightSensorTest
};
// Forward declarations // Forward declarations
inline void setupHeightSensor(); inline void setupHeightSensor();
inline uint8_t testHeightSensor(); inline uint8_t testHeightSensor();
void initSequenceStart(); void initSequenceStart();
void initSequenceSuccess(uint8_t which); void initSequenceSuccess(InitSequenceStep step);
void initSequenceError(uint8_t which); void initSequenceError(InitSequenceStep step);
void initSequenceDisplayHeight(uint16_t measurement); void initSequenceDisplayHeight(uint16_t measurement);
void initSequenceEnd(); void initSequenceEnd();
#define INITSEQ_EEPROM 0
#define INITSEQ_HEIGHTSENSORINIT 1
#define INITSEQ_HEIGHTSENSORBUDGET 2
#define INITSEQ_HEIGHTSENSORTEST 3
#define INITSEQ_MAX INITSEQ_HEIGHTSENSORTEST
auto display = Adafruit_ST7789(Config::DisplayPortCS, Config::DisplayPortDC, Config::DisplayPortRST);
auto display = Adafruit_ST7789(DISPLAY_PORT_CS, DISPLAY_PORT_DC, DISPLAY_PORT_RST);
auto heightSensor = VL53L0X(); auto heightSensor = VL53L0X();
uint32_t currentTime = 0; auto screenManager = ScreenManager(&display);
auto persist = Persist();
auto screenManager = ScreenManager(&display, &currentTime);
/* /*
@ -50,19 +49,20 @@ auto screenManager = ScreenManager(&display, &currentTime);
*/ */
void setup() void setup()
{ {
State.CurrentTime = millis();
DebugInit(); DebugInit();
pinMode(DISPLAY_PORT_BL, OUTPUT); pinMode(Config::DisplayPortBL, OUTPUT);
digitalWrite(DISPLAY_PORT_BL, HIGH); digitalWrite(Config::DisplayPortBL, HIGH);
display.init(DISPLAY_WIDTH, DISPLAY_HEIGHT, SPI_MODE3); display.init(Config::DisplayWidth, Config::DisplayHeight, SPI_MODE3);
display.setRotation(DISPLAY_ROTATION); display.setRotation(Config::DisplayRotation);
initSequenceStart(); initSequenceStart();
// Load settings from EEPROM // Load settings from EEPROM
auto initialized = persist.init(); auto initialized = readSettings();
initSequenceSuccess(INITSEQ_EEPROM); initSequenceSuccess(InitSequenceStep::EEPROM);
// Initialize VL53L0X sensor // Initialize VL53L0X sensor
@ -74,7 +74,7 @@ void setup()
if (initialized) if (initialized)
{ {
setCurrentHeight(currentHeight + persist.getHeightOffset()); State.CurrentHeight = currentHeight;
screenManager.show<HomeScreen>(); screenManager.show<HomeScreen>();
} }
else else
@ -89,9 +89,9 @@ inline void setupHeightSensor()
Wire.begin(); Wire.begin();
VL53L0XResult result; VL53L0XResult result;
if (!heightSensor.init(HEIGHTSENSOR_I2C_ADDRESS, &result)) if (!heightSensor.init(Config::HeightSensorI2CAddress, &result))
{ {
initSequenceError(INITSEQ_HEIGHTSENSORINIT); initSequenceError(InitSequenceStep::HeightSensorInit);
display.print(result.error); display.print(result.error);
display.print(" @ "); display.print(" @ ");
@ -99,19 +99,19 @@ inline void setupHeightSensor()
while(1); while(1);
} }
initSequenceSuccess(INITSEQ_HEIGHTSENSORINIT); initSequenceSuccess(InitSequenceStep::HeightSensorInit);
VL53L0X_Error error; VL53L0X_Error error;
if (!heightSensor.setMeasurementTimingBudget(33000, &error)) if (!heightSensor.setMeasurementTimingBudget(33000, &error))
{ {
initSequenceError(INITSEQ_HEIGHTSENSORBUDGET); initSequenceError(InitSequenceStep::HeightSensorBudget);
display.print(result.error); display.print(result.error);
while(1); while(1);
} }
initSequenceSuccess(INITSEQ_HEIGHTSENSORBUDGET); initSequenceSuccess(InitSequenceStep::HeightSensorBudget);
} }
@ -126,11 +126,11 @@ inline uint8_t testHeightSensor()
{ {
uint16_t measurement; uint16_t measurement;
if (heightSensor.getSingleRangingMeasurement(&measurement, &error) && measurement <= HeightMeasurementMax) if (heightSensor.getSingleRangingMeasurement(&measurement, &error, Config::HeightMeasurementMax))
{ {
initSequenceDisplayHeight(measurement); initSequenceDisplayHeight(measurement);
if (abs(measurement - reference) <= HeightMeasurementStableDelta) if (abs(measurement - reference) <= Config::HeightMeasurementDeltaStable)
closeCount++; closeCount++;
else else
{ {
@ -149,7 +149,7 @@ inline uint8_t testHeightSensor()
delay(500); delay(500);
} }
initSequenceSuccess(INITSEQ_HEIGHTSENSORTEST); initSequenceSuccess(InitSequenceStep::HeightSensorTest);
return reference / 10; return reference / 10;
} }
@ -160,13 +160,84 @@ inline uint8_t testHeightSensor()
Loop Loop
*/ */
// Forward declarations
void updateHeight();
void loop() void loop()
{ {
// TODO State.CurrentTime = millis();
if (State.MoveDirection != Direction::None)
{
if (motorIsOverCurrent())
{
motorStop();
State.MoveDirection = Direction::None;
// TODO go to overcurrent screen
}
else
updateHeight();
}
screenManager.tick();
} }
uint32_t lastValidMeasurement;
void updateHeight()
{
VL53L0X_Error error;
uint16_t measurement;
if (heightSensor.getSingleRangingMeasurement(&measurement, &error, Config::HeightMeasurementMax))
{
State.CurrentHeight = measurement;
lastValidMeasurement = State.CurrentTime;
// Check if we've reached the target
switch (State.MoveDirection)
{
case Direction::Up:
if (measurement >= State.MoveTarget - Config::HeightMeasurementDeltaStop)
{
if (measurement - State.MoveTarget <= Config::HeightMeasurementDeltaOnTarget)
State.CurrentHeight = State.MoveTarget;
motorStop();
State.MoveDirection = Direction::None;
}
break;
case Direction::Down:
if (measurement <= State.MoveTarget + Config::HeightMeasurementDeltaStop)
{
if (State.MoveTarget - measurement <= Config::HeightMeasurementDeltaOnTarget)
State.CurrentHeight = State.MoveTarget;
motorStop();
State.MoveDirection = Direction::None;
}
break;
default:
break;
}
}
else if (State.CurrentTime - lastValidMeasurement >= Config::HeightMeasurementAbortTimeout)
{
motorStop();
State.MoveDirection = Direction::None;
// TODO go to height sensor error screen
}
}
/* /*
@ -176,6 +247,9 @@ void loop()
delay(1000); delay(1000);
display.sendCommand(ST77XX_SLPIN); display.sendCommand(ST77XX_SLPIN);
// toggle backlight pin // toggle backlight pin
For motor sleep toggle slp pin
*/ */
@ -188,19 +262,19 @@ void loop()
#define initSequenceTextSize 2 #define initSequenceTextSize 2
// Default font is 5x7 // Default font is 5x7
#define initSequenceTextY(which) ((1 + which) * ((7 + 3) * initSequenceTextSize)) #define initSequenceTextY(step) ((1 + (uint8_t)step) * ((7 + 3) * initSequenceTextSize))
void initSequenceStart() void initSequenceStart()
{ {
display.fillScreen(COLOR_INITSEQ_BACKGROUND); display.fillScreen(Config::ColorInitSeqBackground);
display.setTextSize(initSequenceTextSize); display.setTextSize(initSequenceTextSize);
display.setCursor(0, 0); display.setCursor(0, 0);
display.setTextColor(COLOR_INITSEQ_TITLE); display.setTextColor(Config::ColorInitSeqTitle);
display.println("Initializing..."); display.println("Initializing...");
display.setTextColor(COLOR_INITSEQ_ITEMS, COLOR_INITSEQ_BACKGROUND); display.setTextColor(Config::ColorInitSeqItems, Config::ColorInitSeqBackground);
display.setCursor(0, initSequenceTextY(0)); display.setCursor(0, initSequenceTextY(0));
display.print(" reading EEPROM"); display.print(" reading EEPROM");
@ -216,23 +290,23 @@ void initSequenceStart()
} }
void initSequenceSuccess(uint8_t which) void initSequenceSuccess(InitSequenceStep step)
{ {
display.drawChar(0, initSequenceTextY(which), 'v', COLOR_INITSEQ_SUCCESS, COLOR_INITSEQ_BACKGROUND, initSequenceTextSize); display.drawChar(0, initSequenceTextY(step), 'v', Config::ColorInitSeqSuccess, Config::ColorInitSeqBackground, initSequenceTextSize);
} }
void initSequenceError(uint8_t which) void initSequenceError(InitSequenceStep step)
{ {
display.drawChar(0, initSequenceTextY(which), 'x', COLOR_INITSEQ_ERROR, COLOR_INITSEQ_BACKGROUND, initSequenceTextSize); display.drawChar(0, initSequenceTextY(step), 'x', Config::ColorInitSeqError, Config::ColorInitSeqBackground, initSequenceTextSize);
display.setCursor(0, initSequenceTextY(INITSEQ_MAX + 2)); display.setCursor(0, initSequenceTextY(InitSequenceStep::Last + 2));
} }
void initSequenceDisplayHeight(uint16_t measurement) void initSequenceDisplayHeight(uint16_t measurement)
{ {
display.setCursor(0, initSequenceTextY(INITSEQ_MAX + 2)); display.setCursor(0, initSequenceTextY(InitSequenceStep::Last + 2));
if (measurement > 0) if (measurement > 0)
{ {