├── Plot.h ├── LICENSE ├── SX1276.h ├── README.md ├── Plot.cpp ├── SSD1306Wire.h ├── SX1276.cpp ├── OLEDDisplay.h ├── OLEDDisplay.cpp ├── ESP32_CRSFSniffer.ino └── OLEDDisplayFonts.h /Plot.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | class PlotClass 4 | { 5 | private: 6 | SSD1306Wire *Display; 7 | char Name[33]; 8 | float *Values; 9 | uint32_t StartPos = 0; 10 | uint32_t Entries = 0; 11 | uint32_t GroupSize = 0; 12 | uint32_t Groups = 0; 13 | 14 | public: 15 | PlotClass(SSD1306Wire *disp, const char *name, uint32_t groupSize, uint32_t groups); 16 | void AddSample(float value); 17 | void SetSample(int pos, float value); 18 | float GetSample(int pos); 19 | void Clear(); 20 | void DrawFullPlot(int x, int y, int w, int h, bool scatter = true, bool desc = true); 21 | uint32_t ValueCount = 0; 22 | 23 | private: 24 | void DrawGrid(int x, int y, int w, int h, int *xStart, int *yStart, int *xSpan, int *ySpan); 25 | void CalcStats(float *minValue, float *maxValue, bool scatter); 26 | }; 27 | 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 g3gg0.de 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SX1276.h: -------------------------------------------------------------------------------- 1 | #ifndef SX1276_H 2 | #define SX1276_H 3 | 4 | #include 5 | #include 6 | 7 | #define SX1276_DEFAULT_SS_PIN SS 8 | #define SX1276_DEFAULT_RESET_PIN RST_LoRa 9 | #define SX1276_DEFAULT_DIO0_PIN DIO0 10 | 11 | #define PA_OUTPUT_PA_BOOST_PIN 1 12 | #define PA_OUTPUT_RFO_PIN 0 13 | 14 | 15 | 16 | class SX1276Class { 17 | public: 18 | SX1276Class(); 19 | 20 | int begin(); 21 | void init(); 22 | void setPins(int ss = SX1276_DEFAULT_SS_PIN, int reset = SX1276_DEFAULT_RESET_PIN, int dio0 = SX1276_DEFAULT_DIO0_PIN); 23 | void setSPIFrequency(uint32_t frequency); 24 | 25 | uint8_t readRegister(uint8_t address); 26 | void writeRegister(uint8_t address, uint8_t value); 27 | uint8_t singleTransfer(uint8_t address, uint8_t value); 28 | 29 | void writePayloadLength(uint8_t length); 30 | void writeBitrate(uint32_t rate); 31 | void writeFreqDev(uint32_t dev); 32 | void writeRxBw(uint32_t bw); 33 | void writeAfcBw(uint32_t bw); 34 | void writeAfc(uint32_t freq); 35 | void writeFreq(uint64_t freq); 36 | void writeRxConfig(uint8_t cfg); 37 | 38 | int32_t readAfc(); 39 | int32_t readFei(); 40 | uint8_t readRssi(); 41 | uint8_t readFifo(); 42 | void setStandby(); 43 | void setSleep(); 44 | void setRx(); 45 | 46 | private: 47 | uint32_t delta(uint32_t ref, uint32_t value); 48 | SPISettings _spiSettings; 49 | int _ss; 50 | int _reset; 51 | int _dio0; 52 | }; 53 | 54 | 55 | #endif 56 | 57 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CRSFSniffer 2 | 3 | This project is about analyzing the functionality of RC control links on the 868 Mhz band. The code is designed for use with a Heltec LoRa ESP32 with SX127**6** (e.g. https://www.aliexpress.com/item/33018609928.html) 4 | You can find more details on my blog: https://www.g3gg0.de/wordpress/fpv/fpv-analysis-of-tbs-crossfire/ 5 | 6 | ## preamble 7 | 8 | **PROJECT IS WIP, RESULTS MAY VARY, USE AT YOUR OWN RISK** 9 | 10 | This project is solely for white-hat scientific/educational hacking. By no means do we want to piss someone off. 11 | 12 | ## getting started with Arduino IDE 13 | 14 | The code is written to be flashed with the [Arduino IDE](https://www.arduino.cc/en/software) onto the LoRa ESP32. 15 | 16 | First, install the IDE. 17 | 18 | Then you need to add support for ESP32 based boards. To do so, got into `File` -> `Preferences`. In `Additional Boards Manager URLs` add the URL `https://dl.espressif.com/dl/package_esp32_index.json`. If you already have some other URL listed there, separate the URLs with a comma. 19 | 20 | Now go to `Tools` -> `Board: XYZ` -> `Board Manager`. Search for `esp32` and install the package. 21 | 22 | Go to `Tools` -> `Board: XYZ` -> `ESP32 Arduino`, scroll down the list and select `Heltec WiFi LoRa 32(V2)`. 23 | 24 | Now you need to adjust one header file. 25 | 26 | Go to `C:\Users\\AppData\Local\Arduino15\packages\esp32\hardware\esp32\\cores\esp32` and open the file `esp32-hal.h` in an editor of your choice. 27 | Add the line `#define CONFIG_DISABLE_HAL_LOCKS 1` to where the other `#define`s are located. 28 | 29 | Now you are ready to flash the code. 30 | 31 | ## technical documentation 32 | 33 | For now there is no technical documentation. Will get updated soon. 34 | 35 | ## development progress documentation 36 | 37 | Here some videos showing progress: 38 | 39 | ### First steps 40 | [![Video](http://img.youtube.com/vi/WCkuwO97zfM/0.jpg)](http://www.youtube.com/watch?v=WCkuwO97zfM "Video") 41 | 42 | ### Display channel values 43 | [![Video](http://img.youtube.com/vi/pvUvxsUui7U/0.jpg)](http://www.youtube.com/watch?v=pvUvxsUui7U "Video") 44 | 45 | ### Add hopping support 46 | [![Video](http://img.youtube.com/vi/Tf6I0-eUbNs/0.jpg)](http://www.youtube.com/watch?v=Tf6I0-eUbNs "Video") 47 | 48 | ### Scan hopping sequence 49 | [![Video](http://img.youtube.com/vi/1E_6FAqVi6U/0.jpg)](http://www.youtube.com/watch?v=1E_6FAqVi6U "Video") 50 | 51 | ### Further analysis and plots 52 | [![Video](http://img.youtube.com/vi/GCU4Pnw3n-c/0.jpg)](http://www.youtube.com/watch?v=GCU4Pnw3n-c "Video") 53 | -------------------------------------------------------------------------------- /Plot.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "SSD1306Wire.h" 3 | #include "Plot.h" 4 | 5 | PlotClass::PlotClass(SSD1306Wire *disp, const char *name, uint32_t groupSize, uint32_t groups) 6 | { 7 | Display = disp; 8 | strncpy(Name, name, 32); 9 | GroupSize = groupSize; 10 | Groups = groups; 11 | ValueCount = GroupSize * Groups; 12 | Values = new float[ValueCount]; 13 | } 14 | 15 | void PlotClass::AddSample(float value) 16 | { 17 | if(Entries < ValueCount) 18 | { 19 | Values[StartPos + Entries] = value; 20 | Entries++; 21 | } 22 | else 23 | { 24 | Values[StartPos] = value; 25 | StartPos = (StartPos + 1) % (ValueCount); 26 | } 27 | } 28 | 29 | float PlotClass::GetSample(int pos) 30 | { 31 | if(pos >= ValueCount) 32 | { 33 | return 0; 34 | } 35 | 36 | return Values[pos]; 37 | } 38 | 39 | void PlotClass::SetSample(int pos, float value) 40 | { 41 | if(pos >= ValueCount) 42 | { 43 | return; 44 | } 45 | 46 | Values[pos] = value; 47 | if(pos >= Entries) 48 | { 49 | Entries = pos + 1; 50 | } 51 | } 52 | 53 | void PlotClass::Clear() 54 | { 55 | StartPos = 0; 56 | Entries = 0; 57 | } 58 | 59 | void PlotClass::CalcStats(float *minValue, float *maxValue, bool scatter) 60 | { 61 | *minValue = 999999; 62 | *maxValue = -999999; 63 | 64 | if(scatter) 65 | { 66 | for(uint32_t pos = 0; pos < Entries; pos++) 67 | { 68 | float value = Values[(StartPos + pos) % (ValueCount)]; 69 | 70 | if(value < *minValue) 71 | { 72 | *minValue = value; 73 | } 74 | if(value > *maxValue) 75 | { 76 | *maxValue = value; 77 | } 78 | } 79 | } 80 | else 81 | { 82 | for(uint32_t pos = 0; pos < Entries; pos += GroupSize) 83 | { 84 | float avgValue = 0; 85 | int entries = 0; 86 | for(uint32_t grp = 0; grp < GroupSize; grp++) 87 | { 88 | if(pos + grp < Entries) 89 | { 90 | avgValue += Values[(StartPos + pos + grp) % (ValueCount)]; 91 | entries++; 92 | } 93 | } 94 | avgValue /= entries; 95 | if(avgValue < *minValue) 96 | { 97 | *minValue = avgValue; 98 | } 99 | if(avgValue > *maxValue) 100 | { 101 | *maxValue = avgValue; 102 | } 103 | } 104 | } 105 | 106 | float delta = *maxValue - *minValue; 107 | float extra = delta/5; 108 | 109 | *maxValue += extra; 110 | *minValue -= extra; 111 | } 112 | 113 | void PlotClass::DrawGrid(int x, int y, int w, int h, int *xStart, int *yStart, int *xSpan, int *ySpan) 114 | { 115 | Display->drawLine(x+2, y, x+2, y+h-1-2); 116 | Display->drawLine(x+2, y, x, y+2); 117 | Display->drawLine(x+2, y+h-1-2, x+w-1, y+h-1-2); 118 | Display->drawLine(x+w-1, y+h-1-2, x+w-1-2, y+h-1); 119 | 120 | *xStart = x+4; 121 | *yStart = y; 122 | *xSpan = w-4; 123 | *ySpan = h-4; 124 | } 125 | 126 | void PlotClass::DrawFullPlot(int x, int y, int w, int h, bool scatter, bool desc) 127 | { 128 | float maxValue = 0; 129 | float minValue = 0; 130 | 131 | CalcStats(&minValue, &maxValue, scatter); 132 | 133 | int xStart = 0; 134 | int yStart = 0; 135 | int xSpan = 0; 136 | int ySpan = 0; 137 | DrawGrid(x, y, w, h, &xStart, &yStart, &xSpan, &ySpan); 138 | 139 | if(scatter) 140 | { 141 | for(uint32_t pos = 0; pos < Entries; pos++) 142 | { 143 | float value = Values[(StartPos + pos) % (ValueCount)]; 144 | float relValue = (value - minValue) / (maxValue - minValue); 145 | 146 | uint32_t xPos = xStart + ((float)pos / GroupSize) * xSpan / (float)Groups; 147 | uint32_t yPos = yStart + ySpan - relValue * ySpan; 148 | 149 | Display->setPixel(xPos, yPos); 150 | } 151 | } 152 | else 153 | { 154 | for(uint32_t pos = 0; pos < Entries; pos += GroupSize) 155 | { 156 | float avgValue = 0; 157 | int entries = 0; 158 | for(uint32_t grp = 0; grp < GroupSize; grp++) 159 | { 160 | if(pos + grp < Entries) 161 | { 162 | avgValue += Values[(StartPos + pos + grp) % (ValueCount)]; 163 | entries++; 164 | } 165 | } 166 | avgValue /= entries; 167 | float relValue = (avgValue - minValue) / (maxValue - minValue); 168 | 169 | uint32_t xPos = xStart + ((float)pos / GroupSize) * xSpan / (float)Groups; 170 | uint32_t yPos = yStart + ySpan - relValue * ySpan; 171 | 172 | Display->setPixel(xPos, yPos); 173 | } 174 | } 175 | 176 | char msg[33]; 177 | Display->setFont(ArialMT_Plain_10); 178 | snprintf(msg, 32, "%2.2f", maxValue); 179 | 180 | /* draw a black halo around the bright text */ 181 | Display->setColor(BLACK); 182 | for(int mod = 0; mod <9; mod++) 183 | { 184 | Display->drawString(x+8 -1 + mod/3, y - 1 + mod %3, msg); 185 | } 186 | Display->setColor(WHITE); 187 | Display->drawString(x+8, y, msg); 188 | 189 | snprintf(msg, 32, "%2.2f", minValue); 190 | 191 | /* draw a black halo around the bright text */ 192 | Display->setColor(BLACK); 193 | for(int mod = 0; mod <9; mod++) 194 | { 195 | Display->drawString(x+w+4 -1 + mod/3, y+4 - 1 + mod %3, msg); 196 | } 197 | Display->setColor(WHITE); 198 | Display->drawString(x+8, y+ySpan-10, msg); 199 | 200 | if(desc) 201 | { 202 | Display->setFont(ArialMT_Plain_16); 203 | Display->drawString(x+w+4, y+4, Name); 204 | 205 | Display->setFont(ArialMT_Plain_10); 206 | snprintf(msg, 32, "(# %d)", Entries); 207 | Display->drawString(x+w+4, y+16+4, msg); 208 | } 209 | } 210 | 211 | 212 | -------------------------------------------------------------------------------- /SSD1306Wire.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn 5 | * Copyright (c) 2018 by Fabrice Weinberg 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | * 25 | * ThingPulse invests considerable time and money to develop these open source libraries. 26 | * Please support us by buying our products (and not the clones) from 27 | * https://thingpulse.com 28 | * 29 | */ 30 | 31 | #ifndef SSD1306Wire_h 32 | #define SSD1306Wire_h 33 | 34 | #include "OLEDDisplay.h" 35 | #include 36 | 37 | 38 | class SSD1306Wire : public OLEDDisplay { 39 | private: 40 | uint8_t _address; 41 | uint8_t _sda; 42 | uint8_t _scl; 43 | uint8_t _rst; 44 | bool _doI2cAutoInit = false; 45 | 46 | public: 47 | SSD1306Wire(uint8_t _address, uint8_t _sda, uint8_t _scl, uint8_t _rst, OLEDDISPLAY_GEOMETRY g = GEOMETRY_128_64) { 48 | setGeometry(g); 49 | 50 | this->_address = _address; 51 | this->_sda = _sda; 52 | this->_scl = _scl; 53 | this->_rst = _rst; 54 | } 55 | 56 | 57 | bool connect() { 58 | pinMode(_rst,OUTPUT); 59 | digitalWrite(_rst, LOW); 60 | delay(50); 61 | digitalWrite(_rst, HIGH); 62 | 63 | Wire.begin(this->_sda, this->_scl); 64 | // Let's use ~700khz if ESP8266 is in 160Mhz mode 65 | // this will be limited to ~400khz if the ESP8266 in 80Mhz mode. 66 | Wire.setClock(700000); 67 | return true; 68 | } 69 | 70 | void display(void) { 71 | initI2cIfNeccesary(); 72 | const int x_offset = (128 - this->width()) / 2; 73 | #ifdef OLEDDISPLAY_DOUBLE_BUFFER 74 | uint8_t minBoundY = UINT8_MAX; 75 | uint8_t maxBoundY = 0; 76 | 77 | uint8_t minBoundX = UINT8_MAX; 78 | uint8_t maxBoundX = 0; 79 | uint8_t x, y; 80 | 81 | // Calculate the Y bounding box of changes 82 | // and copy buffer[pos] to buffer_back[pos]; 83 | for (y = 0; y < (this->height() / 8); y++) { 84 | for (x = 0; x < this->width(); x++) { 85 | uint16_t pos = x + y * this->width(); 86 | if (buffer[pos] != buffer_back[pos]) { 87 | minBoundY = _min(minBoundY, y); 88 | maxBoundY = _max(maxBoundY, y); 89 | minBoundX = _min(minBoundX, x); 90 | maxBoundX = _max(maxBoundX, x); 91 | } 92 | buffer_back[pos] = buffer[pos]; 93 | } 94 | yield(); 95 | } 96 | 97 | // If the minBoundY wasn't updated 98 | // we can savely assume that buffer_back[pos] == buffer[pos] 99 | // holdes true for all values of pos 100 | 101 | if (minBoundY == UINT8_MAX) return; 102 | 103 | sendCommand(COLUMNADDR); 104 | sendCommand(x_offset + minBoundX); 105 | sendCommand(x_offset + maxBoundX); 106 | 107 | sendCommand(PAGEADDR); 108 | sendCommand(minBoundY); 109 | sendCommand(maxBoundY); 110 | 111 | byte k = 0; 112 | for (y = minBoundY; y <= maxBoundY; y++) { 113 | for (x = minBoundX; x <= maxBoundX; x++) { 114 | if (k == 0) { 115 | Wire.beginTransmission(_address); 116 | Wire.write(0x40); 117 | } 118 | 119 | Wire.write(buffer[x + y * this->width()]); 120 | k++; 121 | if (k == 16) { 122 | Wire.endTransmission(); 123 | k = 0; 124 | } 125 | } 126 | yield(); 127 | } 128 | 129 | if (k != 0) { 130 | Wire.endTransmission(); 131 | } 132 | #else 133 | 134 | sendCommand(COLUMNADDR); 135 | sendCommand(x_offset); 136 | sendCommand(x_offset + (this->width() - 1)); 137 | 138 | sendCommand(PAGEADDR); 139 | sendCommand(0x0); 140 | sendCommand((this->height() / 8) - 1); 141 | 142 | if (geometry == GEOMETRY_128_64) { 143 | sendCommand(0x7); 144 | } else if (geometry == GEOMETRY_128_32) { 145 | sendCommand(0x3); 146 | } 147 | 148 | for (uint16_t i=0; i < displayBufferSize; i++) { 149 | Wire.beginTransmission(this->_address); 150 | Wire.write(0x40); 151 | for (uint8_t x = 0; x < 16; x++) { 152 | Wire.write(buffer[i]); 153 | i++; 154 | } 155 | i--; 156 | Wire.endTransmission(); 157 | } 158 | #endif 159 | } 160 | 161 | void setI2cAutoInit(bool doI2cAutoInit) { 162 | _doI2cAutoInit = doI2cAutoInit; 163 | } 164 | 165 | private: 166 | inline void sendCommand(uint8_t command) __attribute__((always_inline)){ 167 | initI2cIfNeccesary(); 168 | Wire.beginTransmission(_address); 169 | Wire.write(0x80); 170 | Wire.write(command); 171 | Wire.endTransmission(); 172 | } 173 | 174 | void initI2cIfNeccesary() { 175 | if (_doI2cAutoInit) { 176 | Wire.begin(this->_sda, this->_scl); 177 | } 178 | } 179 | 180 | }; 181 | 182 | #endif 183 | 184 | -------------------------------------------------------------------------------- /SX1276.cpp: -------------------------------------------------------------------------------- 1 | #include "SX1276.h" 2 | 3 | // registers 4 | #define REG_FIFO 0x00 5 | #define REG_OP_MODE 0x01 6 | #define REG_BITRATE_H 0x02 7 | #define REG_BITRATE_L 0x03 8 | #define REG_FDEV_H 0x04 9 | #define REG_FDEV_L 0x05 10 | #define REG_FRF_H 0x06 11 | #define REG_FRF_M 0x07 12 | #define REG_FRF_L 0x08 13 | #define REG_RXCFG 0x0D 14 | #define REG_RSSI 0x11 15 | #define REG_RXBW 0x12 16 | #define REG_AFCBW 0x13 17 | #define REG_AFC_H 0x1B 18 | #define REG_AFC_L 0x1C 19 | #define REG_FEI_H 0x1D 20 | #define REG_FEI_L 0x1E 21 | #define REG_PAYLOAD_LEN 0x32 22 | #define REG_VERSION 0x42 23 | 24 | // modes 25 | #define MODE_LONG_RANGE_MODE 0x80 26 | #define MODE_SLEEP 0x00 27 | #define MODE_STDBY 0x01 28 | #define MODE_TX 0x03 29 | #define MODE_RX_CONTINUOUS 0x05 30 | #define MODE_RX_SINGLE 0x06 31 | 32 | 33 | 34 | SX1276Class::SX1276Class() : 35 | _spiSettings(10E6, MSBFIRST, SPI_MODE0), 36 | _ss(SX1276_DEFAULT_SS_PIN), 37 | _reset(SX1276_DEFAULT_RESET_PIN), 38 | _dio0(SX1276_DEFAULT_DIO0_PIN) 39 | { 40 | } 41 | 42 | int SX1276Class::begin() 43 | { 44 | pinMode(_ss, OUTPUT); 45 | pinMode(_reset, OUTPUT); 46 | pinMode(_dio0, INPUT); 47 | 48 | digitalWrite(_reset, LOW); 49 | delay(20); 50 | digitalWrite(_reset, HIGH); 51 | delay(50); 52 | digitalWrite(_ss, HIGH); 53 | 54 | SPI.begin(); 55 | 56 | uint8_t version = readRegister(REG_VERSION); 57 | if (version != 0x12) 58 | { 59 | return 0; 60 | } 61 | 62 | init(); 63 | 64 | return 1; 65 | } 66 | 67 | void SX1276Class::init() 68 | { 69 | uint8_t initRegs[] = { 0x01, 0x78, 0x02, 0xB8, 0xD8, 0xFC, 0x8B, 0xFC, 0x49, 0x2B, 0x23, 0x08, 0x02, 0x0A, 0xFF, 0xB9, 0x12, 0x01, 0x28, 0x0C, 0x12, 0x47, 0x32, 0x3E, 0x00, 0x00, 0x00, 0xFD, 0x38, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x05, 0x12, 0x3E, 0x6B, 0x3E, 0x55, 0x55, 0x55, 0x55, 0x55, 0x48, 0x40, 0x17, 0x00, 0x00, 0x0F, 0x00, 0x0C, 0x00, 0xF5, 0x20, 0x82, 0xE2, 0x02, 0xDA, 0x24, 0x00, 0x00, 0x12, 0x24, 0x2D, 0x00, 0x03, 0x00, 0x04, 0x23, 0x00, 0x09, 0x05, 0x84, 0x32, 0x2B, 0x14, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x0C, 0xD9, 0x07, 0x00, 0x5C, 0x78, 0x00, 0x1C, 0x0E, 0x5B, 0xCC, 0x0E, 0x7F, 0x50, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3F, 0xB1, 0x0B }; 70 | 71 | setSleep(); 72 | for(int reg = 0; reg < sizeof(initRegs); reg++) 73 | { 74 | writeRegister(2 + reg, initRegs[reg]); 75 | } 76 | } 77 | 78 | void SX1276Class::writeAfc(uint32_t freq) 79 | { 80 | uint32_t regFreq = (uint64_t)freq * (1<<19) / 32000000ULL; 81 | 82 | writeRegister(REG_AFC_H, regFreq >> 8); 83 | writeRegister(REG_AFC_L, regFreq >> 0); 84 | } 85 | 86 | int32_t SX1276Class::readAfc() 87 | { 88 | int16_t reg = 0; 89 | 90 | reg |= (readRegister(REG_AFC_H) << 8); 91 | reg |= (readRegister(REG_AFC_L) << 0); 92 | 93 | int32_t ret = (int64_t)reg * 32000000ULL / (1<<19); 94 | 95 | return ret; 96 | } 97 | 98 | int32_t SX1276Class::readFei() 99 | { 100 | int16_t reg = 0; 101 | 102 | reg |= (readRegister(REG_FEI_H) << 8); 103 | reg |= (readRegister(REG_FEI_L) << 0); 104 | 105 | int32_t ret = (int64_t)reg * 32000000ULL / (1<<19); 106 | 107 | return ret; 108 | } 109 | 110 | uint8_t SX1276Class::readRssi() 111 | { 112 | return readRegister(REG_RSSI); 113 | } 114 | 115 | uint8_t SX1276Class::readFifo() 116 | { 117 | return readRegister(REG_FIFO); 118 | } 119 | 120 | uint32_t SX1276Class::delta(uint32_t ref, uint32_t value) 121 | { 122 | if(ref > value) 123 | { 124 | return ref - value; 125 | } 126 | 127 | return value - ref; 128 | } 129 | 130 | void SX1276Class::writeRxBw(uint32_t bw) 131 | { 132 | uint32_t regBw = 0; 133 | uint32_t bestBw = 0; 134 | 135 | for(int exp = 1; exp < 8; exp++) 136 | { 137 | for(int mant = 0; mant < 3; mant++) 138 | { 139 | uint32_t matchBw = (8000000 / (16+mant*4)) >> exp; 140 | 141 | if(delta(bw, matchBw) < delta(bw, bestBw)) 142 | { 143 | bestBw = matchBw; 144 | regBw = (exp << 0) | (mant << 3); 145 | } 146 | } 147 | } 148 | 149 | writeRegister(REG_RXBW, regBw); 150 | } 151 | 152 | void SX1276Class::writeAfcBw(uint32_t bw) 153 | { 154 | uint32_t regBw = 0; 155 | uint32_t bestBw = 0; 156 | 157 | for(int exp = 1; exp < 8; exp++) 158 | { 159 | for(int mant = 0; mant < 3; mant++) 160 | { 161 | uint32_t matchBw = (8000000 / (16+mant*4)) >> exp; 162 | 163 | if(delta(bw, matchBw) < delta(bw, bestBw)) 164 | { 165 | bestBw = matchBw; 166 | regBw = (exp << 0) | (mant << 3); 167 | } 168 | } 169 | } 170 | 171 | writeRegister(REG_AFCBW, regBw); 172 | } 173 | 174 | void SX1276Class::writeBitrate(uint32_t rate) 175 | { 176 | uint32_t regBitRate = 32000000ULL / rate; 177 | 178 | writeRegister(REG_BITRATE_H, regBitRate >> 8); 179 | writeRegister(REG_BITRATE_L, regBitRate >> 0); 180 | } 181 | 182 | void SX1276Class::writeFreqDev(uint32_t dev) 183 | { 184 | uint32_t regFreqDev = (uint64_t)dev * (1<<19) / 32000000ULL; 185 | 186 | writeRegister(REG_FDEV_H, regFreqDev >> 8); 187 | writeRegister(REG_FDEV_L, regFreqDev >> 0); 188 | } 189 | 190 | void SX1276Class::writeFreq(uint64_t freq) 191 | { 192 | uint32_t regFrf = freq * (1<<19) / 32000000; 193 | 194 | writeRegister(REG_FRF_H, regFrf >> 16); 195 | writeRegister(REG_FRF_M, regFrf >> 8); 196 | writeRegister(REG_FRF_L, regFrf >> 0); 197 | } 198 | 199 | void SX1276Class::writePayloadLength(uint8_t length) 200 | { 201 | writeRegister(REG_PAYLOAD_LEN, length); 202 | } 203 | 204 | void SX1276Class::writeRxConfig(uint8_t cfg) 205 | { 206 | writeRegister(REG_RXCFG, cfg); 207 | } 208 | 209 | 210 | void SX1276Class::setSleep() 211 | { 212 | delayMicroseconds(100); 213 | writeRegister(REG_OP_MODE, MODE_SLEEP); 214 | delayMicroseconds(100); 215 | writeRegister(REG_OP_MODE, MODE_SLEEP); 216 | } 217 | 218 | void SX1276Class::setStandby() 219 | { 220 | writeRegister(REG_OP_MODE, MODE_STDBY); 221 | } 222 | 223 | void SX1276Class::setRx() 224 | { 225 | writeRegister(REG_OP_MODE, MODE_STDBY); 226 | writeRegister(REG_OP_MODE, MODE_RX_CONTINUOUS); 227 | } 228 | 229 | void SX1276Class::setSPIFrequency(uint32_t frequency) 230 | { 231 | _spiSettings = SPISettings(frequency, MSBFIRST, SPI_MODE0); 232 | } 233 | 234 | uint8_t SX1276Class::readRegister(uint8_t address) 235 | { 236 | return singleTransfer(address & 0x7f, 0x00); 237 | } 238 | 239 | void SX1276Class::writeRegister(uint8_t address, uint8_t value) 240 | { 241 | singleTransfer(address | 0x80, value); 242 | } 243 | 244 | uint8_t SX1276Class::singleTransfer(uint8_t address, uint8_t value) 245 | { 246 | uint8_t response; 247 | digitalWrite(_ss, LOW); 248 | SPI.beginTransaction(_spiSettings); 249 | SPI.transfer(address); 250 | response = SPI.transfer(value); 251 | SPI.endTransaction(); 252 | digitalWrite(_ss, HIGH); 253 | return response; 254 | } 255 | 256 | 257 | -------------------------------------------------------------------------------- /OLEDDisplay.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn 5 | * Copyright (c) 2018 by Fabrice Weinberg 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | * 25 | * ThingPulse invests considerable time and money to develop these open source libraries. 26 | * Please support us by buying our products (and not the clones) from 27 | * https://thingpulse.com 28 | * 29 | */ 30 | 31 | #ifndef OLEDDISPLAY_h 32 | #define OLEDDISPLAY_h 33 | 34 | #include 35 | #include "OLEDDisplayFonts.h" 36 | 37 | //#define DEBUG_OLEDDISPLAY(...) Serial.printf( __VA_ARGS__ ) 38 | 39 | #ifndef DEBUG_OLEDDISPLAY 40 | #define DEBUG_OLEDDISPLAY(...) 41 | #endif 42 | 43 | // Use DOUBLE BUFFERING by default 44 | #ifndef OLEDDISPLAY_REDUCE_MEMORY 45 | #define OLEDDISPLAY_DOUBLE_BUFFER 46 | #endif 47 | 48 | // Header Values 49 | #define JUMPTABLE_BYTES 4 50 | 51 | #define JUMPTABLE_LSB 1 52 | #define JUMPTABLE_SIZE 2 53 | #define JUMPTABLE_WIDTH 3 54 | #define JUMPTABLE_START 4 55 | 56 | #define WIDTH_POS 0 57 | #define HEIGHT_POS 1 58 | #define FIRST_CHAR_POS 2 59 | #define CHAR_NUM_POS 3 60 | 61 | 62 | // Display commands 63 | #define CHARGEPUMP 0x8D 64 | #define COLUMNADDR 0x21 65 | #define COMSCANDEC 0xC8 66 | #define COMSCANINC 0xC0 67 | #define DISPLAYALLON 0xA5 68 | #define DISPLAYALLON_RESUME 0xA4 69 | #define DISPLAYOFF 0xAE 70 | #define DISPLAYON 0xAF 71 | #define EXTERNALVCC 0x1 72 | #define INVERTDISPLAY 0xA7 73 | #define MEMORYMODE 0x20 74 | #define NORMALDISPLAY 0xA6 75 | #define PAGEADDR 0x22 76 | #define SEGREMAP 0xA0 77 | #define SETCOMPINS 0xDA 78 | #define SETCONTRAST 0x81 79 | #define SETDISPLAYCLOCKDIV 0xD5 80 | #define SETDISPLAYOFFSET 0xD3 81 | #define SETHIGHCOLUMN 0x10 82 | #define SETLOWCOLUMN 0x00 83 | #define SETMULTIPLEX 0xA8 84 | #define SETPRECHARGE 0xD9 85 | #define SETSEGMENTREMAP 0xA1 86 | #define SETSTARTLINE 0x40 87 | #define SETVCOMDETECT 0xDB 88 | #define SWITCHCAPVCC 0x2 89 | 90 | #ifndef _swap_int16_t 91 | #define _swap_int16_t(a, b) { int16_t t = a; a = b; b = t; } 92 | #endif 93 | 94 | enum OLEDDISPLAY_COLOR { 95 | BLACK = 0, 96 | WHITE = 1, 97 | INVERSE = 2 98 | }; 99 | 100 | enum OLEDDISPLAY_TEXT_ALIGNMENT { 101 | TEXT_ALIGN_LEFT = 0, 102 | TEXT_ALIGN_RIGHT = 1, 103 | TEXT_ALIGN_CENTER = 2, 104 | TEXT_ALIGN_CENTER_BOTH = 3 105 | }; 106 | 107 | 108 | enum OLEDDISPLAY_GEOMETRY { 109 | GEOMETRY_128_64 = 0, 110 | GEOMETRY_128_32 = 1, 111 | GEOMETRY_64_32 = 2 //Wireless Stick 112 | }; 113 | 114 | typedef byte (*FontTableLookupFunction)(const byte ch); 115 | 116 | 117 | class OLEDDisplay : public Print { 118 | 119 | public: 120 | virtual ~OLEDDisplay(); 121 | 122 | uint16_t width(void) const { return displayWidth; }; 123 | uint16_t height(void) const { return displayHeight; }; 124 | 125 | // Initialize the display 126 | bool init(); 127 | 128 | // Free the memory used by the display 129 | void end(); 130 | 131 | void sleep(); 132 | 133 | void wakeup(); 134 | 135 | // Cycle through the initialization 136 | void resetDisplay(uint8_t rstPin); 137 | 138 | /* Drawing functions */ 139 | // Sets the color of all pixel operations 140 | void setColor(OLEDDISPLAY_COLOR color); 141 | 142 | // Returns the current color. 143 | OLEDDISPLAY_COLOR getColor(); 144 | 145 | // Draw a pixel at given position 146 | void setPixel(int16_t x, int16_t y); 147 | 148 | // Draw a line from position 0 to position 1 149 | void drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1); 150 | 151 | // Draw the border of a rectangle at the given location 152 | void drawRect(int16_t x, int16_t y, int16_t width, int16_t height); 153 | 154 | // Fill the rectangle 155 | void fillRect(int16_t x, int16_t y, int16_t width, int16_t height); 156 | 157 | // Draw the border of a circle 158 | void drawCircle(int16_t x, int16_t y, int16_t radius); 159 | 160 | // Draw all Quadrants specified in the quads bit mask 161 | void drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads); 162 | 163 | // Fill circle 164 | void fillCircle(int16_t x, int16_t y, int16_t radius); 165 | 166 | // Draw a line horizontally 167 | void drawHorizontalLine(int16_t x, int16_t y, int16_t length); 168 | 169 | // Draw a line vertically 170 | void drawVerticalLine(int16_t x, int16_t y, int16_t length); 171 | 172 | // Draws a rounded progress bar with the outer dimensions given by width and height. Progress is 173 | // a unsigned byte value between 0 and 100 174 | void drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress); 175 | 176 | // Draw a bitmap in the internal image format 177 | void drawFastImage(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *image); 178 | 179 | // Draw a XBM 180 | void drawXbm(int16_t x, int16_t y, int16_t width, int16_t height, const uint8_t *xbm); 181 | 182 | /* Text functions */ 183 | 184 | // Draws a string at the given location 185 | void drawString(int16_t x, int16_t y, String text); 186 | 187 | // Draws a String with a maximum width at the given location. 188 | // If the given String is wider than the specified width 189 | // The text will be wrapped to the next line at a space or dash 190 | void drawStringMaxWidth(int16_t x, int16_t y, uint16_t maxLineWidth, String text); 191 | 192 | // Returns the width of the const char* with the current 193 | // font settings 194 | uint16_t getStringWidth(const char* text, uint16_t length); 195 | 196 | // Convencience method for the const char version 197 | uint16_t getStringWidth(String text); 198 | 199 | // Specifies relative to which anchor point 200 | // the text is rendered. Available constants: 201 | // TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, TEXT_ALIGN_CENTER_BOTH 202 | void setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment); 203 | 204 | // Sets the current font. Available default fonts 205 | // ArialMT_Plain_10, ArialMT_Plain_16, ArialMT_Plain_24 206 | void setFont(const uint8_t *fontData); 207 | 208 | // Set the function that will convert utf-8 to font table index 209 | void setFontTableLookupFunction(FontTableLookupFunction function); 210 | 211 | /* Display functions */ 212 | 213 | // Turn the display on 214 | void displayOn(void); 215 | 216 | // Turn the display offs 217 | void displayOff(void); 218 | 219 | // Inverted display mode 220 | void invertDisplay(void); 221 | 222 | // Normal display mode 223 | void normalDisplay(void); 224 | 225 | // Set display contrast 226 | // really low brightness & contrast: contrast = 10, precharge = 5, comdetect = 0 227 | // normal brightness & contrast: contrast = 100 228 | void setContrast(uint8_t contrast, uint8_t precharge = 241, uint8_t comdetect = 64); 229 | 230 | // Convenience method to access 231 | void setBrightness(uint8_t); 232 | 233 | // Reset display rotation or mirroring 234 | void resetOrientation(); 235 | 236 | // Turn the display upside down 237 | void flipScreenVertically(); 238 | 239 | // Mirror the display (to be used in a mirror or as a projector) 240 | void mirrorScreen(); 241 | 242 | // Write the buffer to the display memory 243 | virtual void display(void) = 0; 244 | 245 | // Clear the local pixel buffer 246 | void clear(void); 247 | 248 | // Log buffer implementation 249 | 250 | // This will define the lines and characters you can 251 | // print to the screen. When you exeed the buffer size (lines * chars) 252 | // the output may be truncated due to the size constraint. 253 | bool setLogBuffer(uint16_t lines, uint16_t chars); 254 | 255 | // Draw the log buffer at position (x, y) 256 | void drawLogBuffer(uint16_t x, uint16_t y); 257 | 258 | // Get screen geometry 259 | uint16_t getWidth(void); 260 | uint16_t getHeight(void); 261 | 262 | // Implement needed function to be compatible with Print class 263 | size_t write(uint8_t c); 264 | size_t write(const char* s); 265 | 266 | uint8_t *buffer = NULL; 267 | 268 | #ifdef OLEDDISPLAY_DOUBLE_BUFFER 269 | uint8_t *buffer_back = NULL; 270 | #endif 271 | 272 | protected: 273 | 274 | OLEDDISPLAY_GEOMETRY geometry = GEOMETRY_128_64; 275 | 276 | uint16_t displayWidth = 128; 277 | uint16_t displayHeight = 64; 278 | uint16_t displayBufferSize = 1024; 279 | 280 | // Set the correct height, width and buffer for the geometry 281 | void setGeometry(OLEDDISPLAY_GEOMETRY g); 282 | 283 | OLEDDISPLAY_TEXT_ALIGNMENT textAlignment = TEXT_ALIGN_LEFT; 284 | OLEDDISPLAY_COLOR color = WHITE; 285 | 286 | const uint8_t *fontData = ArialMT_Plain_10; 287 | 288 | // State values for logBuffer 289 | uint16_t logBufferSize = 0; 290 | uint16_t logBufferFilled = 0; 291 | uint16_t logBufferLine = 0; 292 | uint16_t logBufferMaxLines = 0; 293 | char *logBuffer = NULL; 294 | 295 | // Send a command to the display (low level function) 296 | virtual void sendCommand(uint8_t com) {(void)com;}; 297 | 298 | // Connect to the display 299 | virtual bool connect() { return false; }; 300 | 301 | // Send all the init commands 302 | void sendInitCommands(); 303 | 304 | // converts utf8 characters to extended ascii 305 | char* utf8ascii(String s); 306 | 307 | void inline drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) __attribute__((always_inline)); 308 | 309 | void drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth); 310 | 311 | // UTF-8 to font table index converter 312 | // Code form http://playground.arduino.cc/Main/Utf8ascii 313 | FontTableLookupFunction fontTableLookupFunction = [](const byte ch) { 314 | static uint8_t LASTCHAR; 315 | 316 | if (ch < 128) { // Standard ASCII-set 0..0x7F handling 317 | LASTCHAR = 0; 318 | return ch; 319 | } 320 | 321 | uint8_t last = LASTCHAR; // get last char 322 | LASTCHAR = ch; 323 | 324 | switch (last) { // conversion depnding on first UTF8-character 325 | case 0xC2: return (uint8_t) ch; 326 | case 0xC3: return (uint8_t) (ch | 0xC0); 327 | case 0x82: if (ch == 0xAC) return (uint8_t) 0x80; // special case Euro-symbol 328 | } 329 | 330 | return (uint8_t) 0; // otherwise: return zero, if character has to be ignored 331 | }; 332 | }; 333 | 334 | #endif 335 | 336 | 337 | -------------------------------------------------------------------------------- /OLEDDisplay.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2018 by ThingPulse, Daniel Eichhorn 5 | * Copyright (c) 2018 by Fabrice Weinberg 6 | * 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy 8 | * of this software and associated documentation files (the "Software"), to deal 9 | * in the Software without restriction, including without limitation the rights 10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | * copies of the Software, and to permit persons to whom the Software is 12 | * furnished to do so, subject to the following conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be included in all 15 | * copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | * SOFTWARE. 24 | * 25 | * ThingPulse invests considerable time and money to develop these open source libraries. 26 | * Please support us by buying our products (and not the clones) from 27 | * https://thingpulse.com 28 | * 29 | */ 30 | 31 | #include "OLEDDisplay.h" 32 | 33 | OLEDDisplay::~OLEDDisplay() { 34 | end(); 35 | } 36 | 37 | bool OLEDDisplay::init() { 38 | if (!this->connect()) { 39 | //DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Can't establish connection to display\n"); 40 | Serial.print("Can't establish connection to display\n"); 41 | return false; 42 | } 43 | 44 | if(this->buffer==NULL) { 45 | this->buffer = (uint8_t*) malloc(sizeof(uint8_t) * displayBufferSize); 46 | 47 | if(!this->buffer) { 48 | //DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create display\n"); 49 | Serial.print("Not enough memory to create display\n"); 50 | return false; 51 | } 52 | } 53 | 54 | #ifdef OLEDDISPLAY_DOUBLE_BUFFER 55 | if(this->buffer_back==NULL) { 56 | this->buffer_back = (uint8_t*) malloc(sizeof(uint8_t) * displayBufferSize); 57 | 58 | if(!this->buffer_back) { 59 | //DEBUG_OLEDDISPLAY("[OLEDDISPLAY][init] Not enough memory to create back buffer\n"); 60 | Serial.print("Not enough memory to create back buffer\n"); 61 | free(this->buffer); 62 | return false; 63 | } 64 | } 65 | #endif 66 | 67 | resetDisplay(16); 68 | sendInitCommands(); 69 | 70 | clear(); 71 | #ifdef OLEDDISPLAY_DOUBLE_BUFFER 72 | memset(buffer_back, 1, displayBufferSize); 73 | #endif 74 | display(); 75 | return true; 76 | } 77 | 78 | void OLEDDisplay::end() { 79 | if (this->buffer) { free(this->buffer); this->buffer = NULL; } 80 | #ifdef OLEDDISPLAY_DOUBLE_BUFFER 81 | if (this->buffer_back) { free(this->buffer_back); this->buffer_back = NULL; } 82 | #endif 83 | if (this->logBuffer != NULL) { free(this->logBuffer); this->logBuffer = NULL; } 84 | } 85 | 86 | void OLEDDisplay::sleep() { 87 | sendCommand(0x8D); 88 | sendCommand(0x10); 89 | sendCommand(0xAE); 90 | } 91 | 92 | void OLEDDisplay::wakeup() { 93 | sendCommand(0x8D); 94 | sendCommand(0x14); 95 | sendCommand(0xAF); 96 | } 97 | 98 | void OLEDDisplay::resetDisplay(uint8_t rstPin) { 99 | pinMode(rstPin, OUTPUT); 100 | digitalWrite(rstPin,LOW); 101 | delay(100); 102 | digitalWrite(rstPin,HIGH); 103 | } 104 | 105 | void OLEDDisplay::setColor(OLEDDISPLAY_COLOR color) { 106 | this->color = color; 107 | } 108 | 109 | OLEDDISPLAY_COLOR OLEDDisplay::getColor() { 110 | return this->color; 111 | } 112 | 113 | void OLEDDisplay::setPixel(int16_t x, int16_t y) { 114 | if (x >= 0 && x < this->width() && y >= 0 && y < this->height()) { 115 | switch (color) { 116 | case WHITE: buffer[x + (y / 8) * this->width()] |= (1 << (y & 7)); break; 117 | case BLACK: buffer[x + (y / 8) * this->width()] &= ~(1 << (y & 7)); break; 118 | case INVERSE: buffer[x + (y / 8) * this->width()] ^= (1 << (y & 7)); break; 119 | } 120 | } 121 | } 122 | 123 | // Bresenham's algorithm - thx wikipedia and Adafruit_GFX 124 | void OLEDDisplay::drawLine(int16_t x0, int16_t y0, int16_t x1, int16_t y1) { 125 | int16_t steep = abs(y1 - y0) > abs(x1 - x0); 126 | if (steep) { 127 | _swap_int16_t(x0, y0); 128 | _swap_int16_t(x1, y1); 129 | } 130 | 131 | if (x0 > x1) { 132 | _swap_int16_t(x0, x1); 133 | _swap_int16_t(y0, y1); 134 | } 135 | 136 | int16_t dx, dy; 137 | dx = x1 - x0; 138 | dy = abs(y1 - y0); 139 | 140 | int16_t err = dx / 2; 141 | int16_t ystep; 142 | 143 | if (y0 < y1) { 144 | ystep = 1; 145 | } else { 146 | ystep = -1; 147 | } 148 | 149 | for (; x0<=x1; x0++) { 150 | if (steep) { 151 | setPixel(y0, x0); 152 | } else { 153 | setPixel(x0, y0); 154 | } 155 | err -= dy; 156 | if (err < 0) { 157 | y0 += ystep; 158 | err += dx; 159 | } 160 | } 161 | } 162 | 163 | void OLEDDisplay::drawRect(int16_t x, int16_t y, int16_t width, int16_t height) { 164 | drawHorizontalLine(x, y, width); 165 | drawVerticalLine(x, y, height); 166 | drawVerticalLine(x + width - 1, y, height); 167 | drawHorizontalLine(x, y + height - 1, width); 168 | } 169 | 170 | void OLEDDisplay::fillRect(int16_t xMove, int16_t yMove, int16_t width, int16_t height) { 171 | for (int16_t x = xMove; x < xMove + width; x++) { 172 | drawVerticalLine(x, yMove, height); 173 | } 174 | } 175 | 176 | void OLEDDisplay::drawCircle(int16_t x0, int16_t y0, int16_t radius) { 177 | int16_t x = 0, y = radius; 178 | int16_t dp = 1 - radius; 179 | do { 180 | if (dp < 0) 181 | dp = dp + 2 * (++x) + 3; 182 | else 183 | dp = dp + 2 * (++x) - 2 * (--y) + 5; 184 | 185 | setPixel(x0 + x, y0 + y); //For the 8 octants 186 | setPixel(x0 - x, y0 + y); 187 | setPixel(x0 + x, y0 - y); 188 | setPixel(x0 - x, y0 - y); 189 | setPixel(x0 + y, y0 + x); 190 | setPixel(x0 - y, y0 + x); 191 | setPixel(x0 + y, y0 - x); 192 | setPixel(x0 - y, y0 - x); 193 | 194 | } while (x < y); 195 | 196 | setPixel(x0 + radius, y0); 197 | setPixel(x0, y0 + radius); 198 | setPixel(x0 - radius, y0); 199 | setPixel(x0, y0 - radius); 200 | } 201 | 202 | void OLEDDisplay::drawCircleQuads(int16_t x0, int16_t y0, int16_t radius, uint8_t quads) { 203 | int16_t x = 0, y = radius; 204 | int16_t dp = 1 - radius; 205 | while (x < y) { 206 | if (dp < 0) 207 | dp = dp + 2 * (++x) + 3; 208 | else 209 | dp = dp + 2 * (++x) - 2 * (--y) + 5; 210 | if (quads & 0x1) { 211 | setPixel(x0 + x, y0 - y); 212 | setPixel(x0 + y, y0 - x); 213 | } 214 | if (quads & 0x2) { 215 | setPixel(x0 - y, y0 - x); 216 | setPixel(x0 - x, y0 - y); 217 | } 218 | if (quads & 0x4) { 219 | setPixel(x0 - y, y0 + x); 220 | setPixel(x0 - x, y0 + y); 221 | } 222 | if (quads & 0x8) { 223 | setPixel(x0 + x, y0 + y); 224 | setPixel(x0 + y, y0 + x); 225 | } 226 | } 227 | if (quads & 0x1 && quads & 0x8) { 228 | setPixel(x0 + radius, y0); 229 | } 230 | if (quads & 0x4 && quads & 0x8) { 231 | setPixel(x0, y0 + radius); 232 | } 233 | if (quads & 0x2 && quads & 0x4) { 234 | setPixel(x0 - radius, y0); 235 | } 236 | if (quads & 0x1 && quads & 0x2) { 237 | setPixel(x0, y0 - radius); 238 | } 239 | } 240 | 241 | 242 | void OLEDDisplay::fillCircle(int16_t x0, int16_t y0, int16_t radius) { 243 | int16_t x = 0, y = radius; 244 | int16_t dp = 1 - radius; 245 | do { 246 | if (dp < 0) 247 | dp = dp + 2 * (++x) + 3; 248 | else 249 | dp = dp + 2 * (++x) - 2 * (--y) + 5; 250 | 251 | drawHorizontalLine(x0 - x, y0 - y, 2*x); 252 | drawHorizontalLine(x0 - x, y0 + y, 2*x); 253 | drawHorizontalLine(x0 - y, y0 - x, 2*y); 254 | drawHorizontalLine(x0 - y, y0 + x, 2*y); 255 | 256 | 257 | } while (x < y); 258 | drawHorizontalLine(x0 - radius, y0, 2 * radius); 259 | 260 | } 261 | 262 | void OLEDDisplay::drawHorizontalLine(int16_t x, int16_t y, int16_t length) { 263 | if (y < 0 || y >= this->height()) { return; } 264 | 265 | if (x < 0) { 266 | length += x; 267 | x = 0; 268 | } 269 | 270 | if ( (x + length) > this->width()) { 271 | length = (this->width() - x); 272 | } 273 | 274 | if (length <= 0) { return; } 275 | 276 | uint8_t * bufferPtr = buffer; 277 | bufferPtr += (y >> 3) * this->width(); 278 | bufferPtr += x; 279 | 280 | uint8_t drawBit = 1 << (y & 7); 281 | 282 | switch (color) { 283 | case WHITE: while (length--) { 284 | *bufferPtr++ |= drawBit; 285 | }; break; 286 | case BLACK: drawBit = ~drawBit; while (length--) { 287 | *bufferPtr++ &= drawBit; 288 | }; break; 289 | case INVERSE: while (length--) { 290 | *bufferPtr++ ^= drawBit; 291 | }; break; 292 | } 293 | } 294 | 295 | void OLEDDisplay::drawVerticalLine(int16_t x, int16_t y, int16_t length) { 296 | if (x < 0 || x >= this->width()) return; 297 | 298 | if (y < 0) { 299 | length += y; 300 | y = 0; 301 | } 302 | 303 | if ( (y + length) > this->height()) { 304 | length = (this->height() - y); 305 | } 306 | 307 | if (length <= 0) return; 308 | 309 | 310 | uint8_t yOffset = y & 7; 311 | uint8_t drawBit; 312 | uint8_t *bufferPtr = buffer; 313 | 314 | bufferPtr += (y >> 3) * this->width(); 315 | bufferPtr += x; 316 | 317 | if (yOffset) { 318 | yOffset = 8 - yOffset; 319 | drawBit = ~(0xFF >> (yOffset)); 320 | 321 | if (length < yOffset) { 322 | drawBit &= (0xFF >> (yOffset - length)); 323 | } 324 | 325 | switch (color) { 326 | case WHITE: *bufferPtr |= drawBit; break; 327 | case BLACK: *bufferPtr &= ~drawBit; break; 328 | case INVERSE: *bufferPtr ^= drawBit; break; 329 | } 330 | 331 | if (length < yOffset) return; 332 | 333 | length -= yOffset; 334 | bufferPtr += this->width(); 335 | } 336 | 337 | if (length >= 8) { 338 | switch (color) { 339 | case WHITE: 340 | case BLACK: 341 | drawBit = (color == WHITE) ? 0xFF : 0x00; 342 | do { 343 | *bufferPtr = drawBit; 344 | bufferPtr += this->width(); 345 | length -= 8; 346 | } while (length >= 8); 347 | break; 348 | case INVERSE: 349 | do { 350 | *bufferPtr = ~(*bufferPtr); 351 | bufferPtr += this->width(); 352 | length -= 8; 353 | } while (length >= 8); 354 | break; 355 | } 356 | } 357 | 358 | if (length > 0) { 359 | drawBit = (1 << (length & 7)) - 1; 360 | switch (color) { 361 | case WHITE: *bufferPtr |= drawBit; break; 362 | case BLACK: *bufferPtr &= ~drawBit; break; 363 | case INVERSE: *bufferPtr ^= drawBit; break; 364 | } 365 | } 366 | } 367 | 368 | void OLEDDisplay::drawProgressBar(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint8_t progress) { 369 | uint16_t radius = height / 2; 370 | uint16_t xRadius = x + radius; 371 | uint16_t yRadius = y + radius; 372 | uint16_t doubleRadius = 2 * radius; 373 | uint16_t innerRadius = radius - 2; 374 | 375 | setColor(WHITE); 376 | drawCircleQuads(xRadius, yRadius, radius, 0b00000110); 377 | drawHorizontalLine(xRadius, y, width - doubleRadius + 1); 378 | drawHorizontalLine(xRadius, y + height, width - doubleRadius + 1); 379 | drawCircleQuads(x + width - radius, yRadius, radius, 0b00001001); 380 | 381 | uint16_t maxProgressWidth = (width - doubleRadius + 1) * progress / 100; 382 | 383 | fillCircle(xRadius, yRadius, innerRadius); 384 | fillRect(xRadius + 1, y + 2, maxProgressWidth, height - 3); 385 | fillCircle(xRadius + maxProgressWidth, yRadius, innerRadius); 386 | } 387 | 388 | void OLEDDisplay::drawFastImage(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *image) { 389 | drawInternal(xMove, yMove, width, height, image, 0, 0); 390 | } 391 | 392 | void OLEDDisplay::drawXbm(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *xbm) { 393 | int16_t widthInXbm = (width + 7) / 8; 394 | uint8_t data = 0; 395 | 396 | for(int16_t y = 0; y < height; y++) { 397 | for(int16_t x = 0; x < width; x++ ) { 398 | if (x & 7) { 399 | data >>= 1; // Move a bit 400 | } else { // Read new data every 8 bit 401 | data = pgm_read_byte(xbm + (x / 8) + y * widthInXbm); 402 | } 403 | // if there is a bit draw it 404 | if (data & 0x01) { 405 | setPixel(xMove + x, yMove + y); 406 | } 407 | } 408 | } 409 | } 410 | 411 | void OLEDDisplay::drawStringInternal(int16_t xMove, int16_t yMove, char* text, uint16_t textLength, uint16_t textWidth) { 412 | uint8_t textHeight = pgm_read_byte(fontData + HEIGHT_POS); 413 | uint8_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); 414 | uint16_t sizeOfJumpTable = pgm_read_byte(fontData + CHAR_NUM_POS) * JUMPTABLE_BYTES; 415 | 416 | uint8_t cursorX = 0; 417 | uint8_t cursorY = 0; 418 | 419 | switch (textAlignment) { 420 | case TEXT_ALIGN_CENTER_BOTH: 421 | yMove -= textHeight >> 1; 422 | // Fallthrough 423 | case TEXT_ALIGN_CENTER: 424 | xMove -= textWidth >> 1; // divide by 2 425 | break; 426 | case TEXT_ALIGN_RIGHT: 427 | xMove -= textWidth; 428 | break; 429 | case TEXT_ALIGN_LEFT: 430 | break; 431 | } 432 | 433 | // Don't draw anything if it is not on the screen. 434 | if (xMove + textWidth < 0 || xMove > this->width() ) {return;} 435 | if (yMove + textHeight < 0 || yMove > this->width() ) {return;} 436 | 437 | for (uint16_t j = 0; j < textLength; j++) { 438 | int16_t xPos = xMove + cursorX; 439 | int16_t yPos = yMove + cursorY; 440 | 441 | byte code = text[j]; 442 | if (code >= firstChar) { 443 | byte charCode = code - firstChar; 444 | 445 | // 4 Bytes per char code 446 | byte msbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES ); // MSB \ JumpAddress 447 | byte lsbJumpToChar = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_LSB); // LSB / 448 | byte charByteSize = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_SIZE); // Size 449 | byte currentCharWidth = pgm_read_byte( fontData + JUMPTABLE_START + charCode * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); // Width 450 | 451 | // Test if the char is drawable 452 | if (!(msbJumpToChar == 255 && lsbJumpToChar == 255)) { 453 | // Get the position of the char data 454 | uint16_t charDataPosition = JUMPTABLE_START + sizeOfJumpTable + ((msbJumpToChar << 8) + lsbJumpToChar); 455 | drawInternal(xPos, yPos, currentCharWidth, textHeight, fontData, charDataPosition, charByteSize); 456 | } 457 | 458 | cursorX += currentCharWidth; 459 | } 460 | } 461 | } 462 | 463 | 464 | void OLEDDisplay::drawString(int16_t xMove, int16_t yMove, String strUser) { 465 | uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); 466 | 467 | // char* text must be freed! 468 | char* text = utf8ascii(strUser); 469 | 470 | uint16_t yOffset = 0; 471 | // If the string should be centered vertically too 472 | // we need to now how heigh the string is. 473 | if (textAlignment == TEXT_ALIGN_CENTER_BOTH) { 474 | uint16_t lb = 0; 475 | // Find number of linebreaks in text 476 | for (uint16_t i=0;text[i] != 0; i++) { 477 | lb += (text[i] == 10); 478 | } 479 | // Calculate center 480 | yOffset = (lb * lineHeight) / 2; 481 | } 482 | 483 | uint16_t line = 0; 484 | char* textPart = strtok(text,"\n"); 485 | while (textPart != NULL) { 486 | uint16_t length = strlen(textPart); 487 | drawStringInternal(xMove, yMove - yOffset + (line++) * lineHeight, textPart, length, getStringWidth(textPart, length)); 488 | textPart = strtok(NULL, "\n"); 489 | } 490 | free(text); 491 | } 492 | //void OLEDDisplay::drawdata(int16_t xMove, int16_t yMove, int16_t Num) { 493 | // uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); 494 | // unsigned char c = 0,i = 0,j = 0,ch[3]; 495 | // String strUser; 496 | // 497 | // ch[0] = Num/100 + 48;//锟斤拷锟斤拷十锟斤拷锟狡碉拷48锟斤拷为锟剿革拷Num锟斤拷锟斤拷ASCLL锟斤拷母锟�4位0011 0000锟斤拷 498 | // ch[1] = Num%100/10 + 48; 499 | // ch[2] = Num%10 + 48; 500 | // 501 | // if(ch[0] == 48) //锟斤拷锟节帮拷锟斤拷锟斤拷每位为"0"时锟斤拷锟斤拷煽崭瘢锟斤拷锟斤拷锟绞撅拷锟� 502 | // { 503 | // ch[0] = 32; 504 | // if(ch[1] == 48) 505 | // { 506 | // ch[1] = 32; 507 | // if(ch[2] == 48) 508 | // { 509 | // ch[2] = 32; 510 | // } 511 | // else{ch[2] = Num%10 + 48;} 512 | // } 513 | // else{ch[1] = Num%100/10 + 48;} 514 | // } 515 | // else {ch[0] = Num/100 + 48;} 516 | // 517 | // // char* text must be freed! 518 | // char* text = utf8ascii(strUser); 519 | // 520 | // uint16_t yOffset = 0; 521 | // // If the string should be centered vertically too 522 | // // we need to now how heigh the string is. 523 | // if (textAlignment == TEXT_ALIGN_CENTER_BOTH) { 524 | // uint16_t lb = 0; 525 | // // Find number of linebreaks in text 526 | // for (uint16_t i=0;text[i] != 0; i++) { 527 | // lb += (text[i] == 10); 528 | // } 529 | // // Calculate center 530 | // yOffset = (lb * lineHeight) / 2; 531 | // } 532 | // 533 | // uint16_t line = 0; 534 | // char* textPart = strtok(text,"\n"); 535 | // while (textPart != NULL) { 536 | // uint16_t length = strlen(textPart); 537 | // drawStringInternal(xMove, yMove - yOffset + (line++) * lineHeight, textPart, length, getStringWidth(textPart, length)); 538 | // textPart = strtok(NULL, "\n"); 539 | // } 540 | // free(text); 541 | //} 542 | 543 | void OLEDDisplay::drawStringMaxWidth(int16_t xMove, int16_t yMove, uint16_t maxLineWidth, String strUser) { 544 | uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); 545 | uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); 546 | 547 | char* text = utf8ascii(strUser); 548 | 549 | uint16_t length = strlen(text); 550 | uint16_t lastDrawnPos = 0; 551 | uint16_t lineNumber = 0; 552 | uint16_t strWidth = 0; 553 | 554 | uint16_t preferredBreakpoint = 0; 555 | uint16_t widthAtBreakpoint = 0; 556 | 557 | for (uint16_t i = 0; i < length; i++) { 558 | strWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[i] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); 559 | 560 | // Always try to break on a space or dash 561 | if (text[i] == ' ' || text[i]== '-') { 562 | preferredBreakpoint = i; 563 | widthAtBreakpoint = strWidth; 564 | } 565 | 566 | if (strWidth >= maxLineWidth) { 567 | if (preferredBreakpoint == 0) { 568 | preferredBreakpoint = i; 569 | widthAtBreakpoint = strWidth; 570 | } 571 | drawStringInternal(xMove, yMove + (lineNumber++) * lineHeight , &text[lastDrawnPos], preferredBreakpoint - lastDrawnPos, widthAtBreakpoint); 572 | lastDrawnPos = preferredBreakpoint + 1; 573 | // It is possible that we did not draw all letters to i so we need 574 | // to account for the width of the chars from `i - preferredBreakpoint` 575 | // by calculating the width we did not draw yet. 576 | strWidth = strWidth - widthAtBreakpoint; 577 | preferredBreakpoint = 0; 578 | } 579 | } 580 | 581 | // Draw last part if needed 582 | if (lastDrawnPos < length) { 583 | drawStringInternal(xMove, yMove + lineNumber * lineHeight , &text[lastDrawnPos], length - lastDrawnPos, getStringWidth(&text[lastDrawnPos], length - lastDrawnPos)); 584 | } 585 | 586 | free(text); 587 | } 588 | 589 | uint16_t OLEDDisplay::getStringWidth(const char* text, uint16_t length) { 590 | uint16_t firstChar = pgm_read_byte(fontData + FIRST_CHAR_POS); 591 | 592 | uint16_t stringWidth = 0; 593 | uint16_t maxWidth = 0; 594 | 595 | while (length--) { 596 | stringWidth += pgm_read_byte(fontData + JUMPTABLE_START + (text[length] - firstChar) * JUMPTABLE_BYTES + JUMPTABLE_WIDTH); 597 | if (text[length] == 10) { 598 | maxWidth = max(maxWidth, stringWidth); 599 | stringWidth = 0; 600 | } 601 | } 602 | 603 | return max(maxWidth, stringWidth); 604 | } 605 | 606 | uint16_t OLEDDisplay::getStringWidth(String strUser) { 607 | char* text = utf8ascii(strUser); 608 | uint16_t length = strlen(text); 609 | uint16_t width = getStringWidth(text, length); 610 | free(text); 611 | return width; 612 | } 613 | 614 | void OLEDDisplay::setTextAlignment(OLEDDISPLAY_TEXT_ALIGNMENT textAlignment) { 615 | this->textAlignment = textAlignment; 616 | } 617 | 618 | void OLEDDisplay::setFont(const uint8_t *fontData) { 619 | this->fontData = fontData; 620 | } 621 | 622 | void OLEDDisplay::displayOn(void) { 623 | sendCommand(DISPLAYON); 624 | } 625 | 626 | void OLEDDisplay::displayOff(void) { 627 | sendCommand(DISPLAYOFF); 628 | } 629 | 630 | void OLEDDisplay::invertDisplay(void) { 631 | sendCommand(INVERTDISPLAY); 632 | } 633 | 634 | void OLEDDisplay::normalDisplay(void) { 635 | sendCommand(NORMALDISPLAY); 636 | } 637 | 638 | void OLEDDisplay::setContrast(uint8_t contrast, uint8_t precharge, uint8_t comdetect) { 639 | sendCommand(SETPRECHARGE); //0xD9 640 | sendCommand(precharge); //0xF1 default, to lower the contrast, put 1-1F 641 | sendCommand(SETCONTRAST); 642 | sendCommand(contrast); // 0-255 643 | sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast) 644 | sendCommand(comdetect); //0x40 default, to lower the contrast, put 0 645 | sendCommand(DISPLAYALLON_RESUME); 646 | sendCommand(NORMALDISPLAY); 647 | sendCommand(DISPLAYON); 648 | } 649 | 650 | void OLEDDisplay::setBrightness(uint8_t brightness) { 651 | uint8_t contrast = brightness; 652 | if (brightness < 128) { 653 | // Magic values to get a smooth/ step-free transition 654 | contrast = brightness * 1.171; 655 | } else { 656 | contrast = brightness * 1.171 - 43; 657 | } 658 | 659 | uint8_t precharge = 241; 660 | if (brightness == 0) { 661 | precharge = 0; 662 | } 663 | uint8_t comdetect = brightness / 8; 664 | 665 | setContrast(contrast, precharge, comdetect); 666 | } 667 | 668 | void OLEDDisplay::resetOrientation() { 669 | sendCommand(SEGREMAP); 670 | sendCommand(COMSCANINC); //Reset screen rotation or mirroring 671 | } 672 | 673 | void OLEDDisplay::flipScreenVertically() { 674 | sendCommand(SEGREMAP | 0x01); 675 | sendCommand(COMSCANDEC); //Rotate screen 180 Deg 676 | } 677 | 678 | void OLEDDisplay::mirrorScreen() { 679 | sendCommand(SEGREMAP); 680 | sendCommand(COMSCANDEC); //Mirror screen 681 | } 682 | 683 | void OLEDDisplay::clear(void) { 684 | memset(buffer, 0, displayBufferSize); 685 | } 686 | 687 | void OLEDDisplay::drawLogBuffer(uint16_t xMove, uint16_t yMove) { 688 | uint16_t lineHeight = pgm_read_byte(fontData + HEIGHT_POS); 689 | // Always align left 690 | setTextAlignment(TEXT_ALIGN_LEFT); 691 | 692 | // State values 693 | uint16_t length = 0; 694 | uint16_t line = 0; 695 | uint16_t lastPos = 0; 696 | 697 | for (uint16_t i=0;ilogBufferFilled;i++){ 698 | // Everytime we have a \n print 699 | if (this->logBuffer[i] == 10) { 700 | length++; 701 | // Draw string on line `line` from lastPos to length 702 | // Passing 0 as the lenght because we are in TEXT_ALIGN_LEFT 703 | drawStringInternal(xMove, yMove + (line++) * lineHeight, &this->logBuffer[lastPos], length, 0); 704 | // Remember last pos 705 | lastPos = i; 706 | // Reset length 707 | length = 0; 708 | } else { 709 | // Count chars until next linebreak 710 | length++; 711 | } 712 | } 713 | // Draw the remaining string 714 | if (length > 0) { 715 | drawStringInternal(xMove, yMove + line * lineHeight, &this->logBuffer[lastPos], length, 0); 716 | } 717 | } 718 | 719 | uint16_t OLEDDisplay::getWidth(void) { 720 | return displayWidth; 721 | } 722 | 723 | uint16_t OLEDDisplay::getHeight(void) { 724 | return displayHeight; 725 | } 726 | 727 | bool OLEDDisplay::setLogBuffer(uint16_t lines, uint16_t chars){ 728 | if (logBuffer != NULL) free(logBuffer); 729 | uint16_t size = lines * chars; 730 | if (size > 0) { 731 | this->logBufferLine = 0; // Lines printed 732 | this->logBufferFilled = 0; // Nothing stored yet 733 | this->logBufferMaxLines = lines; // Lines max printable 734 | this->logBufferSize = size; // Total number of characters the buffer can hold 735 | this->logBuffer = (char *) malloc(size * sizeof(uint8_t)); 736 | if(!this->logBuffer) { 737 | DEBUG_OLEDDISPLAY("[OLEDDISPLAY][setLogBuffer] Not enough memory to create log buffer\n"); 738 | return false; 739 | } 740 | } 741 | return true; 742 | } 743 | 744 | size_t OLEDDisplay::write(uint8_t c) { 745 | if (this->logBufferSize > 0) { 746 | // Don't waste space on \r\n line endings, dropping \r 747 | if (c == 13) return 1; 748 | 749 | // convert UTF-8 character to font table index 750 | c = (this->fontTableLookupFunction)(c); 751 | // drop unknown character 752 | if (c == 0) return 1; 753 | 754 | bool maxLineNotReached = this->logBufferLine < this->logBufferMaxLines; 755 | bool bufferNotFull = this->logBufferFilled < this->logBufferSize; 756 | 757 | // Can we write to the buffer? 758 | if (bufferNotFull && maxLineNotReached) { 759 | this->logBuffer[logBufferFilled] = c; 760 | this->logBufferFilled++; 761 | // Keep track of lines written 762 | if (c == 10) this->logBufferLine++; 763 | } else { 764 | // Max line number is reached 765 | if (!maxLineNotReached) this->logBufferLine--; 766 | 767 | // Find the end of the first line 768 | uint16_t firstLineEnd = 0; 769 | for (uint16_t i=0;ilogBufferFilled;i++) { 770 | if (this->logBuffer[i] == 10){ 771 | // Include last char too 772 | firstLineEnd = i + 1; 773 | break; 774 | } 775 | } 776 | // If there was a line ending 777 | if (firstLineEnd > 0) { 778 | // Calculate the new logBufferFilled value 779 | this->logBufferFilled = logBufferFilled - firstLineEnd; 780 | // Now we move the lines infront of the buffer 781 | memcpy(this->logBuffer, &this->logBuffer[firstLineEnd], logBufferFilled); 782 | } else { 783 | // Let's reuse the buffer if it was full 784 | if (!bufferNotFull) { 785 | this->logBufferFilled = 0; 786 | }// else { 787 | // Nothing to do here 788 | //} 789 | } 790 | write(c); 791 | } 792 | } 793 | // We are always writing all uint8_t to the buffer 794 | return 1; 795 | } 796 | 797 | size_t OLEDDisplay::write(const char* str) { 798 | if (str == NULL) return 0; 799 | size_t length = strlen(str); 800 | for (size_t i = 0; i < length; i++) { 801 | write(str[i]); 802 | } 803 | return length; 804 | } 805 | 806 | // Private functions 807 | void OLEDDisplay::setGeometry(OLEDDISPLAY_GEOMETRY g) { 808 | this->geometry = g; 809 | if (g == GEOMETRY_128_64) { 810 | this->displayWidth = 128; 811 | this->displayHeight = 64; 812 | } else if (g == GEOMETRY_128_32) { 813 | this->displayWidth = 128; 814 | this->displayHeight = 32; 815 | } else if (g == GEOMETRY_64_32) { 816 | this->displayWidth = 64; 817 | this->displayHeight = 32; 818 | } 819 | this->displayBufferSize = displayWidth*displayHeight/8; 820 | } 821 | 822 | void OLEDDisplay::sendInitCommands(void) { 823 | sendCommand(DISPLAYOFF); 824 | sendCommand(SETDISPLAYCLOCKDIV); 825 | sendCommand(0xF0); // Increase speed of the display max ~96Hz 826 | sendCommand(SETMULTIPLEX); 827 | sendCommand(this->height() - 1); 828 | sendCommand(SETDISPLAYOFFSET); 829 | sendCommand(0x00); 830 | sendCommand(SETSTARTLINE); 831 | sendCommand(CHARGEPUMP); 832 | sendCommand(0x14); 833 | sendCommand(MEMORYMODE); 834 | sendCommand(0x00); 835 | sendCommand(SEGREMAP); 836 | sendCommand(COMSCANINC); 837 | sendCommand(SETCOMPINS); 838 | 839 | if ((geometry == GEOMETRY_128_64) || (geometry == GEOMETRY_64_32)) { 840 | sendCommand(0x12); 841 | } else if (geometry == GEOMETRY_128_32) { 842 | sendCommand(0x02); 843 | } 844 | 845 | sendCommand(SETCONTRAST); 846 | 847 | if ((geometry == GEOMETRY_128_64) || (geometry == GEOMETRY_64_32)) { 848 | sendCommand(0xCF); 849 | } else if (geometry == GEOMETRY_128_32) { 850 | sendCommand(0x8F); 851 | } 852 | 853 | sendCommand(SETPRECHARGE); 854 | sendCommand(0xF1); 855 | sendCommand(SETVCOMDETECT); //0xDB, (additionally needed to lower the contrast) 856 | sendCommand(0x40); //0x40 default, to lower the contrast, put 0 857 | sendCommand(DISPLAYALLON_RESUME); 858 | sendCommand(NORMALDISPLAY); 859 | sendCommand(0x2e); // stop scroll 860 | sendCommand(DISPLAYON); 861 | } 862 | 863 | void inline OLEDDisplay::drawInternal(int16_t xMove, int16_t yMove, int16_t width, int16_t height, const uint8_t *data, uint16_t offset, uint16_t bytesInData) { 864 | if (width < 0 || height < 0) return; 865 | if (yMove + height < 0 || yMove > this->height()) return; 866 | if (xMove + width < 0 || xMove > this->width()) return; 867 | 868 | uint8_t rasterHeight = 1 + ((height - 1) >> 3); // fast ceil(height / 8.0) 869 | int8_t yOffset = yMove & 7; 870 | 871 | bytesInData = bytesInData == 0 ? width * rasterHeight : bytesInData; 872 | 873 | int16_t initYMove = yMove; 874 | int8_t initYOffset = yOffset; 875 | 876 | 877 | for (uint16_t i = 0; i < bytesInData; i++) { 878 | 879 | // Reset if next horizontal drawing phase is started. 880 | if ( i % rasterHeight == 0) { 881 | yMove = initYMove; 882 | yOffset = initYOffset; 883 | } 884 | 885 | byte currentByte = pgm_read_byte(data + offset + i); 886 | 887 | int16_t xPos = xMove + (i / rasterHeight); 888 | int16_t yPos = ((yMove >> 3) + (i % rasterHeight)) * this->width(); 889 | 890 | // int16_t yScreenPos = yMove + yOffset; 891 | int16_t dataPos = xPos + yPos; 892 | 893 | if (dataPos >= 0 && dataPos < displayBufferSize && 894 | xPos >= 0 && xPos < this->width() ) { 895 | 896 | if (yOffset >= 0) { 897 | switch (this->color) { 898 | case WHITE: buffer[dataPos] |= currentByte << yOffset; break; 899 | case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break; 900 | case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break; 901 | } 902 | 903 | if (dataPos < (displayBufferSize - this->width())) { 904 | switch (this->color) { 905 | case WHITE: buffer[dataPos + this->width()] |= currentByte >> (8 - yOffset); break; 906 | case BLACK: buffer[dataPos + this->width()] &= ~(currentByte >> (8 - yOffset)); break; 907 | case INVERSE: buffer[dataPos + this->width()] ^= currentByte >> (8 - yOffset); break; 908 | } 909 | } 910 | } else { 911 | // Make new offset position 912 | yOffset = -yOffset; 913 | 914 | switch (this->color) { 915 | case WHITE: buffer[dataPos] |= currentByte >> yOffset; break; 916 | case BLACK: buffer[dataPos] &= ~(currentByte >> yOffset); break; 917 | case INVERSE: buffer[dataPos] ^= currentByte >> yOffset; break; 918 | } 919 | 920 | // Prepare for next iteration by moving one block up 921 | yMove -= 8; 922 | 923 | // and setting the new yOffset 924 | yOffset = 8 - yOffset; 925 | } 926 | 927 | yield(); 928 | } 929 | } 930 | } 931 | 932 | // You need to free the char! 933 | char* OLEDDisplay::utf8ascii(String str) { 934 | uint16_t k = 0; 935 | uint16_t length = str.length() + 1; 936 | 937 | // Copy the string into a char array 938 | char* s = (char*) malloc(length * sizeof(char)); 939 | if(!s) { 940 | DEBUG_OLEDDISPLAY("[OLEDDISPLAY][utf8ascii] Can't allocate another char array. Drop support for UTF-8.\n"); 941 | return (char*) str.c_str(); 942 | } 943 | str.toCharArray(s, length); 944 | 945 | length--; 946 | 947 | for (uint16_t i=0; i < length; i++) { 948 | char c = (this->fontTableLookupFunction)(s[i]); 949 | if (c!=0) { 950 | s[k++]=c; 951 | } 952 | } 953 | 954 | s[k]=0; 955 | 956 | // This will leak 's' be sure to free it in the calling function. 957 | return s; 958 | } 959 | 960 | void OLEDDisplay::setFontTableLookupFunction(FontTableLookupFunction function) { 961 | this->fontTableLookupFunction = function; 962 | } 963 | 964 | 965 | 966 | -------------------------------------------------------------------------------- /ESP32_CRSFSniffer.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2021 by g3gg0.de 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in all 14 | * copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | * SOFTWARE. 23 | * 24 | * crossfire sniffing receiver 25 | * 26 | */ 27 | 28 | /* needs 29 | #define CONFIG_DISABLE_HAL_LOCKS 1 30 | in 31 | C:\Users\\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.4\cores\esp32\esp32-hal.h 32 | else you will get crashes 33 | */ 34 | 35 | 36 | /* 37 | 38 | Rx 03 AA FC F7 1F 80 A1 84 12 4A 28 00 00 00 00 00 00 00 00 00 00 32 E2 39 | || | | || | | \___/ 40 | || | | || | telemetry payload | CRC 41 | || | 80 bits | || \______________________/ 42 | || | = 10 bits * 8 sticks | | \_ telemetry flags? 43 | || | | \__ telemetry length 44 | || \_________________________/ 45 | || 46 | | \_ packet type: 3 normal FSK uplink data 47 | | 1 50Hz mode uplink data? 48 | | 49 | \__ flags: 2 sticks 8-11 50 | 51 | 52 | 53 | Tx 03 75 64 00 00 00 00 00 00 00 00 00 0F 54 | || | | | | \_ CRC 55 | || | | | telemetry payload | 56 | || \_/ \______________________/ 57 | || | 58 | || \_ cycling metadata (RSSI etc) 59 | || 60 | | \_ packet type: 3 normal FSK downlink data 61 | | 1 50Hz mode downlink data? 62 | | B telemetry payload 63 | | 64 | \__ flags: 2 did not receive uplink for 8 times 65 | 8 metadata cycle start 66 | 67 | 68 | */ 69 | #if !defined(CONFIG_DISABLE_HAL_LOCKS) 70 | #error "please add '#define CONFIG_DISABLE_HAL_LOCKS 1' at about line 66 of esp32-hal.h else this code will crash" 71 | #endif 72 | 73 | #include 74 | #include 75 | 76 | #include "SSD1306Wire.h" 77 | #include "SX1276.h" 78 | #include "Plot.h" 79 | 80 | #include "esp32-hal-timer.h" 81 | 82 | #define COUNT(x) (sizeof(x)/sizeof((x)[0])) 83 | #define CONFIG_MAGIC 0xC0FFFEF6 84 | 85 | typedef struct 86 | { 87 | uint8_t entries; 88 | uint8_t slots[4]; 89 | } timeslotInfo_t; 90 | 91 | typedef struct 92 | { 93 | uint32_t magic; 94 | uint8_t hoppingSequence[150]; 95 | uint64_t startFreq; 96 | } receiver_config; 97 | 98 | receiver_config config; 99 | 100 | SX1276Class SX1276; 101 | SSD1306Wire *Display; 102 | 103 | uint16_t channelValues[16]; 104 | 105 | bool currentDirectionDown = false; 106 | uint16_t currentChannel = 0; 107 | uint16_t currentLength = 0; 108 | int state = 0; 109 | uint64_t startTimestamp = 0; 110 | uint64_t prevTimestamp = 0; 111 | int checkChan = 0; 112 | int retries = 0; 113 | 114 | uint8_t hoppingPos = 0; 115 | uint32_t cfgBitrate = 85000; 116 | uint32_t cfgFreqDev = 42300; 117 | uint32_t cfgChanDist = 260010; 118 | uint64_t cfgStartFreq = 860000000ULL; 119 | bool enableAfc = false; 120 | 121 | float freqCorrectionUp = 0; 122 | float freqCorrectionDown = 0; 123 | 124 | int16_t statRssiUp = 0; 125 | int16_t statRssiDown = 0; 126 | int16_t scanRssi = 0; 127 | uint64_t lastPacketTimestamp = 0; 128 | 129 | timeslotInfo_t timeslotMap[50]; 130 | float packet_ms = 6666.666666666f * 1.00101f; 131 | hw_timer_t * scheduleTimer = NULL; 132 | 133 | uint32_t zeroSyncTime[10]; 134 | uint32_t zeroSyncTimePos = 0; 135 | uint64_t prevSyncStart = 0; 136 | uint32_t channelExpects[10]; 137 | bool synced = false; 138 | uint32_t losses = 0; 139 | 140 | uint64_t freqScanFreq = 859500000ULL; 141 | uint64_t freqScanFreqCur = 0; 142 | uint32_t freqScanBw = 10000; 143 | 144 | 145 | uint32_t statUpScheduled = 0; 146 | uint32_t statUpLoss = 0; 147 | uint32_t statUpReceived = 0; 148 | float statUpHeadroom = 0; 149 | uint32_t statDownScheduled = 0; 150 | uint32_t statDownLoss = 0; 151 | uint32_t statDownReceived = 0; 152 | float statDownHeadroom = 0; 153 | float statAverageScheduleLength = 0; 154 | uint32_t statResyncs = 0; 155 | uint32_t learnSchedLength = 6676; 156 | 157 | PlotClass *plotRssiUp; 158 | PlotClass *plotRssiDown; 159 | PlotClass *plotFCorrUp; 160 | PlotClass *plotFCorrDown; 161 | PlotClass *plotFreq; 162 | PlotClass *plotSchedLen; 163 | PlotClass *plotLossUp; 164 | PlotClass *plotLossDown; 165 | PlotClass *plotScan; 166 | 167 | 168 | void IRAM_ATTR setChan(uint16_t chan, bool downlink) 169 | { 170 | uint16_t chanAbs = chan + (downlink ? 50 : 0); 171 | uint32_t freq = config.startFreq + chanAbs * cfgChanDist + (downlink ? freqCorrectionDown : freqCorrectionUp); 172 | 173 | currentChannel = chan; 174 | currentDirectionDown = downlink; 175 | currentLength = downlink ? 0x0D : 0x17; 176 | 177 | SX1276.setStandby(); 178 | SX1276.writeAfc(0); 179 | SX1276.writeFreq(freq); 180 | SX1276.writePayloadLength(currentLength); 181 | SX1276.writeRegister(0x0C, 0x23); 182 | 183 | /* AgcAutoOn and AGC PreambleDetect RxTrigger */ 184 | SX1276.writeRxConfig(0x08 | 6 | (enableAfc ? 0x10 : 0)); 185 | 186 | SX1276.setRx(); 187 | } 188 | 189 | bool IRAM_ATTR calc_channel(uint32_t *slotDelta, int32_t *remainder, uint64_t timestamp, uint64_t startTimestamp) 190 | { 191 | uint64_t delta = timestamp - startTimestamp; 192 | float distance = (float)delta / packet_ms; 193 | 194 | *slotDelta = (int)(distance + 0.5f) % 150; 195 | *remainder = 100.0f * (distance - (int)(distance + 0.5f)); 196 | 197 | if(*remainder > 1 || *remainder < -1) 198 | { 199 | return false; 200 | } 201 | return true; 202 | } 203 | 204 | int32_t IRAM_ATTR addDelta(uint8_t channel, uint64_t timestamp, uint64_t startTimestamp) 205 | { 206 | uint64_t delta = timestamp - startTimestamp; 207 | uint32_t slotDelta = 0; 208 | int32_t remainder = 0; 209 | 210 | bool match = calc_channel(&slotDelta, &remainder, timestamp, startTimestamp); 211 | 212 | if(remainder > 10 || remainder < -10) 213 | { 214 | Serial.printf("OFF : Channel #%2u %3u (%7llu us, remainder %3i, %llu %llu)\n", channel, slotDelta, delta, remainder, timestamp, startTimestamp); 215 | return remainder; 216 | } 217 | timeslotInfo_t *slot = ×lotMap[channel]; 218 | 219 | for(int pos = 0; pos < slot->entries; pos++) 220 | { 221 | if(slot->slots[pos] == slotDelta) 222 | { 223 | Serial.printf("SKIP: Channel #%2u %3u (%7llu us, remainder %3i) - already contained\n", channel, slotDelta, delta, remainder); 224 | return remainder; 225 | } 226 | } 227 | 228 | if(slot->entries >= 4) 229 | { 230 | Serial.printf("FAIL: Channel #%2u %3u (%7llu us, remainder %3i) - already enough\n", channel, slotDelta, delta, remainder); 231 | return remainder; 232 | } 233 | 234 | slot->slots[slot->entries++] = slotDelta; 235 | Serial.printf("ADD : Channel #%2u %3u (%7llu us, remainder %3i, %llu %llu)\n", channel, slotDelta, delta, remainder, timestamp, startTimestamp); 236 | 237 | return remainder; 238 | } 239 | 240 | void IRAM_ATTR timer_isr_body(uint64_t timestamp) 241 | { 242 | const char *dir = currentDirectionDown ? "D" : "U"; 243 | 244 | if(lastPacketTimestamp == 0) 245 | { 246 | losses++; 247 | } 248 | else 249 | { 250 | losses = 0; 251 | } 252 | 253 | if(losses > 200) 254 | { 255 | statResyncs++; 256 | state = 200; 257 | Serial.printf("Lost Sync\n"); 258 | return; 259 | } 260 | 261 | uint32_t lastPacketDelta = timestamp - lastPacketTimestamp; 262 | 263 | if(currentDirectionDown) 264 | { 265 | setChan(config.hoppingSequence[hoppingPos++], false); 266 | hoppingPos %= 150; 267 | timerAlarmWrite(scheduleTimer, prevTimestamp + learnSchedLength, false); 268 | 269 | statDownScheduled++; 270 | if(lastPacketTimestamp == 0) 271 | { 272 | plotLossDown->AddSample(1); 273 | statDownLoss++; 274 | } 275 | else 276 | { 277 | plotLossDown->AddSample(0); 278 | statDownHeadroom = (63.0f * statDownHeadroom + lastPacketDelta) / 64.0f; 279 | statDownReceived++; 280 | } 281 | } 282 | else 283 | { 284 | uint64_t prevTimestampOld = prevTimestamp; 285 | bool lastSuccessful = false; 286 | 287 | setChan(currentChannel, true); 288 | prevTimestamp += learnSchedLength; 289 | timerAlarmWrite(scheduleTimer, prevTimestamp + 2650, false); 290 | 291 | statUpScheduled++; 292 | if(lastPacketTimestamp == 0) 293 | { 294 | plotLossUp->AddSample(1); 295 | statUpLoss++; 296 | lastSuccessful = false; 297 | } 298 | else 299 | { 300 | plotLossUp->AddSample(0); 301 | statUpHeadroom = (63.0f * statUpHeadroom + lastPacketDelta) / 64.0f; 302 | statUpReceived++; 303 | lastSuccessful = true; 304 | } 305 | 306 | if(lastPacketDelta < 180) 307 | { 308 | prevTimestamp += 10; 309 | } 310 | else if(lastPacketDelta > 220) 311 | { 312 | prevTimestamp -= 10; 313 | } 314 | 315 | uint32_t scheduleLength = prevTimestamp - prevTimestampOld; 316 | 317 | if(scheduleLength > 6500 && scheduleLength < 6800 && lastSuccessful) 318 | { 319 | if(statAverageScheduleLength < 1) 320 | { 321 | statAverageScheduleLength = scheduleLength; 322 | } 323 | statAverageScheduleLength = (63.0f * statAverageScheduleLength + scheduleLength) / 64.0f; 324 | 325 | plotFreq->AddSample(1000000.0f / scheduleLength); 326 | plotSchedLen->AddSample(statAverageScheduleLength); 327 | 328 | static uint32_t update_delay = 0; 329 | if(update_delay++ > 10000) 330 | { 331 | update_delay = 0; 332 | if(learnSchedLength < statAverageScheduleLength) 333 | { 334 | learnSchedLength++; 335 | } 336 | else if(learnSchedLength > statAverageScheduleLength) 337 | { 338 | learnSchedLength--; 339 | } 340 | } 341 | } 342 | } 343 | lastPacketTimestamp = 0; 344 | timerAlarmEnable(scheduleTimer); 345 | //Serial.printf("Lost %s %d times, next #%d %s\n", dir, losses, currentChannel, currentDirectionDown ? "D" : "U"); 346 | } 347 | 348 | #define SKIP_SPACE(l) do { while(*line && *line == ' ') {line++;} } while (0) 349 | 350 | void IRAM_ATTR parseChannels(uint8_t *buffer) 351 | { 352 | uint32_t chanBits = 0; 353 | uint32_t channel = 0; 354 | uint32_t value = 0; 355 | bool upperEight = buffer[0] & 0x20; 356 | 357 | /* go through all payload bytes */ 358 | for (int bitPos = 0; bitPos < 11; bitPos++) 359 | { 360 | /* fetch 8 bits */ 361 | value |= ((uint32_t)buffer[1 + bitPos]) << chanBits; 362 | chanBits += 8; 363 | 364 | /* when we got enough (10) bits, treat this as a sample */ 365 | if(chanBits >= 10) 366 | { 367 | int chanOffset = 0; 368 | 369 | /* handle channel multiplexing */ 370 | if(channel > 3 && upperEight) 371 | { 372 | chanOffset = 4; 373 | } 374 | channelValues[chanOffset + channel++] = (value & 0x3FF); 375 | /* keep remaining bits */ 376 | value >>= 10; 377 | chanBits -= 10; 378 | } 379 | } 380 | } 381 | 382 | typedef struct 383 | { 384 | uint32_t filled = 0; 385 | uint32_t maxLen = 0; 386 | uint8_t receivedBuffer[256]; 387 | } telemetryBuffer; 388 | 389 | void IRAM_ATTR telemetryAdd(uint32_t direction, uint8_t *buffer, uint32_t length) 390 | { 391 | static telemetryBuffer buffers[2]; 392 | const char *dir = direction ? "D" : "U"; 393 | 394 | if(buffers[direction].filled == 0) 395 | { 396 | if(buffer[0] == 0xDA && buffer[1] == 0x09) 397 | { 398 | int thisLen = length - 3; 399 | 400 | buffers[direction].maxLen = buffer[2]; 401 | buffers[direction].filled = 0; 402 | 403 | memcpy(&buffers[direction].receivedBuffer[buffers[direction].filled], &buffer[3], thisLen); 404 | buffers[direction].filled += thisLen; 405 | } 406 | /* 407 | DA 0F 02 22 47 64 9B 408 | | | | | \_ crc 409 | | | | \_ TQly 410 | | | \_ TSNR 411 | | \_ TRSS 412 | \_ RFMD 413 | */ 414 | } 415 | else 416 | { 417 | memcpy(&buffers[direction].receivedBuffer[buffers[direction].filled], buffer, length); 418 | buffers[direction].filled += length; 419 | } 420 | 421 | if(buffers[direction].maxLen > 0 && buffers[direction].filled >= buffers[direction].maxLen) 422 | { 423 | bool parsed = false; 424 | uint8_t *receivedBuffer = buffers[direction].receivedBuffer; 425 | 426 | switch(receivedBuffer[0]) 427 | { 428 | /* 429 | 0x08 Battery sensor 430 | Payload: 431 | uint16_t Voltage ( mV * 100 ) 432 | uint16_t Current ( mA * 100 ) 433 | uint24_t Fuel ( drawn mAh ) 434 | uint8_t Battery remaining ( percent ) 435 | */ 436 | case 0x08: 437 | { 438 | uint16_t voltage = (receivedBuffer[1] << 8) | receivedBuffer[2]; 439 | uint16_t current = (receivedBuffer[3] << 8) | receivedBuffer[4]; 440 | uint32_t drawn = (receivedBuffer[5] << 16) | (receivedBuffer[6] << 8) | receivedBuffer[7]; 441 | uint8_t remain = receivedBuffer[8]; 442 | 443 | Serial.printf("%s: Battery: %2.1fV, %2.1fmA, %dmAh, %d%%\n", dir, (float)voltage / 10.0f, (float)current / 10.0f, drawn, remain); 444 | parsed = true; 445 | break; 446 | } 447 | 448 | case 0x28: 449 | { 450 | Serial.printf("%s: %02X <- %02X discover\n", dir, receivedBuffer[1], receivedBuffer[2]); 451 | parsed = true; 452 | break; 453 | } 454 | 455 | case 0x29: 456 | { 457 | Serial.printf("%s: %02X <- %02X response '%s'\n", dir, receivedBuffer[1], receivedBuffer[2], &receivedBuffer[3]); 458 | parsed = true; 459 | break; 460 | } 461 | 462 | /* 463 | 0x2B config entry response 464 | 2B [dst] [src] [ID] [cont] [parentID] [flags] [name] 00 465 | 466 | [dst] EA = Transmitter 467 | EC = Receiver 468 | [cont] = 0 is last packet, else number of following 469 | [flags] 0x0B = has children list after name, terminated with 0xFF 470 | 0x09 = has option list after name, 00, default value somehow 471 | 0x08 = unknown 472 | 0x0D = executable 473 | 0x80 = hidden 474 | */ 475 | case 0x2B: 476 | { 477 | static uint8_t lastId = 0xFF; 478 | 479 | if(receivedBuffer[3] != lastId) 480 | { 481 | lastId = receivedBuffer[3]; 482 | switch(receivedBuffer[6] & 0x0F) 483 | { 484 | case 0x08: 485 | Serial.printf("%s: Menu #%d - %s\n", dir, receivedBuffer[3], &receivedBuffer[7]); 486 | break; 487 | case 0x09: 488 | Serial.printf("%s: Menu #%d - %s options: %s\n", dir, receivedBuffer[3], &receivedBuffer[7], &receivedBuffer[7+1+strlen((char*)&receivedBuffer[7])]); 489 | break; 490 | case 0x0B: 491 | Serial.printf("%s: Menu #%d - %s (children)\n", dir, receivedBuffer[3], &receivedBuffer[7]); 492 | break; 493 | case 0x0C: 494 | Serial.printf("%s: Menu #%d - ", dir, receivedBuffer[3]); 495 | Serial.printf("%s ", &receivedBuffer[7]); 496 | Serial.printf("%s\n", &receivedBuffer[7+1+strlen((char*)&receivedBuffer[7])]); 497 | break; 498 | case 0x0D: 499 | Serial.printf("%s: Menu #%d - %s (exec)\n", dir, receivedBuffer[3], &receivedBuffer[7]); 500 | break; 501 | } 502 | } 503 | parsed = true; 504 | break; 505 | } 506 | } 507 | 508 | if(!parsed) 509 | { 510 | char buf[512]; 511 | 512 | for(int pos = 0; pos < buffers[direction].filled; pos++) 513 | { 514 | sprintf(&buf[pos*3], "%02X ", buffers[direction].receivedBuffer[pos]); 515 | } 516 | for(int pos = 0; pos < buffers[direction].filled; pos++) 517 | { 518 | char ch = '.'; 519 | if(buffers[direction].receivedBuffer[pos] >= ' ' && buffers[direction].receivedBuffer[pos] <= 'z') 520 | { 521 | ch = buffers[direction].receivedBuffer[pos]; 522 | } 523 | sprintf(&buf[buffers[direction].filled*3 + pos], "%c", ch); 524 | } 525 | Serial.printf("%s: Telemetry (%u): %s\n", dir, buffers[direction].filled, buf); 526 | } 527 | 528 | buffers[direction].maxLen = 0; 529 | buffers[direction].filled = 0; 530 | } 531 | } 532 | 533 | void IRAM_ATTR parseDownlink(uint8_t *buffer) 534 | { 535 | bool first = buffer[0] & 0x80; 536 | uint8_t type = buffer[0] & 0x0F; 537 | char buf[128]; 538 | 539 | switch(type) 540 | { 541 | case 1: 542 | Serial.printf("D: type 0x%02X\n", buffer[0]); 543 | break; 544 | 545 | case 3: 546 | //parseChannels(buffer); 547 | break; 548 | 549 | case 0x0B: 550 | { 551 | uint8_t len = (buffer[2] & 0xF0) >> 4; 552 | 553 | /* as we dont check CRC, invalid packets cause trouble */ 554 | //telemetryAdd(0, &buffer[3], len); 555 | 556 | break; 557 | } 558 | 559 | default: 560 | for(int pos = 0; pos < 0x0D; pos++) 561 | { 562 | sprintf(&buf[pos*3], "%02X ", buffer[pos]); 563 | } 564 | for(int pos = 0; pos < 0x0D; pos++) 565 | { 566 | char ch = '.'; 567 | if(buffer[pos] >= ' ' && buffer[pos] < 'z') 568 | { 569 | ch = buffer[pos]; 570 | } 571 | sprintf(&buf[0x0D*3 + pos], "%c", ch); 572 | } 573 | Serial.printf("D: %s\n", buf); 574 | break; 575 | } 576 | } 577 | 578 | void IRAM_ATTR parseUplink(uint8_t *buffer) 579 | { 580 | bool first = buffer[0] & 0x80; 581 | bool alternate = buffer[0] & 0x20; 582 | uint8_t type = buffer[0] & 0x0F; 583 | uint8_t lenExtra = (buffer[11] & 0xF0) >> 4; 584 | uint8_t flagExtra = (buffer[11] & 0x0F); 585 | char buf[128]; 586 | 587 | switch(type) 588 | { 589 | case 1: 590 | Serial.printf("U: 0x%02X at %d\n", buffer[0], hoppingPos); 591 | parseChannels(buffer); 592 | break; 593 | 594 | case 3: 595 | parseChannels(buffer); 596 | break; 597 | 598 | default: 599 | for(int pos = 0; pos < 0x17; pos++) 600 | { 601 | sprintf(&buf[pos*3], "%02X ", buffer[pos]); 602 | } 603 | Serial.printf("U: %s\n", buf); 604 | break; 605 | } 606 | 607 | if(lenExtra) 608 | { 609 | for(int pos = 0; pos < lenExtra + 1; pos++) 610 | { 611 | sprintf(&buf[pos*3], "%02X ", buffer[11 + pos]); 612 | } 613 | for(int pos = 0; pos < lenExtra + 1; pos++) 614 | { 615 | char ch = '.'; 616 | if(buffer[11 + pos] >= ' ' && buffer[11 + pos] < 'z') 617 | { 618 | ch = buffer[pos]; 619 | } 620 | sprintf(&buf[(lenExtra + 1)*3 + pos], "%c", ch); 621 | } 622 | 623 | /* as we dont check CRC, invalid packets cause trouble */ 624 | //telemetryAdd(1, &buffer[12], lenExtra); 625 | Serial.printf("U: %s\n", buf); 626 | } 627 | } 628 | 629 | uint8_t IRAM_ATTR chanPercent(int channel) 630 | { 631 | uint32_t value = channelValues[channel]; 632 | 633 | if(value < 0xA1) 634 | { 635 | value = 0xA1; 636 | } 637 | value -= 0xA1; 638 | if(value > 0x2BB) 639 | { 640 | value = 0x2BB; 641 | } 642 | 643 | return (value * 100) / 0x2BB; 644 | } 645 | 646 | void IRAM_ATTR fifo_isr_body(uint64_t timestamp) 647 | { 648 | bool restart = false; 649 | bool scanDownlink = false; 650 | 651 | uint8_t rssi = SX1276.readRssi(); 652 | int32_t fei = SX1276.readFei(); 653 | int32_t afc = SX1276.readAfc(); 654 | 655 | switch(state) 656 | { 657 | case 401: 658 | case 402: 659 | { 660 | uint8_t receive_buffer[64]; 661 | char buf[128]; 662 | 663 | if(rssi < scanRssi) 664 | { 665 | scanRssi = rssi; 666 | } 667 | 668 | for(int fifoPos = 0; fifoPos < currentLength; fifoPos++) 669 | { 670 | receive_buffer[fifoPos] = SX1276.readFifo(); 671 | } 672 | for(int pos = 0; pos < 0x17; pos++) 673 | { 674 | sprintf(&buf[pos*3], "%02X ", receive_buffer[pos]); 675 | } 676 | 677 | Serial.printf("ch#%02d: %s, RSSI -%03d, FEI %i\n", currentChannel, buf, rssi/2, fei); 678 | SX1276.setRx(); 679 | break; 680 | } 681 | 682 | case 201: 683 | { 684 | Serial.printf("Sync to slot 0\n"); 685 | setChan(0, false); 686 | zeroSyncTimePos = 0; 687 | state++; 688 | 689 | /* reset statistics - except resyncs */ 690 | statUpScheduled = 0; 691 | statUpLoss = 0; 692 | statUpReceived = 0; 693 | statUpHeadroom = 0; 694 | statDownScheduled = 0; 695 | statDownLoss = 0; 696 | statDownReceived = 0; 697 | statDownHeadroom = 0; 698 | statAverageScheduleLength = 0; 699 | learnSchedLength = 6676; 700 | break; 701 | } 702 | 703 | case 202: 704 | { 705 | /* find the channel 0 packet which is our hopping sequence start position by the time delta 706 | * these numbers are for sure not generic, so maybe use some other way to detect a distinguishable 707 | * pattern that gives us the start of the hopping sequence 708 | */ 709 | if(prevTimestamp != 0) 710 | { 711 | uint32_t delta = (uint32_t)(timestamp - prevTimestamp); 712 | 713 | if(delta > 373000 && delta < 374000) 714 | { 715 | prevTimestamp = timestamp + 200; 716 | startTimestamp = prevTimestamp; 717 | freqCorrectionDown = 0; 718 | freqCorrectionUp = 0; 719 | hoppingPos = 1; 720 | setChan(0, true); 721 | timerAlarmWrite(scheduleTimer, prevTimestamp + 2700, false); 722 | timerAlarmEnable(scheduleTimer); 723 | Serial.printf("Synced\n"); 724 | state++; 725 | break; 726 | } 727 | } 728 | 729 | prevTimestamp = timestamp; 730 | SX1276.setRx(); 731 | break; 732 | } 733 | 734 | case 203: 735 | { 736 | lastPacketTimestamp = timestamp; 737 | 738 | uint8_t receive_buffer[64]; 739 | 740 | for(int fifoPos = 0; fifoPos < currentLength; fifoPos++) 741 | { 742 | receive_buffer[fifoPos] = SX1276.readFifo(); 743 | } 744 | 745 | if(!currentDirectionDown) 746 | { 747 | digitalWrite(LED, HIGH); 748 | statRssiUp = (31.0f*statRssiUp + rssi) / 32.0f; 749 | plotRssiUp->AddSample(rssi * -0.5f); 750 | freqCorrectionUp += afc / 1000.0f; 751 | plotFCorrUp->AddSample(afc); 752 | 753 | parseUplink(receive_buffer); 754 | } 755 | else 756 | { 757 | digitalWrite(LED, LOW); 758 | statRssiDown = (31.0f*statRssiDown + rssi) / 32.0f; 759 | plotRssiDown->AddSample(rssi * -0.5f); 760 | freqCorrectionDown += afc / 1000.0f; 761 | plotFCorrDown->AddSample(afc); 762 | 763 | parseDownlink(receive_buffer); 764 | } 765 | break; 766 | } 767 | 768 | 769 | case 101: 770 | { 771 | Serial.printf("Sync to slot 0\n"); 772 | setChan(0, scanDownlink); 773 | zeroSyncTimePos = 0; 774 | state++; 775 | break; 776 | } 777 | 778 | case 102: 779 | { 780 | if(synced) 781 | { 782 | uint32_t channel = 0; 783 | int32_t remainder = 0; 784 | bool match = calc_channel(&channel, &remainder, timestamp, prevSyncStart); 785 | 786 | if(zeroSyncTimePos == 0) 787 | { 788 | Serial.printf("<-- %7u --> ", (uint32_t)(timestamp - prevSyncStart)); 789 | } 790 | Serial.printf("dist ch%u (%u)\n", channel, remainder); 791 | 792 | for(int pos = 0; pos < 3; pos++) 793 | { 794 | if(channelExpects[(zeroSyncTimePos + pos)%3] == channel) 795 | { 796 | zeroSyncTimePos += pos; 797 | zeroSyncTimePos %= 3; 798 | break; 799 | } 800 | Serial.printf("skipped one slot(?)\n"); 801 | } 802 | } 803 | 804 | zeroSyncTime[zeroSyncTimePos++] = timestamp; 805 | 806 | if(zeroSyncTimePos >= 3) 807 | { 808 | Serial.printf("channel map: "); 809 | 810 | for(int pos = 0; pos < 3; pos++) 811 | { 812 | uint32_t channel = 0; 813 | int32_t remainder = 0; 814 | 815 | bool match = calc_channel(&channel, &remainder, zeroSyncTime[pos], zeroSyncTime[0]); 816 | Serial.printf("ch%u (%u) ", channel, remainder); 817 | 818 | channelExpects[pos] = channel; 819 | } 820 | Serial.printf("\n"); 821 | 822 | prevSyncStart = zeroSyncTime[0]; 823 | synced = true; 824 | setChan(0, scanDownlink); 825 | zeroSyncTimePos = 0; 826 | break; 827 | } 828 | setChan(0, scanDownlink); 829 | break; 830 | } 831 | 832 | case 1: 833 | prevTimestamp = timestamp; 834 | Serial.printf("Sync at %d kHz fei %i afc %i\n", (uint32_t)(config.startFreq / 1000), fei, afc); 835 | 836 | if(!retries) 837 | { 838 | config.startFreq += afc; 839 | enableAfc = false; 840 | } 841 | retries++; 842 | 843 | if(retries > 2) 844 | { 845 | Serial.printf("Sync at %d kHz -> proceed\n", (uint32_t)(config.startFreq / 1000)); 846 | prevTimestamp = 0; 847 | state++; 848 | } 849 | setChan(0, scanDownlink); 850 | break; 851 | 852 | case 2: 853 | { 854 | /* find the channel 0 packet which is our hopping sequence start position by the time delta 855 | * these numbers are for sure not generic, so maybe use some other way to detect a distinguishable 856 | * pattern that gives us the start of the hopping sequence 857 | */ 858 | if(prevTimestamp != 0) 859 | { 860 | uint32_t delta = (uint32_t)(timestamp - prevTimestamp); 861 | //Serial.printf("delta %d\n", delta); 862 | 863 | if(delta > 365000 && delta < 374000) 864 | { 865 | startTimestamp = timestamp; 866 | setChan(checkChan, scanDownlink); 867 | Serial.printf("Channel %d is next\n", checkChan); 868 | state++; 869 | break; 870 | } 871 | } 872 | 873 | prevTimestamp = timestamp; 874 | setChan(0, scanDownlink); 875 | break; 876 | } 877 | 878 | case 3: 879 | { 880 | int32_t remainder = addDelta(checkChan, timestamp, startTimestamp); 881 | 882 | /* try to compensate clock drift */ 883 | if(remainder != 0 && abs(remainder) < 10) 884 | { 885 | //packet_ms *= 1.0f + remainder / 100000.0f; 886 | startTimestamp += (remainder * packet_ms) / 100; 887 | //Serial.printf("packet_ms: %2.2f\n", packet_ms); 888 | } 889 | 890 | if(retries++ >= 3*20 || timeslotMap[checkChan].entries >= 3) 891 | { 892 | retries = 0; 893 | checkChan++; 894 | checkChan %= 50; 895 | 896 | /* done */ 897 | if(checkChan == 0) 898 | { 899 | state++; 900 | break; 901 | } 902 | 903 | /* when the drift gets to high resync to compensate clock drift. only checks last packet in this channel, so leave some margin */ 904 | if(/*(checkChan % 10) == 0 || */ abs(remainder) > 6) 905 | { 906 | state = 2; 907 | setChan(0, scanDownlink); 908 | } 909 | else 910 | { 911 | setChan(checkChan, scanDownlink); 912 | } 913 | break; 914 | } 915 | 916 | setChan(checkChan, scanDownlink); 917 | break; 918 | } 919 | } 920 | } 921 | 922 | 923 | void IRAM_ATTR fifoReadyIsr() 924 | { 925 | uint64_t timestamp_dummy = timerRead(scheduleTimer); 926 | uint64_t timestamp = timerRead(scheduleTimer); 927 | 928 | /* https://esp32.com/viewtopic.php?t=1292 */ 929 | static uint32_t cp0_regs[18]; 930 | uint32_t cp_state = xthal_get_cpenable(); // get FPU state 931 | 932 | if(cp_state) 933 | { 934 | xthal_save_cp0(cp0_regs); // Save FPU registers 935 | } 936 | else 937 | { 938 | xthal_set_cpenable(1); // enable FPU 939 | } 940 | 941 | fifo_isr_body(timestamp); 942 | 943 | if(cp_state) 944 | { 945 | xthal_restore_cp0(cp0_regs); // Restore FPU registers 946 | } 947 | else 948 | { 949 | xthal_set_cpenable(0); // turn it back off 950 | } 951 | } 952 | 953 | void IRAM_ATTR timer_isr() 954 | { 955 | uint64_t timestamp_dummy = timerRead(scheduleTimer); 956 | uint64_t timestamp = timerRead(scheduleTimer); 957 | 958 | /* https://esp32.com/viewtopic.php?t=1292 */ 959 | static uint32_t cp0_regs[18]; 960 | uint32_t cp_state = xthal_get_cpenable(); // get FPU state 961 | 962 | if(cp_state) 963 | { 964 | xthal_save_cp0(cp0_regs); // Save FPU registers 965 | } 966 | else 967 | { 968 | xthal_set_cpenable(1); // enable FPU 969 | } 970 | 971 | timer_isr_body(timestamp); 972 | 973 | if(cp_state) 974 | { 975 | xthal_restore_cp0(cp0_regs); // Restore FPU registers 976 | } 977 | else 978 | { 979 | xthal_set_cpenable(0); // turn it back off 980 | } 981 | } 982 | 983 | void save_config() 984 | { 985 | File file = SPIFFS.open("/config.bin", "w"); 986 | if(!file) 987 | { 988 | Serial.println("[E] failed to open file for writing"); 989 | } 990 | else 991 | { 992 | file.write((const uint8_t *)&config, sizeof(config)); 993 | file.close(); 994 | Serial.println("[i] wrote config to SPIFFS"); 995 | } 996 | } 997 | 998 | void load_config() 999 | { 1000 | File file = SPIFFS.open("/config.bin", "r"); 1001 | if(!file) 1002 | { 1003 | Serial.println("[E] failed to open config file for reading"); 1004 | } 1005 | else 1006 | { 1007 | file.read((uint8_t *)&config, sizeof(receiver_config)); 1008 | file.close(); 1009 | Serial.println("[i] read config from SPIFFS"); 1010 | } 1011 | 1012 | if(config.magic != CONFIG_MAGIC) 1013 | { 1014 | Serial.println("[i] incorrect magics or version, reinit"); 1015 | config.magic = CONFIG_MAGIC; 1016 | 1017 | memset((void *)&config.hoppingSequence, 0x00, sizeof(config.hoppingSequence)); 1018 | config.startFreq = cfgStartFreq; 1019 | save_config(); 1020 | } 1021 | } 1022 | 1023 | void loop_core1(void *unused); 1024 | 1025 | void setup() 1026 | { 1027 | Serial.begin(250000); 1028 | 1029 | Serial.printf("\n\n\n"); 1030 | 1031 | Serial.printf("[i] SDK: '%s'\n", ESP.getSdkVersion()); 1032 | Serial.printf("[i] CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()); 1033 | Serial.printf("[i] Chip Id: %06X\n", ESP.getEfuseMac()); 1034 | Serial.printf("[i] Flash Mode: %08X\n", ESP.getFlashChipMode()); 1035 | Serial.printf("[i] Flash Size: %08X\n", ESP.getFlashChipSize()); 1036 | Serial.printf("[i] Flash Speed: %d MHz\n", ESP.getFlashChipSpeed() / 1000000); 1037 | Serial.printf("[i] Heap %d/%d\n", ESP.getFreeHeap(), ESP.getHeapSize()); 1038 | Serial.printf("[i] SPIRam %d/%d\n", ESP.getFreePsram(), ESP.getPsramSize()); 1039 | Serial.printf("\n"); 1040 | 1041 | Serial.printf("[i] Starting on core %d\n", xPortGetCoreID()); 1042 | Serial.printf("[i] Setup SPIFFS\n"); 1043 | if(!SPIFFS.begin(true)) 1044 | { 1045 | Serial.println(" [E] mount failed"); 1046 | } 1047 | Serial.printf("[i] Load config\n"); 1048 | load_config(); 1049 | 1050 | Serial.printf("[i] Setup SX1276\n"); 1051 | if(!SX1276.begin()) 1052 | { 1053 | Serial.println("[ [E] init failed"); 1054 | } 1055 | 1056 | SX1276.writeBitrate(cfgBitrate); 1057 | SX1276.writeFreqDev(cfgFreqDev); 1058 | 1059 | Serial.printf("[i] Setup Display\n"); 1060 | 1061 | Display = new SSD1306Wire(0x3c, SDA_OLED, SCL_OLED, RST_OLED, GEOMETRY_128_64); 1062 | Display->init(); 1063 | Display->setContrast(5, 5, 0); 1064 | Display->flipScreenVertically(); 1065 | Display->setFont(ArialMT_Plain_10); 1066 | Display->clear(); 1067 | Display->display(); 1068 | 1069 | 1070 | Serial.printf("[i] Setup Timers/Interrupts\n"); 1071 | pinMode(DIO0, INPUT); 1072 | attachInterrupt(digitalPinToInterrupt(DIO0), fifoReadyIsr, RISING); 1073 | 1074 | scheduleTimer = timerBegin(2, 80, true); 1075 | timerAttachInterrupt(scheduleTimer, &timer_isr, true); 1076 | 1077 | pinMode(LED,OUTPUT); 1078 | digitalWrite(LED,LOW); 1079 | 1080 | Serial.printf("[i] Setup Plots\n"); 1081 | plotRssiUp = new PlotClass(Display, "RSSI up", 16, 64); 1082 | plotRssiDown = new PlotClass(Display, "RSSI dn", 16, 64); 1083 | plotFCorrUp = new PlotClass(Display, "Corr up", 56, 64); 1084 | plotFCorrDown = new PlotClass(Display, "Corr dn", 56, 64); 1085 | plotSchedLen = new PlotClass(Display, "PktDly", 56, 64); 1086 | plotFreq = new PlotClass(Display, "PktRate", 56, 64); 1087 | plotLossUp = new PlotClass(Display, "Loss up", 56, 64); 1088 | plotLossDown = new PlotClass(Display, "Loss dn", 56, 64); 1089 | plotScan = new PlotClass(Display, "Scan", 1, 100); 1090 | Serial.println("Setup done"); 1091 | 1092 | /* start with the hop-following sniff code */ 1093 | state = 0; 1094 | } 1095 | 1096 | 1097 | void loop() 1098 | { 1099 | char msg[32]; 1100 | static int lastTime = 0; 1101 | static int lastUpdateTime = 0; 1102 | static int buttonPressTime = 0; 1103 | static int lastButtonPressTime = 0; 1104 | static int currentDisplay = 0; 1105 | static float lastContrast = 0; 1106 | int displayCount = 9; 1107 | uint32_t currentTime = millis(); 1108 | 1109 | const char *menu_entries[] = { "Display", "Scan 868", "Scan 868 CE (ToDo)", "Scan 915", "Scan 915 AU (ToDo)", "Band Scan", "Freq Scan", "Analyze", "----" }; 1110 | static int menu_pos = 0; 1111 | static uint32_t currentScanChan = 0; 1112 | 1113 | 1114 | bool buttonPressed = digitalRead(0) == LOW; 1115 | 1116 | buttonPressed |= chanPercent(8) > 80; 1117 | 1118 | /* fade out display to prevent burn-in */ 1119 | float contrast = 255; 1120 | 1121 | if(currentTime - lastButtonPressTime > 60000) 1122 | { 1123 | contrast = 0; 1124 | } 1125 | 1126 | if((int)contrast != (int)lastContrast) 1127 | { 1128 | lastContrast = (contrast + 15.0f*lastContrast) / 16.0f; 1129 | Display->setBrightness(lastContrast); 1130 | } 1131 | 1132 | 1133 | /* when button gets pressed, save timestamp */ 1134 | if(buttonPressed && buttonPressTime == 0) 1135 | { 1136 | lastButtonPressTime = currentTime; 1137 | buttonPressTime = currentTime; 1138 | } 1139 | 1140 | /* if button is or was pressed */ 1141 | if(buttonPressTime > 0) 1142 | { 1143 | int pressDuration = currentTime - buttonPressTime; 1144 | 1145 | /* no matter if pressed, when it was longer than two seconds */ 1146 | if(pressDuration > 1000) 1147 | { 1148 | buttonPressTime = -1; 1149 | if(state == 300) 1150 | { 1151 | switch(menu_pos) 1152 | { 1153 | case 0: 1154 | /* follow hopping */ 1155 | state = 200; 1156 | break; 1157 | 1158 | case 1: 1159 | /* start hopping scan */ 1160 | cfgChanDist = 260000; 1161 | cfgStartFreq = 860000000; 1162 | state = 0; 1163 | break; 1164 | 1165 | case 2: 1166 | /* start hopping scan */ 1167 | //cfgChanDist = 112000; 1168 | //cfgStartFreq = 860000000; 1169 | //state = 0; 1170 | break; 1171 | 1172 | case 3: 1173 | /* start hopping scan */ 1174 | cfgChanDist = 260000; 1175 | cfgStartFreq = 900000000; 1176 | state = 0; 1177 | break; 1178 | 1179 | case 4: 1180 | /* start hopping scan */ 1181 | //cfgChanDist = 112000; 1182 | //cfgStartFreq = 915000000; 1183 | //state = 0; 1184 | break; 1185 | 1186 | case 5: 1187 | /* start band scan */ 1188 | state = 400; 1189 | break; 1190 | 1191 | case 6: 1192 | /* start freq scan */ 1193 | state = 500; 1194 | break; 1195 | 1196 | case 7: 1197 | /* analyze channel 0 */ 1198 | state = 100; 1199 | break; 1200 | 1201 | case 8: 1202 | break; 1203 | } 1204 | } 1205 | else 1206 | { 1207 | state = 300; 1208 | digitalWrite(LED,LOW); 1209 | timerAlarmDisable(scheduleTimer); 1210 | } 1211 | } 1212 | else if(!buttonPressed && pressDuration > 100) 1213 | { 1214 | if(state == 300) 1215 | { 1216 | menu_pos = (menu_pos + 1) % COUNT(menu_entries); 1217 | } 1218 | else if(state == 401) 1219 | { 1220 | state = 402; 1221 | currentScanChan = 0; 1222 | setChan(currentScanChan, false); 1223 | scanRssi = 200; 1224 | } 1225 | else if(state == 402) 1226 | { 1227 | state = 402; 1228 | currentScanChan = (currentScanChan + 1) % 50; 1229 | setChan(currentScanChan, false); 1230 | scanRssi = 200; 1231 | } 1232 | else 1233 | { 1234 | currentDisplay = (currentDisplay + 1) % displayCount; 1235 | } 1236 | buttonPressTime = -1; 1237 | } 1238 | } 1239 | 1240 | /* when start time marked as "reset", reset if button is released again */ 1241 | if(buttonPressTime < 0) 1242 | { 1243 | if(!buttonPressed) 1244 | { 1245 | buttonPressTime = 0; 1246 | } 1247 | } 1248 | 1249 | switch(state) 1250 | { 1251 | case 500: 1252 | freqCorrectionUp = 0; 1253 | freqCorrectionDown = 0; 1254 | currentScanChan = 0; 1255 | state++; 1256 | break; 1257 | 1258 | case 501: 1259 | { 1260 | if(currentScanChan >= plotScan->ValueCount) 1261 | { 1262 | currentScanChan = 0; 1263 | } 1264 | freqScanFreqCur = freqScanFreq + currentScanChan * freqScanBw; 1265 | SX1276.setStandby(); 1266 | SX1276.writeRxBw(freqScanBw); 1267 | SX1276.writeRxConfig(0); 1268 | SX1276.writeRegister(0x0E, 3); 1269 | SX1276.writeFreq(freqScanFreqCur); 1270 | SX1276.setRx(); 1271 | //plotScan->SetSample(currentScanChan, -100); 1272 | state++; 1273 | break; 1274 | } 1275 | 1276 | case 502: 1277 | { 1278 | float oldValue = plotScan->GetSample(currentScanChan); 1279 | float value = SX1276.readRssi() * -0.5f; 1280 | if(oldValue < value) 1281 | { 1282 | plotScan->SetSample(currentScanChan, value); 1283 | } 1284 | 1285 | if(currentTime - lastTime > 20) 1286 | { 1287 | lastTime = currentTime; 1288 | currentScanChan++; 1289 | state = 501; 1290 | } 1291 | 1292 | if(currentTime - lastUpdateTime > 100) 1293 | { 1294 | lastUpdateTime = currentTime; 1295 | Display->clear(); 1296 | plotScan->DrawFullPlot(0, 0, 100, 60, true, false); 1297 | char msg[33]; 1298 | snprintf(msg, 32, "%d kHz", (uint32_t)( freqScanFreqCur /1000)); 1299 | Display->setFont(ArialMT_Plain_10); 1300 | Display->drawString(64, 46, msg); 1301 | Display->display(); 1302 | } 1303 | 1304 | break; 1305 | } 1306 | 1307 | 1308 | case 400: 1309 | for(int pos = 0; pos < 50; pos++) 1310 | { 1311 | plotScan->SetSample(pos, -100); 1312 | } 1313 | freqCorrectionUp = 0; 1314 | freqCorrectionDown = 0; 1315 | state++; 1316 | break; 1317 | 1318 | case 401: 1319 | { 1320 | if(currentTime - lastTime > 100 || scanRssi != 200) 1321 | { 1322 | float oldValue = plotScan->GetSample(currentScanChan); 1323 | float value = scanRssi * -0.5f; 1324 | if(oldValue < value) 1325 | { 1326 | plotScan->SetSample(currentScanChan, value); 1327 | } 1328 | currentScanChan = (currentScanChan + 1) % 50; 1329 | setChan(currentScanChan, false); 1330 | scanRssi = 200; 1331 | Display->clear(); 1332 | plotScan->DrawFullPlot(0, 0, 54, 60); 1333 | char msg[33]; 1334 | snprintf(msg, 32, "ch#%d", currentScanChan); 1335 | Display->setFont(ArialMT_Plain_16); 1336 | Display->drawString(68, 48, msg); 1337 | Display->display(); 1338 | } 1339 | break; 1340 | } 1341 | 1342 | case 402: 1343 | { 1344 | if(currentTime - lastTime > 50) 1345 | { 1346 | float oldValue = plotScan->GetSample(currentScanChan); 1347 | float value = scanRssi * -0.5f; 1348 | if(oldValue < value) 1349 | { 1350 | plotScan->SetSample(currentScanChan, value); 1351 | } 1352 | Display->clear(); 1353 | plotScan->DrawFullPlot(0, 0, 54, 60); 1354 | char msg[33]; 1355 | snprintf(msg, 32, "ch#%d %c", currentScanChan, (scanRssi == 200)?' ':'*'); 1356 | Display->setFont(ArialMT_Plain_16); 1357 | Display->drawString(68, 48, msg); 1358 | Display->display(); 1359 | scanRssi = 200; 1360 | } 1361 | break; 1362 | } 1363 | 1364 | case 300: 1365 | Display->setFont(ArialMT_Plain_24); 1366 | Display->clear(); 1367 | Display->drawString(0, 0, "Menu"); 1368 | Display->setFont(ArialMT_Plain_10); 1369 | for(int pos = 0; pos < COUNT(menu_entries); pos++) 1370 | { 1371 | if(pos > 3) 1372 | { 1373 | break; 1374 | } 1375 | int entry = (menu_pos + pos + COUNT(menu_entries) - 1) % COUNT(menu_entries); 1376 | const char *menu_name = menu_entries[entry]; 1377 | if(entry == menu_pos) 1378 | { 1379 | Display->drawString(8, 26 + 1 + pos * 10, menu_name); 1380 | Display->drawString(8+1, 26 + pos * 10, menu_name); 1381 | Display->drawString(8+1, 26 + 1 + pos * 10, menu_name); 1382 | } 1383 | Display->drawString(8, 26 + pos * 10, menu_name); 1384 | } 1385 | Display->display(); 1386 | break; 1387 | 1388 | case 200: 1389 | Display->setFont(ArialMT_Plain_24); 1390 | Display->clear(); 1391 | Display->drawString(0, 0, "Search..."); 1392 | Display->display(); 1393 | 1394 | Serial.printf("Init hopping follow\n"); 1395 | 1396 | SX1276.init(); 1397 | 1398 | setChan(0, false); 1399 | state++; 1400 | break; 1401 | 1402 | case 202: 1403 | { 1404 | Display->setFont(ArialMT_Plain_24); 1405 | Display->clear(); 1406 | Display->drawString(0, 0, "Sync..."); 1407 | Display->display(); 1408 | enableAfc = true; 1409 | 1410 | break; 1411 | } 1412 | 1413 | case 203: 1414 | { 1415 | if(0 && currentTime - lastTime > 500) 1416 | { 1417 | lastTime = currentTime; 1418 | if(statUpScheduled && statDownScheduled) 1419 | { 1420 | Serial.printf("Statistics:\n"); 1421 | Serial.printf(" Up scheduled: %6u\n", statUpScheduled); 1422 | Serial.printf(" recv: %6u\n", statUpReceived); 1423 | Serial.printf(" loss: %6u (%d%%)\n", statUpLoss, 100*statUpLoss/statUpScheduled); 1424 | Serial.printf(" head: %4.0f\n", statUpHeadroom); 1425 | Serial.printf(" fr.corr: %4i\n", (int16_t)freqCorrectionUp); 1426 | Serial.printf(" dBm: -%2.1f\n", (float)statRssiUp / 2); 1427 | Serial.printf(" Dn scheduled: %6u\n", statDownScheduled); 1428 | Serial.printf(" recv: %6u\n", statDownReceived); 1429 | Serial.printf(" loss: %6u (%d%%)\n", statDownLoss, 100*statDownLoss/statDownScheduled); 1430 | Serial.printf(" head: %4.0f\n", statDownHeadroom); 1431 | Serial.printf(" fr.corr: %4i\n", (int16_t)freqCorrectionDown); 1432 | Serial.printf(" dBm: -%2.1f\n", (float)statRssiDown / 2); 1433 | Serial.printf(" Sched len avg: %4.0f\n", statAverageScheduleLength); 1434 | Serial.printf(" Sched len set: %4u\n", learnSchedLength); 1435 | Serial.printf(" Resyncs: %6u\n", statResyncs); 1436 | Serial.printf("\n"); 1437 | } 1438 | } 1439 | 1440 | Display->clear(); 1441 | switch(currentDisplay) 1442 | { 1443 | /* show values */ 1444 | case 0: 1445 | { 1446 | if(statUpScheduled && statDownScheduled) 1447 | { 1448 | Display->setFont(ArialMT_Plain_24); 1449 | Display->drawString(0, 0, "CRSF"); 1450 | 1451 | Display->setFont(ArialMT_Plain_10); 1452 | for(int chan = 0; chan < 12; chan++) 1453 | { 1454 | uint8_t pct = chanPercent(chan); 1455 | sprintf(msg, "%d %3d%%", chan, pct); 1456 | Display->drawString(3 + 43*(chan/4), 24 + (chan%4)*10, msg); 1457 | } 1458 | sprintf(msg, "Ch %d %c", currentChannel, currentDirectionDown ? 'D':'U'); 1459 | Display->drawString(68, 0, msg); 1460 | sprintf(msg, "-%2u -%2u", statRssiUp / 2, statRssiDown / 2); 1461 | Display->drawString(68, 11, msg); 1462 | Display->drawLine(0, 24, 0, 64); 1463 | Display->drawLine(43, 24, 43, 64); 1464 | Display->drawLine(86, 24, 86, 64); 1465 | Display->drawLine(127, 24, 127, 64); 1466 | } 1467 | else 1468 | { 1469 | Display->setFont(ArialMT_Plain_24); 1470 | Display->drawString(0, 0, "Waiting"); 1471 | } 1472 | break; 1473 | } 1474 | 1475 | case 1: 1476 | plotRssiUp->DrawFullPlot(0, 0, 60, 60); 1477 | break; 1478 | 1479 | case 2: 1480 | plotRssiDown->DrawFullPlot(0, 0, 60, 60); 1481 | break; 1482 | 1483 | case 3: 1484 | plotFCorrUp->DrawFullPlot(0, 0, 60, 60); 1485 | break; 1486 | 1487 | case 4: 1488 | plotFCorrDown->DrawFullPlot(0, 0, 60, 60); 1489 | break; 1490 | 1491 | case 5: 1492 | plotLossUp->DrawFullPlot(0, 0, 60, 60, false); 1493 | break; 1494 | 1495 | case 6: 1496 | plotLossDown->DrawFullPlot(0, 0, 60, 60, false); 1497 | break; 1498 | 1499 | case 7: 1500 | plotFreq->DrawFullPlot(0, 0, 60, 60, false); 1501 | break; 1502 | 1503 | case 8: 1504 | plotSchedLen->DrawFullPlot(0, 0, 60, 60); 1505 | break; 1506 | } 1507 | Display->display(); 1508 | 1509 | break; 1510 | } 1511 | 1512 | case 100: 1513 | Display->setFont(ArialMT_Plain_10); 1514 | //Display->drawString(0, 0, "Init channel 0 analysis"); 1515 | Display->display(); 1516 | Serial.printf("Init channel 0 analysis\n"); 1517 | SX1276.init(); 1518 | setChan(0, false); 1519 | state++; 1520 | break; 1521 | 1522 | case 0: 1523 | { 1524 | Display->setFont(ArialMT_Plain_24); 1525 | Display->clear(); 1526 | Display->drawString(0, 0, "Hop scan"); 1527 | Display->setFont(ArialMT_Plain_10); 1528 | Display->drawString(0, 30, "Initializing..."); 1529 | Display->display(); 1530 | 1531 | Serial.printf("Init hopping scan\n"); 1532 | 1533 | memset(×lotMap, 0x00, sizeof(timeslotMap)); 1534 | addDelta(0, 0, 0); 1535 | 1536 | freqCorrectionUp = 0; 1537 | freqCorrectionDown = 0; 1538 | SX1276.init(); 1539 | 1540 | SX1276.writeAfcBw(100000); 1541 | enableAfc = true; 1542 | config.startFreq = cfgStartFreq; 1543 | 1544 | retries = 0; 1545 | state++; 1546 | 1547 | setChan(0, false); 1548 | break; 1549 | } 1550 | 1551 | case 1: 1552 | { 1553 | bool skip = false; 1554 | 1555 | if(!retries) 1556 | { 1557 | if((currentTime - lastTime) > 500) 1558 | { 1559 | skip = true; 1560 | } 1561 | } 1562 | else 1563 | { 1564 | if((currentTime - lastTime) > 2000) 1565 | { 1566 | Serial.printf("timed out\n"); 1567 | skip = true; 1568 | } 1569 | } 1570 | 1571 | if(skip) 1572 | { 1573 | lastTime = currentTime; 1574 | 1575 | config.startFreq += 50000; 1576 | enableAfc = true; 1577 | retries = 0; 1578 | setChan(0, false); 1579 | 1580 | char msg[33]; 1581 | snprintf(msg, 32, "Check %d.%03d MHz", (uint32_t)(config.startFreq /1000000), (uint32_t)(config.startFreq /1000) % 1000); 1582 | Display->setFont(ArialMT_Plain_24); 1583 | Display->clear(); 1584 | Display->drawString(0, 0, "Hop scan"); 1585 | Display->setFont(ArialMT_Plain_10); 1586 | Display->drawString(0, 30, msg); 1587 | Display->display(); 1588 | 1589 | Serial.printf("%s\n", msg); 1590 | } 1591 | break; 1592 | } 1593 | 1594 | case 3: 1595 | { 1596 | Display->setFont(ArialMT_Plain_24); 1597 | Display->clear(); 1598 | Display->drawString(0, 0, "Hop scan"); 1599 | Display->setFont(ArialMT_Plain_10); 1600 | sprintf(msg, "Channel #%u (%u/3)", (checkChan+1), timeslotMap[checkChan].entries); 1601 | Display->drawString(0, 26, msg); 1602 | Display->drawString(0, 38, "Map:"); 1603 | 1604 | int mapX = 8; 1605 | int mapY = 50; 1606 | 1607 | Display->drawRect(mapX, mapY, 2 + 50 * 2 + 2, 2 + 3 * 2 + 2); 1608 | for(int chan = 0; chan < 50; chan++) 1609 | { 1610 | for(int entry = 0; entry < timeslotMap[chan].entries; entry++) 1611 | { 1612 | int hop = timeslotMap[chan].slots[entry]; 1613 | int x = mapX + 2 + (hop % 50) * 2; 1614 | int y = mapY + 2 + (hop / 50) * 2; 1615 | Display->setPixel(x, y); 1616 | Display->setPixel(x+1, y); 1617 | Display->setPixel(x, y+1); 1618 | Display->setPixel(x+1, y+1); 1619 | } 1620 | } 1621 | 1622 | Display->display(); 1623 | 1624 | break; 1625 | } 1626 | 1627 | case 4: 1628 | { 1629 | Serial.printf("\n"); 1630 | Serial.printf("-----------------------\n"); 1631 | Serial.printf(" Unsorted hopping list\n"); 1632 | Serial.printf("-----------------------\n"); 1633 | for(int chan = 0; chan < COUNT(timeslotMap); chan++) 1634 | { 1635 | for(int pos = 0; pos < timeslotMap[chan].entries; pos++) 1636 | { 1637 | Serial.printf("slot #%03d channel #%02d\n", timeslotMap[chan].slots[pos], chan); 1638 | } 1639 | } 1640 | Serial.printf("\n"); 1641 | Serial.printf("-----------------------\n"); 1642 | Serial.printf(" Sorted hopping list\n"); 1643 | Serial.printf("-----------------------\n"); 1644 | Serial.printf("{ "); 1645 | for(int hop = 0; hop < 150; hop++) 1646 | { 1647 | for(int chan = 0; chan < COUNT(timeslotMap); chan++) 1648 | { 1649 | for(int pos = 0; pos < timeslotMap[chan].entries; pos++) 1650 | { 1651 | if(hop == timeslotMap[chan].slots[pos]) 1652 | { 1653 | Serial.printf("%d%s", chan, (hop != 149)?", ":" "); 1654 | config.hoppingSequence[hop] = chan; 1655 | } 1656 | } 1657 | } 1658 | } 1659 | Serial.printf("}"); 1660 | save_config(); 1661 | state = 200; 1662 | break; 1663 | } 1664 | } 1665 | } 1666 | 1667 | -------------------------------------------------------------------------------- /OLEDDisplayFonts.h: -------------------------------------------------------------------------------- 1 | #ifndef OLEDDISPLAYFONTS_h 2 | #define OLEDDISPLAYFONTS_h 3 | 4 | const uint8_t ArialMT_Plain_10[] PROGMEM = { 5 | 0x0A, // Width: 10 6 | 0x0D, // Height: 13 7 | 0x20, // First Char: 32 8 | 0xE0, // Numbers of Chars: 224 9 | 10 | // Jump Table: 11 | 0xFF, 0xFF, 0x00, 0x03, // 32:65535 12 | 0x00, 0x00, 0x04, 0x03, // 33:0 13 | 0x00, 0x04, 0x05, 0x04, // 34:4 14 | 0x00, 0x09, 0x09, 0x06, // 35:9 15 | 0x00, 0x12, 0x0A, 0x06, // 36:18 16 | 0x00, 0x1C, 0x10, 0x09, // 37:28 17 | 0x00, 0x2C, 0x0E, 0x07, // 38:44 18 | 0x00, 0x3A, 0x01, 0x02, // 39:58 19 | 0x00, 0x3B, 0x06, 0x03, // 40:59 20 | 0x00, 0x41, 0x06, 0x03, // 41:65 21 | 0x00, 0x47, 0x05, 0x04, // 42:71 22 | 0x00, 0x4C, 0x09, 0x06, // 43:76 23 | 0x00, 0x55, 0x04, 0x03, // 44:85 24 | 0x00, 0x59, 0x03, 0x03, // 45:89 25 | 0x00, 0x5C, 0x04, 0x03, // 46:92 26 | 0x00, 0x60, 0x05, 0x03, // 47:96 27 | 0x00, 0x65, 0x0A, 0x06, // 48:101 28 | 0x00, 0x6F, 0x08, 0x06, // 49:111 29 | 0x00, 0x77, 0x0A, 0x06, // 50:119 30 | 0x00, 0x81, 0x0A, 0x06, // 51:129 31 | 0x00, 0x8B, 0x0B, 0x06, // 52:139 32 | 0x00, 0x96, 0x0A, 0x06, // 53:150 33 | 0x00, 0xA0, 0x0A, 0x06, // 54:160 34 | 0x00, 0xAA, 0x09, 0x06, // 55:170 35 | 0x00, 0xB3, 0x0A, 0x06, // 56:179 36 | 0x00, 0xBD, 0x0A, 0x06, // 57:189 37 | 0x00, 0xC7, 0x04, 0x03, // 58:199 38 | 0x00, 0xCB, 0x04, 0x03, // 59:203 39 | 0x00, 0xCF, 0x0A, 0x06, // 60:207 40 | 0x00, 0xD9, 0x09, 0x06, // 61:217 41 | 0x00, 0xE2, 0x09, 0x06, // 62:226 42 | 0x00, 0xEB, 0x0B, 0x06, // 63:235 43 | 0x00, 0xF6, 0x14, 0x0A, // 64:246 44 | 0x01, 0x0A, 0x0E, 0x07, // 65:266 45 | 0x01, 0x18, 0x0C, 0x07, // 66:280 46 | 0x01, 0x24, 0x0C, 0x07, // 67:292 47 | 0x01, 0x30, 0x0B, 0x07, // 68:304 48 | 0x01, 0x3B, 0x0C, 0x07, // 69:315 49 | 0x01, 0x47, 0x09, 0x06, // 70:327 50 | 0x01, 0x50, 0x0D, 0x08, // 71:336 51 | 0x01, 0x5D, 0x0C, 0x07, // 72:349 52 | 0x01, 0x69, 0x04, 0x03, // 73:361 53 | 0x01, 0x6D, 0x08, 0x05, // 74:365 54 | 0x01, 0x75, 0x0E, 0x07, // 75:373 55 | 0x01, 0x83, 0x0C, 0x06, // 76:387 56 | 0x01, 0x8F, 0x10, 0x08, // 77:399 57 | 0x01, 0x9F, 0x0C, 0x07, // 78:415 58 | 0x01, 0xAB, 0x0E, 0x08, // 79:427 59 | 0x01, 0xB9, 0x0B, 0x07, // 80:441 60 | 0x01, 0xC4, 0x0E, 0x08, // 81:452 61 | 0x01, 0xD2, 0x0C, 0x07, // 82:466 62 | 0x01, 0xDE, 0x0C, 0x07, // 83:478 63 | 0x01, 0xEA, 0x0B, 0x06, // 84:490 64 | 0x01, 0xF5, 0x0C, 0x07, // 85:501 65 | 0x02, 0x01, 0x0D, 0x07, // 86:513 66 | 0x02, 0x0E, 0x11, 0x09, // 87:526 67 | 0x02, 0x1F, 0x0E, 0x07, // 88:543 68 | 0x02, 0x2D, 0x0D, 0x07, // 89:557 69 | 0x02, 0x3A, 0x0C, 0x06, // 90:570 70 | 0x02, 0x46, 0x06, 0x03, // 91:582 71 | 0x02, 0x4C, 0x06, 0x03, // 92:588 72 | 0x02, 0x52, 0x04, 0x03, // 93:594 73 | 0x02, 0x56, 0x09, 0x05, // 94:598 74 | 0x02, 0x5F, 0x0C, 0x06, // 95:607 75 | 0x02, 0x6B, 0x03, 0x03, // 96:619 76 | 0x02, 0x6E, 0x0A, 0x06, // 97:622 77 | 0x02, 0x78, 0x0A, 0x06, // 98:632 78 | 0x02, 0x82, 0x0A, 0x05, // 99:642 79 | 0x02, 0x8C, 0x0A, 0x06, // 100:652 80 | 0x02, 0x96, 0x0A, 0x06, // 101:662 81 | 0x02, 0xA0, 0x05, 0x03, // 102:672 82 | 0x02, 0xA5, 0x0A, 0x06, // 103:677 83 | 0x02, 0xAF, 0x0A, 0x06, // 104:687 84 | 0x02, 0xB9, 0x04, 0x02, // 105:697 85 | 0x02, 0xBD, 0x04, 0x02, // 106:701 86 | 0x02, 0xC1, 0x08, 0x05, // 107:705 87 | 0x02, 0xC9, 0x04, 0x02, // 108:713 88 | 0x02, 0xCD, 0x10, 0x08, // 109:717 89 | 0x02, 0xDD, 0x0A, 0x06, // 110:733 90 | 0x02, 0xE7, 0x0A, 0x06, // 111:743 91 | 0x02, 0xF1, 0x0A, 0x06, // 112:753 92 | 0x02, 0xFB, 0x0A, 0x06, // 113:763 93 | 0x03, 0x05, 0x05, 0x03, // 114:773 94 | 0x03, 0x0A, 0x08, 0x05, // 115:778 95 | 0x03, 0x12, 0x06, 0x03, // 116:786 96 | 0x03, 0x18, 0x0A, 0x06, // 117:792 97 | 0x03, 0x22, 0x09, 0x05, // 118:802 98 | 0x03, 0x2B, 0x0E, 0x07, // 119:811 99 | 0x03, 0x39, 0x0A, 0x05, // 120:825 100 | 0x03, 0x43, 0x09, 0x05, // 121:835 101 | 0x03, 0x4C, 0x0A, 0x05, // 122:844 102 | 0x03, 0x56, 0x06, 0x03, // 123:854 103 | 0x03, 0x5C, 0x04, 0x03, // 124:860 104 | 0x03, 0x60, 0x05, 0x03, // 125:864 105 | 0x03, 0x65, 0x09, 0x06, // 126:869 106 | 0xFF, 0xFF, 0x00, 0x00, // 127:65535 107 | 0xFF, 0xFF, 0x00, 0x0A, // 128:65535 108 | 0xFF, 0xFF, 0x00, 0x0A, // 129:65535 109 | 0xFF, 0xFF, 0x00, 0x0A, // 130:65535 110 | 0xFF, 0xFF, 0x00, 0x0A, // 131:65535 111 | 0xFF, 0xFF, 0x00, 0x0A, // 132:65535 112 | 0xFF, 0xFF, 0x00, 0x0A, // 133:65535 113 | 0xFF, 0xFF, 0x00, 0x0A, // 134:65535 114 | 0xFF, 0xFF, 0x00, 0x0A, // 135:65535 115 | 0xFF, 0xFF, 0x00, 0x0A, // 136:65535 116 | 0xFF, 0xFF, 0x00, 0x0A, // 137:65535 117 | 0xFF, 0xFF, 0x00, 0x0A, // 138:65535 118 | 0xFF, 0xFF, 0x00, 0x0A, // 139:65535 119 | 0xFF, 0xFF, 0x00, 0x0A, // 140:65535 120 | 0xFF, 0xFF, 0x00, 0x0A, // 141:65535 121 | 0xFF, 0xFF, 0x00, 0x0A, // 142:65535 122 | 0xFF, 0xFF, 0x00, 0x0A, // 143:65535 123 | 0xFF, 0xFF, 0x00, 0x0A, // 144:65535 124 | 0xFF, 0xFF, 0x00, 0x0A, // 145:65535 125 | 0xFF, 0xFF, 0x00, 0x0A, // 146:65535 126 | 0xFF, 0xFF, 0x00, 0x0A, // 147:65535 127 | 0xFF, 0xFF, 0x00, 0x0A, // 148:65535 128 | 0xFF, 0xFF, 0x00, 0x0A, // 149:65535 129 | 0xFF, 0xFF, 0x00, 0x0A, // 150:65535 130 | 0xFF, 0xFF, 0x00, 0x0A, // 151:65535 131 | 0xFF, 0xFF, 0x00, 0x0A, // 152:65535 132 | 0xFF, 0xFF, 0x00, 0x0A, // 153:65535 133 | 0xFF, 0xFF, 0x00, 0x0A, // 154:65535 134 | 0xFF, 0xFF, 0x00, 0x0A, // 155:65535 135 | 0xFF, 0xFF, 0x00, 0x0A, // 156:65535 136 | 0xFF, 0xFF, 0x00, 0x0A, // 157:65535 137 | 0xFF, 0xFF, 0x00, 0x0A, // 158:65535 138 | 0xFF, 0xFF, 0x00, 0x0A, // 159:65535 139 | 0xFF, 0xFF, 0x00, 0x03, // 160:65535 140 | 0x03, 0x6E, 0x04, 0x03, // 161:878 141 | 0x03, 0x72, 0x0A, 0x06, // 162:882 142 | 0x03, 0x7C, 0x0C, 0x06, // 163:892 143 | 0x03, 0x88, 0x0A, 0x06, // 164:904 144 | 0x03, 0x92, 0x0A, 0x06, // 165:914 145 | 0x03, 0x9C, 0x04, 0x03, // 166:924 146 | 0x03, 0xA0, 0x0A, 0x06, // 167:928 147 | 0x03, 0xAA, 0x05, 0x03, // 168:938 148 | 0x03, 0xAF, 0x0D, 0x07, // 169:943 149 | 0x03, 0xBC, 0x07, 0x04, // 170:956 150 | 0x03, 0xC3, 0x0A, 0x06, // 171:963 151 | 0x03, 0xCD, 0x09, 0x06, // 172:973 152 | 0x03, 0xD6, 0x03, 0x03, // 173:982 153 | 0x03, 0xD9, 0x0D, 0x07, // 174:985 154 | 0x03, 0xE6, 0x0B, 0x06, // 175:998 155 | 0x03, 0xF1, 0x07, 0x04, // 176:1009 156 | 0x03, 0xF8, 0x0A, 0x05, // 177:1016 157 | 0x04, 0x02, 0x05, 0x03, // 178:1026 158 | 0x04, 0x07, 0x05, 0x03, // 179:1031 159 | 0x04, 0x0C, 0x05, 0x03, // 180:1036 160 | 0x04, 0x11, 0x0A, 0x06, // 181:1041 161 | 0x04, 0x1B, 0x09, 0x05, // 182:1051 162 | 0x04, 0x24, 0x03, 0x03, // 183:1060 163 | 0x04, 0x27, 0x06, 0x03, // 184:1063 164 | 0x04, 0x2D, 0x05, 0x03, // 185:1069 165 | 0x04, 0x32, 0x07, 0x04, // 186:1074 166 | 0x04, 0x39, 0x0A, 0x06, // 187:1081 167 | 0x04, 0x43, 0x10, 0x08, // 188:1091 168 | 0x04, 0x53, 0x10, 0x08, // 189:1107 169 | 0x04, 0x63, 0x10, 0x08, // 190:1123 170 | 0x04, 0x73, 0x0A, 0x06, // 191:1139 171 | 0x04, 0x7D, 0x0E, 0x07, // 192:1149 172 | 0x04, 0x8B, 0x0E, 0x07, // 193:1163 173 | 0x04, 0x99, 0x0E, 0x07, // 194:1177 174 | 0x04, 0xA7, 0x0E, 0x07, // 195:1191 175 | 0x04, 0xB5, 0x0E, 0x07, // 196:1205 176 | 0x04, 0xC3, 0x0E, 0x07, // 197:1219 177 | 0x04, 0xD1, 0x12, 0x0A, // 198:1233 178 | 0x04, 0xE3, 0x0C, 0x07, // 199:1251 179 | 0x04, 0xEF, 0x0C, 0x07, // 200:1263 180 | 0x04, 0xFB, 0x0C, 0x07, // 201:1275 181 | 0x05, 0x07, 0x0C, 0x07, // 202:1287 182 | 0x05, 0x13, 0x0C, 0x07, // 203:1299 183 | 0x05, 0x1F, 0x05, 0x03, // 204:1311 184 | 0x05, 0x24, 0x04, 0x03, // 205:1316 185 | 0x05, 0x28, 0x04, 0x03, // 206:1320 186 | 0x05, 0x2C, 0x05, 0x03, // 207:1324 187 | 0x05, 0x31, 0x0B, 0x07, // 208:1329 188 | 0x05, 0x3C, 0x0C, 0x07, // 209:1340 189 | 0x05, 0x48, 0x0E, 0x08, // 210:1352 190 | 0x05, 0x56, 0x0E, 0x08, // 211:1366 191 | 0x05, 0x64, 0x0E, 0x08, // 212:1380 192 | 0x05, 0x72, 0x0E, 0x08, // 213:1394 193 | 0x05, 0x80, 0x0E, 0x08, // 214:1408 194 | 0x05, 0x8E, 0x0A, 0x06, // 215:1422 195 | 0x05, 0x98, 0x0D, 0x08, // 216:1432 196 | 0x05, 0xA5, 0x0C, 0x07, // 217:1445 197 | 0x05, 0xB1, 0x0C, 0x07, // 218:1457 198 | 0x05, 0xBD, 0x0C, 0x07, // 219:1469 199 | 0x05, 0xC9, 0x0C, 0x07, // 220:1481 200 | 0x05, 0xD5, 0x0D, 0x07, // 221:1493 201 | 0x05, 0xE2, 0x0B, 0x07, // 222:1506 202 | 0x05, 0xED, 0x0C, 0x06, // 223:1517 203 | 0x05, 0xF9, 0x0A, 0x06, // 224:1529 204 | 0x06, 0x03, 0x0A, 0x06, // 225:1539 205 | 0x06, 0x0D, 0x0A, 0x06, // 226:1549 206 | 0x06, 0x17, 0x0A, 0x06, // 227:1559 207 | 0x06, 0x21, 0x0A, 0x06, // 228:1569 208 | 0x06, 0x2B, 0x0A, 0x06, // 229:1579 209 | 0x06, 0x35, 0x10, 0x09, // 230:1589 210 | 0x06, 0x45, 0x0A, 0x05, // 231:1605 211 | 0x06, 0x4F, 0x0A, 0x06, // 232:1615 212 | 0x06, 0x59, 0x0A, 0x06, // 233:1625 213 | 0x06, 0x63, 0x0A, 0x06, // 234:1635 214 | 0x06, 0x6D, 0x0A, 0x06, // 235:1645 215 | 0x06, 0x77, 0x05, 0x03, // 236:1655 216 | 0x06, 0x7C, 0x04, 0x03, // 237:1660 217 | 0x06, 0x80, 0x05, 0x03, // 238:1664 218 | 0x06, 0x85, 0x05, 0x03, // 239:1669 219 | 0x06, 0x8A, 0x0A, 0x06, // 240:1674 220 | 0x06, 0x94, 0x0A, 0x06, // 241:1684 221 | 0x06, 0x9E, 0x0A, 0x06, // 242:1694 222 | 0x06, 0xA8, 0x0A, 0x06, // 243:1704 223 | 0x06, 0xB2, 0x0A, 0x06, // 244:1714 224 | 0x06, 0xBC, 0x0A, 0x06, // 245:1724 225 | 0x06, 0xC6, 0x0A, 0x06, // 246:1734 226 | 0x06, 0xD0, 0x09, 0x05, // 247:1744 227 | 0x06, 0xD9, 0x0A, 0x06, // 248:1753 228 | 0x06, 0xE3, 0x0A, 0x06, // 249:1763 229 | 0x06, 0xED, 0x0A, 0x06, // 250:1773 230 | 0x06, 0xF7, 0x0A, 0x06, // 251:1783 231 | 0x07, 0x01, 0x0A, 0x06, // 252:1793 232 | 0x07, 0x0B, 0x09, 0x05, // 253:1803 233 | 0x07, 0x14, 0x0A, 0x06, // 254:1812 234 | 0x07, 0x1E, 0x09, 0x05, // 255:1822 235 | 236 | // Font Data: 237 | 0x00,0x00,0xF8,0x02, // 33 238 | 0x38,0x00,0x00,0x00,0x38, // 34 239 | 0xA0,0x03,0xE0,0x00,0xB8,0x03,0xE0,0x00,0xB8, // 35 240 | 0x30,0x01,0x28,0x02,0xF8,0x07,0x48,0x02,0x90,0x01, // 36 241 | 0x00,0x00,0x30,0x00,0x48,0x00,0x30,0x03,0xC0,0x00,0xB0,0x01,0x48,0x02,0x80,0x01, // 37 242 | 0x80,0x01,0x50,0x02,0x68,0x02,0xA8,0x02,0x18,0x01,0x80,0x03,0x80,0x02, // 38 243 | 0x38, // 39 244 | 0xE0,0x03,0x10,0x04,0x08,0x08, // 40 245 | 0x08,0x08,0x10,0x04,0xE0,0x03, // 41 246 | 0x28,0x00,0x18,0x00,0x28, // 42 247 | 0x40,0x00,0x40,0x00,0xF0,0x01,0x40,0x00,0x40, // 43 248 | 0x00,0x00,0x00,0x06, // 44 249 | 0x80,0x00,0x80, // 45 250 | 0x00,0x00,0x00,0x02, // 46 251 | 0x00,0x03,0xE0,0x00,0x18, // 47 252 | 0xF0,0x01,0x08,0x02,0x08,0x02,0x08,0x02,0xF0,0x01, // 48 253 | 0x00,0x00,0x20,0x00,0x10,0x00,0xF8,0x03, // 49 254 | 0x10,0x02,0x08,0x03,0x88,0x02,0x48,0x02,0x30,0x02, // 50 255 | 0x10,0x01,0x08,0x02,0x48,0x02,0x48,0x02,0xB0,0x01, // 51 256 | 0xC0,0x00,0xA0,0x00,0x90,0x00,0x88,0x00,0xF8,0x03,0x80, // 52 257 | 0x60,0x01,0x38,0x02,0x28,0x02,0x28,0x02,0xC8,0x01, // 53 258 | 0xF0,0x01,0x28,0x02,0x28,0x02,0x28,0x02,0xD0,0x01, // 54 259 | 0x08,0x00,0x08,0x03,0xC8,0x00,0x38,0x00,0x08, // 55 260 | 0xB0,0x01,0x48,0x02,0x48,0x02,0x48,0x02,0xB0,0x01, // 56 261 | 0x70,0x01,0x88,0x02,0x88,0x02,0x88,0x02,0xF0,0x01, // 57 262 | 0x00,0x00,0x20,0x02, // 58 263 | 0x00,0x00,0x20,0x06, // 59 264 | 0x00,0x00,0x40,0x00,0xA0,0x00,0xA0,0x00,0x10,0x01, // 60 265 | 0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0,0x00,0xA0, // 61 266 | 0x00,0x00,0x10,0x01,0xA0,0x00,0xA0,0x00,0x40, // 62 267 | 0x10,0x00,0x08,0x00,0x08,0x00,0xC8,0x02,0x48,0x00,0x30, // 63 268 | 0x00,0x00,0xC0,0x03,0x30,0x04,0xD0,0x09,0x28,0x0A,0x28,0x0A,0xC8,0x0B,0x68,0x0A,0x10,0x05,0xE0,0x04, // 64 269 | 0x00,0x02,0xC0,0x01,0xB0,0x00,0x88,0x00,0xB0,0x00,0xC0,0x01,0x00,0x02, // 65 270 | 0x00,0x00,0xF8,0x03,0x48,0x02,0x48,0x02,0x48,0x02,0xF0,0x01, // 66 271 | 0x00,0x00,0xF0,0x01,0x08,0x02,0x08,0x02,0x08,0x02,0x10,0x01, // 67 272 | 0x00,0x00,0xF8,0x03,0x08,0x02,0x08,0x02,0x10,0x01,0xE0, // 68 273 | 0x00,0x00,0xF8,0x03,0x48,0x02,0x48,0x02,0x48,0x02,0x48,0x02, // 69 274 | 0x00,0x00,0xF8,0x03,0x48,0x00,0x48,0x00,0x08, // 70 275 | 0x00,0x00,0xE0,0x00,0x10,0x01,0x08,0x02,0x48,0x02,0x50,0x01,0xC0, // 71 276 | 0x00,0x00,0xF8,0x03,0x40,0x00,0x40,0x00,0x40,0x00,0xF8,0x03, // 72 277 | 0x00,0x00,0xF8,0x03, // 73 278 | 0x00,0x03,0x00,0x02,0x00,0x02,0xF8,0x01, // 74 279 | 0x00,0x00,0xF8,0x03,0x80,0x00,0x60,0x00,0x90,0x00,0x08,0x01,0x00,0x02, // 75 280 | 0x00,0x00,0xF8,0x03,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02, // 76 281 | 0x00,0x00,0xF8,0x03,0x30,0x00,0xC0,0x01,0x00,0x02,0xC0,0x01,0x30,0x00,0xF8,0x03, // 77 282 | 0x00,0x00,0xF8,0x03,0x30,0x00,0x40,0x00,0x80,0x01,0xF8,0x03, // 78 283 | 0x00,0x00,0xF0,0x01,0x08,0x02,0x08,0x02,0x08,0x02,0x08,0x02,0xF0,0x01, // 79 284 | 0x00,0x00,0xF8,0x03,0x48,0x00,0x48,0x00,0x48,0x00,0x30, // 80 285 | 0x00,0x00,0xF0,0x01,0x08,0x02,0x08,0x02,0x08,0x03,0x08,0x03,0xF0,0x02, // 81 286 | 0x00,0x00,0xF8,0x03,0x48,0x00,0x48,0x00,0xC8,0x00,0x30,0x03, // 82 287 | 0x00,0x00,0x30,0x01,0x48,0x02,0x48,0x02,0x48,0x02,0x90,0x01, // 83 288 | 0x00,0x00,0x08,0x00,0x08,0x00,0xF8,0x03,0x08,0x00,0x08, // 84 289 | 0x00,0x00,0xF8,0x01,0x00,0x02,0x00,0x02,0x00,0x02,0xF8,0x01, // 85 290 | 0x08,0x00,0x70,0x00,0x80,0x01,0x00,0x02,0x80,0x01,0x70,0x00,0x08, // 86 291 | 0x18,0x00,0xE0,0x01,0x00,0x02,0xF0,0x01,0x08,0x00,0xF0,0x01,0x00,0x02,0xE0,0x01,0x18, // 87 292 | 0x00,0x02,0x08,0x01,0x90,0x00,0x60,0x00,0x90,0x00,0x08,0x01,0x00,0x02, // 88 293 | 0x08,0x00,0x10,0x00,0x20,0x00,0xC0,0x03,0x20,0x00,0x10,0x00,0x08, // 89 294 | 0x08,0x03,0x88,0x02,0xC8,0x02,0x68,0x02,0x38,0x02,0x18,0x02, // 90 295 | 0x00,0x00,0xF8,0x0F,0x08,0x08, // 91 296 | 0x18,0x00,0xE0,0x00,0x00,0x03, // 92 297 | 0x08,0x08,0xF8,0x0F, // 93 298 | 0x40,0x00,0x30,0x00,0x08,0x00,0x30,0x00,0x40, // 94 299 | 0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08, // 95 300 | 0x08,0x00,0x10, // 96 301 | 0x00,0x00,0x00,0x03,0xA0,0x02,0xA0,0x02,0xE0,0x03, // 97 302 | 0x00,0x00,0xF8,0x03,0x20,0x02,0x20,0x02,0xC0,0x01, // 98 303 | 0x00,0x00,0xC0,0x01,0x20,0x02,0x20,0x02,0x40,0x01, // 99 304 | 0x00,0x00,0xC0,0x01,0x20,0x02,0x20,0x02,0xF8,0x03, // 100 305 | 0x00,0x00,0xC0,0x01,0xA0,0x02,0xA0,0x02,0xC0,0x02, // 101 306 | 0x20,0x00,0xF0,0x03,0x28, // 102 307 | 0x00,0x00,0xC0,0x05,0x20,0x0A,0x20,0x0A,0xE0,0x07, // 103 308 | 0x00,0x00,0xF8,0x03,0x20,0x00,0x20,0x00,0xC0,0x03, // 104 309 | 0x00,0x00,0xE8,0x03, // 105 310 | 0x00,0x08,0xE8,0x07, // 106 311 | 0xF8,0x03,0x80,0x00,0xC0,0x01,0x20,0x02, // 107 312 | 0x00,0x00,0xF8,0x03, // 108 313 | 0x00,0x00,0xE0,0x03,0x20,0x00,0x20,0x00,0xE0,0x03,0x20,0x00,0x20,0x00,0xC0,0x03, // 109 314 | 0x00,0x00,0xE0,0x03,0x20,0x00,0x20,0x00,0xC0,0x03, // 110 315 | 0x00,0x00,0xC0,0x01,0x20,0x02,0x20,0x02,0xC0,0x01, // 111 316 | 0x00,0x00,0xE0,0x0F,0x20,0x02,0x20,0x02,0xC0,0x01, // 112 317 | 0x00,0x00,0xC0,0x01,0x20,0x02,0x20,0x02,0xE0,0x0F, // 113 318 | 0x00,0x00,0xE0,0x03,0x20, // 114 319 | 0x40,0x02,0xA0,0x02,0xA0,0x02,0x20,0x01, // 115 320 | 0x20,0x00,0xF8,0x03,0x20,0x02, // 116 321 | 0x00,0x00,0xE0,0x01,0x00,0x02,0x00,0x02,0xE0,0x03, // 117 322 | 0x20,0x00,0xC0,0x01,0x00,0x02,0xC0,0x01,0x20, // 118 323 | 0xE0,0x01,0x00,0x02,0xC0,0x01,0x20,0x00,0xC0,0x01,0x00,0x02,0xE0,0x01, // 119 324 | 0x20,0x02,0x40,0x01,0x80,0x00,0x40,0x01,0x20,0x02, // 120 325 | 0x20,0x00,0xC0,0x09,0x00,0x06,0xC0,0x01,0x20, // 121 326 | 0x20,0x02,0x20,0x03,0xA0,0x02,0x60,0x02,0x20,0x02, // 122 327 | 0x80,0x00,0x78,0x0F,0x08,0x08, // 123 328 | 0x00,0x00,0xF8,0x0F, // 124 329 | 0x08,0x08,0x78,0x0F,0x80, // 125 330 | 0xC0,0x00,0x40,0x00,0xC0,0x00,0x80,0x00,0xC0, // 126 331 | 0x00,0x00,0xA0,0x0F, // 161 332 | 0x00,0x00,0xC0,0x01,0xA0,0x0F,0x78,0x02,0x40,0x01, // 162 333 | 0x40,0x02,0x70,0x03,0xC8,0x02,0x48,0x02,0x08,0x02,0x10,0x02, // 163 334 | 0x00,0x00,0xE0,0x01,0x20,0x01,0x20,0x01,0xE0,0x01, // 164 335 | 0x48,0x01,0x70,0x01,0xC0,0x03,0x70,0x01,0x48,0x01, // 165 336 | 0x00,0x00,0x38,0x0F, // 166 337 | 0xD0,0x04,0x28,0x09,0x48,0x09,0x48,0x0A,0x90,0x05, // 167 338 | 0x08,0x00,0x00,0x00,0x08, // 168 339 | 0xE0,0x00,0x10,0x01,0x48,0x02,0xA8,0x02,0xA8,0x02,0x10,0x01,0xE0, // 169 340 | 0x68,0x00,0x68,0x00,0x68,0x00,0x78, // 170 341 | 0x00,0x00,0x80,0x01,0x40,0x02,0x80,0x01,0x40,0x02, // 171 342 | 0x20,0x00,0x20,0x00,0x20,0x00,0x20,0x00,0xE0, // 172 343 | 0x80,0x00,0x80, // 173 344 | 0xE0,0x00,0x10,0x01,0xE8,0x02,0x68,0x02,0xC8,0x02,0x10,0x01,0xE0, // 174 345 | 0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02,0x00,0x02, // 175 346 | 0x00,0x00,0x38,0x00,0x28,0x00,0x38, // 176 347 | 0x40,0x02,0x40,0x02,0xF0,0x03,0x40,0x02,0x40,0x02, // 177 348 | 0x48,0x00,0x68,0x00,0x58, // 178 349 | 0x48,0x00,0x58,0x00,0x68, // 179 350 | 0x00,0x00,0x10,0x00,0x08, // 180 351 | 0x00,0x00,0xE0,0x0F,0x00,0x02,0x00,0x02,0xE0,0x03, // 181 352 | 0x70,0x00,0xF8,0x0F,0x08,0x00,0xF8,0x0F,0x08, // 182 353 | 0x00,0x00,0x40, // 183 354 | 0x00,0x00,0x00,0x14,0x00,0x18, // 184 355 | 0x00,0x00,0x10,0x00,0x78, // 185 356 | 0x30,0x00,0x48,0x00,0x48,0x00,0x30, // 186 357 | 0x00,0x00,0x40,0x02,0x80,0x01,0x40,0x02,0x80,0x01, // 187 358 | 0x00,0x00,0x10,0x02,0x78,0x01,0xC0,0x00,0x20,0x01,0x90,0x01,0xC8,0x03,0x00,0x01, // 188 359 | 0x00,0x00,0x10,0x02,0x78,0x01,0x80,0x00,0x60,0x00,0x50,0x02,0x48,0x03,0xC0,0x02, // 189 360 | 0x48,0x00,0x58,0x00,0x68,0x03,0x80,0x00,0x60,0x01,0x90,0x01,0xC8,0x03,0x00,0x01, // 190 361 | 0x00,0x00,0x00,0x06,0x00,0x09,0xA0,0x09,0x00,0x04, // 191 362 | 0x00,0x02,0xC0,0x01,0xB0,0x00,0x89,0x00,0xB2,0x00,0xC0,0x01,0x00,0x02, // 192 363 | 0x00,0x02,0xC0,0x01,0xB0,0x00,0x8A,0x00,0xB1,0x00,0xC0,0x01,0x00,0x02, // 193 364 | 0x00,0x02,0xC0,0x01,0xB2,0x00,0x89,0x00,0xB2,0x00,0xC0,0x01,0x00,0x02, // 194 365 | 0x00,0x02,0xC2,0x01,0xB1,0x00,0x8A,0x00,0xB1,0x00,0xC0,0x01,0x00,0x02, // 195 366 | 0x00,0x02,0xC0,0x01,0xB2,0x00,0x88,0x00,0xB2,0x00,0xC0,0x01,0x00,0x02, // 196 367 | 0x00,0x02,0xC0,0x01,0xBE,0x00,0x8A,0x00,0xBE,0x00,0xC0,0x01,0x00,0x02, // 197 368 | 0x00,0x03,0xC0,0x00,0xE0,0x00,0x98,0x00,0x88,0x00,0xF8,0x03,0x48,0x02,0x48,0x02,0x48,0x02, // 198 369 | 0x00,0x00,0xF0,0x01,0x08,0x02,0x08,0x16,0x08,0x1A,0x10,0x01, // 199 370 | 0x00,0x00,0xF8,0x03,0x49,0x02,0x4A,0x02,0x48,0x02,0x48,0x02, // 200 371 | 0x00,0x00,0xF8,0x03,0x48,0x02,0x4A,0x02,0x49,0x02,0x48,0x02, // 201 372 | 0x00,0x00,0xFA,0x03,0x49,0x02,0x4A,0x02,0x48,0x02,0x48,0x02, // 202 373 | 0x00,0x00,0xF8,0x03,0x4A,0x02,0x48,0x02,0x4A,0x02,0x48,0x02, // 203 374 | 0x00,0x00,0xF9,0x03,0x02, // 204 375 | 0x02,0x00,0xF9,0x03, // 205 376 | 0x01,0x00,0xFA,0x03, // 206 377 | 0x02,0x00,0xF8,0x03,0x02, // 207 378 | 0x40,0x00,0xF8,0x03,0x48,0x02,0x48,0x02,0x10,0x01,0xE0, // 208 379 | 0x00,0x00,0xFA,0x03,0x31,0x00,0x42,0x00,0x81,0x01,0xF8,0x03, // 209 380 | 0x00,0x00,0xF0,0x01,0x08,0x02,0x09,0x02,0x0A,0x02,0x08,0x02,0xF0,0x01, // 210 381 | 0x00,0x00,0xF0,0x01,0x08,0x02,0x0A,0x02,0x09,0x02,0x08,0x02,0xF0,0x01, // 211 382 | 0x00,0x00,0xF0,0x01,0x08,0x02,0x0A,0x02,0x09,0x02,0x0A,0x02,0xF0,0x01, // 212 383 | 0x00,0x00,0xF0,0x01,0x0A,0x02,0x09,0x02,0x0A,0x02,0x09,0x02,0xF0,0x01, // 213 384 | 0x00,0x00,0xF0,0x01,0x0A,0x02,0x08,0x02,0x0A,0x02,0x08,0x02,0xF0,0x01, // 214 385 | 0x10,0x01,0xA0,0x00,0xE0,0x00,0xA0,0x00,0x10,0x01, // 215 386 | 0x00,0x00,0xF0,0x02,0x08,0x03,0xC8,0x02,0x28,0x02,0x18,0x03,0xE8, // 216 387 | 0x00,0x00,0xF8,0x01,0x01,0x02,0x02,0x02,0x00,0x02,0xF8,0x01, // 217 388 | 0x00,0x00,0xF8,0x01,0x02,0x02,0x01,0x02,0x00,0x02,0xF8,0x01, // 218 389 | 0x00,0x00,0xF8,0x01,0x02,0x02,0x01,0x02,0x02,0x02,0xF8,0x01, // 219 390 | 0x00,0x00,0xF8,0x01,0x02,0x02,0x00,0x02,0x02,0x02,0xF8,0x01, // 220 391 | 0x08,0x00,0x10,0x00,0x20,0x00,0xC2,0x03,0x21,0x00,0x10,0x00,0x08, // 221 392 | 0x00,0x00,0xF8,0x03,0x10,0x01,0x10,0x01,0x10,0x01,0xE0, // 222 393 | 0x00,0x00,0xF0,0x03,0x08,0x01,0x48,0x02,0xB0,0x02,0x80,0x01, // 223 394 | 0x00,0x00,0x00,0x03,0xA4,0x02,0xA8,0x02,0xE0,0x03, // 224 395 | 0x00,0x00,0x00,0x03,0xA8,0x02,0xA4,0x02,0xE0,0x03, // 225 396 | 0x00,0x00,0x00,0x03,0xA8,0x02,0xA4,0x02,0xE8,0x03, // 226 397 | 0x00,0x00,0x08,0x03,0xA4,0x02,0xA8,0x02,0xE4,0x03, // 227 398 | 0x00,0x00,0x00,0x03,0xA8,0x02,0xA0,0x02,0xE8,0x03, // 228 399 | 0x00,0x00,0x00,0x03,0xAE,0x02,0xAA,0x02,0xEE,0x03, // 229 400 | 0x00,0x00,0x40,0x03,0xA0,0x02,0xA0,0x02,0xC0,0x01,0xA0,0x02,0xA0,0x02,0xC0,0x02, // 230 401 | 0x00,0x00,0xC0,0x01,0x20,0x16,0x20,0x1A,0x40,0x01, // 231 402 | 0x00,0x00,0xC0,0x01,0xA4,0x02,0xA8,0x02,0xC0,0x02, // 232 403 | 0x00,0x00,0xC0,0x01,0xA8,0x02,0xA4,0x02,0xC0,0x02, // 233 404 | 0x00,0x00,0xC0,0x01,0xA8,0x02,0xA4,0x02,0xC8,0x02, // 234 405 | 0x00,0x00,0xC0,0x01,0xA8,0x02,0xA0,0x02,0xC8,0x02, // 235 406 | 0x00,0x00,0xE4,0x03,0x08, // 236 407 | 0x08,0x00,0xE4,0x03, // 237 408 | 0x08,0x00,0xE4,0x03,0x08, // 238 409 | 0x08,0x00,0xE0,0x03,0x08, // 239 410 | 0x00,0x00,0xC0,0x01,0x28,0x02,0x38,0x02,0xE0,0x01, // 240 411 | 0x00,0x00,0xE8,0x03,0x24,0x00,0x28,0x00,0xC4,0x03, // 241 412 | 0x00,0x00,0xC0,0x01,0x24,0x02,0x28,0x02,0xC0,0x01, // 242 413 | 0x00,0x00,0xC0,0x01,0x28,0x02,0x24,0x02,0xC0,0x01, // 243 414 | 0x00,0x00,0xC0,0x01,0x28,0x02,0x24,0x02,0xC8,0x01, // 244 415 | 0x00,0x00,0xC8,0x01,0x24,0x02,0x28,0x02,0xC4,0x01, // 245 416 | 0x00,0x00,0xC0,0x01,0x28,0x02,0x20,0x02,0xC8,0x01, // 246 417 | 0x40,0x00,0x40,0x00,0x50,0x01,0x40,0x00,0x40, // 247 418 | 0x00,0x00,0xC0,0x02,0xA0,0x03,0x60,0x02,0xA0,0x01, // 248 419 | 0x00,0x00,0xE0,0x01,0x04,0x02,0x08,0x02,0xE0,0x03, // 249 420 | 0x00,0x00,0xE0,0x01,0x08,0x02,0x04,0x02,0xE0,0x03, // 250 421 | 0x00,0x00,0xE8,0x01,0x04,0x02,0x08,0x02,0xE0,0x03, // 251 422 | 0x00,0x00,0xE0,0x01,0x08,0x02,0x00,0x02,0xE8,0x03, // 252 423 | 0x20,0x00,0xC0,0x09,0x08,0x06,0xC4,0x01,0x20, // 253 424 | 0x00,0x00,0xF8,0x0F,0x20,0x02,0x20,0x02,0xC0,0x01, // 254 425 | 0x20,0x00,0xC8,0x09,0x00,0x06,0xC8,0x01,0x20 // 255 426 | }; 427 | 428 | const uint8_t ArialMT_Plain_16[] PROGMEM = { 429 | 0x10, // Width: 16 430 | 0x13, // Height: 19 431 | 0x20, // First Char: 32 432 | 0xE0, // Numbers of Chars: 224 433 | 434 | // Jump Table: 435 | 0xFF, 0xFF, 0x00, 0x04, // 32:65535 436 | 0x00, 0x00, 0x08, 0x04, // 33:0 437 | 0x00, 0x08, 0x0D, 0x06, // 34:8 438 | 0x00, 0x15, 0x1A, 0x09, // 35:21 439 | 0x00, 0x2F, 0x17, 0x09, // 36:47 440 | 0x00, 0x46, 0x26, 0x0E, // 37:70 441 | 0x00, 0x6C, 0x1D, 0x0B, // 38:108 442 | 0x00, 0x89, 0x04, 0x03, // 39:137 443 | 0x00, 0x8D, 0x0C, 0x05, // 40:141 444 | 0x00, 0x99, 0x0B, 0x05, // 41:153 445 | 0x00, 0xA4, 0x0D, 0x06, // 42:164 446 | 0x00, 0xB1, 0x17, 0x09, // 43:177 447 | 0x00, 0xC8, 0x09, 0x04, // 44:200 448 | 0x00, 0xD1, 0x0B, 0x05, // 45:209 449 | 0x00, 0xDC, 0x08, 0x04, // 46:220 450 | 0x00, 0xE4, 0x0A, 0x04, // 47:228 451 | 0x00, 0xEE, 0x17, 0x09, // 48:238 452 | 0x01, 0x05, 0x11, 0x09, // 49:261 453 | 0x01, 0x16, 0x17, 0x09, // 50:278 454 | 0x01, 0x2D, 0x17, 0x09, // 51:301 455 | 0x01, 0x44, 0x17, 0x09, // 52:324 456 | 0x01, 0x5B, 0x17, 0x09, // 53:347 457 | 0x01, 0x72, 0x17, 0x09, // 54:370 458 | 0x01, 0x89, 0x16, 0x09, // 55:393 459 | 0x01, 0x9F, 0x17, 0x09, // 56:415 460 | 0x01, 0xB6, 0x17, 0x09, // 57:438 461 | 0x01, 0xCD, 0x05, 0x04, // 58:461 462 | 0x01, 0xD2, 0x06, 0x04, // 59:466 463 | 0x01, 0xD8, 0x17, 0x09, // 60:472 464 | 0x01, 0xEF, 0x17, 0x09, // 61:495 465 | 0x02, 0x06, 0x17, 0x09, // 62:518 466 | 0x02, 0x1D, 0x16, 0x09, // 63:541 467 | 0x02, 0x33, 0x2F, 0x10, // 64:563 468 | 0x02, 0x62, 0x1D, 0x0B, // 65:610 469 | 0x02, 0x7F, 0x1D, 0x0B, // 66:639 470 | 0x02, 0x9C, 0x20, 0x0C, // 67:668 471 | 0x02, 0xBC, 0x20, 0x0C, // 68:700 472 | 0x02, 0xDC, 0x1D, 0x0B, // 69:732 473 | 0x02, 0xF9, 0x19, 0x0A, // 70:761 474 | 0x03, 0x12, 0x20, 0x0C, // 71:786 475 | 0x03, 0x32, 0x1D, 0x0C, // 72:818 476 | 0x03, 0x4F, 0x05, 0x04, // 73:847 477 | 0x03, 0x54, 0x14, 0x08, // 74:852 478 | 0x03, 0x68, 0x1D, 0x0B, // 75:872 479 | 0x03, 0x85, 0x17, 0x09, // 76:901 480 | 0x03, 0x9C, 0x23, 0x0D, // 77:924 481 | 0x03, 0xBF, 0x1D, 0x0C, // 78:959 482 | 0x03, 0xDC, 0x20, 0x0C, // 79:988 483 | 0x03, 0xFC, 0x1C, 0x0B, // 80:1020 484 | 0x04, 0x18, 0x20, 0x0C, // 81:1048 485 | 0x04, 0x38, 0x1D, 0x0C, // 82:1080 486 | 0x04, 0x55, 0x1D, 0x0B, // 83:1109 487 | 0x04, 0x72, 0x19, 0x0A, // 84:1138 488 | 0x04, 0x8B, 0x1D, 0x0C, // 85:1163 489 | 0x04, 0xA8, 0x1C, 0x0B, // 86:1192 490 | 0x04, 0xC4, 0x2B, 0x0F, // 87:1220 491 | 0x04, 0xEF, 0x20, 0x0B, // 88:1263 492 | 0x05, 0x0F, 0x19, 0x0B, // 89:1295 493 | 0x05, 0x28, 0x1A, 0x0A, // 90:1320 494 | 0x05, 0x42, 0x0C, 0x04, // 91:1346 495 | 0x05, 0x4E, 0x0B, 0x04, // 92:1358 496 | 0x05, 0x59, 0x09, 0x04, // 93:1369 497 | 0x05, 0x62, 0x14, 0x08, // 94:1378 498 | 0x05, 0x76, 0x1B, 0x09, // 95:1398 499 | 0x05, 0x91, 0x07, 0x05, // 96:1425 500 | 0x05, 0x98, 0x17, 0x09, // 97:1432 501 | 0x05, 0xAF, 0x17, 0x09, // 98:1455 502 | 0x05, 0xC6, 0x14, 0x08, // 99:1478 503 | 0x05, 0xDA, 0x17, 0x09, // 100:1498 504 | 0x05, 0xF1, 0x17, 0x09, // 101:1521 505 | 0x06, 0x08, 0x0A, 0x04, // 102:1544 506 | 0x06, 0x12, 0x17, 0x09, // 103:1554 507 | 0x06, 0x29, 0x14, 0x09, // 104:1577 508 | 0x06, 0x3D, 0x05, 0x04, // 105:1597 509 | 0x06, 0x42, 0x06, 0x04, // 106:1602 510 | 0x06, 0x48, 0x17, 0x08, // 107:1608 511 | 0x06, 0x5F, 0x05, 0x04, // 108:1631 512 | 0x06, 0x64, 0x23, 0x0D, // 109:1636 513 | 0x06, 0x87, 0x14, 0x09, // 110:1671 514 | 0x06, 0x9B, 0x17, 0x09, // 111:1691 515 | 0x06, 0xB2, 0x17, 0x09, // 112:1714 516 | 0x06, 0xC9, 0x18, 0x09, // 113:1737 517 | 0x06, 0xE1, 0x0D, 0x05, // 114:1761 518 | 0x06, 0xEE, 0x14, 0x08, // 115:1774 519 | 0x07, 0x02, 0x0B, 0x04, // 116:1794 520 | 0x07, 0x0D, 0x14, 0x09, // 117:1805 521 | 0x07, 0x21, 0x13, 0x08, // 118:1825 522 | 0x07, 0x34, 0x1F, 0x0C, // 119:1844 523 | 0x07, 0x53, 0x14, 0x08, // 120:1875 524 | 0x07, 0x67, 0x13, 0x08, // 121:1895 525 | 0x07, 0x7A, 0x14, 0x08, // 122:1914 526 | 0x07, 0x8E, 0x0F, 0x05, // 123:1934 527 | 0x07, 0x9D, 0x06, 0x04, // 124:1949 528 | 0x07, 0xA3, 0x0E, 0x05, // 125:1955 529 | 0x07, 0xB1, 0x17, 0x09, // 126:1969 530 | 0xFF, 0xFF, 0x00, 0x00, // 127:65535 531 | 0xFF, 0xFF, 0x00, 0x10, // 128:65535 532 | 0xFF, 0xFF, 0x00, 0x10, // 129:65535 533 | 0xFF, 0xFF, 0x00, 0x10, // 130:65535 534 | 0xFF, 0xFF, 0x00, 0x10, // 131:65535 535 | 0xFF, 0xFF, 0x00, 0x10, // 132:65535 536 | 0xFF, 0xFF, 0x00, 0x10, // 133:65535 537 | 0xFF, 0xFF, 0x00, 0x10, // 134:65535 538 | 0xFF, 0xFF, 0x00, 0x10, // 135:65535 539 | 0xFF, 0xFF, 0x00, 0x10, // 136:65535 540 | 0xFF, 0xFF, 0x00, 0x10, // 137:65535 541 | 0xFF, 0xFF, 0x00, 0x10, // 138:65535 542 | 0xFF, 0xFF, 0x00, 0x10, // 139:65535 543 | 0xFF, 0xFF, 0x00, 0x10, // 140:65535 544 | 0xFF, 0xFF, 0x00, 0x10, // 141:65535 545 | 0xFF, 0xFF, 0x00, 0x10, // 142:65535 546 | 0xFF, 0xFF, 0x00, 0x10, // 143:65535 547 | 0xFF, 0xFF, 0x00, 0x10, // 144:65535 548 | 0xFF, 0xFF, 0x00, 0x10, // 145:65535 549 | 0xFF, 0xFF, 0x00, 0x10, // 146:65535 550 | 0xFF, 0xFF, 0x00, 0x10, // 147:65535 551 | 0xFF, 0xFF, 0x00, 0x10, // 148:65535 552 | 0xFF, 0xFF, 0x00, 0x10, // 149:65535 553 | 0xFF, 0xFF, 0x00, 0x10, // 150:65535 554 | 0xFF, 0xFF, 0x00, 0x10, // 151:65535 555 | 0xFF, 0xFF, 0x00, 0x10, // 152:65535 556 | 0xFF, 0xFF, 0x00, 0x10, // 153:65535 557 | 0xFF, 0xFF, 0x00, 0x10, // 154:65535 558 | 0xFF, 0xFF, 0x00, 0x10, // 155:65535 559 | 0xFF, 0xFF, 0x00, 0x10, // 156:65535 560 | 0xFF, 0xFF, 0x00, 0x10, // 157:65535 561 | 0xFF, 0xFF, 0x00, 0x10, // 158:65535 562 | 0xFF, 0xFF, 0x00, 0x10, // 159:65535 563 | 0xFF, 0xFF, 0x00, 0x04, // 160:65535 564 | 0x07, 0xC8, 0x09, 0x05, // 161:1992 565 | 0x07, 0xD1, 0x17, 0x09, // 162:2001 566 | 0x07, 0xE8, 0x17, 0x09, // 163:2024 567 | 0x07, 0xFF, 0x14, 0x09, // 164:2047 568 | 0x08, 0x13, 0x1A, 0x09, // 165:2067 569 | 0x08, 0x2D, 0x06, 0x04, // 166:2093 570 | 0x08, 0x33, 0x17, 0x09, // 167:2099 571 | 0x08, 0x4A, 0x07, 0x05, // 168:2122 572 | 0x08, 0x51, 0x23, 0x0C, // 169:2129 573 | 0x08, 0x74, 0x0E, 0x06, // 170:2164 574 | 0x08, 0x82, 0x14, 0x09, // 171:2178 575 | 0x08, 0x96, 0x17, 0x09, // 172:2198 576 | 0x08, 0xAD, 0x0B, 0x05, // 173:2221 577 | 0x08, 0xB8, 0x23, 0x0C, // 174:2232 578 | 0x08, 0xDB, 0x19, 0x09, // 175:2267 579 | 0x08, 0xF4, 0x0D, 0x06, // 176:2292 580 | 0x09, 0x01, 0x17, 0x09, // 177:2305 581 | 0x09, 0x18, 0x0E, 0x05, // 178:2328 582 | 0x09, 0x26, 0x0D, 0x05, // 179:2342 583 | 0x09, 0x33, 0x0A, 0x05, // 180:2355 584 | 0x09, 0x3D, 0x17, 0x09, // 181:2365 585 | 0x09, 0x54, 0x19, 0x09, // 182:2388 586 | 0x09, 0x6D, 0x08, 0x05, // 183:2413 587 | 0x09, 0x75, 0x0C, 0x05, // 184:2421 588 | 0x09, 0x81, 0x0B, 0x05, // 185:2433 589 | 0x09, 0x8C, 0x0D, 0x06, // 186:2444 590 | 0x09, 0x99, 0x17, 0x09, // 187:2457 591 | 0x09, 0xB0, 0x26, 0x0D, // 188:2480 592 | 0x09, 0xD6, 0x26, 0x0D, // 189:2518 593 | 0x09, 0xFC, 0x26, 0x0D, // 190:2556 594 | 0x0A, 0x22, 0x1A, 0x0A, // 191:2594 595 | 0x0A, 0x3C, 0x1D, 0x0B, // 192:2620 596 | 0x0A, 0x59, 0x1D, 0x0B, // 193:2649 597 | 0x0A, 0x76, 0x1D, 0x0B, // 194:2678 598 | 0x0A, 0x93, 0x1D, 0x0B, // 195:2707 599 | 0x0A, 0xB0, 0x1D, 0x0B, // 196:2736 600 | 0x0A, 0xCD, 0x1D, 0x0B, // 197:2765 601 | 0x0A, 0xEA, 0x2C, 0x10, // 198:2794 602 | 0x0B, 0x16, 0x20, 0x0C, // 199:2838 603 | 0x0B, 0x36, 0x1D, 0x0B, // 200:2870 604 | 0x0B, 0x53, 0x1D, 0x0B, // 201:2899 605 | 0x0B, 0x70, 0x1D, 0x0B, // 202:2928 606 | 0x0B, 0x8D, 0x1D, 0x0B, // 203:2957 607 | 0x0B, 0xAA, 0x05, 0x04, // 204:2986 608 | 0x0B, 0xAF, 0x07, 0x04, // 205:2991 609 | 0x0B, 0xB6, 0x0A, 0x04, // 206:2998 610 | 0x0B, 0xC0, 0x07, 0x04, // 207:3008 611 | 0x0B, 0xC7, 0x20, 0x0C, // 208:3015 612 | 0x0B, 0xE7, 0x1D, 0x0C, // 209:3047 613 | 0x0C, 0x04, 0x20, 0x0C, // 210:3076 614 | 0x0C, 0x24, 0x20, 0x0C, // 211:3108 615 | 0x0C, 0x44, 0x20, 0x0C, // 212:3140 616 | 0x0C, 0x64, 0x20, 0x0C, // 213:3172 617 | 0x0C, 0x84, 0x20, 0x0C, // 214:3204 618 | 0x0C, 0xA4, 0x17, 0x09, // 215:3236 619 | 0x0C, 0xBB, 0x20, 0x0C, // 216:3259 620 | 0x0C, 0xDB, 0x1D, 0x0C, // 217:3291 621 | 0x0C, 0xF8, 0x1D, 0x0C, // 218:3320 622 | 0x0D, 0x15, 0x1D, 0x0C, // 219:3349 623 | 0x0D, 0x32, 0x1D, 0x0C, // 220:3378 624 | 0x0D, 0x4F, 0x19, 0x0B, // 221:3407 625 | 0x0D, 0x68, 0x1D, 0x0B, // 222:3432 626 | 0x0D, 0x85, 0x17, 0x0A, // 223:3461 627 | 0x0D, 0x9C, 0x17, 0x09, // 224:3484 628 | 0x0D, 0xB3, 0x17, 0x09, // 225:3507 629 | 0x0D, 0xCA, 0x17, 0x09, // 226:3530 630 | 0x0D, 0xE1, 0x17, 0x09, // 227:3553 631 | 0x0D, 0xF8, 0x17, 0x09, // 228:3576 632 | 0x0E, 0x0F, 0x17, 0x09, // 229:3599 633 | 0x0E, 0x26, 0x29, 0x0E, // 230:3622 634 | 0x0E, 0x4F, 0x14, 0x08, // 231:3663 635 | 0x0E, 0x63, 0x17, 0x09, // 232:3683 636 | 0x0E, 0x7A, 0x17, 0x09, // 233:3706 637 | 0x0E, 0x91, 0x17, 0x09, // 234:3729 638 | 0x0E, 0xA8, 0x17, 0x09, // 235:3752 639 | 0x0E, 0xBF, 0x05, 0x04, // 236:3775 640 | 0x0E, 0xC4, 0x07, 0x04, // 237:3780 641 | 0x0E, 0xCB, 0x0A, 0x04, // 238:3787 642 | 0x0E, 0xD5, 0x07, 0x04, // 239:3797 643 | 0x0E, 0xDC, 0x17, 0x09, // 240:3804 644 | 0x0E, 0xF3, 0x14, 0x09, // 241:3827 645 | 0x0F, 0x07, 0x17, 0x09, // 242:3847 646 | 0x0F, 0x1E, 0x17, 0x09, // 243:3870 647 | 0x0F, 0x35, 0x17, 0x09, // 244:3893 648 | 0x0F, 0x4C, 0x17, 0x09, // 245:3916 649 | 0x0F, 0x63, 0x17, 0x09, // 246:3939 650 | 0x0F, 0x7A, 0x17, 0x09, // 247:3962 651 | 0x0F, 0x91, 0x17, 0x0A, // 248:3985 652 | 0x0F, 0xA8, 0x14, 0x09, // 249:4008 653 | 0x0F, 0xBC, 0x14, 0x09, // 250:4028 654 | 0x0F, 0xD0, 0x14, 0x09, // 251:4048 655 | 0x0F, 0xE4, 0x14, 0x09, // 252:4068 656 | 0x0F, 0xF8, 0x13, 0x08, // 253:4088 657 | 0x10, 0x0B, 0x17, 0x09, // 254:4107 658 | 0x10, 0x22, 0x13, 0x08, // 255:4130 659 | 660 | // Font Data: 661 | 0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x5F, // 33 662 | 0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, // 34 663 | 0x80,0x08,0x00,0x80,0x78,0x00,0xC0,0x0F,0x00,0xB8,0x08,0x00,0x80,0x08,0x00,0x80,0x78,0x00,0xC0,0x0F,0x00,0xB8,0x08,0x00,0x80,0x08, // 35 664 | 0x00,0x00,0x00,0xE0,0x10,0x00,0x10,0x21,0x00,0x08,0x41,0x00,0xFC,0xFF,0x00,0x08,0x42,0x00,0x10,0x22,0x00,0x20,0x1C, // 36 665 | 0x00,0x00,0x00,0xF0,0x00,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0x08,0x61,0x00,0xF0,0x18,0x00,0x00,0x06,0x00,0xC0,0x01,0x00,0x30,0x3C,0x00,0x08,0x42,0x00,0x00,0x42,0x00,0x00,0x42,0x00,0x00,0x3C, // 37 666 | 0x00,0x00,0x00,0x00,0x1C,0x00,0x70,0x22,0x00,0x88,0x41,0x00,0x08,0x43,0x00,0x88,0x44,0x00,0x70,0x28,0x00,0x00,0x10,0x00,0x00,0x28,0x00,0x00,0x44, // 38 667 | 0x00,0x00,0x00,0x78, // 39 668 | 0x00,0x00,0x00,0x80,0x3F,0x00,0x70,0xC0,0x01,0x08,0x00,0x02, // 40 669 | 0x00,0x00,0x00,0x08,0x00,0x02,0x70,0xC0,0x01,0x80,0x3F, // 41 670 | 0x10,0x00,0x00,0xD0,0x00,0x00,0x38,0x00,0x00,0xD0,0x00,0x00,0x10, // 42 671 | 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0xC0,0x1F,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02, // 43 672 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x01, // 44 673 | 0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08, // 45 674 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40, // 46 675 | 0x00,0x60,0x00,0x00,0x1E,0x00,0xE0,0x01,0x00,0x18, // 47 676 | 0x00,0x00,0x00,0xE0,0x1F,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0xE0,0x1F, // 48 677 | 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0x00,0x10,0x00,0x00,0xF8,0x7F, // 49 678 | 0x00,0x00,0x00,0x20,0x40,0x00,0x10,0x60,0x00,0x08,0x50,0x00,0x08,0x48,0x00,0x08,0x44,0x00,0x10,0x43,0x00,0xE0,0x40, // 50 679 | 0x00,0x00,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x88,0x41,0x00,0xF0,0x22,0x00,0x00,0x1C, // 51 680 | 0x00,0x0C,0x00,0x00,0x0A,0x00,0x00,0x09,0x00,0xC0,0x08,0x00,0x20,0x08,0x00,0x10,0x08,0x00,0xF8,0x7F,0x00,0x00,0x08, // 52 681 | 0x00,0x00,0x00,0xC0,0x11,0x00,0xB8,0x20,0x00,0x88,0x40,0x00,0x88,0x40,0x00,0x88,0x40,0x00,0x08,0x21,0x00,0x08,0x1E, // 53 682 | 0x00,0x00,0x00,0xE0,0x1F,0x00,0x10,0x21,0x00,0x88,0x40,0x00,0x88,0x40,0x00,0x88,0x40,0x00,0x10,0x21,0x00,0x20,0x1E, // 54 683 | 0x00,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x78,0x00,0x08,0x07,0x00,0xC8,0x00,0x00,0x28,0x00,0x00,0x18, // 55 684 | 0x00,0x00,0x00,0x60,0x1C,0x00,0x90,0x22,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x90,0x22,0x00,0x60,0x1C, // 56 685 | 0x00,0x00,0x00,0xE0,0x11,0x00,0x10,0x22,0x00,0x08,0x44,0x00,0x08,0x44,0x00,0x08,0x44,0x00,0x10,0x22,0x00,0xE0,0x1F, // 57 686 | 0x00,0x00,0x00,0x40,0x40, // 58 687 | 0x00,0x00,0x00,0x40,0xC0,0x01, // 59 688 | 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x05,0x00,0x00,0x05,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x40,0x10, // 60 689 | 0x00,0x00,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08, // 61 690 | 0x00,0x00,0x00,0x40,0x10,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x80,0x08,0x00,0x00,0x05,0x00,0x00,0x05,0x00,0x00,0x02, // 62 691 | 0x00,0x00,0x00,0x60,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0x08,0x5C,0x00,0x08,0x02,0x00,0x10,0x01,0x00,0xE0, // 63 692 | 0x00,0x00,0x00,0x00,0x3F,0x00,0xC0,0x40,0x00,0x20,0x80,0x00,0x10,0x1E,0x01,0x10,0x21,0x01,0x88,0x40,0x02,0x48,0x40,0x02,0x48,0x40,0x02,0x48,0x20,0x02,0x88,0x7C,0x02,0xC8,0x43,0x02,0x10,0x40,0x02,0x10,0x20,0x01,0x60,0x10,0x01,0x80,0x8F, // 64 693 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x70,0x04,0x00,0x08,0x04,0x00,0x70,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 65 694 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x90,0x22,0x00,0x60,0x1C, // 66 695 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10, // 67 696 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 68 697 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 69 698 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08, // 70 699 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x10,0x22,0x00,0x20,0x12,0x00,0x00,0x0E, // 71 700 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0xF8,0x7F, // 72 701 | 0x00,0x00,0x00,0xF8,0x7F, // 73 702 | 0x00,0x00,0x00,0x00,0x38,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0xF8,0x3F, // 74 703 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x04,0x00,0x00,0x02,0x00,0x00,0x01,0x00,0x80,0x03,0x00,0x40,0x04,0x00,0x20,0x18,0x00,0x10,0x20,0x00,0x08,0x40, // 75 704 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40, // 76 705 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x30,0x00,0x00,0xC0,0x00,0x00,0x00,0x03,0x00,0x00,0x1C,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x00,0x03,0x00,0xC0,0x00,0x00,0x30,0x00,0x00,0xF8,0x7F, // 77 706 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x10,0x00,0x00,0x60,0x00,0x00,0x80,0x00,0x00,0x00,0x03,0x00,0x00,0x04,0x00,0x00,0x18,0x00,0x00,0x20,0x00,0xF8,0x7F, // 78 707 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 79 708 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x10,0x01,0x00,0xE0, // 80 709 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x08,0x50,0x00,0x08,0x50,0x00,0x10,0x20,0x00,0x20,0x70,0x00,0xC0,0x4F, // 81 710 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x02,0x00,0x08,0x06,0x00,0x08,0x1A,0x00,0x10,0x21,0x00,0xE0,0x40, // 82 711 | 0x00,0x00,0x00,0x60,0x10,0x00,0x90,0x20,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x10,0x22,0x00,0x20,0x1C, // 83 712 | 0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0xF8,0x7F,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08, // 84 713 | 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 85 714 | 0x00,0x00,0x00,0x18,0x00,0x00,0xE0,0x00,0x00,0x00,0x07,0x00,0x00,0x18,0x00,0x00,0x60,0x00,0x00,0x18,0x00,0x00,0x07,0x00,0xE0,0x00,0x00,0x18, // 86 715 | 0x18,0x00,0x00,0xE0,0x01,0x00,0x00,0x1E,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x03,0x00,0x70,0x00,0x00,0x08,0x00,0x00,0x70,0x00,0x00,0x80,0x03,0x00,0x00,0x1C,0x00,0x00,0x60,0x00,0x00,0x1E,0x00,0xE0,0x01,0x00,0x18, // 87 716 | 0x00,0x40,0x00,0x08,0x20,0x00,0x10,0x10,0x00,0x60,0x0C,0x00,0x80,0x02,0x00,0x00,0x01,0x00,0x80,0x02,0x00,0x60,0x0C,0x00,0x10,0x10,0x00,0x08,0x20,0x00,0x00,0x40, // 88 717 | 0x08,0x00,0x00,0x30,0x00,0x00,0x40,0x00,0x00,0x80,0x01,0x00,0x00,0x7E,0x00,0x80,0x01,0x00,0x40,0x00,0x00,0x30,0x00,0x00,0x08, // 89 718 | 0x00,0x40,0x00,0x08,0x60,0x00,0x08,0x58,0x00,0x08,0x44,0x00,0x08,0x43,0x00,0x88,0x40,0x00,0x68,0x40,0x00,0x18,0x40,0x00,0x08,0x40, // 90 719 | 0x00,0x00,0x00,0xF8,0xFF,0x03,0x08,0x00,0x02,0x08,0x00,0x02, // 91 720 | 0x18,0x00,0x00,0xE0,0x01,0x00,0x00,0x1E,0x00,0x00,0x60, // 92 721 | 0x08,0x00,0x02,0x08,0x00,0x02,0xF8,0xFF,0x03, // 93 722 | 0x00,0x01,0x00,0xC0,0x00,0x00,0x30,0x00,0x00,0x08,0x00,0x00,0x30,0x00,0x00,0xC0,0x00,0x00,0x00,0x01, // 94 723 | 0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02, // 95 724 | 0x00,0x00,0x00,0x08,0x00,0x00,0x10, // 96 725 | 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 97 726 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 98 727 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20, // 99 728 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0xF8,0x7F, // 100 729 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 101 730 | 0x40,0x00,0x00,0xF0,0x7F,0x00,0x48,0x00,0x00,0x48, // 102 731 | 0x00,0x00,0x00,0x00,0x1F,0x01,0x80,0x20,0x02,0x40,0x40,0x02,0x40,0x40,0x02,0x40,0x40,0x02,0x80,0x20,0x01,0xC0,0xFF, // 103 732 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x80,0x7F, // 104 733 | 0x00,0x00,0x00,0xC8,0x7F, // 105 734 | 0x00,0x00,0x02,0xC8,0xFF,0x01, // 106 735 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x06,0x00,0x00,0x19,0x00,0x80,0x20,0x00,0x40,0x40, // 107 736 | 0x00,0x00,0x00,0xF8,0x7F, // 108 737 | 0x00,0x00,0x00,0xC0,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x80,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x80,0x7F, // 109 738 | 0x00,0x00,0x00,0xC0,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x80,0x7F, // 110 739 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 111 740 | 0x00,0x00,0x00,0xC0,0xFF,0x03,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 112 741 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0xC0,0xFF,0x03, // 113 742 | 0x00,0x00,0x00,0xC0,0x7F,0x00,0x80,0x00,0x00,0x40,0x00,0x00,0x40, // 114 743 | 0x00,0x00,0x00,0x80,0x23,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x80,0x38, // 115 744 | 0x40,0x00,0x00,0xF0,0x7F,0x00,0x40,0x40,0x00,0x40,0x40, // 116 745 | 0x00,0x00,0x00,0xC0,0x3F,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xC0,0x7F, // 117 746 | 0xC0,0x00,0x00,0x00,0x03,0x00,0x00,0x1C,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x00,0x03,0x00,0xC0, // 118 747 | 0xC0,0x00,0x00,0x00,0x1F,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x00,0x03,0x00,0xC0,0x00,0x00,0x00,0x03,0x00,0x00,0x1C,0x00,0x00,0x60,0x00,0x00,0x1F,0x00,0xC0, // 119 748 | 0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1B,0x00,0x00,0x04,0x00,0x00,0x1B,0x00,0x80,0x20,0x00,0x40,0x40, // 120 749 | 0xC0,0x01,0x00,0x00,0x06,0x02,0x00,0x38,0x02,0x00,0xE0,0x01,0x00,0x38,0x00,0x00,0x07,0x00,0xC0, // 121 750 | 0x40,0x40,0x00,0x40,0x60,0x00,0x40,0x58,0x00,0x40,0x44,0x00,0x40,0x43,0x00,0xC0,0x40,0x00,0x40,0x40, // 122 751 | 0x00,0x04,0x00,0x00,0x04,0x00,0xF0,0xFB,0x01,0x08,0x00,0x02,0x08,0x00,0x02, // 123 752 | 0x00,0x00,0x00,0xF8,0xFF,0x03, // 124 753 | 0x08,0x00,0x02,0x08,0x00,0x02,0xF0,0xFB,0x01,0x00,0x04,0x00,0x00,0x04, // 125 754 | 0x00,0x02,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x01,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x01, // 126 755 | 0x00,0x00,0x00,0x00,0x00,0x00,0x40,0xFF,0x03, // 161 756 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x03,0x40,0xF0,0x00,0x40,0x4E,0x00,0xC0,0x41,0x00,0xB8,0x20,0x00,0x00,0x11, // 162 757 | 0x00,0x41,0x00,0xE0,0x31,0x00,0x10,0x2F,0x00,0x08,0x21,0x00,0x08,0x21,0x00,0x08,0x40,0x00,0x10,0x40,0x00,0x20,0x20, // 163 758 | 0x00,0x00,0x00,0x40,0x0B,0x00,0x80,0x04,0x00,0x40,0x08,0x00,0x40,0x08,0x00,0x80,0x04,0x00,0x40,0x0B, // 164 759 | 0x08,0x0A,0x00,0x10,0x0A,0x00,0x60,0x0A,0x00,0x80,0x0B,0x00,0x00,0x7E,0x00,0x80,0x0B,0x00,0x60,0x0A,0x00,0x10,0x0A,0x00,0x08,0x0A, // 165 760 | 0x00,0x00,0x00,0xF8,0xF1,0x03, // 166 761 | 0x00,0x86,0x00,0x70,0x09,0x01,0xC8,0x10,0x02,0x88,0x10,0x02,0x08,0x21,0x02,0x08,0x61,0x02,0x30,0xD2,0x01,0x00,0x0C, // 167 762 | 0x08,0x00,0x00,0x00,0x00,0x00,0x08, // 168 763 | 0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0xC8,0x47,0x00,0x28,0x48,0x00,0x28,0x48,0x00,0x28,0x48,0x00,0x28,0x48,0x00,0x48,0x44,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 169 764 | 0xD0,0x00,0x00,0x48,0x01,0x00,0x28,0x01,0x00,0x28,0x01,0x00,0xF0,0x01, // 170 765 | 0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x1B,0x00,0x80,0x20,0x00,0x00,0x04,0x00,0x00,0x1B,0x00,0x80,0x20, // 171 766 | 0x00,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x00,0x00,0x80,0x0F, // 172 767 | 0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08,0x00,0x00,0x08, // 173 768 | 0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0xE8,0x4F,0x00,0x28,0x41,0x00,0x28,0x41,0x00,0x28,0x43,0x00,0x28,0x45,0x00,0xC8,0x48,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 174 769 | 0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04,0x00,0x00,0x04, // 175 770 | 0x00,0x00,0x00,0x30,0x00,0x00,0x48,0x00,0x00,0x48,0x00,0x00,0x30, // 176 771 | 0x00,0x00,0x00,0x00,0x41,0x00,0x00,0x41,0x00,0x00,0x41,0x00,0xE0,0x4F,0x00,0x00,0x41,0x00,0x00,0x41,0x00,0x00,0x41, // 177 772 | 0x10,0x01,0x00,0x88,0x01,0x00,0x48,0x01,0x00,0x48,0x01,0x00,0x30,0x01, // 178 773 | 0x90,0x00,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0x28,0x01,0x00,0xD8, // 179 774 | 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x08, // 180 775 | 0x00,0x00,0x00,0xC0,0xFF,0x03,0x00,0x20,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xC0,0x7F, // 181 776 | 0xF0,0x00,0x00,0xF8,0x00,0x00,0xF8,0x01,0x00,0xF8,0x01,0x00,0xF8,0xFF,0x03,0x08,0x00,0x00,0x08,0x00,0x00,0xF8,0xFF,0x03,0x08, // 182 777 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02, // 183 778 | 0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x80,0x02,0x00,0x00,0x03, // 184 779 | 0x00,0x00,0x00,0x10,0x00,0x00,0x08,0x00,0x00,0xF8,0x01, // 185 780 | 0xF0,0x00,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0x08,0x01,0x00,0xF0, // 186 781 | 0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x20,0x00,0x00,0x1B,0x00,0x00,0x04,0x00,0x80,0x20,0x00,0x00,0x1B,0x00,0x00,0x04, // 187 782 | 0x00,0x00,0x00,0x10,0x00,0x00,0x08,0x40,0x00,0xF8,0x21,0x00,0x00,0x10,0x00,0x00,0x0C,0x00,0x00,0x02,0x00,0x80,0x01,0x00,0x40,0x30,0x00,0x30,0x28,0x00,0x08,0x24,0x00,0x00,0x7E,0x00,0x00,0x20, // 188 783 | 0x00,0x00,0x00,0x10,0x00,0x00,0x08,0x40,0x00,0xF8,0x31,0x00,0x00,0x08,0x00,0x00,0x04,0x00,0x00,0x03,0x00,0x80,0x00,0x00,0x60,0x44,0x00,0x10,0x62,0x00,0x08,0x52,0x00,0x00,0x52,0x00,0x00,0x4C, // 189 784 | 0x90,0x00,0x00,0x08,0x01,0x00,0x08,0x41,0x00,0x28,0x21,0x00,0xD8,0x18,0x00,0x00,0x04,0x00,0x00,0x03,0x00,0x80,0x00,0x00,0x40,0x30,0x00,0x30,0x28,0x00,0x08,0x24,0x00,0x00,0x7E,0x00,0x00,0x20, // 190 785 | 0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x10,0x01,0x00,0x08,0x02,0x40,0x07,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x01,0x00,0xC0, // 191 786 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x71,0x04,0x00,0x0A,0x04,0x00,0x70,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 192 787 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x70,0x04,0x00,0x0A,0x04,0x00,0x71,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 193 788 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x72,0x04,0x00,0x09,0x04,0x00,0x71,0x04,0x00,0x82,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 194 789 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x72,0x04,0x00,0x09,0x04,0x00,0x72,0x04,0x00,0x81,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 195 790 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x72,0x04,0x00,0x08,0x04,0x00,0x72,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 196 791 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x80,0x07,0x00,0x7E,0x04,0x00,0x0A,0x04,0x00,0x7E,0x04,0x00,0x80,0x07,0x00,0x00,0x1C,0x00,0x00,0x60, // 197 792 | 0x00,0x60,0x00,0x00,0x18,0x00,0x00,0x06,0x00,0x80,0x05,0x00,0x60,0x04,0x00,0x18,0x04,0x00,0x08,0x04,0x00,0x08,0x04,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41, // 198 793 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x08,0x40,0x02,0x08,0xC0,0x02,0x08,0x40,0x03,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10, // 199 794 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x09,0x41,0x00,0x0A,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 200 795 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x0A,0x41,0x00,0x09,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 201 796 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x0A,0x41,0x00,0x09,0x41,0x00,0x09,0x41,0x00,0x0A,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 202 797 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x0A,0x41,0x00,0x08,0x41,0x00,0x0A,0x41,0x00,0x08,0x41,0x00,0x08,0x41,0x00,0x08,0x40, // 203 798 | 0x01,0x00,0x00,0xFA,0x7F, // 204 799 | 0x00,0x00,0x00,0xFA,0x7F,0x00,0x01, // 205 800 | 0x02,0x00,0x00,0xF9,0x7F,0x00,0x01,0x00,0x00,0x02, // 206 801 | 0x02,0x00,0x00,0xF8,0x7F,0x00,0x02, // 207 802 | 0x00,0x02,0x00,0xF8,0x7F,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x08,0x42,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 208 803 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x10,0x00,0x00,0x60,0x00,0x00,0x82,0x00,0x00,0x01,0x03,0x00,0x02,0x04,0x00,0x01,0x18,0x00,0x00,0x20,0x00,0xF8,0x7F, // 209 804 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x09,0x40,0x00,0x0A,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 210 805 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x0A,0x40,0x00,0x09,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 211 806 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x0A,0x40,0x00,0x09,0x40,0x00,0x09,0x40,0x00,0x0A,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 212 807 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x0A,0x40,0x00,0x09,0x40,0x00,0x0A,0x40,0x00,0x09,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 213 808 | 0x00,0x00,0x00,0xC0,0x0F,0x00,0x20,0x10,0x00,0x10,0x20,0x00,0x08,0x40,0x00,0x0A,0x40,0x00,0x08,0x40,0x00,0x0A,0x40,0x00,0x10,0x20,0x00,0x20,0x10,0x00,0xC0,0x0F, // 214 809 | 0x00,0x00,0x00,0x40,0x10,0x00,0x80,0x08,0x00,0x00,0x05,0x00,0x00,0x07,0x00,0x00,0x05,0x00,0x80,0x08,0x00,0x40,0x10, // 215 810 | 0x00,0x00,0x00,0xC0,0x4F,0x00,0x20,0x30,0x00,0x10,0x30,0x00,0x08,0x4C,0x00,0x08,0x42,0x00,0x08,0x41,0x00,0xC8,0x40,0x00,0x30,0x20,0x00,0x30,0x10,0x00,0xC8,0x0F, // 216 811 | 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x01,0x40,0x00,0x02,0x40,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 217 812 | 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x02,0x40,0x00,0x01,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 218 813 | 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x02,0x40,0x00,0x01,0x40,0x00,0x01,0x40,0x00,0x02,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 219 814 | 0x00,0x00,0x00,0xF8,0x1F,0x00,0x00,0x20,0x00,0x00,0x40,0x00,0x02,0x40,0x00,0x00,0x40,0x00,0x02,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xF8,0x1F, // 220 815 | 0x08,0x00,0x00,0x30,0x00,0x00,0x40,0x00,0x00,0x80,0x01,0x00,0x02,0x7E,0x00,0x81,0x01,0x00,0x40,0x00,0x00,0x30,0x00,0x00,0x08, // 221 816 | 0x00,0x00,0x00,0xF8,0x7F,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x20,0x10,0x00,0x40,0x08,0x00,0x80,0x07, // 222 817 | 0x00,0x00,0x00,0xE0,0x7F,0x00,0x10,0x00,0x00,0x08,0x20,0x00,0x88,0x43,0x00,0x70,0x42,0x00,0x00,0x44,0x00,0x00,0x38, // 223 818 | 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x40,0x44,0x00,0x48,0x44,0x00,0x50,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 224 819 | 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x40,0x44,0x00,0x50,0x44,0x00,0x48,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 225 820 | 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x50,0x44,0x00,0x48,0x44,0x00,0x48,0x42,0x00,0x50,0x22,0x00,0x80,0x7F, // 226 821 | 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x50,0x44,0x00,0x48,0x44,0x00,0x50,0x42,0x00,0x48,0x22,0x00,0x80,0x7F, // 227 822 | 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x50,0x44,0x00,0x40,0x44,0x00,0x50,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 228 823 | 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x5C,0x44,0x00,0x54,0x44,0x00,0x5C,0x42,0x00,0x40,0x22,0x00,0x80,0x7F, // 229 824 | 0x00,0x00,0x00,0x00,0x39,0x00,0x80,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x42,0x00,0x40,0x22,0x00,0x80,0x3F,0x00,0x80,0x24,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x40,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 230 825 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x02,0x40,0xC0,0x02,0x40,0x40,0x03,0x80,0x20, // 231 826 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x48,0x44,0x00,0x50,0x44,0x00,0x40,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 232 827 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x40,0x44,0x00,0x50,0x44,0x00,0x48,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 233 828 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x50,0x44,0x00,0x48,0x44,0x00,0x48,0x44,0x00,0x90,0x24,0x00,0x00,0x17, // 234 829 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x24,0x00,0x50,0x44,0x00,0x40,0x44,0x00,0x50,0x44,0x00,0x80,0x24,0x00,0x00,0x17, // 235 830 | 0x08,0x00,0x00,0xD0,0x7F, // 236 831 | 0x00,0x00,0x00,0xD0,0x7F,0x00,0x08, // 237 832 | 0x10,0x00,0x00,0xC8,0x7F,0x00,0x08,0x00,0x00,0x10, // 238 833 | 0x10,0x00,0x00,0xC0,0x7F,0x00,0x10, // 239 834 | 0x00,0x00,0x00,0x00,0x1F,0x00,0xA0,0x20,0x00,0x68,0x40,0x00,0x58,0x40,0x00,0x70,0x40,0x00,0xE8,0x20,0x00,0x00,0x1F, // 240 835 | 0x00,0x00,0x00,0xC0,0x7F,0x00,0x90,0x00,0x00,0x48,0x00,0x00,0x50,0x00,0x00,0x48,0x00,0x00,0x80,0x7F, // 241 836 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x48,0x40,0x00,0x50,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 242 837 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x40,0x40,0x00,0x50,0x40,0x00,0x48,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 243 838 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x50,0x40,0x00,0x48,0x40,0x00,0x48,0x40,0x00,0x90,0x20,0x00,0x00,0x1F, // 244 839 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x50,0x40,0x00,0x48,0x40,0x00,0x50,0x40,0x00,0x88,0x20,0x00,0x00,0x1F, // 245 840 | 0x00,0x00,0x00,0x00,0x1F,0x00,0x80,0x20,0x00,0x50,0x40,0x00,0x40,0x40,0x00,0x50,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 246 841 | 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x80,0x0A,0x00,0x00,0x02,0x00,0x00,0x02,0x00,0x00,0x02, // 247 842 | 0x00,0x00,0x00,0x00,0x5F,0x00,0x80,0x30,0x00,0x40,0x48,0x00,0x40,0x44,0x00,0x40,0x42,0x00,0x80,0x21,0x00,0x40,0x1F, // 248 843 | 0x00,0x00,0x00,0xC0,0x3F,0x00,0x00,0x40,0x00,0x08,0x40,0x00,0x10,0x40,0x00,0x00,0x20,0x00,0xC0,0x7F, // 249 844 | 0x00,0x00,0x00,0xC0,0x3F,0x00,0x00,0x40,0x00,0x00,0x40,0x00,0x10,0x40,0x00,0x08,0x20,0x00,0xC0,0x7F, // 250 845 | 0x00,0x00,0x00,0xC0,0x3F,0x00,0x10,0x40,0x00,0x08,0x40,0x00,0x08,0x40,0x00,0x10,0x20,0x00,0xC0,0x7F, // 251 846 | 0x00,0x00,0x00,0xD0,0x3F,0x00,0x00,0x40,0x00,0x10,0x40,0x00,0x00,0x40,0x00,0x00,0x20,0x00,0xC0,0x7F, // 252 847 | 0xC0,0x01,0x00,0x00,0x06,0x02,0x00,0x38,0x02,0x10,0xE0,0x01,0x08,0x38,0x00,0x00,0x07,0x00,0xC0, // 253 848 | 0x00,0x00,0x00,0xF8,0xFF,0x03,0x80,0x20,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x40,0x40,0x00,0x80,0x20,0x00,0x00,0x1F, // 254 849 | 0xC0,0x01,0x00,0x00,0x06,0x02,0x10,0x38,0x02,0x00,0xE0,0x01,0x10,0x38,0x00,0x00,0x07,0x00,0xC0 // 255 850 | }; 851 | const uint8_t ArialMT_Plain_24[] PROGMEM = { 852 | 0x18, // Width: 24 853 | 0x1C, // Height: 28 854 | 0x20, // First Char: 32 855 | 0xE0, // Numbers of Chars: 224 856 | 857 | // Jump Table: 858 | 0xFF, 0xFF, 0x00, 0x07, // 32:65535 859 | 0x00, 0x00, 0x13, 0x07, // 33:0 860 | 0x00, 0x13, 0x1A, 0x09, // 34:19 861 | 0x00, 0x2D, 0x33, 0x0D, // 35:45 862 | 0x00, 0x60, 0x2F, 0x0D, // 36:96 863 | 0x00, 0x8F, 0x4F, 0x15, // 37:143 864 | 0x00, 0xDE, 0x3B, 0x10, // 38:222 865 | 0x01, 0x19, 0x0A, 0x05, // 39:281 866 | 0x01, 0x23, 0x1C, 0x08, // 40:291 867 | 0x01, 0x3F, 0x1B, 0x08, // 41:319 868 | 0x01, 0x5A, 0x21, 0x09, // 42:346 869 | 0x01, 0x7B, 0x32, 0x0E, // 43:379 870 | 0x01, 0xAD, 0x10, 0x07, // 44:429 871 | 0x01, 0xBD, 0x1B, 0x08, // 45:445 872 | 0x01, 0xD8, 0x0F, 0x07, // 46:472 873 | 0x01, 0xE7, 0x19, 0x07, // 47:487 874 | 0x02, 0x00, 0x2F, 0x0D, // 48:512 875 | 0x02, 0x2F, 0x23, 0x0D, // 49:559 876 | 0x02, 0x52, 0x2F, 0x0D, // 50:594 877 | 0x02, 0x81, 0x2F, 0x0D, // 51:641 878 | 0x02, 0xB0, 0x2F, 0x0D, // 52:688 879 | 0x02, 0xDF, 0x2F, 0x0D, // 53:735 880 | 0x03, 0x0E, 0x2F, 0x0D, // 54:782 881 | 0x03, 0x3D, 0x2D, 0x0D, // 55:829 882 | 0x03, 0x6A, 0x2F, 0x0D, // 56:874 883 | 0x03, 0x99, 0x2F, 0x0D, // 57:921 884 | 0x03, 0xC8, 0x0F, 0x07, // 58:968 885 | 0x03, 0xD7, 0x10, 0x07, // 59:983 886 | 0x03, 0xE7, 0x2F, 0x0E, // 60:999 887 | 0x04, 0x16, 0x2F, 0x0E, // 61:1046 888 | 0x04, 0x45, 0x2E, 0x0E, // 62:1093 889 | 0x04, 0x73, 0x2E, 0x0D, // 63:1139 890 | 0x04, 0xA1, 0x5B, 0x18, // 64:1185 891 | 0x04, 0xFC, 0x3B, 0x10, // 65:1276 892 | 0x05, 0x37, 0x3B, 0x10, // 66:1335 893 | 0x05, 0x72, 0x3F, 0x11, // 67:1394 894 | 0x05, 0xB1, 0x3F, 0x11, // 68:1457 895 | 0x05, 0xF0, 0x3B, 0x10, // 69:1520 896 | 0x06, 0x2B, 0x35, 0x0F, // 70:1579 897 | 0x06, 0x60, 0x43, 0x13, // 71:1632 898 | 0x06, 0xA3, 0x3B, 0x11, // 72:1699 899 | 0x06, 0xDE, 0x0F, 0x07, // 73:1758 900 | 0x06, 0xED, 0x27, 0x0C, // 74:1773 901 | 0x07, 0x14, 0x3F, 0x10, // 75:1812 902 | 0x07, 0x53, 0x2F, 0x0D, // 76:1875 903 | 0x07, 0x82, 0x43, 0x14, // 77:1922 904 | 0x07, 0xC5, 0x3B, 0x11, // 78:1989 905 | 0x08, 0x00, 0x47, 0x13, // 79:2048 906 | 0x08, 0x47, 0x3A, 0x10, // 80:2119 907 | 0x08, 0x81, 0x47, 0x13, // 81:2177 908 | 0x08, 0xC8, 0x3F, 0x11, // 82:2248 909 | 0x09, 0x07, 0x3B, 0x10, // 83:2311 910 | 0x09, 0x42, 0x35, 0x0F, // 84:2370 911 | 0x09, 0x77, 0x3B, 0x11, // 85:2423 912 | 0x09, 0xB2, 0x39, 0x10, // 86:2482 913 | 0x09, 0xEB, 0x59, 0x17, // 87:2539 914 | 0x0A, 0x44, 0x3B, 0x10, // 88:2628 915 | 0x0A, 0x7F, 0x3D, 0x10, // 89:2687 916 | 0x0A, 0xBC, 0x37, 0x0F, // 90:2748 917 | 0x0A, 0xF3, 0x14, 0x07, // 91:2803 918 | 0x0B, 0x07, 0x1B, 0x07, // 92:2823 919 | 0x0B, 0x22, 0x18, 0x07, // 93:2850 920 | 0x0B, 0x3A, 0x2A, 0x0B, // 94:2874 921 | 0x0B, 0x64, 0x34, 0x0D, // 95:2916 922 | 0x0B, 0x98, 0x11, 0x08, // 96:2968 923 | 0x0B, 0xA9, 0x2F, 0x0D, // 97:2985 924 | 0x0B, 0xD8, 0x33, 0x0D, // 98:3032 925 | 0x0C, 0x0B, 0x2B, 0x0C, // 99:3083 926 | 0x0C, 0x36, 0x2F, 0x0D, // 100:3126 927 | 0x0C, 0x65, 0x2F, 0x0D, // 101:3173 928 | 0x0C, 0x94, 0x1A, 0x07, // 102:3220 929 | 0x0C, 0xAE, 0x2F, 0x0D, // 103:3246 930 | 0x0C, 0xDD, 0x2F, 0x0D, // 104:3293 931 | 0x0D, 0x0C, 0x0F, 0x05, // 105:3340 932 | 0x0D, 0x1B, 0x10, 0x05, // 106:3355 933 | 0x0D, 0x2B, 0x2F, 0x0C, // 107:3371 934 | 0x0D, 0x5A, 0x0F, 0x05, // 108:3418 935 | 0x0D, 0x69, 0x47, 0x14, // 109:3433 936 | 0x0D, 0xB0, 0x2F, 0x0D, // 110:3504 937 | 0x0D, 0xDF, 0x2F, 0x0D, // 111:3551 938 | 0x0E, 0x0E, 0x33, 0x0D, // 112:3598 939 | 0x0E, 0x41, 0x30, 0x0D, // 113:3649 940 | 0x0E, 0x71, 0x1E, 0x08, // 114:3697 941 | 0x0E, 0x8F, 0x2B, 0x0C, // 115:3727 942 | 0x0E, 0xBA, 0x1B, 0x07, // 116:3770 943 | 0x0E, 0xD5, 0x2F, 0x0D, // 117:3797 944 | 0x0F, 0x04, 0x2A, 0x0C, // 118:3844 945 | 0x0F, 0x2E, 0x42, 0x11, // 119:3886 946 | 0x0F, 0x70, 0x2B, 0x0C, // 120:3952 947 | 0x0F, 0x9B, 0x2A, 0x0C, // 121:3995 948 | 0x0F, 0xC5, 0x2B, 0x0C, // 122:4037 949 | 0x0F, 0xF0, 0x1C, 0x08, // 123:4080 950 | 0x10, 0x0C, 0x10, 0x06, // 124:4108 951 | 0x10, 0x1C, 0x1B, 0x08, // 125:4124 952 | 0x10, 0x37, 0x32, 0x0E, // 126:4151 953 | 0xFF, 0xFF, 0x00, 0x00, // 127:65535 954 | 0xFF, 0xFF, 0x00, 0x18, // 128:65535 955 | 0xFF, 0xFF, 0x00, 0x18, // 129:65535 956 | 0xFF, 0xFF, 0x00, 0x18, // 130:65535 957 | 0xFF, 0xFF, 0x00, 0x18, // 131:65535 958 | 0xFF, 0xFF, 0x00, 0x18, // 132:65535 959 | 0xFF, 0xFF, 0x00, 0x18, // 133:65535 960 | 0xFF, 0xFF, 0x00, 0x18, // 134:65535 961 | 0xFF, 0xFF, 0x00, 0x18, // 135:65535 962 | 0xFF, 0xFF, 0x00, 0x18, // 136:65535 963 | 0xFF, 0xFF, 0x00, 0x18, // 137:65535 964 | 0xFF, 0xFF, 0x00, 0x18, // 138:65535 965 | 0xFF, 0xFF, 0x00, 0x18, // 139:65535 966 | 0xFF, 0xFF, 0x00, 0x18, // 140:65535 967 | 0xFF, 0xFF, 0x00, 0x18, // 141:65535 968 | 0xFF, 0xFF, 0x00, 0x18, // 142:65535 969 | 0xFF, 0xFF, 0x00, 0x18, // 143:65535 970 | 0xFF, 0xFF, 0x00, 0x18, // 144:65535 971 | 0xFF, 0xFF, 0x00, 0x18, // 145:65535 972 | 0xFF, 0xFF, 0x00, 0x18, // 146:65535 973 | 0xFF, 0xFF, 0x00, 0x18, // 147:65535 974 | 0xFF, 0xFF, 0x00, 0x18, // 148:65535 975 | 0xFF, 0xFF, 0x00, 0x18, // 149:65535 976 | 0xFF, 0xFF, 0x00, 0x18, // 150:65535 977 | 0xFF, 0xFF, 0x00, 0x18, // 151:65535 978 | 0xFF, 0xFF, 0x00, 0x18, // 152:65535 979 | 0xFF, 0xFF, 0x00, 0x18, // 153:65535 980 | 0xFF, 0xFF, 0x00, 0x18, // 154:65535 981 | 0xFF, 0xFF, 0x00, 0x18, // 155:65535 982 | 0xFF, 0xFF, 0x00, 0x18, // 156:65535 983 | 0xFF, 0xFF, 0x00, 0x18, // 157:65535 984 | 0xFF, 0xFF, 0x00, 0x18, // 158:65535 985 | 0xFF, 0xFF, 0x00, 0x18, // 159:65535 986 | 0xFF, 0xFF, 0x00, 0x07, // 160:65535 987 | 0x10, 0x69, 0x14, 0x08, // 161:4201 988 | 0x10, 0x7D, 0x2B, 0x0D, // 162:4221 989 | 0x10, 0xA8, 0x2F, 0x0D, // 163:4264 990 | 0x10, 0xD7, 0x33, 0x0D, // 164:4311 991 | 0x11, 0x0A, 0x31, 0x0D, // 165:4362 992 | 0x11, 0x3B, 0x10, 0x06, // 166:4411 993 | 0x11, 0x4B, 0x2F, 0x0D, // 167:4427 994 | 0x11, 0x7A, 0x19, 0x08, // 168:4474 995 | 0x11, 0x93, 0x46, 0x12, // 169:4499 996 | 0x11, 0xD9, 0x1A, 0x09, // 170:4569 997 | 0x11, 0xF3, 0x27, 0x0D, // 171:4595 998 | 0x12, 0x1A, 0x2F, 0x0E, // 172:4634 999 | 0x12, 0x49, 0x1B, 0x08, // 173:4681 1000 | 0x12, 0x64, 0x46, 0x12, // 174:4708 1001 | 0x12, 0xAA, 0x31, 0x0D, // 175:4778 1002 | 0x12, 0xDB, 0x1E, 0x0A, // 176:4827 1003 | 0x12, 0xF9, 0x33, 0x0D, // 177:4857 1004 | 0x13, 0x2C, 0x1A, 0x08, // 178:4908 1005 | 0x13, 0x46, 0x1A, 0x08, // 179:4934 1006 | 0x13, 0x60, 0x19, 0x08, // 180:4960 1007 | 0x13, 0x79, 0x2F, 0x0E, // 181:4985 1008 | 0x13, 0xA8, 0x31, 0x0D, // 182:5032 1009 | 0x13, 0xD9, 0x12, 0x08, // 183:5081 1010 | 0x13, 0xEB, 0x18, 0x08, // 184:5099 1011 | 0x14, 0x03, 0x16, 0x08, // 185:5123 1012 | 0x14, 0x19, 0x1E, 0x09, // 186:5145 1013 | 0x14, 0x37, 0x2E, 0x0D, // 187:5175 1014 | 0x14, 0x65, 0x4F, 0x14, // 188:5221 1015 | 0x14, 0xB4, 0x4B, 0x14, // 189:5300 1016 | 0x14, 0xFF, 0x4B, 0x14, // 190:5375 1017 | 0x15, 0x4A, 0x33, 0x0F, // 191:5450 1018 | 0x15, 0x7D, 0x3B, 0x10, // 192:5501 1019 | 0x15, 0xB8, 0x3B, 0x10, // 193:5560 1020 | 0x15, 0xF3, 0x3B, 0x10, // 194:5619 1021 | 0x16, 0x2E, 0x3B, 0x10, // 195:5678 1022 | 0x16, 0x69, 0x3B, 0x10, // 196:5737 1023 | 0x16, 0xA4, 0x3B, 0x10, // 197:5796 1024 | 0x16, 0xDF, 0x5B, 0x18, // 198:5855 1025 | 0x17, 0x3A, 0x3F, 0x11, // 199:5946 1026 | 0x17, 0x79, 0x3B, 0x10, // 200:6009 1027 | 0x17, 0xB4, 0x3B, 0x10, // 201:6068 1028 | 0x17, 0xEF, 0x3B, 0x10, // 202:6127 1029 | 0x18, 0x2A, 0x3B, 0x10, // 203:6186 1030 | 0x18, 0x65, 0x11, 0x07, // 204:6245 1031 | 0x18, 0x76, 0x11, 0x07, // 205:6262 1032 | 0x18, 0x87, 0x15, 0x07, // 206:6279 1033 | 0x18, 0x9C, 0x15, 0x07, // 207:6300 1034 | 0x18, 0xB1, 0x3F, 0x11, // 208:6321 1035 | 0x18, 0xF0, 0x3B, 0x11, // 209:6384 1036 | 0x19, 0x2B, 0x47, 0x13, // 210:6443 1037 | 0x19, 0x72, 0x47, 0x13, // 211:6514 1038 | 0x19, 0xB9, 0x47, 0x13, // 212:6585 1039 | 0x1A, 0x00, 0x47, 0x13, // 213:6656 1040 | 0x1A, 0x47, 0x47, 0x13, // 214:6727 1041 | 0x1A, 0x8E, 0x2B, 0x0E, // 215:6798 1042 | 0x1A, 0xB9, 0x47, 0x13, // 216:6841 1043 | 0x1B, 0x00, 0x3B, 0x11, // 217:6912 1044 | 0x1B, 0x3B, 0x3B, 0x11, // 218:6971 1045 | 0x1B, 0x76, 0x3B, 0x11, // 219:7030 1046 | 0x1B, 0xB1, 0x3B, 0x11, // 220:7089 1047 | 0x1B, 0xEC, 0x3D, 0x10, // 221:7148 1048 | 0x1C, 0x29, 0x3A, 0x10, // 222:7209 1049 | 0x1C, 0x63, 0x37, 0x0F, // 223:7267 1050 | 0x1C, 0x9A, 0x2F, 0x0D, // 224:7322 1051 | 0x1C, 0xC9, 0x2F, 0x0D, // 225:7369 1052 | 0x1C, 0xF8, 0x2F, 0x0D, // 226:7416 1053 | 0x1D, 0x27, 0x2F, 0x0D, // 227:7463 1054 | 0x1D, 0x56, 0x2F, 0x0D, // 228:7510 1055 | 0x1D, 0x85, 0x2F, 0x0D, // 229:7557 1056 | 0x1D, 0xB4, 0x53, 0x15, // 230:7604 1057 | 0x1E, 0x07, 0x2B, 0x0C, // 231:7687 1058 | 0x1E, 0x32, 0x2F, 0x0D, // 232:7730 1059 | 0x1E, 0x61, 0x2F, 0x0D, // 233:7777 1060 | 0x1E, 0x90, 0x2F, 0x0D, // 234:7824 1061 | 0x1E, 0xBF, 0x2F, 0x0D, // 235:7871 1062 | 0x1E, 0xEE, 0x11, 0x07, // 236:7918 1063 | 0x1E, 0xFF, 0x11, 0x07, // 237:7935 1064 | 0x1F, 0x10, 0x15, 0x07, // 238:7952 1065 | 0x1F, 0x25, 0x15, 0x07, // 239:7973 1066 | 0x1F, 0x3A, 0x2F, 0x0D, // 240:7994 1067 | 0x1F, 0x69, 0x2F, 0x0D, // 241:8041 1068 | 0x1F, 0x98, 0x2F, 0x0D, // 242:8088 1069 | 0x1F, 0xC7, 0x2F, 0x0D, // 243:8135 1070 | 0x1F, 0xF6, 0x2F, 0x0D, // 244:8182 1071 | 0x20, 0x25, 0x2F, 0x0D, // 245:8229 1072 | 0x20, 0x54, 0x2F, 0x0D, // 246:8276 1073 | 0x20, 0x83, 0x32, 0x0D, // 247:8323 1074 | 0x20, 0xB5, 0x33, 0x0F, // 248:8373 1075 | 0x20, 0xE8, 0x2F, 0x0D, // 249:8424 1076 | 0x21, 0x17, 0x2F, 0x0D, // 250:8471 1077 | 0x21, 0x46, 0x2F, 0x0D, // 251:8518 1078 | 0x21, 0x75, 0x2F, 0x0D, // 252:8565 1079 | 0x21, 0xA4, 0x2A, 0x0C, // 253:8612 1080 | 0x21, 0xCE, 0x2F, 0x0D, // 254:8654 1081 | 0x21, 0xFD, 0x2A, 0x0C, // 255:8701 1082 | 1083 | // Font Data: 1084 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x33,0x00,0xE0,0xFF,0x33, // 33 1085 | 0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xE0,0x07, // 34 1086 | 0x00,0x0C,0x03,0x00,0x00,0x0C,0x33,0x00,0x00,0x0C,0x3F,0x00,0x00,0xFC,0x0F,0x00,0x80,0xFF,0x03,0x00,0xE0,0x0F,0x03,0x00,0x60,0x0C,0x33,0x00,0x00,0x0C,0x3F,0x00,0x00,0xFC,0x0F,0x00,0x80,0xFF,0x03,0x00,0xE0,0x0F,0x03,0x00,0x60,0x0C,0x03,0x00,0x00,0x0C,0x03, // 35 1087 | 0x00,0x00,0x00,0x00,0x80,0x07,0x06,0x00,0xC0,0x0F,0x1E,0x00,0xC0,0x18,0x1C,0x00,0x60,0x18,0x38,0x00,0x60,0x30,0x30,0x00,0xF0,0xFF,0xFF,0x00,0x60,0x30,0x30,0x00,0x60,0x60,0x38,0x00,0xC0,0x60,0x18,0x00,0xC0,0xC1,0x1F,0x00,0x00,0x81,0x07, // 36 1088 | 0x00,0x00,0x00,0x00,0x80,0x0F,0x00,0x00,0xC0,0x1F,0x00,0x00,0x60,0x30,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x20,0x20,0x00,0x60,0x30,0x38,0x00,0xC0,0x1F,0x1E,0x00,0x80,0x8F,0x0F,0x00,0x00,0xC0,0x03,0x00,0x00,0xF0,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x8F,0x0F,0x00,0xC0,0xC3,0x1F,0x00,0xE0,0x60,0x30,0x00,0x20,0x20,0x20,0x00,0x00,0x20,0x20,0x00,0x00,0x60,0x30,0x00,0x00,0xC0,0x1F,0x00,0x00,0x80,0x0F, // 37 1089 | 0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x00,0xC0,0x0F,0x00,0x80,0xE3,0x1C,0x00,0xC0,0x77,0x38,0x00,0xE0,0x3C,0x30,0x00,0x60,0x38,0x30,0x00,0x60,0x78,0x30,0x00,0xE0,0xEC,0x38,0x00,0xC0,0x8F,0x1B,0x00,0x80,0x03,0x1F,0x00,0x00,0x00,0x0F,0x00,0x00,0xC0,0x1F,0x00,0x00,0xC0,0x38,0x00,0x00,0x00,0x10, // 38 1090 | 0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xE0,0x07, // 39 1091 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x0F,0x00,0x00,0xFE,0x7F,0x00,0x80,0x0F,0xF0,0x01,0xC0,0x01,0x80,0x03,0x60,0x00,0x00,0x06,0x20,0x00,0x00,0x04, // 40 1092 | 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x04,0x60,0x00,0x00,0x06,0xC0,0x01,0x80,0x03,0x80,0x0F,0xF0,0x01,0x00,0xFE,0x7F,0x00,0x00,0xF0,0x0F, // 41 1093 | 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x80,0x04,0x00,0x00,0x80,0x0F,0x00,0x00,0xE0,0x03,0x00,0x00,0xE0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x80,0x04,0x00,0x00,0x80, // 42 1094 | 0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xFF,0x0F,0x00,0x00,0xFF,0x0F,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60, // 43 1095 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x03,0x00,0x00,0xF0,0x01, // 44 1096 | 0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01, // 45 1097 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30, // 46 1098 | 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0xE0,0x0F,0x00,0x00,0xFC,0x01,0x00,0x80,0x3F,0x00,0x00,0xE0,0x03,0x00,0x00,0x60, // 47 1099 | 0x00,0x00,0x00,0x00,0x00,0xFE,0x03,0x00,0x80,0xFF,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xE0,0x00,0x38,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x38,0x00,0xC0,0x01,0x1C,0x00,0x80,0xFF,0x0F,0x00,0x00,0xFE,0x03, // 48 1100 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x03,0x00,0x00,0x80,0x01,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 49 1101 | 0x00,0x00,0x00,0x00,0x00,0x03,0x30,0x00,0xC0,0x03,0x38,0x00,0xC0,0x00,0x3C,0x00,0x60,0x00,0x36,0x00,0x60,0x00,0x33,0x00,0x60,0x80,0x31,0x00,0x60,0xC0,0x30,0x00,0x60,0x60,0x30,0x00,0xC0,0x30,0x30,0x00,0xC0,0x1F,0x30,0x00,0x00,0x0F,0x30, // 50 1102 | 0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x00,0xC0,0x01,0x0E,0x00,0xC0,0x00,0x1C,0x00,0x60,0x00,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0xC0,0x38,0x30,0x00,0xC0,0x6F,0x18,0x00,0x80,0xC7,0x0F,0x00,0x00,0x80,0x07, // 51 1103 | 0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0xC0,0x03,0x00,0x00,0xF0,0x03,0x00,0x00,0x3C,0x03,0x00,0x00,0x0E,0x03,0x00,0x80,0x07,0x03,0x00,0xC0,0x01,0x03,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x03, // 52 1104 | 0x00,0x00,0x00,0x00,0x00,0x30,0x06,0x00,0x80,0x3F,0x0E,0x00,0xE0,0x1F,0x18,0x00,0x60,0x08,0x30,0x00,0x60,0x0C,0x30,0x00,0x60,0x0C,0x30,0x00,0x60,0x0C,0x30,0x00,0x60,0x0C,0x30,0x00,0x60,0x18,0x1C,0x00,0x60,0xF0,0x0F,0x00,0x00,0xE0,0x03, // 53 1105 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x03,0x00,0x80,0xFF,0x0F,0x00,0xC0,0x63,0x1C,0x00,0xC0,0x30,0x38,0x00,0x60,0x18,0x30,0x00,0x60,0x18,0x30,0x00,0x60,0x18,0x30,0x00,0x60,0x18,0x30,0x00,0xE0,0x30,0x18,0x00,0xC0,0xF1,0x0F,0x00,0x80,0xC1,0x07, // 54 1106 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x3C,0x00,0x60,0x80,0x3F,0x00,0x60,0xE0,0x03,0x00,0x60,0x78,0x00,0x00,0x60,0x0E,0x00,0x00,0x60,0x03,0x00,0x00,0xE0,0x01,0x00,0x00,0x60, // 55 1107 | 0x00,0x00,0x00,0x00,0x00,0x80,0x07,0x00,0x80,0xC7,0x1F,0x00,0xC0,0x6F,0x18,0x00,0xE0,0x38,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0xE0,0x38,0x30,0x00,0xC0,0x6F,0x18,0x00,0x80,0xC7,0x1F,0x00,0x00,0x80,0x07, // 56 1108 | 0x00,0x00,0x00,0x00,0x00,0x1F,0x0C,0x00,0x80,0x7F,0x1C,0x00,0xC0,0x61,0x38,0x00,0x60,0xC0,0x30,0x00,0x60,0xC0,0x30,0x00,0x60,0xC0,0x30,0x00,0x60,0xC0,0x30,0x00,0x60,0x60,0x18,0x00,0xC0,0x31,0x1E,0x00,0x80,0xFF,0x0F,0x00,0x00,0xFE,0x01, // 57 1109 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30, // 58 1110 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x30,0x03,0x00,0x06,0xF0,0x01, // 59 1111 | 0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0xD8,0x00,0x00,0x00,0xD8,0x00,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x04,0x01,0x00,0x00,0x06,0x03,0x00,0x00,0x06,0x03,0x00,0x00,0x03,0x06, // 60 1112 | 0x00,0x00,0x00,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01, // 61 1113 | 0x00,0x00,0x00,0x00,0x00,0x03,0x06,0x00,0x00,0x06,0x03,0x00,0x00,0x06,0x03,0x00,0x00,0x04,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0x8C,0x01,0x00,0x00,0xD8,0x00,0x00,0x00,0xD8,0x00,0x00,0x00,0x50,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x20, // 62 1114 | 0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x80,0x03,0x00,0x00,0xC0,0x01,0x00,0x00,0xE0,0x00,0x00,0x00,0x60,0x80,0x33,0x00,0x60,0xC0,0x33,0x00,0x60,0xE0,0x00,0x00,0x60,0x30,0x00,0x00,0xC0,0x38,0x00,0x00,0xC0,0x1F,0x00,0x00,0x00,0x07, // 63 1115 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x0F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x1E,0xF0,0x00,0x00,0x07,0xC0,0x01,0x80,0xC3,0x87,0x01,0xC0,0xF1,0x9F,0x03,0xC0,0x38,0x18,0x03,0xC0,0x0C,0x30,0x03,0x60,0x0E,0x30,0x06,0x60,0x06,0x30,0x06,0x60,0x06,0x18,0x06,0x60,0x06,0x0C,0x06,0x60,0x0C,0x1E,0x06,0x60,0xF8,0x3F,0x06,0xE0,0xFE,0x31,0x06,0xC0,0x0E,0x30,0x06,0xC0,0x01,0x18,0x03,0x80,0x03,0x1C,0x03,0x00,0x07,0x8F,0x01,0x00,0xFE,0x87,0x01,0x00,0xF8,0xC1,0x00,0x00,0x00,0x40, // 64 1116 | 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x80,0x8F,0x01,0x00,0xE0,0x83,0x01,0x00,0x60,0x80,0x01,0x00,0xE0,0x83,0x01,0x00,0x80,0x8F,0x01,0x00,0x00,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 65 1117 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0xC0,0x78,0x30,0x00,0xC0,0xFF,0x18,0x00,0x80,0xC7,0x1F,0x00,0x00,0x80,0x07, // 66 1118 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x03,0x0F,0x00,0x00,0x02,0x03, // 67 1119 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x03,0x0E,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 68 1120 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 69 1121 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60, // 70 1122 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x18,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x60,0x30,0x00,0x60,0x60,0x30,0x00,0xE0,0x60,0x38,0x00,0xC0,0x60,0x18,0x00,0xC0,0x61,0x18,0x00,0x80,0xE3,0x0F,0x00,0x00,0xE2,0x0F, // 71 1123 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 72 1124 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 73 1125 | 0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x38,0x00,0xE0,0xFF,0x1F,0x00,0xE0,0xFF,0x0F, // 74 1126 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0xE0,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0xE7,0x01,0x00,0x80,0x83,0x07,0x00,0xC0,0x01,0x0F,0x00,0xE0,0x00,0x1E,0x00,0x60,0x00,0x38,0x00,0x20,0x00,0x30,0x00,0x00,0x00,0x20, // 75 1127 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30, // 76 1128 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0x01,0x00,0x00,0xC0,0x0F,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3F,0x00,0x00,0xE0,0x07,0x00,0x00,0xFE,0x00,0x00,0xC0,0x0F,0x00,0x00,0xE0,0x01,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 77 1129 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0xC0,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0xE0,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 78 1130 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 79 1131 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0xC0,0x30,0x00,0x00,0xC0,0x3F,0x00,0x00,0x00,0x0F, // 80 1132 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x0C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x18,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x36,0x00,0x60,0x00,0x36,0x00,0xE0,0x00,0x3C,0x00,0xC0,0x00,0x1C,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x3F,0x00,0x00,0xFF,0x77,0x00,0x00,0xFC,0x61, // 81 1133 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x70,0x00,0x00,0x60,0xF0,0x00,0x00,0x60,0xF0,0x03,0x00,0x60,0xB0,0x07,0x00,0xE0,0x18,0x1F,0x00,0xC0,0x1F,0x3C,0x00,0x80,0x0F,0x30,0x00,0x00,0x00,0x20, // 82 1134 | 0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x07,0x0F,0x00,0xC0,0x1F,0x1C,0x00,0xC0,0x18,0x18,0x00,0x60,0x38,0x38,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x70,0x30,0x00,0xC0,0x60,0x18,0x00,0xC0,0xE1,0x18,0x00,0x80,0xC3,0x0F,0x00,0x00,0x83,0x07, // 83 1135 | 0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60, // 84 1136 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 85 1137 | 0x20,0x00,0x00,0x00,0xE0,0x01,0x00,0x00,0xC0,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0xF8,0x01,0x00,0x00,0xC0,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x3E,0x00,0x00,0xC0,0x0F,0x00,0x00,0xF8,0x01,0x00,0x00,0x3E,0x00,0x00,0xC0,0x0F,0x00,0x00,0xE0,0x01,0x00,0x00,0x20, // 86 1138 | 0x60,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0x80,0xFF,0x00,0x00,0x00,0xF8,0x0F,0x00,0x00,0x80,0x3F,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3F,0x00,0x00,0xE0,0x0F,0x00,0x00,0xFC,0x01,0x00,0x80,0x1F,0x00,0x00,0xE0,0x03,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x80,0x1F,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xE0,0x0F,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x30,0x00,0x00,0x80,0x3F,0x00,0x00,0xF8,0x0F,0x00,0x80,0xFF,0x00,0x00,0xE0,0x07,0x00,0x00,0x60, // 87 1139 | 0x00,0x00,0x20,0x00,0x20,0x00,0x30,0x00,0x60,0x00,0x3C,0x00,0xE0,0x01,0x1E,0x00,0xC0,0x83,0x07,0x00,0x00,0xCF,0x03,0x00,0x00,0xFE,0x01,0x00,0x00,0x38,0x00,0x00,0x00,0xFE,0x01,0x00,0x00,0xCF,0x03,0x00,0xC0,0x03,0x07,0x00,0xE0,0x01,0x1E,0x00,0x60,0x00,0x3C,0x00,0x20,0x00,0x30,0x00,0x00,0x00,0x20, // 88 1140 | 0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xC0,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0xF0,0x3F,0x00,0x00,0xF0,0x3F,0x00,0x00,0x3C,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x07,0x00,0x00,0xC0,0x03,0x00,0x00,0xE0,0x01,0x00,0x00,0x60,0x00,0x00,0x00,0x20, // 89 1141 | 0x00,0x00,0x30,0x00,0x60,0x00,0x38,0x00,0x60,0x00,0x3C,0x00,0x60,0x00,0x37,0x00,0x60,0x80,0x33,0x00,0x60,0xC0,0x31,0x00,0x60,0xE0,0x30,0x00,0x60,0x38,0x30,0x00,0x60,0x1C,0x30,0x00,0x60,0x0E,0x30,0x00,0x60,0x07,0x30,0x00,0xE0,0x01,0x30,0x00,0xE0,0x00,0x30,0x00,0x60,0x00,0x30, // 90 1142 | 0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x60,0x00,0x00,0x06,0x60,0x00,0x00,0x06, // 91 1143 | 0x60,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x80,0x3F,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xE0,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 92 1144 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x06,0x60,0x00,0x00,0x06,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07, // 93 1145 | 0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1F,0x00,0x00,0xC0,0x07,0x00,0x00,0xE0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xC0,0x07,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x20, // 94 1146 | 0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06, // 95 1147 | 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x80, // 96 1148 | 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x00,0x8C,0x39,0x00,0x00,0x86,0x31,0x00,0x00,0x86,0x31,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x18,0x00,0x00,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 97 1149 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x18,0x0C,0x00,0x00,0x0C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xE0,0x03, // 98 1150 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0x18,0x0C, // 99 1151 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0C,0x18,0x00,0x00,0x18,0x0C,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 100 1152 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0x00,0xCE,0x38,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xCE,0x38,0x00,0x00,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 101 1153 | 0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0xC0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x06,0x00,0x00,0x60,0x06,0x00,0x00,0x60,0x06, // 102 1154 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x83,0x01,0x00,0xF8,0x8F,0x03,0x00,0x1C,0x1C,0x07,0x00,0x0E,0x38,0x06,0x00,0x06,0x30,0x06,0x00,0x06,0x30,0x06,0x00,0x06,0x30,0x06,0x00,0x0C,0x18,0x07,0x00,0x18,0x8C,0x03,0x00,0xFE,0xFF,0x01,0x00,0xFE,0xFF, // 103 1155 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0xFC,0x3F,0x00,0x00,0xF8,0x3F, // 104 1156 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0xFE,0x3F,0x00,0x60,0xFE,0x3F, // 105 1157 | 0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x60,0xFE,0xFF,0x07,0x60,0xFE,0xFF,0x03, // 106 1158 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0xC0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0xF0,0x01,0x00,0x00,0x98,0x07,0x00,0x00,0x0C,0x0E,0x00,0x00,0x06,0x3C,0x00,0x00,0x02,0x30,0x00,0x00,0x00,0x20, // 107 1159 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 108 1160 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F,0x00,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0xFC,0x3F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x0C,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0xFC,0x3F,0x00,0x00,0xF8,0x3F, // 109 1161 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F,0x00,0x00,0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0xFC,0x3F,0x00,0x00,0xF8,0x3F, // 110 1162 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 111 1163 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x07,0x00,0xFE,0xFF,0x07,0x00,0x18,0x0C,0x00,0x00,0x0C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xE0,0x03, // 112 1164 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0C,0x18,0x00,0x00,0x18,0x0C,0x00,0x00,0xFE,0xFF,0x07,0x00,0xFE,0xFF,0x07, // 113 1165 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F,0x00,0x00,0x0C,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06, // 114 1166 | 0x00,0x00,0x00,0x00,0x00,0x38,0x0C,0x00,0x00,0x7C,0x1C,0x00,0x00,0xEE,0x38,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x31,0x00,0x00,0xC6,0x31,0x00,0x00,0x8E,0x39,0x00,0x00,0x9C,0x1F,0x00,0x00,0x18,0x0F, // 115 1167 | 0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0xC0,0xFF,0x1F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30, // 116 1168 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 117 1169 | 0x00,0x06,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xC0,0x07,0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1F,0x00,0x00,0xC0,0x07,0x00,0x00,0xF8,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x06, // 118 1170 | 0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x80,0x1F,0x00,0x00,0xE0,0x03,0x00,0x00,0x7C,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x80,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x80,0x1F,0x00,0x00,0xF0,0x03,0x00,0x00,0x7E,0x00,0x00,0x00,0x0E, // 119 1171 | 0x00,0x02,0x20,0x00,0x00,0x06,0x30,0x00,0x00,0x1E,0x3C,0x00,0x00,0x38,0x0E,0x00,0x00,0xF0,0x07,0x00,0x00,0xC0,0x01,0x00,0x00,0xE0,0x07,0x00,0x00,0x38,0x0E,0x00,0x00,0x1C,0x3C,0x00,0x00,0x0E,0x30,0x00,0x00,0x02,0x20, // 120 1172 | 0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x06,0x00,0xF0,0x01,0x06,0x00,0x80,0x0F,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xFC,0x00,0x00,0xC0,0x1F,0x00,0x00,0xF8,0x03,0x00,0x00,0x3E,0x00,0x00,0x00,0x06, // 121 1173 | 0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x06,0x3C,0x00,0x00,0x06,0x3E,0x00,0x00,0x06,0x37,0x00,0x00,0xC6,0x33,0x00,0x00,0xE6,0x30,0x00,0x00,0x76,0x30,0x00,0x00,0x3E,0x30,0x00,0x00,0x1E,0x30,0x00,0x00,0x06,0x30, // 122 1174 | 0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xC0,0x03,0x00,0xC0,0x7F,0xFE,0x03,0xE0,0x3F,0xFC,0x07,0x60,0x00,0x00,0x06,0x60,0x00,0x00,0x06, // 123 1175 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x0F,0xE0,0xFF,0xFF,0x0F, // 124 1176 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x06,0x60,0x00,0x00,0x06,0xE0,0x3F,0xFC,0x07,0xC0,0x7F,0xFF,0x03,0x00,0xC0,0x03,0x00,0x00,0x80,0x01, // 125 1177 | 0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x60, // 126 1178 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE6,0xFF,0x07,0x00,0xE6,0xFF,0x07, // 161 1179 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x9C,0x07,0x00,0x0E,0x78,0x00,0x00,0x06,0x3F,0x00,0x00,0xF6,0x30,0x00,0x00,0x0E,0x30,0x00,0xE0,0x0D,0x1C,0x00,0x00,0x1C,0x0E,0x00,0x00,0x10,0x06, // 162 1180 | 0x00,0x60,0x10,0x00,0x00,0x60,0x38,0x00,0x00,0x7F,0x1C,0x00,0xC0,0xFF,0x1F,0x00,0xE0,0xE0,0x19,0x00,0x60,0x60,0x18,0x00,0x60,0x60,0x18,0x00,0x60,0x60,0x30,0x00,0xE0,0x00,0x30,0x00,0xC0,0x01,0x30,0x00,0x80,0x01,0x38,0x00,0x00,0x00,0x10, // 163 1181 | 0x00,0x00,0x00,0x00,0x00,0x02,0x04,0x00,0x00,0xF7,0x0E,0x00,0x00,0xFE,0x07,0x00,0x00,0x0C,0x03,0x00,0x00,0x06,0x06,0x00,0x00,0x06,0x06,0x00,0x00,0x06,0x06,0x00,0x00,0x06,0x06,0x00,0x00,0x0C,0x03,0x00,0x00,0xFE,0x07,0x00,0x00,0xF7,0x0E,0x00,0x00,0x02,0x04, // 164 1182 | 0xE0,0x60,0x06,0x00,0xC0,0x61,0x06,0x00,0x80,0x67,0x06,0x00,0x00,0x7E,0x06,0x00,0x00,0x7C,0x06,0x00,0x00,0xF0,0x3F,0x00,0x00,0xF0,0x3F,0x00,0x00,0x7C,0x06,0x00,0x00,0x7E,0x06,0x00,0x80,0x67,0x06,0x00,0xC0,0x61,0x06,0x00,0xE0,0x60,0x06,0x00,0x20, // 165 1183 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x7F,0xF8,0x0F,0xE0,0x7F,0xF8,0x0F, // 166 1184 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x00,0x00,0x80,0xF3,0xC1,0x00,0xC0,0x1F,0xC3,0x03,0xE0,0x0C,0x07,0x03,0x60,0x1C,0x06,0x06,0x60,0x18,0x0C,0x06,0x60,0x30,0x1C,0x06,0xE0,0x70,0x38,0x07,0xC0,0xE1,0xF4,0x03,0x80,0xC1,0xE7,0x01,0x00,0x80,0x03, // 167 1185 | 0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60, // 168 1186 | 0x00,0xF8,0x00,0x00,0x00,0xFE,0x03,0x00,0x00,0x07,0x07,0x00,0x80,0x01,0x0C,0x00,0xC0,0x79,0x1C,0x00,0xC0,0xFE,0x19,0x00,0x60,0x86,0x31,0x00,0x60,0x03,0x33,0x00,0x60,0x03,0x33,0x00,0x60,0x03,0x33,0x00,0x60,0x03,0x33,0x00,0x60,0x87,0x33,0x00,0xC0,0x86,0x19,0x00,0xC0,0x85,0x1C,0x00,0x80,0x01,0x0C,0x00,0x00,0x07,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xF8, // 169 1187 | 0x00,0x00,0x00,0x00,0xC0,0x1C,0x00,0x00,0xE0,0x3E,0x00,0x00,0x60,0x32,0x00,0x00,0x60,0x32,0x00,0x00,0xE0,0x3F,0x00,0x00,0xC0,0x3F, // 170 1188 | 0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0xE0,0x03,0x00,0x00,0x78,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x84,0x10,0x00,0x00,0xE0,0x03,0x00,0x00,0x78,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x04,0x10, // 171 1189 | 0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFC,0x01, // 172 1190 | 0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x80,0x01, // 173 1191 | 0x00,0xF8,0x00,0x00,0x00,0xFE,0x03,0x00,0x00,0x07,0x07,0x00,0x80,0x01,0x0C,0x00,0xC0,0x01,0x1C,0x00,0xC0,0xFE,0x1B,0x00,0x60,0xFE,0x33,0x00,0x60,0x66,0x30,0x00,0x60,0x66,0x30,0x00,0x60,0xE6,0x30,0x00,0x60,0xFE,0x31,0x00,0x60,0x3C,0x33,0x00,0xC0,0x00,0x1A,0x00,0xC0,0x01,0x1C,0x00,0x80,0x01,0x0C,0x00,0x00,0x07,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xF8, // 174 1192 | 0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0x0C, // 175 1193 | 0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0x40,0x04,0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x08,0x00,0x00,0x20,0x08,0x00,0x00,0x40,0x04,0x00,0x00,0x80,0x03, // 176 1194 | 0x00,0x00,0x00,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0xFF,0x3F,0x00,0x00,0xFF,0x3F,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30,0x00,0x00,0x60,0x30, // 177 1195 | 0x40,0x20,0x00,0x00,0x60,0x30,0x00,0x00,0x20,0x38,0x00,0x00,0x20,0x2C,0x00,0x00,0x20,0x26,0x00,0x00,0xE0,0x23,0x00,0x00,0xC0,0x21, // 178 1196 | 0x40,0x10,0x00,0x00,0x60,0x30,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x22,0x00,0x00,0x20,0x22,0x00,0x00,0xE0,0x3D,0x00,0x00,0xC0,0x1D, // 179 1197 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0xE0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x20, // 180 1198 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFF,0x07,0x00,0xFE,0xFF,0x07,0x00,0x00,0x1C,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x1C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 181 1199 | 0x00,0x0F,0x00,0x00,0xC0,0x3F,0x00,0x00,0xC0,0x3F,0x00,0x00,0xE0,0x7F,0x00,0x00,0xE0,0x7F,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x60,0x00,0x00,0x00,0x60, // 182 1200 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60, // 183 1201 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x02,0x00,0x00,0xC0,0x02,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x01, // 184 1202 | 0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0xE0,0x3F,0x00,0x00,0xE0,0x3F, // 185 1203 | 0x00,0x00,0x00,0x00,0x80,0x0F,0x00,0x00,0xC0,0x1F,0x00,0x00,0xE0,0x38,0x00,0x00,0x60,0x30,0x00,0x00,0xE0,0x38,0x00,0x00,0xC0,0x1F,0x00,0x00,0x80,0x0F, // 186 1204 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x10,0x00,0x00,0x1C,0x1C,0x00,0x00,0x78,0x0F,0x00,0x00,0xE0,0x03,0x00,0x00,0x84,0x10,0x00,0x00,0x1C,0x1C,0x00,0x00,0x78,0x0F,0x00,0x00,0xE0,0x03,0x00,0x00,0x80, // 187 1205 | 0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x20,0x00,0xE0,0x3F,0x38,0x00,0xE0,0x3F,0x1C,0x00,0x00,0x00,0x0E,0x00,0x00,0x80,0x03,0x00,0x00,0xC0,0x01,0x00,0x00,0xE0,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x07,0x0C,0x00,0xC0,0x01,0x0E,0x00,0xE0,0x80,0x0B,0x00,0x60,0xC0,0x08,0x00,0x00,0xE0,0x3F,0x00,0x00,0xE0,0x3F,0x00,0x00,0x00,0x08, // 188 1206 | 0x00,0x00,0x00,0x00,0x80,0x01,0x00,0x00,0xC0,0x00,0x00,0x00,0xC0,0x00,0x20,0x00,0xE0,0x3F,0x30,0x00,0xE0,0x3F,0x1C,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x07,0x00,0x00,0xC0,0x01,0x00,0x00,0xE0,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x4E,0x20,0x00,0x00,0x67,0x30,0x00,0xC0,0x21,0x38,0x00,0xE0,0x20,0x2C,0x00,0x60,0x20,0x26,0x00,0x00,0xE0,0x27,0x00,0x00,0xC0,0x21, // 189 1207 | 0x40,0x10,0x00,0x00,0x60,0x30,0x00,0x00,0x20,0x20,0x00,0x00,0x20,0x22,0x20,0x00,0x20,0x22,0x30,0x00,0xE0,0x3D,0x38,0x00,0xC0,0x1D,0x0E,0x00,0x00,0x00,0x07,0x00,0x00,0x80,0x03,0x00,0x00,0xE0,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x0E,0x0C,0x00,0x00,0x07,0x0E,0x00,0x80,0x83,0x0B,0x00,0xE0,0xC0,0x08,0x00,0x60,0xE0,0x3F,0x00,0x20,0xE0,0x3F,0x00,0x00,0x00,0x08, // 190 1208 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x00,0x00,0x00,0xF8,0x03,0x00,0x00,0x1E,0x03,0x00,0x00,0x07,0x07,0x00,0xE6,0x03,0x06,0x00,0xE6,0x01,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x07,0x00,0x00,0x80,0x03,0x00,0x00,0xC0,0x01,0x00,0x00,0xC0, // 191 1209 | 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x82,0x8F,0x01,0x00,0xE6,0x83,0x01,0x00,0x6E,0x80,0x01,0x00,0xE8,0x83,0x01,0x00,0x80,0x8F,0x01,0x00,0x00,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 192 1210 | 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x80,0x8F,0x01,0x00,0xE8,0x83,0x01,0x00,0x6E,0x80,0x01,0x00,0xE6,0x83,0x01,0x00,0x82,0x8F,0x01,0x00,0x00,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 193 1211 | 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x88,0x8F,0x01,0x00,0xEC,0x83,0x01,0x00,0x66,0x80,0x01,0x00,0xE6,0x83,0x01,0x00,0x8C,0x8F,0x01,0x00,0x08,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 194 1212 | 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x0C,0xFE,0x01,0x00,0x8E,0x8F,0x01,0x00,0xE6,0x83,0x01,0x00,0x66,0x80,0x01,0x00,0xEC,0x83,0x01,0x00,0x8C,0x8F,0x01,0x00,0x0E,0xFE,0x01,0x00,0x06,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 195 1213 | 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x8C,0x8F,0x01,0x00,0xEC,0x83,0x01,0x00,0x60,0x80,0x01,0x00,0xE0,0x83,0x01,0x00,0x8C,0x8F,0x01,0x00,0x0C,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 196 1214 | 0x00,0x00,0x30,0x00,0x00,0x00,0x3E,0x00,0x00,0x80,0x0F,0x00,0x00,0xF0,0x03,0x00,0x00,0xFE,0x01,0x00,0x9C,0x8F,0x01,0x00,0xE2,0x83,0x01,0x00,0x62,0x80,0x01,0x00,0xE2,0x83,0x01,0x00,0x9C,0x8F,0x01,0x00,0x00,0xFE,0x01,0x00,0x00,0xF0,0x03,0x00,0x00,0x80,0x0F,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x30, // 197 1215 | 0x00,0x00,0x30,0x00,0x00,0x00,0x3C,0x00,0x00,0x00,0x0F,0x00,0x00,0xC0,0x03,0x00,0x00,0xF0,0x01,0x00,0x00,0xBC,0x01,0x00,0x00,0x8F,0x01,0x00,0xC0,0x83,0x01,0x00,0xE0,0x80,0x01,0x00,0x60,0x80,0x01,0x00,0x60,0x80,0x01,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 198 1216 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0x60,0x00,0x30,0x02,0x60,0x00,0x30,0x02,0x60,0x00,0xF0,0x02,0x60,0x00,0xB0,0x03,0x60,0x00,0x30,0x01,0x60,0x00,0x30,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x03,0x0F,0x00,0x00,0x02,0x03, // 199 1217 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x62,0x30,0x30,0x00,0x66,0x30,0x30,0x00,0x6E,0x30,0x30,0x00,0x68,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 200 1218 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x68,0x30,0x30,0x00,0x6E,0x30,0x30,0x00,0x66,0x30,0x30,0x00,0x62,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 201 1219 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x68,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x66,0x30,0x30,0x00,0x66,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x68,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 202 1220 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x6C,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30, // 203 1221 | 0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0xE6,0xFF,0x3F,0x00,0xEE,0xFF,0x3F,0x00,0x08, // 204 1222 | 0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0xEE,0xFF,0x3F,0x00,0xE6,0xFF,0x3F,0x00,0x02, // 205 1223 | 0x08,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0xE6,0xFF,0x3F,0x00,0xE6,0xFF,0x3F,0x00,0x0C,0x00,0x00,0x00,0x08, // 206 1224 | 0x0C,0x00,0x00,0x00,0x0C,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x0C,0x00,0x00,0x00,0x0C, // 207 1225 | 0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x30,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x03,0x0E,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 208 1226 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0xC0,0x01,0x00,0x00,0x8C,0x03,0x00,0x00,0x0E,0x0E,0x00,0x00,0x06,0x3C,0x00,0x00,0x06,0x70,0x00,0x00,0x0C,0xE0,0x01,0x00,0x0C,0x80,0x03,0x00,0x0E,0x00,0x0F,0x00,0x06,0x00,0x1C,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F, // 209 1227 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x62,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x6E,0x00,0x30,0x00,0x68,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 210 1228 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x60,0x00,0x30,0x00,0x68,0x00,0x30,0x00,0x6E,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x62,0x00,0x30,0x00,0xE0,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 211 1229 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x68,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0xE8,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 212 1230 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xCC,0x00,0x18,0x00,0xEE,0x00,0x38,0x00,0x66,0x00,0x30,0x00,0x66,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0x6E,0x00,0x30,0x00,0xE6,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 213 1231 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x01,0x00,0x00,0xFF,0x07,0x00,0x80,0x07,0x0F,0x00,0xC0,0x01,0x1C,0x00,0xC0,0x00,0x18,0x00,0xE0,0x00,0x38,0x00,0x6C,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x6C,0x00,0x30,0x00,0xEC,0x00,0x38,0x00,0xC0,0x00,0x18,0x00,0xC0,0x01,0x1C,0x00,0x80,0x07,0x0F,0x00,0x00,0xFF,0x07,0x00,0x00,0xFC,0x01, // 214 1232 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x03,0x00,0x00,0x8E,0x03,0x00,0x00,0xDC,0x01,0x00,0x00,0xF8,0x00,0x00,0x00,0x70,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0xDC,0x01,0x00,0x00,0x8E,0x03,0x00,0x00,0x06,0x03, // 215 1233 | 0x00,0x00,0x00,0x00,0x00,0xFC,0x21,0x00,0x00,0xFF,0x77,0x00,0x80,0x07,0x3F,0x00,0xC0,0x01,0x1E,0x00,0xC0,0x00,0x1F,0x00,0xE0,0x80,0x3B,0x00,0x60,0xC0,0x31,0x00,0x60,0xE0,0x30,0x00,0x60,0x70,0x30,0x00,0x60,0x38,0x30,0x00,0x60,0x1C,0x30,0x00,0xE0,0x0E,0x38,0x00,0xC0,0x07,0x18,0x00,0xC0,0x03,0x1C,0x00,0xE0,0x07,0x0F,0x00,0x70,0xFF,0x07,0x00,0x20,0xFC,0x01, // 216 1234 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x02,0x00,0x30,0x00,0x06,0x00,0x30,0x00,0x0E,0x00,0x30,0x00,0x08,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 217 1235 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x08,0x00,0x30,0x00,0x0E,0x00,0x30,0x00,0x06,0x00,0x30,0x00,0x02,0x00,0x30,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 218 1236 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x08,0x00,0x30,0x00,0x0C,0x00,0x30,0x00,0x06,0x00,0x30,0x00,0x06,0x00,0x30,0x00,0x0C,0x00,0x30,0x00,0x08,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 219 1237 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x03,0x00,0xE0,0xFF,0x0F,0x00,0x00,0x00,0x1C,0x00,0x00,0x00,0x38,0x00,0x0C,0x00,0x30,0x00,0x0C,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x0C,0x00,0x30,0x00,0x0C,0x00,0x38,0x00,0x00,0x00,0x1C,0x00,0xE0,0xFF,0x0F,0x00,0xE0,0xFF,0x03, // 220 1238 | 0x20,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0xC0,0x01,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x1E,0x00,0x00,0x00,0x3C,0x00,0x00,0x08,0xF0,0x3F,0x00,0x0E,0xF0,0x3F,0x00,0x06,0x3C,0x00,0x00,0x02,0x1E,0x00,0x00,0x00,0x07,0x00,0x00,0xC0,0x03,0x00,0x00,0xE0,0x01,0x00,0x00,0x60,0x00,0x00,0x00,0x20, // 221 1239 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0x3F,0x00,0xE0,0xFF,0x3F,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x06,0x00,0x00,0x03,0x07,0x00,0x00,0x86,0x03,0x00,0x00,0xFE,0x01,0x00,0x00,0xF8, // 222 1240 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x3F,0x00,0xC0,0xFF,0x3F,0x00,0xC0,0x00,0x00,0x00,0x60,0x00,0x08,0x00,0x60,0x00,0x1C,0x00,0x60,0x00,0x38,0x00,0xE0,0x78,0x30,0x00,0xC0,0x7F,0x30,0x00,0x80,0xC7,0x30,0x00,0x00,0x80,0x39,0x00,0x00,0x80,0x1F,0x00,0x00,0x00,0x0F, // 223 1241 | 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x00,0x8C,0x39,0x00,0x20,0x86,0x31,0x00,0x60,0x86,0x31,0x00,0xE0,0xC6,0x30,0x00,0x80,0xC6,0x18,0x00,0x00,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 224 1242 | 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x00,0x8C,0x39,0x00,0x00,0x86,0x31,0x00,0x80,0x86,0x31,0x00,0xE0,0xC6,0x30,0x00,0x60,0xC6,0x18,0x00,0x20,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 225 1243 | 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x80,0x8C,0x39,0x00,0xC0,0x86,0x31,0x00,0x60,0x86,0x31,0x00,0x60,0xC6,0x30,0x00,0xC0,0xC6,0x18,0x00,0x80,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 226 1244 | 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0xC0,0x1C,0x1F,0x00,0xE0,0x8C,0x39,0x00,0x60,0x86,0x31,0x00,0x60,0x86,0x31,0x00,0xC0,0xC6,0x30,0x00,0xC0,0xC6,0x18,0x00,0xE0,0xCE,0x0C,0x00,0x60,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 227 1245 | 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0xC0,0x8C,0x39,0x00,0xC0,0x86,0x31,0x00,0x00,0x86,0x31,0x00,0x00,0xC6,0x30,0x00,0xC0,0xC6,0x18,0x00,0xC0,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 228 1246 | 0x00,0x00,0x00,0x00,0x00,0x18,0x0E,0x00,0x00,0x1C,0x1F,0x00,0x00,0x8C,0x39,0x00,0x70,0x86,0x31,0x00,0x88,0x86,0x31,0x00,0x88,0xC6,0x30,0x00,0x88,0xC6,0x18,0x00,0x70,0xCE,0x0C,0x00,0x00,0xFC,0x1F,0x00,0x00,0xF8,0x3F,0x00,0x00,0x00,0x20, // 229 1247 | 0x00,0x00,0x00,0x00,0x00,0x10,0x0F,0x00,0x00,0x9C,0x1F,0x00,0x00,0xCC,0x39,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0x66,0x18,0x00,0x00,0x6E,0x1C,0x00,0x00,0xFC,0x0F,0x00,0x00,0xFC,0x1F,0x00,0x00,0xCC,0x1C,0x00,0x00,0xCE,0x38,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xCC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xE0,0x04, // 230 1248 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x02,0x00,0x06,0x30,0x02,0x00,0x06,0xF0,0x02,0x00,0x06,0xB0,0x03,0x00,0x0E,0x38,0x01,0x00,0x1C,0x1C,0x00,0x00,0x18,0x0C, // 231 1249 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0x20,0xCE,0x38,0x00,0x60,0xC6,0x30,0x00,0xE0,0xC6,0x30,0x00,0x80,0xC6,0x30,0x00,0x00,0xCE,0x38,0x00,0x00,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 232 1250 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0x00,0xCE,0x38,0x00,0x80,0xC6,0x30,0x00,0xE0,0xC6,0x30,0x00,0x60,0xC6,0x30,0x00,0x20,0xCE,0x38,0x00,0x00,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 233 1251 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0x80,0xCE,0x38,0x00,0xC0,0xC6,0x30,0x00,0x60,0xC6,0x30,0x00,0x60,0xC6,0x30,0x00,0xC0,0xCE,0x38,0x00,0x80,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 234 1252 | 0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0xDC,0x1C,0x00,0xC0,0xCE,0x38,0x00,0xC0,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0x00,0xC6,0x30,0x00,0xC0,0xCE,0x38,0x00,0xC0,0xDC,0x18,0x00,0x00,0xF8,0x0C,0x00,0x00,0xF0,0x04, // 235 1253 | 0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x60,0xFE,0x3F,0x00,0xE0,0xFE,0x3F,0x00,0x80, // 236 1254 | 0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0xE0,0xFE,0x3F,0x00,0x60,0xFE,0x3F,0x00,0x20, // 237 1255 | 0x80,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x60,0xFE,0x3F,0x00,0x60,0xFE,0x3F,0x00,0xC0,0x00,0x00,0x00,0x80, // 238 1256 | 0xC0,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F,0x00,0xC0,0x00,0x00,0x00,0xC0, // 239 1257 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1D,0x1C,0x00,0xA0,0x0F,0x38,0x00,0xA0,0x06,0x30,0x00,0xE0,0x06,0x30,0x00,0xC0,0x06,0x30,0x00,0xC0,0x0F,0x38,0x00,0x20,0x1F,0x1C,0x00,0x00,0xFC,0x0F,0x00,0x00,0xE0,0x07, // 240 1258 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x3F,0x00,0xC0,0xFE,0x3F,0x00,0xE0,0x18,0x00,0x00,0x60,0x0C,0x00,0x00,0x60,0x06,0x00,0x00,0xC0,0x06,0x00,0x00,0xC0,0x06,0x00,0x00,0xE0,0x0E,0x00,0x00,0x60,0xFC,0x3F,0x00,0x00,0xF8,0x3F, // 241 1259 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x20,0x0E,0x38,0x00,0x60,0x06,0x30,0x00,0xE0,0x06,0x30,0x00,0x80,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 242 1260 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x38,0x00,0x80,0x06,0x30,0x00,0xE0,0x06,0x30,0x00,0x60,0x06,0x30,0x00,0x20,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 243 1261 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0x80,0x0E,0x38,0x00,0xC0,0x06,0x30,0x00,0x60,0x06,0x30,0x00,0x60,0x06,0x30,0x00,0xC0,0x0E,0x38,0x00,0x80,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 244 1262 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0xC0,0x1C,0x1C,0x00,0xE0,0x0E,0x38,0x00,0x60,0x06,0x30,0x00,0x60,0x06,0x30,0x00,0xC0,0x06,0x30,0x00,0xC0,0x0E,0x38,0x00,0xE0,0x1C,0x1C,0x00,0x60,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 245 1263 | 0x00,0x00,0x00,0x00,0x00,0xF0,0x07,0x00,0x00,0xF8,0x0F,0x00,0x00,0x1C,0x1C,0x00,0xC0,0x0E,0x38,0x00,0xC0,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0xC0,0x0E,0x38,0x00,0xC0,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x07, // 246 1264 | 0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0xB6,0x01,0x00,0x00,0xB6,0x01,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30, // 247 1265 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF0,0x67,0x00,0x00,0xF8,0x7F,0x00,0x00,0x1C,0x1C,0x00,0x00,0x0E,0x3F,0x00,0x00,0x86,0x33,0x00,0x00,0xE6,0x31,0x00,0x00,0x76,0x30,0x00,0x00,0x3E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xFF,0x0F,0x00,0x00,0xF3,0x07, // 248 1266 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0x20,0x00,0x38,0x00,0x60,0x00,0x30,0x00,0xE0,0x00,0x30,0x00,0x80,0x00,0x30,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 249 1267 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x30,0x00,0x80,0x00,0x30,0x00,0xE0,0x00,0x30,0x00,0x60,0x00,0x18,0x00,0x20,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 250 1268 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0x80,0x00,0x38,0x00,0xC0,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0x60,0x00,0x30,0x00,0xC0,0x00,0x18,0x00,0x80,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 251 1269 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x0F,0x00,0x00,0xFE,0x1F,0x00,0xC0,0x00,0x38,0x00,0xC0,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0xC0,0x00,0x18,0x00,0xC0,0x00,0x0C,0x00,0x00,0xFE,0x3F,0x00,0x00,0xFE,0x3F, // 252 1270 | 0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x06,0x00,0xF0,0x01,0x06,0x00,0x80,0x0F,0x07,0x80,0x00,0xFE,0x03,0xE0,0x00,0xFC,0x00,0x60,0xC0,0x1F,0x00,0x20,0xF8,0x03,0x00,0x00,0x3E,0x00,0x00,0x00,0x06, // 253 1271 | 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xFF,0xFF,0x07,0xE0,0xFF,0xFF,0x07,0x00,0x1C,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0x30,0x00,0x00,0x0E,0x38,0x00,0x00,0x1C,0x1C,0x00,0x00,0xF8,0x0F,0x00,0x00,0xF0,0x03, // 254 1272 | 0x00,0x00,0x00,0x00,0x00,0x0E,0x00,0x00,0x00,0x7E,0x00,0x06,0xC0,0xF0,0x01,0x06,0xC0,0x80,0x0F,0x07,0x00,0x00,0xFE,0x03,0x00,0x00,0xFC,0x00,0xC0,0xC0,0x1F,0x00,0xC0,0xF8,0x03,0x00,0x00,0x3E,0x00,0x00,0x00,0x06 // 255 1273 | }; 1274 | #endif 1275 | 1276 | --------------------------------------------------------------------------------