Xiaomi m365 dashboard 0.96

Bonjour j'aimerais pouvoir mettre un écran 0,96 pouces sur ma trottinette xiaomi mais j'ai une erreur avec le code quand je le compile avez-vous une idée d'où ça peut venir ?

#include "WatchDog.h"

// Select either SPI or I2C(Wire) Display Mode
//#define DISPLAY_SPI
#define DISPLAY_I2C

//#define US_Version

#include "SSD1306Ascii.h"
#ifdef DISPLAY_SPI
#include <SPI.h>
#include "SSD1306AsciiSpi.h"
#define PIN_CS 10
#define PIN_RST 9
#define PIN_DC 8
#define PIN_D0 13
#define PIN_D1 11
#endif
#ifdef DISPLAY_I2C
#include "SSD1306AsciiWire.h"
#endif
GLCDFONTDECL(m365) = {
0x0, 0x0,
0x80,
0x40,
0x20,
0x02,

0x00, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xF8,
0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x80, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xF8,
0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xF0, 0xE0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFC, 0xFC, 0xF8, 0xF8, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFC,
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x1F, 0x1F, 0x1F,
0x3F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x3F, 0x3F, 0x1F, 0x1F, 0x0F, 0x0F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x03, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x03, 0x07, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x03,
0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F,
0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F,
0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x80, 0xC3,
0xC3, 0xC3, 0x83, 0x83, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xE0, 0x00, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0,
0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xC7, 0x81, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x07, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x1F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x1F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC3, 0xC3, 0x03, 0x07, 0x0F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xE0, 0xC0, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF8, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFE, 0xFC, 0xFC, 0xF8, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
0xC0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x7F, 0x3F, 0x1F, 0x0F, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xC0, 0xC0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F,
0x00, 0x00, 0x00, 0x07, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xC0, 0xE0, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x07, 0x0F,
0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x3F, 0x1F, 0x1F, 0x1F, 0x0F, 0x07, 0x07, 0x03, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F,
0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x1F, 0x1F, 0x07, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
0x7F, 0x3F, 0x3F, 0x1F, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x1F,
0x3F, 0x3F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F, 0x3F, 0x1F, 0x0F, 0x03, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0xE0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFC,
0xFC, 0xFC, 0xF8, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F,
0x1F, 0x8F, 0xC7, 0xE7, 0xE7, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0xE3, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x0F, 0x0F, 0x1F, 0x3F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xC0, 0xC0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x00,
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00,
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC,
0xF8, 0xF1, 0xE3, 0xE7, 0xE7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC7, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xFC,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8,
0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F,
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x3F,
0x3F, 0x3F, 0x1F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F,
0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00
};

#if Language == RU
/*
*

  • System5x7
  • File Name : System5x7.h
  • Date : 28 Oct 2008
  • Font size in bytes : 470
  • Font width : 5
  • Font height : 7
  • Font first char : 32
  • Font last char : 127
  • Font used chars : 94
  • The font data are defined as
  • struct FONT {
  • uint16_t   font_Size_in_Bytes_over_all_included_Size_it_self;
    
  • uint8_t    font_Width_in_Pixel_for_fixed_drawing;
    
  • uint8_t    font_Height_in_Pixel_for_all_characters;
    
  • unit8_t    font_First_Char;
    
  • uint8_t    font_Char_Count;
    
  • uint8_t    font_Char_Widths[font_Last_Char - font_First_Char +1];
    
  •              // for each character the separate width in pixels,
    
  •              // characters < 128 have an implicit virtual right empty row
    
  • uint8_t    font_data[];
    
  •              // bit field of all characters
    

*/

#ifndef SYSTEM5x7mod_H
#define SYSTEM5x7mod_H

#define SYSTEM5x7mod_WIDTH 5
#define SYSTEM5x7mod_HEIGHT 7

GLCDFONTDECL(System5x7mod) = {
0x0, 0x0, // size of zero indicates fixed width font,
0x05, // width
0x07, // height
0x20, // first char
0x66, // char count

// Fixed width; char width table not used !!!!

// font data

0x00, 0x00, 0x00, 0x00, 0x00, // sp
0x00, 0x00, 0x2f, 0x00, 0x00, // !
0x00, 0x07, 0x00, 0x07, 0x00, // "
0x14, 0x7f, 0x14, 0x7f, 0x14, // #
0x24, 0x2a, 0x7f, 0x2a, 0x12, // $
0x23, 0x13, 0x08, 0x64, 0x62, // %
0x36, 0x49, 0x55, 0x22, 0x50, // &
0x00, 0x05, 0x03, 0x00, 0x00, // '
0x00, 0x1c, 0x22, 0x41, 0x00, // (
0x00, 0x41, 0x22, 0x1c, 0x00, // )
0x14, 0x08, 0x3E, 0x08, 0x14, // *
0x08, 0x08, 0x3E, 0x08, 0x08, // +
0x3E, 0x49, 0x45, 0x45, 0x38, // ,
0x08, 0x08, 0x08, 0x08, 0x08, // -
0x00, 0x60, 0x60, 0x00, 0x00, // .
0x20, 0x10, 0x08, 0x04, 0x02, // /

0x3E, 0x51, 0x49, 0x45, 0x3E, // 0
0x00, 0x42, 0x7F, 0x40, 0x00, // 1
0x42, 0x61, 0x51, 0x49, 0x46, // 2
0x21, 0x41, 0x45, 0x4B, 0x31, // 3
0x18, 0x14, 0x12, 0x7F, 0x10, // 4
0x27, 0x45, 0x45, 0x45, 0x39, // 5
0x3C, 0x4A, 0x49, 0x49, 0x30, // 6
0x01, 0x71, 0x09, 0x05, 0x03, // 7
0x36, 0x49, 0x49, 0x49, 0x36, // 8
0x06, 0x49, 0x49, 0x29, 0x1E, // 9
0x00, 0x36, 0x36, 0x00, 0x00, // :
0x4C, 0x30, 0x7C, 0x30, 0x4C, // ;
0x00, 0x08, 0x14, 0x22, 0x41, // <
0x6c, 0x10, 0x7c, 0x10, 0x6c, // =
0x41, 0x22, 0x14, 0x08, 0x00, // >
0x7f, 0x49, 0x49, 0x49, 0x33, // ?

0x32, 0x49, 0x59, 0x51, 0x3E, // @
0x1C, 0x22, 0x7F, 0x22, 0x1C, // A
0x7F, 0x10, 0x08, 0x04, 0x7F, // B
0x3E, 0x41, 0x41, 0x41, 0x22, // C
0x7F, 0x45, 0x45, 0x45, 0x3A, // D
0x61, 0x26, 0x18, 0x06, 0x01, // E
0x7C, 0x12, 0x11, 0x12, 0x7C, // F
0x7F, 0x01, 0x01, 0x01, 0x7F, // G
0x7F, 0x09, 0x09, 0x09, 0x06, // H
0x7F, 0x40, 0x7F, 0x40, 0x7F, // I
0x3E, 0x41, 0x41, 0x41, 0x3E, // J
0x40, 0x3F, 0x01, 0x01, 0x7F, // K
0x60, 0x3F, 0x21, 0x3F, 0x60, // L
0x7F, 0x48, 0x48, 0x30, 0x00, // M
0x03, 0x01, 0x7F, 0x01, 0x03, // N
0x3F, 0x20, 0x3F, 0x20, 0x7F, // O

0x21, 0x41, 0x49, 0x4D, 0x33, // P
0x7E, 0x20, 0x11, 0x08, 0x7E, // Q
0x7F, 0x08, 0x14, 0x22, 0x41, // R
0x7f, 0x48, 0x30, 0x00, 0x7f, // S
0x7F, 0x49, 0x49, 0x49, 0x41, // T
0x7F, 0x01, 0x01, 0x01, 0x03, // U
0x7F, 0x06, 0x08, 0x06, 0x7F, // V
0x3F, 0x20, 0x20, 0x3F, 0x60, // W
0x07, 0x08, 0x08, 0x08, 0x7F, // X
0x7F, 0x08, 0x08, 0x08, 0x7F, // Y
0x66, 0x19, 0x09, 0x09, 0x7F, // Z
0x44, 0x28, 0x10, 0x28, 0x44, // [
0x55, 0xAA, 0x55, 0xAA, 0x55, // Backslash (Checker pattern)
0x00, 0x45, 0x7C, 0x41, 0x00, // ]
0x04, 0x02, 0x01, 0x02, 0x04, // ^
0x40, 0x40, 0x40, 0x40, 0x40, // _

0x38, 0x54, 0x54, 0x44, 0x00, // `
0x18, 0x24, 0x7E, 0x24, 0x18, // a
0x7C, 0x20, 0x10, 0x7C, 0x00, // b
0x38, 0x44, 0x44, 0x44, 0x28, // c
0x7E, 0x4A, 0x4A, 0x34, 0x00, // d
0x4C, 0x90, 0x90, 0x90, 0x7C, // e
0x20, 0x54, 0x54, 0x54, 0x78, // f
0x7C, 0x04, 0x04, 0x7C, 0x00, // g
0xFC, 0x18, 0x24, 0x24, 0x18, // h
0x7C, 0x40, 0x7C, 0x40, 0x7C, // i
0x38, 0x44, 0x44, 0x44, 0x38, // j
0x40, 0x3C, 0x04, 0x04, 0x7C, // k
0x38, 0x45, 0x45, 0x49, 0x3E, // l
0x7C, 0x50, 0x70, 0x00, 0x00, // m
0x04, 0x04, 0x7C, 0x04, 0x04, // n
0x3C, 0x20, 0x3C, 0x20, 0x7C, // o

0x44, 0x54, 0x54, 0x28, 0x00, // p
0x7C, 0x21, 0x11, 0x7C, 0x00, // q
0x7C, 0x10, 0x28, 0x44, 0x00, // r
0x7c, 0x50, 0x50, 0x20, 0x7c, // s
0x38, 0x54, 0x54, 0x54, 0x18, // t
0x7C, 0x04, 0x04, 0x0C, 0x00, // u
0x7C, 0x08, 0x10, 0x08, 0x7C, // v
0x3C, 0x20, 0x20, 0x3C, 0x60, // w
0x1C, 0x10, 0x10, 0x7C, 0x00, // x
0x7C, 0x10, 0x10, 0x7C, 0x00, // y
0x48, 0x34, 0x14, 0x7C, 0x00, // z
0x63, 0x14, 0x08, 0x14, 0x63, // {
0x00, 0x00, 0xFF, 0x00, 0x00, // |
0x00, 0x45, 0x7C, 0x45, 0x00, // }
0x08, 0x08, 0x2A, 0x1C, 0x08,// ->
0x08, 0x1C, 0x2A, 0x08, 0x08,// <-
0x00, 0x06, 0x09, 0x09, 0x06,// ~ (Degrees)
0x00, 0x00, 0x00, 0x7F, 0x41,// [
0x5D, 0x5D, 0x5D, 0x5D, 0x41,// =
0x41, 0x41, 0x41, 0x41, 0x41,// -
0x7F, 0x00, 0x00, 0x00, 0x00,// ]
0x7C, 0x7C, 0x7C, 0x7C, 0x7C // .
};

#endif
#else
#include "fonts/System5x7mod.h"
#endif
GLCDFONTDECL(stdNumb) =
{
0x0, 0x0,
10,
14,
' ',
27,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0xFC, 0xFE, 0xFF, 0x07, 0x03, 0x03, 0xFF, 0xFE, 0xFC, 0x00,
0x0F, 0x1F, 0x3F, 0x30, 0x30, 0x38, 0x3F, 0x1F, 0x0F, 0x00,

0x00, 0x00, 0x0C, 0x0C, 0x0E, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x00, 0x00,

0x00, 0x1C, 0x1E, 0x1F, 0x07, 0xC7, 0xFF, 0xFE, 0x3C, 0x00,
0x00, 0x30, 0x38, 0x3E, 0x3F, 0x3F, 0x33, 0x30, 0x30, 0x00,

0x0E, 0x0F, 0x6F, 0x63, 0xE3, 0xE7, 0xFF, 0xFE, 0xDC, 0x00,
0x0F, 0x1F, 0x3F, 0x38, 0x30, 0x38, 0x3F, 0x1F, 0x0F, 0x00,

0x80, 0xE0, 0xF8, 0x3F, 0x07, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x07, 0x07, 0x07, 0x07, 0x07, 0x3F, 0x3F, 0x3F, 0x07, 0x00,

0x7F, 0x7F, 0x7F, 0x33, 0x33, 0x73, 0xF3, 0xF3, 0xE3, 0x00,
0x0E, 0x1E, 0x3E, 0x38, 0x30, 0x38, 0x3F, 0x1F, 0x0F, 0x00,

0xFC, 0xFE, 0xFF, 0x67, 0x63, 0xE7, 0xEF, 0xEE, 0xCC, 0x00,
0x0F, 0x1F, 0x3F, 0x38, 0x30, 0x30, 0x3F, 0x1F, 0x0F, 0x00,

0x00, 0x03, 0x03, 0x03, 0xE3, 0xFF, 0xFF, 0x3F, 0x07, 0x00,
0x00, 0x00, 0x38, 0x3F, 0x3F, 0x0F, 0x01, 0x00, 0x00, 0x00,

0xBC, 0xFE, 0xFF, 0xC7, 0xC3, 0xE3, 0xFF, 0xFE, 0xBC, 0x00,
0x0F, 0x1F, 0x3F, 0x31, 0x30, 0x38, 0x3F, 0x1F, 0x0F, 0x00,

0xFC, 0xFE, 0xFF, 0x87, 0x83, 0xC3, 0xFF, 0xFE, 0xFC, 0x00,
0x0C, 0x1D, 0x3D, 0x31, 0x31, 0x38, 0x3F, 0x1F, 0x0F, 0x00,

0x00, 0x00, 0x00, 0x00, 0x70, 0x70, 0x70, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x1C, 0x1C, 0x1C, 0x00, 0x00, 0x00
};
GLCDFONTDECL(bigNumb) = {
0x0, 0x0,
0x1C,
0x32,
0x30,
0x0C,

0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x00,
0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x00,
0x00, 0x03, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F, 0x0F, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0xC0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8, 0xF8, 0xE0, 0xC0, 0x00, 0x00, 0x00,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x00,
0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x80, 0xE0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xC0, 0xF0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x1F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00,
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,

0xC0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xCF, 0x87, 0x01, 0x00, 0x00,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE3, 0xE3, 0x03, 0x03, 0x07, 0x07, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x01, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xFC, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0xE0, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0xC0, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,

0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xC0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00,
0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x0F, 0x07, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00,
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x07, 0x0F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F, 0x07, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0xC0, 0xE0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFC, 0xFC, 0xF8, 0xF0, 0xC0, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x7C, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xF8, 0xF0, 0xC0, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x01, 0x07, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x3F, 0x1F, 0x07, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x03, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x80, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x01, 0x07, 0x8F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xCF, 0x8F, 0x07, 0x01, 0x00,
0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x03, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x01, 0x07, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0xC0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFC, 0xF8, 0xF8, 0xE0, 0xC0, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x07, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7C, 0x3E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0xF1, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x01, 0x0F, 0x1F, 0x3F, 0x7F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xF8, 0xDC, 0x8E, 0x06, 0x00, 0xFE, 0xFE, 0xFE, 0x06, 0xFE, 0xFC, 0xFE, 0x06, 0xFE, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x03, 0x03, 0x00, 0x01, 0x03, 0x03, 0x00, 0x03, 0x03, 0xE3, 0xE0, 0x03, 0xE3, 0xE3, 0x00, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF8, 0x3F, 0x07, 0x00, 0x00, 0xFF, 0xFF, 0x06, 0x06, 0xFE, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

#include <EEPROM.h>

//***********************************
//LANGUAGE SELECTION. Uncomment only one line
//***********************************
//#define LANG_ENG //English
#define LANG_FRA //French
//#define LANG_DE //German
//#define LANG_RU //Russian, use together with the russian font in libraries folder
//#define LANG_ES //Spanish
//#define LANG_CZ //Czech
//#define LANG_IT //Italian

#ifdef LANG_FRA
#define defaultFont System5x7mod

const char noBUS1[] PROGMEM = {"BUS non"};
const char noBUS2[] PROGMEM = {"connesso!"};
const char noBUS3[] PROGMEM = {"Nessun dato da"};
const char noBUS4[] PROGMEM = {"visualizzare"};

const char confScr1[] PROGMEM = {"Contakilometri: "};
const char confScr2[] PROGMEM = {"Conta Km: "};
const char confScr2a[] PROGMEM = {" VEL"};
const char confScr2b[] PROGMEM = {"CORRENTE"};
const char confScr3[] PROGMEM = {"Messaggio Batteria: "};
const char confScr4[] PROGMEM = {"Messaggio Batteria: "};
const char confScr5[] PROGMEM = {"Info Batteria"};
const char confScr6[] PROGMEM = {"Configura M365"};
const char confScr7[] PROGMEM = {"Salva e esci"};

const char infoScr1[] PROGMEM = {"Distance totale"};
const char infoScr2[] PROGMEM = {"Tempo acceso"};

const char battScr[] PROGMEM = {">>> Freno per uscire <<<"};

const char M365CfgScr1[] PROGMEM = {"Cruise control: "};
const char M365CfgScr2[] PROGMEM = {"Agg. Cruise"};
const char M365CfgScr3[] PROGMEM = {"Fanale Post.: "};
const char M365CfgScr4[] PROGMEM = {"Agg. Fanale Post."};
const char M365CfgScr5[] PROGMEM = {"Rec.En.Cinetica: "};
const char M365CfgScr6[] PROGMEM = {"Agg. Rec.En.Cinetica"};
const char M365CfgScr8[] PROGMEM = {"Esci"};
const char M365CfgScr7[] PROGMEM = {"Ruote: "};

const char l_85inch[] PROGMEM = {" 8,5""};
const char l_10inch[] PROGMEM = {" 10""};

const char l_Weak[] PROGMEM = {" DEBOLE"};
const char l_Medium[] PROGMEM = {"MEDIO"};
const char l_Strong[] PROGMEM = {"FORTE"};

const char l_Yes[] PROGMEM = {"SI"};
const char l_No[] PROGMEM = {" NO"};
const char l_On[] PROGMEM = {" ON"};
const char l_Off[] PROGMEM = {"OFF"};

const char l_km[] PROGMEM = {"km"};
const char l_kmh[] PROGMEM = {"km/h"};
const char l_mah[] PROGMEM = {"mAh"};
const char l_v[] PROGMEM = {"V"};
const char l_a[] PROGMEM = {"A"};
const char l_c[] PROGMEM = {"C"};
const char l_t[] PROGMEM = {"T"};
#endif

#ifndef MESSAGES_h
#define MESSAGES_h

#define MAX_MESSAGES 15
#define MAX_BROADCAST 2

#include "Arduino.h"

#define DROP 0
#define NEW 1
#define READY 2

class MessagesClass
{
private:
uint8_t messages[MAX_MESSAGES];
uint8_t broadcast[MAX_BROADCAST];

public:
MessagesClass();
void Post(uint8_t);
uint8_t Get(uint8_t);
uint8_t Peek(uint8_t); //for sniffer
void Process();
void PostBroadcast(uint8_t);
uint8_t GetBroadcast(uint8_t);
void ProcessBroadcast();
};

#endif

MessagesClass Message;

const uint16_t LONG_PRESS = 2000;
uint8_t warnBatteryPercent = 5;

bool autoBig = true;
uint8_t bigMode = 0;
bool bigWarn = true;

bool Settings = false;
bool ShowBattInfo = false;
bool M365Settings = false;

uint8_t menuPos = 0;
uint8_t sMenuPos = 0;

bool cfgCruise = false;
bool cfgTailight = false;
uint8_t cfgKERS = 0;

volatile int16_t oldBrakeVal = -1;
volatile int16_t oldThrottleVal = -1;
volatile bool btnPressed = false;
bool bAlarm = false;

uint32_t timer = 0;

#ifdef DISPLAY_SPI
SSD1306AsciiSpi display;
#endif
#ifdef DISPLAY_I2C
SSD1306AsciiWire display;
#endif

bool WheelSize = true; //whell 8,5"

uint8_t WDTcounts = 0;
void(* resetFunc) (void) = 0;

// -----------------------------------------------------------------------------------------------------------

#define XIAOMI_PORT Serial
#define RX_DISABLE UCSR0B &= ~_BV(RXEN0);
#define RX_ENABLE UCSR0B |= _BV(RXEN0);

struct {
uint8_t prepared; //1 if prepared, 0 after writing
uint8_t DataLen; //lenght of data to write
uint8_t buf[16]; //buffer
uint16_t cs; //cs of data into buffer
uint8_t _dynQueries[5];
uint8_t _dynSize = 0;
} _Query;

volatile uint8_t _NewDataFlag = 0; //assign '1' for renew display once
volatile bool _Hibernate = false; //disable requests. For flashind or other things

enum {CMD_CRUISE_ON, CMD_CRUISE_OFF, CMD_LED_ON, CMD_LED_OFF, CMD_WEAK, CMD_MEDIUM, CMD_STRONG};
struct attribute((packed)) CMD{
uint8_t len;
uint8_t addr;
uint8_t rlen;
uint8_t param;
int16_t value;
}_cmd;

const uint8_t _commandsWeWillSend[] = {1, 8, 10}; //insert INDEXES of commands, wich will be send in a circle

    // INDEX                     //0     1     2     3     4     5     6     7     8     9    10    11    12    13    14

const uint8_t _q[] PROGMEM = {0x3B, 0x31, 0x20, 0x1B, 0x10, 0x1A, 0x69, 0x3E, 0xB0, 0x23, 0x3A, 0x7B, 0x7C, 0x7D, 0x40}; //commands
const uint8_t _l[] PROGMEM = { 2, 10, 6, 4, 18, 12, 2, 2, 32, 6, 4, 2, 2, 2, 30}; //expected answer length of command
const uint8_t _f[] PROGMEM = { 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1}; //format of packet

//wrappers for known commands
const uint8_t _h0[] PROGMEM = {0x55, 0xAA};
const uint8_t _h1[] PROGMEM = {0x03, 0x22, 0x01};
const uint8_t _h2[] PROGMEM = {0x06, 0x20, 0x61};
const uint8_t _hc[] PROGMEM = {0x04, 0x20, 0x03}; //head of control commands

struct attribute ((packed)){ //dynamic end of long queries
uint8_t hz; //unknown
uint8_t th; //current throttle value
uint8_t br; //current brake value
}_end20t;

const uint8_t RECV_TIMEOUT = 5;
const uint8_t RECV_BUFLEN = 64;

struct attribute((packed)) ANSWER_HEADER{ //header of receiving answer
uint8_t len;
uint8_t addr;
uint8_t hz;
uint8_t cmd;
} AnswerHeader;

struct attribute ((packed)) {
uint8_t state; //0-stall, 1-drive, 2-eco stall, 3-eco drive
uint8_t ledBatt; //battery status 0 - min, 7(or 8...) - max
uint8_t headLamp; //0-off, 0x64-on
uint8_t beepAction;
} S21C00HZ64;

struct attribute((packed))A20C00HZ65 {
uint8_t hz1;
uint8_t throttle; //throttle
uint8_t brake; //brake
uint8_t hz2;
uint8_t hz3;
} S20C00HZ65;

struct attribute((packed))A25C31 {
uint16_t remainCapacity; //remaining capacity mAh
uint8_t remainPercent; //charge in percent
uint8_t u4; //battery status??? (unknown)
int16_t current; //current /100 = A
int16_t voltage; //batt voltage /100 = V
uint8_t temp1; //-=20
uint8_t temp2; //-=20
} S25C31;

struct attribute((packed))A25C40 {
int16_t c1; //cell1 /1000
int16_t c2; //cell2
int16_t c3; //etc.
int16_t c4;
int16_t c5;
int16_t c6;
int16_t c7;
int16_t c8;
int16_t c9;
int16_t c10;
int16_t c11;
int16_t c12;
int16_t c13;
int16_t c14;
int16_t c15;
} S25C40;

struct attribute((packed))A23C3E {
int16_t i1; //mainframe temp
} S23C3E;

struct attribute((packed))A23CB0 {
//32 bytes;
uint8_t u1[10];
int16_t speed; // /1000
uint16_t averageSpeed; // /1000
uint32_t mileageTotal; // /1000
uint16_t mileageCurrent; // /100
uint16_t elapsedPowerOnTime; //time from power on, in seconds
int16_t mainframeTemp; // /10
uint8_t u2[8];
} S23CB0;

struct attribute((packed))A23C23 { //skip
uint8_t u1;
uint8_t u2;
uint8_t u3; //0x30
uint8_t u4; //0x09
uint16_t remainMileage; // /100
} S23C23;

struct attribute((packed))A23C3A {
uint16_t powerOnTime;
uint16_t ridingTime;
} S23C3A;

bool displayClear(byte ID = 1, bool force = false) {
volatile static uint8_t oldID = 0;

if ((oldID != ID) || force) {
display.clear();
oldID = ID;
return true;
} else return false;
}

void WDTint_() {
if (WDTcounts > 2) {
WDTcounts = 0;
resetFunc();
} else WDTcounts++;
}

void setup() {
XIAOMI_PORT.begin(115200);

uint8_t cfgID = EEPROM.read(0);
if (cfgID == 128) {
autoBig = EEPROM.read(1);
warnBatteryPercent = EEPROM.read(2);
bigMode = EEPROM.read(3);
bigWarn = EEPROM.read(4);
WheelSize = EEPROM.read(5);
cfgCruise = EEPROM.read(6);
cfgTailight = EEPROM.read(7);
cfgKERS = EEPROM.read(8);
} else {
EEPROM.put(0, 128);
EEPROM.put(1, autoBig);
EEPROM.put(2, warnBatteryPercent);
EEPROM.put(3, bigMode);
EEPROM.put(4, bigWarn);
EEPROM.put(5, WheelSize);
EEPROM.put(6, cfgCruise);
EEPROM.put(7, cfgTailight);
EEPROM.put(8, cfgKERS);
}

#ifdef DISPLAY_I2C
Wire.begin();
Wire.setClock(400000L);
display.begin(&Adafruit128x64, 0x3C);
//display.begin(&SH1106_128x64, 0x3C); // if you use 1.3" display
#endif
#ifdef DISPLAY_SPI
display.begin(&Adafruit128x64, PIN_CS, PIN_DC, PIN_RST);
//display.begin(&SH1106_128x64, PIN_CS, PIN_DC, PIN_RST); // if you use 1.3" display
#endif
// Uncomment to invert the screen. Useful for better vision on the yellow / blue screens
// display.displayRemap(true);
display.setFont(m365);
displayClear(0, true);
display.setCursor(0, 0);
display.print((char)0x20);
display.setFont(defaultFont);

uint32_t wait = millis() + 2000;
while ((wait > millis()) || ((wait - 1000 > millis()) && (S25C31.current != 0) && (S25C31.voltage != 0) && (S25C31.remainPercent != 0))) {
dataFSM();
if (_Query.prepared == 0) prepareNextQuery();
Message.Process();
}

if ((S25C31.current == 0) && (S25C31.voltage == 0) && (S25C31.remainPercent == 0)) {
displayClear(1);
display.set2X();
display.setCursor(0, 0);
display.println((const __FlashStringHelper *) noBUS1);
display.println((const __FlashStringHelper *) noBUS2);
display.println((const __FlashStringHelper *) noBUS3);
display.println((const __FlashStringHelper *) noBUS4);
display.set1X();
} else displayClear(1);

WDTcounts = 0;
WatchDog::init(WDTint_, 500);
}

void loop() { //cycle time w\o data exchange ~8 us :slight_smile:
dataFSM();

if (_Query.prepared == 0) prepareNextQuery();

if (_NewDataFlag == 1) {
_NewDataFlag = 0;
displayFSM();
}

Message.Process();
Message.ProcessBroadcast();

WDTcounts=0;
}

void showBatt(int percent, bool blinkIt) {
display.set1X();
display.setFont(defaultFont);
display.setCursor(0, 7);
if (bigWarn || (warnBatteryPercent == 0) || (percent > warnBatteryPercent) || ((warnBatteryPercent != 0) && (millis() % 1000 < 500))) {
display.print((char)0x81);
for (int i = 0; i < 19; i++) {
display.setCursor(5 + i * 5, 7);
if (blinkIt && (millis() % 1000 < 500))
display.print((char)0x83);
else
if (float(19) / 100 * percent > i)
display.print((char)0x82);
else
display.print((char)0x83);
}
display.setCursor(99, 7);
display.print((char)0x84);
if (percent < 100) display.print(' ');
if (percent < 10) display.print(' ');
display.print(percent);
display.print('%');
} else
for (int i = 0; i < 34; i++) {
display.setCursor(i * 5, 7);
display.print(' ');
}
}

void fsBattInfo() {
displayClear(6);

int16_t tmp_0, tmp_1;

display.setCursor(0, 0);
display.set1X();

tmp_0 = abs(S25C31.voltage) / 100; //voltage
tmp_1 = abs(S25C31.voltage) % 100;

if (tmp_0 < 10) display.print(' ');
display.print(tmp_0);
display.print('.');
if (tmp_1 < 10) display.print('0');
display.print(tmp_1);
display.print((const __FlashStringHelper *) l_v);
display.print(' ');

tmp_0 = abs(S25C31.current) / 100; //current
tmp_1 = abs(S25C31.current) % 100;

if (tmp_0 < 10) display.print(' ');
display.print(tmp_0);
display.print('.');
if (tmp_1 < 10) display.print('0');
display.print(tmp_1);
display.print((const __FlashStringHelper *) l_a);
display.print(' ');
if (S25C31.remainCapacity < 1000) display.print(' ');
if (S25C31.remainCapacity < 100) display.print(' ');
if (S25C31.remainCapacity < 10) display.print(' ');
display.print(S25C31.remainCapacity);
display.print((const __FlashStringHelper *) l_mah);
int temp;
temp = S25C31.temp1 - 20;
display.setCursor(9, 1);
display.print((const __FlashStringHelper *) l_t);
display.print("1: ");
if (temp < 10) display.print(' ');
display.print(temp);
display.print((char)0x80);
display.print("C");
display.setCursor(74, 1);
display.print((const __FlashStringHelper *) l_t);
display.print("2: ");
temp = S25C31.temp2 - 20;
if (temp < 10) display.print(' ');
display.print(temp);
display.print((char)0x80);
display.print("C");

int16_t v;
int16_t * ptr;
int * ptr2;
ptr = (int16_t*)&S25C40;
ptr2 = ptr + 5;
for (uint8_t i = 0; i < 5; i++) {
display.setCursor(5, 2 + i);
display.print(i);
display.print(": ");
v = *ptr / 1000;
display.print(v);
display.print('.');
v = *ptr % 1000;
if (v < 100) display.print('0');
if (v < 10) display.print('0');
display.print(v);
display.print((const __FlashStringHelper *) l_v);

display.setCursor(70, 2 + i);
display.print(i + 5); 
display.print(": ");
v = *ptr2 / 1000;
display.print(v);
display.print('.');
v = *ptr2 % 1000;
if (v < 100) display.print('0');
if (v < 10) display.print('0');
display.print(v);
display.print((const __FlashStringHelper *) l_v);

ptr++;
ptr2++;

}
}

void displayFSM() {
struct {
uint16_t curh;
uint16_t curl;
uint16_t vh;
uint16_t vl;
uint32_t sph;
uint16_t spl;
uint16_t milh;
uint16_t mill;
uint16_t Min;
uint16_t Sec;
uint16_t temp;
} m365_info;

int brakeVal = -1;
int throttleVal = -1;

int tmp_0, tmp_1;
long _speed;
long c_speed; //current speed
// CURRENT SPEED CALCULATE ALGORYTHM
if (S23CB0.speed < -10000) {// If speed if more than 32.767 km/h (32767)
c_speed = S23CB0.speed + 32768 + 32767; // calculate speed over 32.767 (hex 0x8000 and above) add 32768 and 32767 to conver to unsigned int
} else {
c_speed = abs(S23CB0.speed); }; //always + speed, even drive backwards :wink:
// 10 INCH WHEEL SIZE CALCULATE
if (WheelSize) {
_speed = (long) c_speed * 10 / 8.5; // 10" Whell
} else {
_speed = c_speed; //8,5" Whell
};

m365_info.sph = (uint32_t) abs(_speed) / 1000L; // speed (GOOD)
m365_info.spl = (uint16_t) c_speed % 1000 / 100;
#ifdef US_Version
m365_info.sph = m365_info.sph/1.609;
m365_info.spl = m365_info.spl/1.609;
#endif
m365_info.curh = abs(S25C31.current) / 100; //current
m365_info.curl = abs(S25C31.current) % 100;
m365_info.vh = abs(S25C31.voltage) / 100; //voltage
m365_info.vl = abs(S25C31.voltage) % 100;

if ((m365_info.sph > 1) && Settings) {
ShowBattInfo = false;
M365Settings = false;
Settings = false;
}

if ((c_speed <= 200) || Settings) {
if (S20C00HZ65.brake > 130)
brakeVal = 1;
else
if (S20C00HZ65.brake < 50)
brakeVal = -1;
else
brakeVal = 0;
if (S20C00HZ65.throttle > 150)
throttleVal = 1;
else
if (S20C00HZ65.throttle < 50)
throttleVal = -1;
else
throttleVal = 0;

if (((brakeVal == 1) && (throttleVal == 1) && !Settings) && ((oldBrakeVal != 1) || (oldThrottleVal != 1))) { // brake max + throttle max = menu on
  menuPos = 0;
  timer = millis() + LONG_PRESS;
  Settings = true;
}

if (M365Settings) {
  if ((throttleVal == 1) && (oldThrottleVal != 1) && (brakeVal == -1) && (oldBrakeVal == -1))                // brake min + throttle max = change menu value
  switch (sMenuPos) {
    case 0:
      cfgCruise = !cfgCruise;
EEPROM.put(6, cfgCruise);
      break;
    case 1:
      if (cfgCruise)
        prepareCommand(CMD_CRUISE_ON);
        else
        prepareCommand(CMD_CRUISE_OFF);
      break;
    case 2:
      cfgTailight = !cfgTailight;
EEPROM.put(7, cfgTailight);
      break;
    case 3:
      if (cfgTailight)
        prepareCommand(CMD_LED_ON);
        else
        prepareCommand(CMD_LED_OFF);
      break;
    case 4:
      switch (cfgKERS) {
        case 1:
          cfgKERS = 2;
    EEPROM.put(8, cfgKERS);
          break;
        case 2:
          cfgKERS = 0;
    EEPROM.put(8, cfgKERS);
          break;
        default: 
          cfgKERS = 1;
    EEPROM.put(8, cfgKERS);
      }
      break;
    case 5:
      switch (cfgKERS) { 
        case 1:
          prepareCommand(CMD_MEDIUM);
          break;
        case 2:
          prepareCommand(CMD_STRONG);
          break;
        default: 
          prepareCommand(CMD_WEAK);
      }
      break;
    case 6:
      WheelSize = !WheelSize;
      EEPROM.put(5, WheelSize);
break;
    case 7:
      oldBrakeVal = brakeVal;
      oldThrottleVal = throttleVal;
      timer = millis() + LONG_PRESS;
      M365Settings = false;
      break;
  } else
  if ((brakeVal == 1) && (oldBrakeVal != 1) && (throttleVal == -1) && (oldThrottleVal == -1)) {               // brake max + throttle min = change menu position
    if (sMenuPos < 7)
      sMenuPos++;
      else
      sMenuPos = 0;
    timer = millis() + LONG_PRESS;
  }

  if (displayClear(7)) sMenuPos = 0;
  display.set1X();
  display.setCursor(0, 0);

  if (sMenuPos == 0)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) M365CfgScr1);
  if (cfgCruise)
    display.print((const __FlashStringHelper *) l_On);
    else
    display.print((const __FlashStringHelper *) l_Off);

  display.setCursor(0, 1);

  if (sMenuPos == 1)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) M365CfgScr2);

  display.setCursor(0, 2);

  if (sMenuPos == 2)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) M365CfgScr3);
  if (cfgTailight)
    display.print((const __FlashStringHelper *) l_Yes);
    else
    display.print((const __FlashStringHelper *) l_No);

  display.setCursor(0, 3);

  if (sMenuPos == 3)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) M365CfgScr4);

  display.setCursor(0, 4);

  if (sMenuPos == 4)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) M365CfgScr5);
  switch (cfgKERS) {
    case 1:
      display.print((const __FlashStringHelper *) l_Medium);
      break;
    case 2:
      display.print((const __FlashStringHelper *) l_Strong);
      break;
    default:
      display.print((const __FlashStringHelper *) l_Weak);
      break;
  }

display.setCursor(0, 5);

  if (sMenuPos == 5)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) M365CfgScr6);

display.setCursor(0, 6);

if (sMenuPos == 6)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) M365CfgScr7);
   if(WheelSize) {
      display.print((const __FlashStringHelper *) l_10inch);
 }else{
      display.print((const __FlashStringHelper *) l_85inch);
  }  
  //display.setCursor(0, 7);

  /*for (int i = 0; i < 25; i++) {
    display.setCursor(i * 5, 6);
    display.print('-');
  }*/

  display.setCursor(0, 7);
  
  if (sMenuPos == 7)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) M365CfgScr8);

  oldBrakeVal = brakeVal;
  oldThrottleVal = throttleVal;

  return;
} else
if (ShowBattInfo) {
  if ((brakeVal == 1) && (oldBrakeVal != 1) && (throttleVal == -1) && (oldThrottleVal == -1)) {
    oldBrakeVal = brakeVal;
    oldThrottleVal = throttleVal;
    timer = millis() + LONG_PRESS;
    ShowBattInfo = false;
    return;
  }

  fsBattInfo();

  display.setCursor(0, 7);
  display.print((const __FlashStringHelper *) battScr);

  oldBrakeVal = brakeVal;
  oldThrottleVal = throttleVal;

  return;
} else
if (Settings) {
  if ((brakeVal == 1) && (oldBrakeVal == 1) && (throttleVal == -1) && (oldThrottleVal == -1) && (timer != 0))
    if (millis() > timer) {
      Settings = false;
      return;
    }

  if ((throttleVal == 1) && (oldThrottleVal != 1) && (brakeVal == -1) && (oldBrakeVal == -1))                // brake min + throttle max = change menu value
  switch (menuPos) {
    case 0:
      autoBig = !autoBig;
      break;
    case 1:
      switch (bigMode) {
        case 0:
          bigMode = 1;
          break;
        default:
          bigMode = 0;
      }
      break;
    case 2:
      switch (warnBatteryPercent) {
        case 0:
          warnBatteryPercent = 5;
          break;
        case 5:
          warnBatteryPercent = 10;
          break;
        case 10:
          warnBatteryPercent = 15;
          break;
        default:
          warnBatteryPercent = 0;
      }
      break;
    case 3:
      bigWarn = !bigWarn;
      break;
    case 4:
      ShowBattInfo = true;
      break;
    case 5:
      M365Settings = true;
      break;
    case 6:
      EEPROM.put(1, autoBig);
      EEPROM.put(2, warnBatteryPercent);
      EEPROM.put(3, bigMode);
      EEPROM.put(4, bigWarn);
      Settings = false;
      break;
  } else
  if ((brakeVal == 1) && (oldBrakeVal != 1) && (throttleVal == -1) && (oldThrottleVal == -1)) {               // brake max + throttle min = change menu position
    if (menuPos < 6)
      menuPos++;
      else
      menuPos = 0;
    timer = millis() + LONG_PRESS;
  }

  displayClear(2);

  display.set1X();
  display.setCursor(0, 0);

  if (menuPos == 0)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) confScr1);
  if (autoBig)
    display.print((const __FlashStringHelper *) l_Yes);
    else
    display.print((const __FlashStringHelper *) l_No);

  display.setCursor(0, 1);

  if (menuPos == 1)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) confScr2);
  switch (bigMode) {
    case 1:
      display.print((const __FlashStringHelper *) confScr2b);
      break;
    default:
      display.print((const __FlashStringHelper *) confScr2a);
  }

  display.setCursor(0, 2);

  if (menuPos == 2)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) confScr3);
  switch (warnBatteryPercent) {
    case 5:
      display.print(" 5%");
      break;
    case 10:
      display.print("10%");
      break;
    case 15:
      display.print("15%");
      break;
    default:
      display.print((const __FlashStringHelper *) l_Off);
      break;
  }

  display.setCursor(0, 3);

  if (menuPos == 3)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) confScr4);
  if (bigWarn)
    display.print((const __FlashStringHelper *) l_Yes);
    else
    display.print((const __FlashStringHelper *) l_No);

  display.setCursor(0, 4);

  if (menuPos == 4)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) confScr5);

  display.setCursor(0, 5);

  if (menuPos == 5)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) confScr6);

  display.setCursor(0, 6);

  for (uint8_t i = 0; i < 25; i++) {
    display.setCursor(i * 5, 6);
    display.print('-');
  }

  display.setCursor(0, 7);

  if (menuPos == 6)
    display.print((char)0x7E);
    else
    display.print(" ");

  display.print((const __FlashStringHelper *) confScr7);

  display.setCursor(0, 8);

  if (menuPos == 7)
    display.print((char)0x7E);
  else
    display.print(" ");

  oldBrakeVal = brakeVal;
  oldThrottleVal = throttleVal;

  return;
} else
if ((throttleVal == 1) && (oldThrottleVal != 1) && (brakeVal == -1) && (oldBrakeVal == -1)) {
  displayClear(3);

  display.set1X();
  display.setFont(defaultFont);
  display.setCursor(0, 0);
  display.print((const __FlashStringHelper *) infoScr1);
  display.print(':');
  display.setFont(stdNumb);
  display.setCursor(15, 1);
  tmp_0 = S23CB0.mileageTotal / 1000;
  tmp_1 = (S23CB0.mileageTotal % 1000) / 10;
  if (tmp_0 < 1000) display.print(' ');
  if (tmp_0 < 100) display.print(' ');
  if (tmp_0 < 10) display.print(' ');
  display.print(tmp_0);
  display.print('.');
  if (tmp_1 < 10) display.print('0');
  display.print(tmp_1);
  display.setFont(defaultFont);
  display.print((const __FlashStringHelper *) l_km);

  display.setCursor(0, 5);
  display.print((const __FlashStringHelper *) infoScr2);
  display.print(':');
  display.setFont(stdNumb);
  display.setCursor(15, 6);
  tmp_0 = S23C3A.powerOnTime / 60;
  tmp_1 = S23C3A.powerOnTime % 60;
  if (tmp_0 < 100) display.print(' '); 
  if (tmp_0 < 10) display.print(' ');
  display.print(tmp_0);
  display.print(':');
  if (tmp_1 < 10) display.print('0');
  display.print(tmp_1);

  return;
}

oldBrakeVal = brakeVal;
oldThrottleVal = throttleVal;

}

if (bigWarn && (((warnBatteryPercent > 0) && (S25C31.remainPercent <= warnBatteryPercent)) && (millis() % 2000 < 700))) {
if (displayClear(4)) {
display.setFont(m365);
display.setCursor(0, 0);
display.print((char)0x21);
display.setFont(defaultFont);
}
} else
if ((m365_info.sph > 1) && (autoBig)) {
displayClear(5);
display.set1X();

  switch (bigMode) {
    case 1:
      display.setFont(bigNumb);
      tmp_0 = m365_info.curh / 10;
      tmp_1 = m365_info.curh % 10;
      display.setCursor(2, 0);
      if (tmp_0 > 0)
        display.print(tmp_0);
        else
        display.print((char)0x3B);
      display.setCursor(32, 0);
      display.print(tmp_1);
      tmp_0 = m365_info.curl / 10;
      tmp_1 = m365_info.curl % 10;
      display.setCursor(75, 0);
      display.print(tmp_0);
      display.setCursor(108, 0);
      display.setFont(stdNumb);
      display.print(tmp_1);
      display.setFont(defaultFont);
      if ((S25C31.current >= 0) || ((S25C31.current < 0) && (millis() % 1000 < 500))) {
        display.set2X();
        display.setCursor(108, 4);
        display.print((const __FlashStringHelper *) l_a);
      }
      display.set1X();
      display.setCursor(64, 5);
      display.print((char)0x85);
      break;
    default:
      display.setFont(bigNumb);
      tmp_0 = m365_info.sph / 10;
      tmp_1 = m365_info.sph % 10;
      display.setCursor(2, 0);
      if (tmp_0 > 0)
        display.print(tmp_0);
        else
        display.print((char)0x3B);
      display.setCursor(32, 0);
      display.print(tmp_1);
      display.setCursor(75, 0);
      display.print(m365_info.spl);
      display.setCursor(106, 0);
      display.print((char)0x3A);
      display.setFont(defaultFont);
      display.set1X();
      display.setCursor(64, 5);
      display.print((char)0x85);
  }
  showBatt(S25C31.remainPercent, S25C31.current < 0);
} else {
  if ((S25C31.current < -100) && (c_speed <= 200)) {
    fsBattInfo();
  } else {
    displayClear(0);

    m365_info.milh = S23CB0.mileageCurrent / 100;   //mileage
    m365_info.mill = S23CB0.mileageCurrent % 100;
    m365_info.Min = S23C3A.ridingTime / 60;         //riding time
    m365_info.Sec = S23C3A.ridingTime % 60;
    m365_info.temp = S23CB0.mainframeTemp / 10;     //temperature

#ifdef US_Version
m365_info.milh = m365_info.milh/1.609;
m365_info.mill = m365_info.mill/1.609;
m365_info.temp = m365_info.temp*9/5+32;
#endif
display.set1X();
display.setFont(stdNumb);
display.setCursor(0, 0);

    if (m365_info.sph < 10) display.print(' ');
    display.print(m365_info.sph);
    display.print('.');
    display.print(m365_info.spl);
    display.setFont(defaultFont);
    display.print((const __FlashStringHelper *) l_kmh);
    display.setFont(stdNumb);

    display.setCursor(95, 0);

    if (m365_info.temp < 10) display.print(' ');
    display.print(m365_info.temp);
    display.setFont(defaultFont);
    display.print((char)0x80);
    display.print((const __FlashStringHelper *) l_c);
    display.setFont(stdNumb);

    display.setCursor(0, 2);

    if (m365_info.milh < 10) display.print(' ');
    display.print(m365_info.milh);
    display.print('.');
    if (m365_info.mill < 10) display.print('0');
    display.print(m365_info.mill);
    display.setFont(defaultFont);
    display.print((const __FlashStringHelper *) l_km);
    display.setFont(stdNumb);

    display.setCursor(0, 4);

    if (m365_info.Min < 10) display.print('0');
    display.print(m365_info.Min);
    display.print(':');
    if (m365_info.Sec < 10) display.print('0');
    display.print(m365_info.Sec);

    display.setCursor(68, 4);

    if (m365_info.curh < 10) display.print(' ');
    display.print(m365_info.curh);
    display.print('.');
    if (m365_info.curl < 10) display.print('0');
    display.print(m365_info.curl);
    display.setFont(defaultFont);
    display.print((const __FlashStringHelper *) l_a);
  }

  showBatt(S25C31.remainPercent, S25C31.current < 0);
}

}

// -----------------------------------------------------------------------------------------------------------

void dataFSM() {
static uint8_t step = 0, _step = 0, entry = 1;
static uint32_t beginMillis;
static uint8_t Buf[RECV_BUFLEN]; // char
static uint8_t* _bufPtr;
_bufPtr = (uint8_t*)&Buf; // char

switch (step) {
case 0: //search header sequence
while (XIAOMI_PORT.available() >= 2)
if (XIAOMI_PORT.read() == 0x55 && XIAOMI_PORT.peek() == 0xAA) {
XIAOMI_PORT.read(); //discard second part of header
step = 1;
break;
}
break;
case 1: //preamble complete, receive body
static uint8_t readCounter;
static uint16_t _cs;
static uint8_t* bufPtr;
static uint8_t* asPtr; //
uint8_t bt;
if (entry) { // init variables
memset((void*)&AnswerHeader, 0, sizeof(AnswerHeader));
bufPtr = _bufPtr;
readCounter = 0;
beginMillis = millis();
asPtr = (uint8_t*)&AnswerHeader; //pointer onto header structure
_cs = 0xFFFF;
}
if (readCounter >= RECV_BUFLEN) { //overrun
step = 2;
break;
}
if (millis() - beginMillis >= RECV_TIMEOUT) { //timeout
step = 2;
break;
}

  while (XIAOMI_PORT.available()) {               //read available bytes from port-buffer
    bt = XIAOMI_PORT.read();
    readCounter++;
    if (readCounter <= sizeof(AnswerHeader)) {    //separate header into header-structure
      *asPtr++ = bt;
      _cs -= bt;
    }
    if (readCounter > sizeof(AnswerHeader)) {     //now begin read data
      *bufPtr++ = bt;
      if(readCounter < (AnswerHeader.len + 3)) _cs -= bt;
    }
    beginMillis = millis();                     //reset timeout
  }

  if (AnswerHeader.len == (readCounter - 4)) {    //if len in header == current received len
    uint16_t cs;
    uint16_t* ipcs;
    ipcs = (uint16_t*)(bufPtr-2);
    cs = *ipcs;
    if(cs != _cs) {   //check cs
      step = 2;
      break;
    }
    //here cs is ok, header in AnswerHeader, data in _bufPtr
    processPacket(_bufPtr, readCounter);

    step = 2;
    break;
  }
  break; //case 1:
case 2:  //end of receiving data
  step = 0;
  break;

}

if (_step != step) {
_step = step;
entry = 1;
} else entry = 0;
}

void processPacket(uint8_t* data, uint8_t len) {
uint8_t RawDataLen;
RawDataLen = len - sizeof(AnswerHeader) - 2;//(crc)

switch (AnswerHeader.addr) { //store data into each other structure
case 0x20: //0x20
switch (AnswerHeader.cmd) {
case 0x00:
switch (AnswerHeader.hz) {
case 0x64: //BLE ask controller
break;
case 0x65:
if (_Query.prepared == 1 && !_Hibernate) writeQuery();

          memcpy((void*)& S20C00HZ65, (void*)data, RawDataLen);

          break;
        default: //no suitable hz
          break;
      }
      break;
    case 0x1A:
      break;
    case 0x69:
      break;
    case 0x3E:
      break;
    case 0xB0:
      break;
    case 0x23:
      break;
    case 0x3A:
      break;
    case 0x7C:
      break;
    default: //no suitable cmd
      break;
  }
  break;
case 0x21:
  switch (AnswerHeader.cmd) {
    case 0x00:
    switch(AnswerHeader.hz) {
      case 0x64: //answer to BLE
        memcpy((void*)& S21C00HZ64, (void*)data, RawDataLen);
        break;
      }
      break;
  default:
    break;
  }
  break;
case 0x22:
  switch (AnswerHeader.cmd) {
    case 0x3B:
      break;
    case 0x31:
      break;
    case 0x20:
      break;
    case 0x1B:
      break;
    case 0x10:
      break;
    default:
      break;
  }
  break;
case 0x23:
  switch (AnswerHeader.cmd) {
    case 0x17:
      break;
    case 0x1A:
      break;
    case 0x69:
      break;
    case 0x3E: //mainframe temperature
      if (RawDataLen == sizeof(A23C3E)) memcpy((void*)& S23C3E, (void*)data, RawDataLen);
      break;
    case 0xB0: //speed, average speed, mileage total, mileage current, power on time, mainframe temp
      if (RawDataLen == sizeof(A23CB0)) memcpy((void*)& S23CB0, (void*)data, RawDataLen);
      break;
    case 0x23: //remain mileage
      if (RawDataLen == sizeof(A23C23)) memcpy((void*)& S23C23, (void*)data, RawDataLen);
      break;
    case 0x3A: //power on time, riding time
      if (RawDataLen == sizeof(A23C3A)) memcpy((void*)& S23C3A, (void*)data, RawDataLen);
      break;
    case 0x7C:
      break;
    case 0x7B:
      break;
    case 0x7D:
      break;
    default:
      break;
  }
  break;          
case 0x25:
  switch (AnswerHeader.cmd) {
    case 0x40: //cells info
      if(RawDataLen == sizeof(A25C40)) memcpy((void*)& S25C40, (void*)data, RawDataLen);
      break;
    case 0x3B:
      break;
    case 0x31: //capacity, remain persent, current, voltage
      if (RawDataLen == sizeof(A25C31)) memcpy((void*)& S25C31, (void*)data, RawDataLen);
      break;
    case 0x20:
      break;
    case 0x1B:
      break;
    case 0x10:
      break;
    default:
      break;
    }
    break;
  default:
    break;

}

for (uint8_t i = 0; i < sizeof(_commandsWeWillSend); i++)
if (AnswerHeader.cmd == _q[_commandsWeWillSend[i]]) {
_NewDataFlag = 1;
break;
}
}

void prepareNextQuery() {
static uint8_t index = 0;

_Query._dynQueries[0] = 1;
_Query._dynQueries[1] = 8;
_Query._dynQueries[2] = 10;
_Query._dynQueries[3] = 14;
_Query._dynSize = 4;

if (preloadQueryFromTable(_Query._dynQueries[index]) == 0) _Query.prepared = 1;

index++;

if (index >= _Query._dynSize) index = 0;
}

uint8_t preloadQueryFromTable(unsigned char index) {
uint8_t* ptrBuf;
uint8_t* pp; //pointer preamble
uint8_t* ph; //pointer header
uint8_t* pe; //pointer end

uint8_t cmdFormat;
uint8_t hLen; //header length
uint8_t eLen; //ender length

if (index >= sizeof(_q)) return 1; //unknown index

if (_Query.prepared != 0) return 2; //if query not send yet

cmdFormat = pgm_read_byte_near(_f + index);

pp = (uint8_t*)&_h0;
ph = NULL;
pe = NULL;

switch(cmdFormat) {
case 1: //h1 only
ph = (uint8_t*)&_h1;
hLen = sizeof(_h1);
pe = NULL;
break;
case 2: //h2 + end20
ph = (uint8_t*)&_h2;
hLen = sizeof(_h2);

  //copies last known throttle & brake values
  _end20t.hz = 0x02;
  _end20t.th = S20C00HZ65.throttle;
  _end20t.br = S20C00HZ65.brake;
  pe = (uint8_t*)&_end20t;
  eLen = sizeof(_end20t);
  break;

}

ptrBuf = (uint8_t*)&_Query.buf;

memcpy_P((void*)ptrBuf, (void*)pp, sizeof(_h0)); //copy preamble
ptrBuf += sizeof(_h0);

memcpy_P((void*)ptrBuf, (void*)ph, hLen); //copy header
ptrBuf += hLen;

memcpy_P((void*)ptrBuf, (void*)(_q + index), 1); //copy query
ptrBuf++;

memcpy_P((void*)ptrBuf, (void*)(_l + index), 1); //copy expected answer length
ptrBuf++;

if (pe != NULL) {
memcpy((void*)ptrBuf, (void*)pe, eLen); //if needed - copy ender
ptrBuf+= hLen;
}

//unsigned char
_Query.DataLen = ptrBuf - (uint8_t*)&_Query.buf[2]; //calculate length of data in buf, w\o preamble and cs
_Query.cs = calcCs((uint8_t*)&_Query.buf[2], _Query.DataLen); //calculate cs of buffer

return 0;
}

void prepareCommand(uint8_t cmd) {
uint8_t* ptrBuf;

_cmd.len = 4;
_cmd.addr = 0x20;
_cmd.rlen = 0x03;

switch(cmd){
case CMD_CRUISE_ON: //0x7C, 0x01, 0x00
_cmd.param = 0x7C;
_cmd.value = 1;
break;
case CMD_CRUISE_OFF: //0x7C, 0x00, 0x00
_cmd.param = 0x7C;
_cmd.value = 0;
break;
case CMD_LED_ON: //0x7D, 0x02, 0x00
_cmd.param = 0x7D;
_cmd.value = 2;
break;
case CMD_LED_OFF: //0x7D, 0x00, 0x00
_cmd.param = 0x7D;
_cmd.value = 0;
break;
case CMD_WEAK: //0x7B, 0x00, 0x00
_cmd.param = 0x7B;
_cmd.value = 0;
break;
case CMD_MEDIUM: //0x7B, 0x01, 0x00
_cmd.param = 0x7B;
_cmd.value = 1;
break;
case CMD_STRONG: //0x7B, 0x02, 0x00
_cmd.param = 0x7B;
_cmd.value = 2;
break;
default:
return; //undefined command - do nothing
break;
}
ptrBuf = (uint8_t*)&_Query.buf;

memcpy_P((void*)ptrBuf, (void*)_h0, sizeof(_h0)); //copy preamble
ptrBuf += sizeof(_h0);

memcpy((void*)ptrBuf, (void*)&_cmd, sizeof(_cmd)); //copy command body
ptrBuf += sizeof(_cmd);

//unsigned char
_Query.DataLen = ptrBuf - (uint8_t*)&_Query.buf[2]; //calculate length of data in buf, w\o preamble and cs
_Query.cs = calcCs((uint8_t*)&_Query.buf[2], _Query.DataLen); //calculate cs of buffer

_Query.prepared = 1;
}

void writeQuery() {
RX_DISABLE;
XIAOMI_PORT.write((uint8_t*)&_Query.buf, _Query.DataLen + 2); //DataLen + length of preamble
XIAOMI_PORT.write((uint8_t*)&_Query.cs, 2);
RX_ENABLE;
_Query.prepared = 0;
}

uint16_t calcCs(uint8_t* data, uint8_t len) {
uint16_t cs = 0xFFFF;
for (uint8_t i = len; i > 0; i--) cs -= *data++;

return cs;
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.