├── LICENSE ├── README.md ├── assets ├── espressif-logo-in_64.png ├── espressif-logo_64.png ├── espressif.png └── ic_stat_espressif.XBM └── sketches └── esp32_android ├── battery_icon.h ├── esp32_android.ino └── espressif_logo.h /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Mitchell Wong Ho 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP-Alerts-for-Arduino 2 | Send Android Notifications to an ESP32 with OLED display 3 | -------------------------------------------------------------------------------- /assets/espressif-logo-in_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchwongho/ESP-Alerts-for-Arduino/af1cfdb0600c80ec9ec7bb6e07b00321cec07ee5/assets/espressif-logo-in_64.png -------------------------------------------------------------------------------- /assets/espressif-logo_64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchwongho/ESP-Alerts-for-Arduino/af1cfdb0600c80ec9ec7bb6e07b00321cec07ee5/assets/espressif-logo_64.png -------------------------------------------------------------------------------- /assets/espressif.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitchwongho/ESP-Alerts-for-Arduino/af1cfdb0600c80ec9ec7bb6e07b00321cec07ee5/assets/espressif.png -------------------------------------------------------------------------------- /assets/ic_stat_espressif.XBM: -------------------------------------------------------------------------------- 1 | #define 1514496701020_width 64 2 | #define 1514496701020_height 64 3 | static char 1514496701020_bits[] = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 7 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 9 | 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x0F, 0x00, 0x00, 10 | 0x00, 0x00, 0xE0, 0x01, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x1F, 11 | 0xF8, 0x7F, 0x00, 0x00, 0x00, 0x38, 0xFC, 0xFF, 0xE0, 0xFF, 0x00, 0x00, 12 | 0x00, 0x3C, 0xFE, 0xFF, 0x83, 0xFF, 0x03, 0x00, 0x00, 0x1C, 0xFF, 0xFF, 13 | 0x0F, 0xFF, 0x07, 0x00, 0x00, 0x0E, 0xFE, 0xFF, 0x1F, 0xFC, 0x07, 0x00, 14 | 0x00, 0x07, 0xFF, 0xFF, 0x7F, 0xF8, 0x0F, 0x00, 0x00, 0x07, 0xFE, 0xFF, 15 | 0xFF, 0xE0, 0x1F, 0x00, 0x80, 0x03, 0x80, 0xFF, 0xFF, 0xE3, 0x3F, 0x00, 16 | 0xC0, 0x03, 0x00, 0xFC, 0xFF, 0xC7, 0x3F, 0x00, 0xC0, 0x81, 0x09, 0xE0, 17 | 0xFF, 0x8F, 0x7F, 0x00, 0xC0, 0xF9, 0xFF, 0x81, 0xFF, 0x1F, 0xFF, 0x00, 18 | 0xE0, 0xFC, 0xFF, 0x07, 0xFE, 0x3F, 0xFE, 0x00, 0xE0, 0xFC, 0xFF, 0x3F, 19 | 0xFC, 0x7F, 0xFC, 0x00, 0xE0, 0xFE, 0xFF, 0xFF, 0xF0, 0x7F, 0xFC, 0x01, 20 | 0x70, 0xFE, 0xFF, 0xFF, 0xE1, 0xFF, 0xF8, 0x01, 0x60, 0xFE, 0xFF, 0xFF, 21 | 0xC7, 0xFF, 0xF1, 0x01, 0x70, 0xFE, 0xFF, 0xFF, 0x87, 0xFF, 0xF1, 0x01, 22 | 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xE3, 0x03, 0x70, 0x0F, 0xC0, 0xFF, 23 | 0x1F, 0xFE, 0xE7, 0x03, 0x70, 0x07, 0x00, 0xFE, 0x3F, 0xFE, 0xC7, 0x03, 24 | 0x70, 0xC7, 0x1B, 0xF8, 0x7F, 0xFC, 0xCF, 0x03, 0x30, 0xF7, 0x7F, 0xF0, 25 | 0xFF, 0xF8, 0x8F, 0x01, 0x70, 0xFF, 0xFF, 0xC1, 0xFF, 0xF8, 0x8F, 0x03, 26 | 0x30, 0xFF, 0xFF, 0x87, 0xFF, 0xF1, 0x1F, 0x00, 0x70, 0xFE, 0xFF, 0x0F, 27 | 0xFF, 0xF3, 0x1F, 0x00, 0x70, 0xFE, 0xFF, 0x1F, 0xFF, 0xE3, 0x3F, 0x00, 28 | 0x70, 0xFE, 0xFF, 0x3F, 0xFE, 0xE7, 0x3F, 0x00, 0x60, 0xFE, 0xFF, 0x7F, 29 | 0xFC, 0xE7, 0x3F, 0x00, 0xE0, 0xFC, 0xFE, 0x7F, 0xFC, 0xC7, 0x3F, 0x00, 30 | 0xE0, 0x3C, 0xE0, 0xFF, 0xF8, 0xCF, 0x7F, 0x00, 0xE0, 0x00, 0xC0, 0xFF, 31 | 0xF8, 0xCF, 0x7F, 0x00, 0xC0, 0x01, 0x00, 0xFF, 0xF9, 0x8F, 0x7F, 0x00, 32 | 0xC0, 0x01, 0x07, 0xFF, 0xF1, 0x8F, 0x7F, 0x00, 0x80, 0xC3, 0x0F, 0xFE, 33 | 0xF3, 0xCF, 0x3F, 0x00, 0x80, 0xE3, 0x1F, 0xFE, 0xF3, 0x9F, 0x3F, 0x00, 34 | 0x00, 0xE7, 0x3F, 0xFE, 0xF1, 0x8F, 0x1F, 0x00, 0x00, 0xEF, 0x3F, 0xFE, 35 | 0xF3, 0x9F, 0x0F, 0x00, 0x00, 0xEE, 0x3F, 0xFE, 0xF3, 0x0F, 0x05, 0x00, 36 | 0x00, 0xFC, 0x1F, 0xFE, 0xF3, 0x0F, 0x00, 0x00, 0x00, 0xF8, 0x1F, 0xFE, 37 | 0xF1, 0x0F, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0xFF, 0xF1, 0x0F, 0x18, 0x00, 38 | 0x00, 0xF0, 0x00, 0xFF, 0xF9, 0x0F, 0x1C, 0x00, 0x00, 0xE0, 0x01, 0xFF, 39 | 0xF9, 0x0F, 0x1E, 0x00, 0x00, 0x80, 0x07, 0xFE, 0xF8, 0x87, 0x0F, 0x00, 40 | 0x00, 0x00, 0x1F, 0xFC, 0xE0, 0xE1, 0x03, 0x00, 0x00, 0x00, 0x7E, 0x60, 41 | 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x7F, 0x00, 0x00, 42 | 0x00, 0x00, 0xE0, 0xFF, 0xFA, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 43 | 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0xBF, 0x00, 0x00, 0x00, 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; 47 | -------------------------------------------------------------------------------- /sketches/esp32_android/battery_icon.h: -------------------------------------------------------------------------------- 1 | #define batt_icon_width 16 2 | #define batt_icon_height 16 3 | static char batt_icon_bits[] = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x60, 0x06, 0x20, 0x04, 5 | 0x20, 0x04, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 6 | 0xE0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; 7 | -------------------------------------------------------------------------------- /sketches/esp32_android/esp32_android.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * The MIT License (MIT) 3 | * 4 | * Copyright (c) 2016 by Daniel Eichhorn 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 | */ 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include "espressif_logo.h" 30 | #include "battery_icon.h" 31 | //#include 32 | // Include the correct display library 33 | // For a connection via I2C using Wire include 34 | #include // Only needed for Arduino 1.6.5 and earlier 35 | #include "SSD1306.h" // alias for `#include "SSD1306Wire.h"` 36 | 37 | // BLE UUIDs 38 | #define GENERIC_DISPLAY 320 39 | static const BLEUUID ALERT_DISPLAY_SERVICE_UUID = BLEUUID("3db02924-b2a6-4d47-be1f-0f90ad62a048"); 40 | static const BLEUUID DISPLAY_MESSAGE_CHARACTERISTIC_UUID = BLEUUID("8d8218b6-97bc-4527-a8db-13094ac06b1d"); 41 | static const BLEUUID DISPLAY_TIME_CHARACTERISTIC_UUID = BLEUUID("b7b0a14b-3e94-488f-b262-5d584a1ef9e1"); 42 | static const BLEUUID DISPLAY_DISPLAY_ORIENTATION_CHARACTERISTIC_UUID = BLEUUID("0070b87e-d825-43f5-be0c-7d86f75e4900"); 43 | 44 | #define BUFF_LEN 256 45 | 46 | 47 | volatile bool connected = false; //0=advertising; 1=connected 48 | volatile bool hasText = false, hasBattText = false; 49 | volatile bool hasTimeText = false; 50 | volatile bool hasLongText = false; 51 | volatile int yScrollPos = 0; 52 | char* payload = new char[BUFF_LEN]; 53 | char* time_buffer = new char[BUFF_LEN]; 54 | volatile int batt_level = 0; // 55 | volatile int display_orientation = 0; //0=none;1=flip 56 | 57 | #define SCROLL_DELAY 6 58 | #define MAX_SCROLL_WINDOW_HEIGHT 75 59 | 60 | // Initialize the OLED display using Wire library 61 | SSD1306 display(0x3c, 5, 4); 62 | 63 | 64 | class DisplayOrientationCharacteristicCallback: public BLECharacteristicCallbacks { 65 | void onWrite(BLECharacteristic* pCharacteristic) { 66 | std::string str = pCharacteristic->getValue(); //read values 67 | display_orientation = (int)str[0]; 68 | Serial.println(" DisplayOrientationCharacteristicCallback->onWrite()"); 69 | } 70 | 71 | }; 72 | /** 73 | * Callback to handle Time Charcterisitc events 74 | */ 75 | class TimeCharacteristicCallback: public BLECharacteristicCallbacks { 76 | void onWrite(BLECharacteristic* pTimeCharacteristic) { 77 | std::string str = pTimeCharacteristic->getValue(); //read values 78 | memset(time_buffer, '\0', sizeof(time_buffer)); //clear buffer 79 | strcpy(time_buffer, &str.c_str()[1]); //first char indicates battery-level 80 | batt_level = (int)str[0]; //char to int 81 | 82 | 83 | char buff[16]; 84 | sprintf(buff, "Batt: %d%%", str[0]); 85 | Serial.print(buff); 86 | Serial.println(" TimeCharacteristicCallback->onWrite()"); 87 | 88 | hasLongText = false; 89 | hasText = false; 90 | hasTimeText = true; 91 | } 92 | }; 93 | /** 94 | * Callback to handle Notification characteristic events 95 | */ 96 | class DisplayCharacteristicCallback: public BLECharacteristicCallbacks { 97 | void onWrite(BLECharacteristic* pCharacteristic) { 98 | // write text to OLED 99 | std::string str = pCharacteristic->getValue(); 100 | BLEUUID uuid = pCharacteristic->getUUID(); 101 | std::string uuid_s = uuid.toString(); 102 | Serial.print("onWrite() {uuid="); 103 | Serial.print(String(uuid_s.c_str())); 104 | Serial.print(",len="); 105 | Serial.print(str.length()); 106 | Serial.println("}"); 107 | 108 | memset(payload, '\0', sizeof(payload)); 109 | strcpy(payload, str.c_str()); 110 | yScrollPos = 0; 111 | 112 | hasLongText = str.length() > 40; 113 | hasText = true; 114 | hasTimeText = false; 115 | } 116 | }; 117 | 118 | class MyServerCallback: public BLEServerCallbacks { 119 | void onConnect(BLEServer* pServer) { 120 | //todo display `connected` on the screen 121 | Serial.println("LE onConnect"); 122 | 123 | connected = true; 124 | memset(payload, 0x00, BUFF_LEN); 125 | hasLongText = false; 126 | hasText = false; 127 | hasTimeText = false; 128 | yScrollPos = 0; 129 | } 130 | 131 | void onDisconnect(BLEServer* pServer) { 132 | // todo display `disconnected` on the screen 133 | Serial.println("LE onDisconnect"); 134 | connected = false; 135 | } 136 | }; 137 | 138 | void setupBLEServer() { 139 | //init BLE server 140 | BLEDevice::init("VESPA-32"); 141 | BLEServer *pServer = BLEDevice::createServer(); 142 | pServer->setCallbacks(new MyServerCallback()); 143 | // Alert Display Service 144 | BLEService *pService = pServer->createService( ALERT_DISPLAY_SERVICE_UUID ); 145 | 146 | // BLECharacteristic* pCharacteristic = pService->createCharacteristic( 147 | // DISPLAY_MESSAGE_CHARACTERISTIC_UUID, 148 | // BLECharacteristic::PROPERTY_WRITE 149 | // ); 150 | // pCharacteristic->setWriteProperty(true); 151 | 152 | BLECharacteristic* pCharacteristicText = new BLECharacteristic(DISPLAY_MESSAGE_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE_NR); //Request MTU=500 from client 153 | pCharacteristicText->setCallbacks(new DisplayCharacteristicCallback()); 154 | pService->addCharacteristic(pCharacteristicText); 155 | 156 | // Display Time Characteristic 157 | BLECharacteristic* pCharacteristicTime = new BLECharacteristic(DISPLAY_TIME_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE_NR); 158 | pCharacteristicTime->setCallbacks(new TimeCharacteristicCallback()); 159 | pService->addCharacteristic(pCharacteristicTime); 160 | 161 | // Change Display Orientation 162 | BLECharacteristic* pCharacteristicDisplayOrientation = new BLECharacteristic(DISPLAY_DISPLAY_ORIENTATION_CHARACTERISTIC_UUID, BLECharacteristic::PROPERTY_WRITE_NR); 163 | pCharacteristicDisplayOrientation->setCallbacks(new DisplayOrientationCharacteristicCallback()); 164 | pService->addCharacteristic(pCharacteristicDisplayOrientation); 165 | 166 | pService->start(); 167 | 168 | BLEAdvertising *pAdvertising = pServer->getAdvertising(); 169 | // https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.gap.appearance.xml 170 | pAdvertising->setAppearance(GENERIC_DISPLAY); //Generic Display 171 | pAdvertising->start(); 172 | } 173 | 174 | void setup() { 175 | // put your setup code here, to run once: 176 | Serial.begin(115200); 177 | Serial.println(); 178 | Serial.println("hello"); 179 | 180 | //init BLE server 181 | setupBLEServer(); 182 | 183 | // Initialising the UI will init the display too. 184 | display.init(); 185 | 186 | // display.flipScreenVertically(); 187 | display.setFont(ArialMT_Plain_10); 188 | } 189 | 190 | //void drawFontFaceDemo() { 191 | // // Font Demo1 192 | // // create more fonts at http://oleddisplay.squix.ch/ 193 | // display.setTextAlignment(TEXT_ALIGN_LEFT); 194 | // display.setFont(ArialMT_Plain_10); 195 | // display.drawString(0, 0, "Hello world 2"); 196 | // display.setFont(ArialMT_Plain_16); 197 | // display.drawString(3, 10, "Hello world 3"); 198 | // display.setFont(ArialMT_Plain_24); 199 | // display.drawString(6, 26, "Hello world 4"); 200 | //} 201 | 202 | 203 | void oledWriteText(char* text, uint32_t y = 0) { 204 | display.setTextAlignment(TEXT_ALIGN_LEFT); 205 | display.setFont(ArialMT_Plain_16); 206 | display.drawStringMaxWidth(0, y, 120, text); 207 | } 208 | 209 | void drawBatteryIcon() { 210 | // see http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html 211 | // on how to create xbm files 212 | display.drawXbm(0, 49, batt_icon_width, batt_icon_height, batt_icon_bits); 213 | } 214 | 215 | void oledWriteBattLevel(int batt_level) { 216 | char buff[16]; 217 | // itoa(batt_level, buff, 10); 218 | drawBatteryIcon(); 219 | sprintf(buff, "%d%%", batt_level); 220 | display.setTextAlignment(TEXT_ALIGN_LEFT); 221 | display.setFont(ArialMT_Plain_16); 222 | display.drawString(15, 48, buff); 223 | } 224 | 225 | void oledWriteTimeText(char* text, int batt_level) { 226 | display.setTextAlignment(TEXT_ALIGN_LEFT); 227 | display.setFont(ArialMT_Plain_24); 228 | display.drawString(36, 10, text); 229 | // 230 | oledWriteBattLevel(batt_level); 231 | } 232 | 233 | void drawImageDemo() { 234 | // see http://blog.squix.org/2015/05/esp8266-nodemcu-how-to-create-xbm.html 235 | // on how to create xbm files 236 | display.drawXbm(35, 2, logo_width, logo_height, logo_bits); 237 | } 238 | 239 | void loop() { 240 | // clear the display 241 | display.clear(); 242 | // put your main code here, to run repeatedly: 243 | if (connected) { 244 | if (hasText) { 245 | int yPos = 0; 246 | if (hasLongText) { 247 | yScrollPos = (yScrollPos + 1) % MAX_SCROLL_WINDOW_HEIGHT; 248 | if (yScrollPos >= SCROLL_DELAY) { 249 | // a small delay before applying the scroll-y position 250 | yPos = -(yScrollPos - SCROLL_DELAY); 251 | } 252 | } 253 | oledWriteText(payload, yPos); 254 | } else if (hasTimeText) { 255 | oledWriteTimeText(time_buffer, batt_level); 256 | } else if (display_orientation != 0) { 257 | display.flipScreenVertically(); 258 | display_orientation = 0; 259 | } else { 260 | oledWriteText("Connected"); 261 | } 262 | } else { 263 | // oledWriteText("Advertising..."); 264 | drawImageDemo(); 265 | } 266 | // 267 | 268 | // drawFontFaceDemo(); 269 | // write the buffer to the display 270 | display.display(); 271 | // 272 | delay(500); //500ms 273 | } 274 | 275 | 276 | -------------------------------------------------------------------------------- /sketches/esp32_android/espressif_logo.h: -------------------------------------------------------------------------------- 1 | #define logo_width 64 2 | #define logo_height 64 3 | static char logo_bits[] = { 4 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 5 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 6 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 7 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 8 | 0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 9 | 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x0F, 0x00, 0x00, 10 | 0x00, 0x00, 0xE0, 0x01, 0xFE, 0x3F, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x1F, 11 | 0xF8, 0x7F, 0x00, 0x00, 0x00, 0x38, 0xFC, 0xFF, 0xE0, 0xFF, 0x00, 0x00, 12 | 0x00, 0x3C, 0xFE, 0xFF, 0x83, 0xFF, 0x03, 0x00, 0x00, 0x1C, 0xFF, 0xFF, 13 | 0x0F, 0xFF, 0x07, 0x00, 0x00, 0x0E, 0xFE, 0xFF, 0x1F, 0xFC, 0x07, 0x00, 14 | 0x00, 0x07, 0xFF, 0xFF, 0x7F, 0xF8, 0x0F, 0x00, 0x00, 0x07, 0xFE, 0xFF, 15 | 0xFF, 0xE0, 0x1F, 0x00, 0x80, 0x03, 0x80, 0xFF, 0xFF, 0xE3, 0x3F, 0x00, 16 | 0xC0, 0x03, 0x00, 0xFC, 0xFF, 0xC7, 0x3F, 0x00, 0xC0, 0x81, 0x09, 0xE0, 17 | 0xFF, 0x8F, 0x7F, 0x00, 0xC0, 0xF9, 0xFF, 0x81, 0xFF, 0x1F, 0xFF, 0x00, 18 | 0xE0, 0xFC, 0xFF, 0x07, 0xFE, 0x3F, 0xFE, 0x00, 0xE0, 0xFC, 0xFF, 0x3F, 19 | 0xFC, 0x7F, 0xFC, 0x00, 0xE0, 0xFE, 0xFF, 0xFF, 0xF0, 0x7F, 0xFC, 0x01, 20 | 0x70, 0xFE, 0xFF, 0xFF, 0xE1, 0xFF, 0xF8, 0x01, 0x60, 0xFE, 0xFF, 0xFF, 21 | 0xC7, 0xFF, 0xF1, 0x01, 0x70, 0xFE, 0xFF, 0xFF, 0x87, 0xFF, 0xF1, 0x01, 22 | 0x70, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xE3, 0x03, 0x70, 0x0F, 0xC0, 0xFF, 23 | 0x1F, 0xFE, 0xE7, 0x03, 0x70, 0x07, 0x00, 0xFE, 0x3F, 0xFE, 0xC7, 0x03, 24 | 0x70, 0xC7, 0x1B, 0xF8, 0x7F, 0xFC, 0xCF, 0x03, 0x30, 0xF7, 0x7F, 0xF0, 25 | 0xFF, 0xF8, 0x8F, 0x01, 0x70, 0xFF, 0xFF, 0xC1, 0xFF, 0xF8, 0x8F, 0x03, 26 | 0x30, 0xFF, 0xFF, 0x87, 0xFF, 0xF1, 0x1F, 0x00, 0x70, 0xFE, 0xFF, 0x0F, 27 | 0xFF, 0xF3, 0x1F, 0x00, 0x70, 0xFE, 0xFF, 0x1F, 0xFF, 0xE3, 0x3F, 0x00, 28 | 0x70, 0xFE, 0xFF, 0x3F, 0xFE, 0xE7, 0x3F, 0x00, 0x60, 0xFE, 0xFF, 0x7F, 29 | 0xFC, 0xE7, 0x3F, 0x00, 0xE0, 0xFC, 0xFE, 0x7F, 0xFC, 0xC7, 0x3F, 0x00, 30 | 0xE0, 0x3C, 0xE0, 0xFF, 0xF8, 0xCF, 0x7F, 0x00, 0xE0, 0x00, 0xC0, 0xFF, 31 | 0xF8, 0xCF, 0x7F, 0x00, 0xC0, 0x01, 0x00, 0xFF, 0xF9, 0x8F, 0x7F, 0x00, 32 | 0xC0, 0x01, 0x07, 0xFF, 0xF1, 0x8F, 0x7F, 0x00, 0x80, 0xC3, 0x0F, 0xFE, 33 | 0xF3, 0xCF, 0x3F, 0x00, 0x80, 0xE3, 0x1F, 0xFE, 0xF3, 0x9F, 0x3F, 0x00, 34 | 0x00, 0xE7, 0x3F, 0xFE, 0xF1, 0x8F, 0x1F, 0x00, 0x00, 0xEF, 0x3F, 0xFE, 35 | 0xF3, 0x9F, 0x0F, 0x00, 0x00, 0xEE, 0x3F, 0xFE, 0xF3, 0x0F, 0x05, 0x00, 36 | 0x00, 0xFC, 0x1F, 0xFE, 0xF3, 0x0F, 0x00, 0x00, 0x00, 0xF8, 0x1F, 0xFE, 37 | 0xF1, 0x0F, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0xFF, 0xF1, 0x0F, 0x18, 0x00, 38 | 0x00, 0xF0, 0x00, 0xFF, 0xF9, 0x0F, 0x1C, 0x00, 0x00, 0xE0, 0x01, 0xFF, 39 | 0xF9, 0x0F, 0x1E, 0x00, 0x00, 0x80, 0x07, 0xFE, 0xF8, 0x87, 0x0F, 0x00, 40 | 0x00, 0x00, 0x1F, 0xFC, 0xE0, 0xE1, 0x03, 0x00, 0x00, 0x00, 0x7E, 0x60, 41 | 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x7F, 0x00, 0x00, 42 | 0x00, 0x00, 0xE0, 0xFF, 0xFA, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 43 | 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF4, 0xBF, 0x00, 0x00, 0x00, 44 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 46 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; 47 | 48 | --------------------------------------------------------------------------------