I am building Dynamic QR generator using ESP32 Wroom and TFT display ILI9341 and for audio i am using DAC module . The code is pretty lengthy i divided it separate cpp files. i ll provide the libraries i use .
#ifndef HEADER_H
#define HEADER_H
#define GIF_IMAGE paysucces
// #include "ESPWEBCONFIG.h"
// #include "Arduino.h"
#include <LittleFS.h>
#include <Audio.h>
#include <WiFi.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ArduinoJson.h>
#include <TFT_eSPI.h> // Hardware-specific library
#include "SPI.h"
#include <PNGdec.h>
#include "logo.h"
#include <qrcode.h>
#include <AnimatedGIF.h>
#include "../test_images/grapes.h"
#define I2S_DOUT 23
#define I2S_BCLK 27
#define I2S_LRC 26
#define DISPLAY_WIDTH tft.width()
#define DISPLAY_HEIGHT tft.height()
#define BUFFER_SIZE 256 // Optimum is >= GIF width or integral division of width
// TFT Setup
#define TFT_GREY 0x5AEB
#define MAX_IMAGE_WIDTH 240
#define FileSys LittleFS
// #define USE_DMA
#define NORMAL_SPEED
extern const char *ssid;
extern const char *password;
extern AsyncWebServer server;
extern AnimatedGIF gif;
extern AsyncWebSocket ws;
extern IPAddress local_ip; // Static IP
extern IPAddress gateway; // Gateway IP
extern IPAddress subnet; // Subnet Mask
extern IPAddress dns; // Primary DNS (e.g., Google DNS)
extern IPAddress dns_secondary;
// NTP Server and Time Zone
// extern const char *ntpServer;
// extern const long utcOffsetInSeconds; // Indian Standard Time (IST) UTC+5:30
extern uint16_t color;
extern PNG png;
extern TFT_eSPI tft; // Invoke custom library
extern uint32_t targetTime; // for next 1 second timeout
extern WiFiUDP ntpUDP;
extern NTPClient timeClient; // Update every minute
extern uint8_t omm, oss;
extern uint8_t xcolon, xsecs;
extern bool isPM; // Track whether it's PM
extern int16_t bgxpos;
extern int16_t bgypos;
enum VIEWMODE {
NORMAL,
QR,
PAYMENT_SUCCESS
};
extern Audio audio;
extern VIEWMODE state;
extern QueueHandle_t numberQueue;
extern unsigned long previousMillis; // To store last time function was called
extern const unsigned long interval; // Interval for the function switch (1 second)
extern unsigned long qrDisplayStartMillis; // To track when the QR should stop
extern const unsigned long qrDisplayDuration; // 1 minute in milliseconds
// extern bool functionSwitch; // Flag to toggle between functions
// extern bool isQRDisplayed; // Flag to check if QR is currently displayed
// extern bool qrsuccess;
// Functions
void background();
void textDisp(int x, int y, int font);
void tft_time_loop();
float extractAmountFromUPI(String url);
// QR
void dispQR(const String &name, int mrnumber, const String &url);
// Dfplayer
// void audio_begin();
void audioInit();
void audioTask(void *parameter);
void playNumber(float num);
void playAudioFile(const char *filename);
// Websocket
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len);
void websockethandle(AsyncWebSocketClient *client, void *arg, uint8_t *data, size_t len);
void handlejson(const char *json);
void successPAy(const String &message, bool sda);
void setup_codes();
#endif
The Output
c:/users/user/appdata/local/arduino15/packages/esp32/tools/esp-x32/2302/bin/../lib/gcc/xtensa-esp32-elf/12.2.0/../../../../xtensa-esp32-elf/bin/ld.exe: C:\Users\user\AppData\Local\arduino\sketches\782C4FD3F46C097DC41D0ED66202A2BD/display_i2c_audio.ino.elf section `.dram0.bss' will not fit in region `dram0_0_seg'
c:/users/user/appdata/local/arduino15/packages/esp32/tools/esp-x32/2302/bin/../lib/gcc/xtensa-esp32-elf/12.2.0/../../../../xtensa-esp32-elf/bin/ld.exe: DRAM segment data does not fit.
c:/users/user/appdata/local/arduino15/packages/esp32/tools/esp-x32/2302/bin/../lib/gcc/xtensa-esp32-elf/12.2.0/../../../../xtensa-esp32-elf/bin/ld.exe: DRAM segment data does not fit.
c:/users/user/appdata/local/arduino15/packages/esp32/tools/esp-x32/2302/bin/../lib/gcc/xtensa-esp32-elf/12.2.0/../../../../xtensa-esp32-elf/bin/ld.exe: region `dram0_0_seg' overflowed by 856 bytes
I tried to reduce some global variables , All my declarations global
#include "header.h"
const char* ssid = "ssid";
const char* password = "password";
AsyncWebServer server(80);
AsyncWebSocket ws("/ws");
IPAddress local_ip(192, 168, 1, 65); // Static IP
IPAddress gateway(192, 168, 1, 1); // Gateway IP
IPAddress subnet(255, 255, 255, 0); // Subnet Mask
IPAddress dns(8, 8, 8, 8); // Primary DNS (e.g., Google DNS)
IPAddress dns_secondary(8, 8, 4, 4); // Secondary DNS (optional, e.g., Googl
PNG png;
AnimatedGIF gif;
TFT_eSPI tft = TFT_eSPI(); // Invoke custom library
// NTP Server and Time Zone
uint16_t color = 0x500a;
uint32_t targetTime = 0; // for next 1 second timeout
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org", 19800, 60000); // Update every minute
uint8_t omm = 99, oss = 99;
uint8_t xcolon = 0, xsecs = 0;
bool isPM = false; // Track whether it's PM
int16_t bgxpos = 0;
int16_t bgypos = 0;
VIEWMODE state = NORMAL;
QueueHandle_t numberQueue = NULL;
Audio audio;
unsigned long previousMillis = 0; // To store last time function was called
const unsigned long interval = 1000; // Interval for the function switch (1 second)
unsigned long qrDisplayStartMillis = 0; // To track when the QR should stop
const unsigned long qrDisplayDuration = 5000; // 10 second in milliseconds
float extractAmountFromUPI(String url) {
float amount = 0.0;
// Find the position of "am=" in the URL
int startIndex = url.indexOf("am=");
// If "am=" is found, extract the amount
if (startIndex != -1) {
startIndex += 3; // Skip "am=" part
int endIndex = url.indexOf("&", startIndex); // Find the end of the amount
// If no "&" is found, the amount goes till the end of the string
if (endIndex == -1) {
endIndex = url.length();
}
// Extract the amount as a substring
String amountString = url.substring(startIndex, endIndex);
// Convert the extracted string to a float
amount = amountString.toFloat();
}
Serial.print("Amount: ");
Serial.println(amount);
return amount;
}
But still it shows
overflowed by 856 bytes
Is there a way to fix this and run in this board or should i upgrade my ESP32 wroom to ESP32 wrover or something more powerful.
My need : To run display,Qr,Image and gif , Play audio using I2c Dac converter.
ino file
#include "header.h"
#include "esp_task_wdt.h"
esp_task_wdt_user_handle_t gif_watchdog_handle = NULL;
bool wdt_initialized = false;
File pngfile;
File f;
void setup() {
Serial.begin(115200);
setup_codes();
// esp_task_wdt_init(WDT_TIMEOUT, true); // enable panic so ESP32 restarts
// esp_task_wdt_add(NULL);
}
void loop() {
// Check if serial input is available
unsigned long currentMillis;
switch (state) {
case NORMAL:
tft_time_loop();
break;
case QR:
// playAudioQueue();
break;
case PAYMENT_SUCCESS:
currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (currentMillis - qrDisplayStartMillis >= qrDisplayDuration) {
state = NORMAL;
}
}
break;
default:
state = NORMAL;
break;
}
}
void background() {
if (LittleFS.begin()) {
return;
}
fs::File root = LittleFS.open("/", "r");
// Check if the directory is opened successfully
if (!root) {
Serial.println("Failed to open directory!");
return;
}
// Iterate through the files in the directory
while (fs::File file = root.openNextFile()) {
String strname = file.name();
strname = "/" + strname;
// Print the filename to serial for debugging
Serial.println(file.name());
// Check if the file is named "bg.png" (case-sensitive check)
if (!file.isDirectory() && strname.endsWith(".png")) {
// Attempt to open the PNG file using the appropriate callback functions
int16_t rc = png.open(strname.c_str(), pngOpen, pngClose, pngRead, pngSeek, pngDraw);
if (rc == PNG_SUCCESS) {
tft.startWrite(); // Start writing to the TFT screen
// Print image details to the serial monitor
Serial.printf("Image specs: (%d x %d), %d bpp, pixel type: %d\n", png.getWidth(), png.getHeight(), png.getBpp(), png.getPixelType());
uint32_t dt = millis();
// Check if the image width exceeds the max allowed width
if (png.getWidth() > MAX_IMAGE_WIDTH) {
Serial.println("Image too wide for allocated line buffer size!");
} else {
// Decode and display the PNG image
rc = png.decode(NULL, 0);
png.close(); // Close the PNG file after decoding
}
tft.endWrite(); // End writing to the TFT screen
// Log how long the rendering took
Serial.print("Rendering took: ");
Serial.print(millis() - dt);
Serial.println("ms");
} else {
// Print error if PNG decoding failed
Serial.println("Error decoding PNG: " + String(rc));
}
break; // Exit after displaying bg.png
}
}
// Close the root directory
root.close();
}
void pngDraw(PNGDRAW *pDraw) {
int16_t xpos = 0;
int16_t ypos = 0;
uint16_t lineBuffer[MAX_IMAGE_WIDTH];
png.getLineAsRGB565(pDraw, lineBuffer, PNG_RGB565_BIG_ENDIAN, 0xffffffff);
tft.pushImage(xpos, ypos + pDraw->y, pDraw->iWidth, 1, lineBuffer);
}
void gifdisp(bool fds) {
const char *item = fds ? "/grapes.gif" : "/failed.gif";
if (gif.open((uint8_t *)GIF_IMAGE, sizeof(GIF_IMAGE), GIFDraw)) {
Serial.printf("Successfully opened GIF; Canvas size = %d x %d\n", gif.getCanvasWidth(), gif.getCanvasHeight());
tft.startWrite(); // Lock the TFT chip select
// Check if TWDT has been initialized already
if (!wdt_initialized) {
esp_task_wdt_config_t wdt_config = {
.timeout_ms = 15000, // Timeout value for the watchdog (in milliseconds)
};
// Initialize the TWDT with the configuration
esp_task_wdt_init(&wdt_config);
wdt_initialized = true; // Set the flag indicating that TWDT is initialized
}
// Add the current task to the TWDT if it's not already added
if (esp_task_wdt_add(NULL) != ESP_OK) {
Serial.println("Task already subscribed to TWDT.");
}
// Add a user to the TWDT to monitor specific code (provide user name as string)
const char *user_name = "GIF_WATCHDOG"; // Provide a user name string
if (esp_task_wdt_add_user(user_name, &gif_watchdog_handle) != ESP_OK) {
Serial.println("User already subscribed to TWDT.");
}
unsigned long previousMillis = millis(); // Track the interval for watchdog reset
unsigned long interval = 50; // Interval in milliseconds to reset the TWDT
// Play GIF frames
while (gif.playFrame(true, NULL)) {
// Feed the watchdog periodically to avoid a reset
if (millis() - previousMillis >= interval) {
previousMillis = millis();
esp_task_wdt_reset(); // Feed the TWDT to avoid timeout
// Optionally, feed the specific user (if you've used esp_task_wdt_add_user)
esp_task_wdt_reset_user(gif_watchdog_handle);
}
yield(); // Allow other tasks to run and avoid blocking
}
// Close the GIF file after playback
gif.close();
tft.endWrite(); // Release TFT chip select
// Unsubscribe from the TWDT for the current task
esp_task_wdt_delete(NULL);
// Unsubscribe the user from the TWDT
esp_task_wdt_delete_user(gif_watchdog_handle);
} else {
Serial.println("Could not open gif");
}
}
void successPAy(const String &message, bool sda) {
tft.fillScreen(TFT_WHITE);
int textYPosition = 220 + 30; // Position the text 10 pixels below the GIF
tft.setFreeFont(&FreeSansBold9pt7b);
tft.setTextColor(TFT_BLACK); // Set text color to black
tft.setTextSize(1); // Set text size (you can adjust the size)
// You can set any message you'd like to display here
tft.setCursor((DISPLAY_WIDTH - tft.textWidth("Payment Successful")) / 2, textYPosition);
tft.println(message); // Print the text
if (sda) {
playAudioFile("/audio/SUCCESSFUL.mp3");
} else {
playAudioFile("/audio/FAILED.mp3");
}
gifdisp(sda);
state = PAYMENT_SUCCESS;
qrDisplayStartMillis = millis();
}
void *pngOpen(const char *filename, int32_t *size) {
Serial.printf("Attempting to open %s\n", filename);
pngfile = FileSys.open(filename, "r");
*size = pngfile.size();
return &pngfile;
}
void pngClose(void *handle) {
File pngfile = *((File *)handle);
if (pngfile) pngfile.close();
}
int32_t pngRead(PNGFILE *page, uint8_t *buffer, int32_t length) {
if (!pngfile) return 0;
page = page; // Avoid warning
return pngfile.read(buffer, length);
}
int32_t pngSeek(PNGFILE *page, int32_t position) {
if (!pngfile) return 0;
page = page; // Avoid warning
return pngfile.seek(position);
}
bool dmaBuf = 0;
// Draw a line of image directly on the LCD
void GIFDraw(GIFDRAW *pDraw) {
#ifdef USE_DMA
uint16_t usTemp[2][BUFFER_SIZE]; // Global to support DMA use
#else
uint16_t usTemp[1][BUFFER_SIZE]; // Global to support DMA use
#endif
uint8_t *s;
uint16_t *d, *usPalette;
int x, y, iWidth, iCount;
// Calculate the shift to center the GIF on the screen
int gifWidth = pDraw->iWidth; // GIF width
int gifHeight = pDraw->iHeight; // GIF height
// Calculate the horizontal and vertical offset to center the GIF
int shiftX = (DISPLAY_WIDTH - gifWidth) / 2; // Center horizontally
int shiftY = (DISPLAY_HEIGHT - gifHeight) / 2; // Center vertically
// Display bounds check and cropping
iWidth = pDraw->iWidth;
if (iWidth + pDraw->iX + shiftX > DISPLAY_WIDTH)
iWidth = DISPLAY_WIDTH - (pDraw->iX + shiftX); // Adjust width if it goes beyond the screen
usPalette = pDraw->pPalette;
y = pDraw->iY + pDraw->y + shiftY; // Apply vertical shift to the y-coordinate
if (y >= DISPLAY_HEIGHT || pDraw->iX + shiftX >= DISPLAY_WIDTH || iWidth < 1)
return;
// Old image disposal (restore background color)
s = pDraw->pPixels;
if (pDraw->ucDisposalMethod == 2) { // restore to background color
for (x = 0; x < iWidth; x++) {
if (s[x] == pDraw->ucTransparent)
s[x] = pDraw->ucBackground;
}
pDraw->ucHasTransparency = 0;
}
// Apply the new pixels to the main image
if (pDraw->ucHasTransparency) { // if transparency is used
uint8_t *pEnd, c, ucTransparent = pDraw->ucTransparent;
pEnd = s + iWidth;
x = 0;
iCount = 0; // count non-transparent pixels
while (x < iWidth) {
c = ucTransparent - 1;
d = &usTemp[0][0];
while (c != ucTransparent && s < pEnd && iCount < BUFFER_SIZE) {
c = *s++;
if (c == ucTransparent) { // done, stop
s--; // back up to treat it like transparent
} else { // opaque
*d++ = usPalette[c];
iCount++;
}
}
if (iCount) { // any opaque pixels?
// Adjust the horizontal position based on shiftX
tft.setAddrWindow(pDraw->iX + x + shiftX, y, iCount, 1);
tft.pushPixels(usTemp, iCount);
x += iCount;
iCount = 0;
}
// Skip transparent pixels
c = ucTransparent;
while (c == ucTransparent && s < pEnd) {
c = *s++;
if (c == ucTransparent)
x++;
else
s--;
}
}
} else { // No transparency
s = pDraw->pPixels;
// Translate the 8-bit pixels through the RGB565 palette
if (iWidth <= BUFFER_SIZE)
for (iCount = 0; iCount < iWidth; iCount++) usTemp[dmaBuf][iCount] = usPalette[*s++];
else
for (iCount = 0; iCount < BUFFER_SIZE; iCount++) usTemp[dmaBuf][iCount] = usPalette[*s++];
// Push the pixels to the screen
#ifdef USE_DMA
tft.dmaWait();
tft.setAddrWindow(pDraw->iX + shiftX, y, iWidth, 1); // Adjust position with shiftX
tft.pushPixelsDMA(&usTemp[dmaBuf][0], iCount);
dmaBuf = !dmaBuf;
#else
tft.setAddrWindow(pDraw->iX + shiftX, y, iWidth, 1); // Adjust position with shiftX
tft.pushPixels(&usTemp[0][0], iCount);
#endif
iWidth -= iCount;
while (iWidth > 0) {
if (iWidth <= BUFFER_SIZE)
for (iCount = 0; iCount < iWidth; iCount++) usTemp[dmaBuf][iCount] = usPalette[*s++];
else
for (iCount = 0; iCount < BUFFER_SIZE; iCount++) usTemp[dmaBuf][iCount] = usPalette[*s++];
#ifdef USE_DMA
tft.dmaWait();
tft.pushPixelsDMA(&usTemp[dmaBuf][0], iCount);
dmaBuf = !dmaBuf;
#else
tft.pushPixels(&usTemp[0][0], iCount);
#endif
iWidth -= iCount;
}
}
}
// void *GIFOpenFile(const char *fname, int32_t *pSize) {
// f = FileSys.open(fname, "r");
// if (f) {
// *pSize = f.size();
// return (void *)&f;
// }
// return NULL;
// } /* GIFOpenFile() */
// void GIFCloseFile(void *pHandle) {
// File *f = static_cast<File *>(pHandle);
// if (f != NULL)
// f->close();
// } /* GIFCloseFile() */
// int32_t GIFReadFile(GIFFILE *pFile, uint8_t *pBuf, int32_t iLen) {
// int32_t iBytesRead;
// iBytesRead = iLen;
// File *f = static_cast<File *>(pFile->fHandle);
// // Note: If you read a file all the way to the last byte, seek() stops working
// if ((pFile->iSize - pFile->iPos) < iLen)
// iBytesRead = pFile->iSize - pFile->iPos - 1; // <-- ugly work-around
// if (iBytesRead <= 0)
// return 0;
// iBytesRead = (int32_t)f->read(pBuf, iBytesRead);
// pFile->iPos = f->position();
// return iBytesRead;
// } /* GIFReadFile() */
// int32_t GIFSeekFile(GIFFILE *pFile, int32_t iPosition) {
// int i = micros();
// File *f = static_cast<File *>(pFile->fHandle);
// f->seek(iPosition);
// pFile->iPos = (int32_t)f->position();
// i = micros() - i;
// // Serial.printf("Seek time = %d us\n", i);
// return pFile->iPos;
// } /* GIFSeekFile() */
config.cpp
#include "header.h"
void setup_codes() {
if (!WiFi.config(local_ip, gateway, subnet,dns, dns_secondary)) {
Serial.println("STA Failed to configure");
}
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("Connected to WiFi");
Serial.print("IP :");
Serial.println(WiFi.localIP());
timeClient.begin();
timeClient.update();
targetTime = millis() + 1000;
softwareSerial.begin(9600);
if (player.begin(softwareSerial)) {
Serial.println("DFPlayer Mini is ready.");
player.volume(30); // Set volume (0-30)
} else {
Serial.println("Connecting to DFPlayer Mini failed!");
}
ws.onEvent(onEvent);
server.addHandler(&ws);
server.begin();
LittleFS.begin();
tft.begin();
tft.setRotation(0); // Set the rotation to 0 (portrait mode)
tft.fillScreen(TFT_BLACK);
tft.setFreeFont(&FreeSansBold9pt7b);
tft.setTextColor(TFT_BLACK);
background();
logodraw(170, 245);
textDisp(20, 290, 1);
gif.begin(BIG_ENDIAN_PIXELS);
}
music.cpp
#include "header.h"
void storeNumberAudio(float number) {
long int integerPart = (long int)number; // Extract integer part
float dec = (number - integerPart) * 100; // Get the first two digits of the decimal part (up to two decimal places)
int decimalPart = round(dec);
// Store the integer part
storeIntegerPart(integerPart);
// Store the decimal point and the decimal digits
storeDecimalPart(decimalPart);
// audio = true;
}
// Function to store the integer part in the playQueue array
void storeIntegerPart(long int number) {
if (number <= 0) return; // Nothing to store for zero or negative numbers
// Handle numbers <= 100 (treating them as a single case)
if (number <= 100) {
playQueue[queueSize++] = number + 1; // Add the number directly (1 to 100)
} else if (number <= 1000) {
storeHundreds(number);
} else if (number <= 10000) {
storeThousands(number);
} else if (number < 100000) {
storeTenThousands(number);
} else {
storeLargeNumbers(number);
}
}
// Function to store numbers in the hundreds range
void storeHundreds(long int number) {
int num = number / 100;
playQueue[queueSize++] = num + 100; // Store the hundreds place
number -= num * 100; // Subtract the hundreds part
// Now store the remainder (tens and ones)
storeIntegerPart(number);
}
// Function to store numbers in the thousands range
void storeThousands(long int number) {
int num = number / 1000;
playQueue[queueSize++] = num + 109; // Store the thousands place
number -= num * 1000;
// Now store the remainder (hundreds, tens, and ones)
storeIntegerPart(number);
}
// Function to store numbers in the ten-thousands range
void storeTenThousands(long int number) {
int num = number / 1000;
playQueue[queueSize++] = num + 1; // Store the ten-thousands place
playQueue[queueSize++] = 121; // Store the word "thousand" or similar
number -= num * 1000;
// Now store the remainder (hundreds, tens, and ones)
storeIntegerPart(number);
}
// Function to handle very large numbers (greater than 100000)
void storeLargeNumbers(long int number) {
int num = number / 100000;
playQueue[queueSize++] = num + 1; // Store the hundreds of thousands place
playQueue[queueSize++] = 120; // Store the word "hundred thousand" or similar
number -= num * 100000;
// Now store the remainder (thousands, hundreds, etc.)
storeIntegerPart(number);
}
// Function to store the decimal part in the playQueue array
void storeDecimalPart(int decimalPart) {
// Store the decimal point
playQueue[queueSize++] = 122; // Assuming '122' corresponds to the "point" sound
// Store the first and second digits of the decimal part
if (decimalPart >= 0) {
int firstDigit = decimalPart / 10; // Get the first digit
int secondDigit = decimalPart % 10; // Get the second digit
playQueue[queueSize++] = firstDigit + 1; // Store the first digit
playQueue[queueSize++] = secondDigit + 1; // Store the second digit
}
playQueue[queueSize++] = 123;
}
// Function to play the audio queue with non-blocking timing
void playAudioQueue() {
if (queueSize > 0 && (millis() - lastPlayTime >= playInterval)) {
player.play(playQueue[0]); // Play the first item in the queue
lastPlayTime = millis(); // Update the last play time
// Shift the queue
for (int i = 1; i < queueSize; i++) {
playQueue[i - 1] = playQueue[i]; // Shift each element left
}
queueSize--; // Decrease the queue size
}
}
logo.h
#define ASSET_1_HEIGHT 34
#define ASSET_1_WIDTH 60
// array size is 4080
const uint16_t logo[] PROGMEM = {
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4809, 0x480b, 0x4809, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x4008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x480a, 0x500a, 0x500b, 0x500a, 0x500b, 0x500a, 0x500b, 0x500a, 0x500b, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x480b, 0x500a, 0x500a, 0x500a, 0x480b, 0x4008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x4008, 0x500a, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x3006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x500a, 0x500a, 0x500b, 0x500b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x4008, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500b, 0x500a, 0x400a, 0x500b, 0x500a, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x500a, 0x500b, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x480a, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x500a, 0x500b, 0x500b, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b, 0x500a, 0x4008, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x500b, 0x500b, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500b, 0x500b, 0x500a, 0x500a, 0x500b, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x480b, 0x500a, 0x500a, 0x500a, 0x480b, 0x0000, 0x4809, 0x0000,
0x0000, 0x500b, 0x500b, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b, 0x500a, 0x0000, 0x500a, 0x500b, 0x500a, 0x500b, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x500b, 0x3006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500b, 0x500a, 0x500b, 0x500a, 0x500a, 0x500a, 0x500b, 0x500a, 0x0000,
0x0000, 0x500a, 0x500b, 0x500b, 0x500b, 0x4809, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b, 0x500a, 0x0000, 0x400a, 0x500a, 0x500b, 0x0000, 0x0000, 0x0000, 0x8010, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500a, 0x480a, 0x3006, 0x500a, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x4809, 0x500a, 0x500b, 0x480a, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x0000,
0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x4809, 0x400a, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b, 0x500a, 0x0000, 0x4008, 0x500a, 0x500b, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x0000, 0x480b, 0x500b, 0x500a, 0x4008, 0x0000, 0x0000, 0x0000, 0x480a, 0x500a, 0x280a,
0x0000, 0x0000, 0x480a, 0x500a, 0x500b, 0x500b, 0x500a, 0x500b, 0x500b, 0x500a, 0x500b, 0x8010, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b, 0x3006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x500b, 0x500b, 0x500b, 0x500a, 0x4008, 0x500b, 0x500a, 0x4809, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500a, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000,
0x0000, 0x500b, 0x500a, 0x500b, 0x0000, 0x500a, 0x480a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x4008, 0x500b, 0x500b, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b, 0x000a, 0x0000, 0x0000, 0x0000, 0x500b, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x0000, 0x0000, 0x400a, 0x500b, 0x500b, 0x0000, 0x500a, 0x500a, 0x500b, 0x500b, 0x500b, 0x500a, 0x500b, 0x500a, 0x400b,
0x4809, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4809, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x500a, 0x480b, 0x500b, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500b, 0x500b, 0x500b, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x500a, 0x500a,
0x500a, 0x500b, 0x500b, 0x500b, 0x500a, 0x580b, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4809, 0x500b, 0x500a, 0x480b, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x500b, 0x500b, 0x500a, 0x500a, 0x500b, 0x4809, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b,
0x4809, 0x500a, 0x500b, 0x500b, 0x500b, 0x500b, 0x500b, 0x500a, 0x500b, 0x500b, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x500a, 0x500b, 0x3006, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x500a, 0x500b, 0x500b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x480a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x480a, 0x500a, 0x500a,
0x0000, 0x500a, 0x500a, 0x500b, 0x500b, 0x500b, 0x500b, 0x500b, 0x500b, 0x500b, 0x500b, 0x500b, 0x500b, 0x500b, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x500b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4809, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a,
0x0000, 0x500a, 0x500b, 0x480a, 0x500b, 0x500a, 0x500b, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x500b, 0x500b, 0x500a, 0x500a, 0x3006, 0x3006, 0x3006, 0x0000, 0x380a, 0x500a, 0x500b, 0x500b, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x500b, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x0000,
0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4008, 0x4809, 0x500a, 0x500b, 0x500b, 0x500a, 0x3006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x4008, 0x4008, 0x4809, 0x0000, 0x500a, 0x500b, 0x500b, 0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x500b, 0x0000, 0x0000, 0x500b, 0x500a, 0x500a, 0x480a, 0x500a, 0x500a, 0x480b, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x4008, 0x0000, 0x0000,
0x500a, 0x500b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x3006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b, 0x500a, 0x500b, 0x500b, 0x500a, 0x4809, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x480a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x480b, 0x500b, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x500a, 0x500a, 0x500b, 0x500a, 0x500a, 0x4008, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x500a, 0x500a, 0x500a, 0x500a, 0x500b, 0x500b, 0x500a, 0x500b, 0x500a, 0x500a, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500a, 0x580b, 0x500a, 0x500a, 0x500a, 0x3006, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500a, 0x4809, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x500a, 0x500b, 0x500b, 0x500b, 0x500a, 0x500a, 0x500a, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4008, 0x4809, 0x4809, 0x4809, 0x4809, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
};
#define ICON_HEIGHT 60
#define ICON_WIDTH 60
// array size is 7200
const uint16_t icon[] PROGMEM = {
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xef7d, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xe71c, 0xf7be, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x5aeb, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x31a6, 0x39c7, 0xef7d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xa514, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18e3, 0xad75, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xe73c, 0x4a69, 0x39e7, 0x39e7, 0x39e7, 0x2965, 0x18e3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x39c7, 0x39e7, 0x39e7, 0x39e7, 0x632c, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xf7be, 0xc618, 0x630c, 0x2104, 0x18c3, 0x18c3, 0x18c3, 0x8c71, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xf7be, 0xad55, 0x18e3, 0x18c3, 0x18c3, 0x2104, 0xe73c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xdefb, 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, 0xce79, 0xce59, 0x31a6, 0x18c3, 0x18c3, 0x18c3, 0x9492, 0xce79, 0xce79, 0xce79, 0xce79, 0xf79e, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0x4208, 0x2124, 0x2124, 0x2124, 0x2124, 0x2124, 0x2124, 0x2124, 0x18e3, 0x18c3, 0x18c3, 0x18c3, 0x2104, 0x2124, 0x2124, 0x2124, 0x39c7, 0xf79e, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0x7bcf, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x18c3, 0x2104, 0xd69a, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xef5d, 0x7bcf, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x73ae, 0x5aeb, 0x18c3, 0x18c3, 0x18c3, 0x4a49, 0x73ae, 0x73ae, 0x9492, 0xffdf, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xad55, 0x18c3, 0x18c3, 0x18c3, 0xb596, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0x52aa, 0x18c3, 0x18c3, 0x2124, 0xef7d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xce59, 0x2104, 0x18c3, 0x18c3, 0x9492, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xad55, 0x2965, 0x18c3, 0x18c3, 0x31a6, 0xef7d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xf79e, 0xce79, 0xd69a, 0xce79, 0xc638, 0xa514, 0x528a, 0x18c3, 0x18c3, 0x18c3, 0x4a49, 0xef5d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xce79, 0x2124, 0x2124, 0x2124, 0x18e3, 0x18c3, 0x18c3, 0x18c3, 0x18e3, 0x8c51, 0xe73c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xce79, 0x18c3, 0x18c3, 0x18c3, 0x18e3, 0x39e7, 0x4a49, 0x8430, 0xdefb, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xe71c, 0x2104, 0x18c3, 0x18c3, 0x2104, 0xc618, 0xf7be, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x8410, 0x18c3, 0x18c3, 0x18c3, 0x4208, 0xef7d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xf79e, 0x4a69, 0x18c3, 0x18c3, 0x18c3, 0x73ae, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xd6ba, 0x2945, 0x18c3, 0x18c3, 0x18c3, 0xb596, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0xad75, 0x18c3, 0x18c3, 0x18c3, 0x3186, 0xef5d, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x6b4d, 0x18c3, 0x18c3, 0x18c3, 0x4a49, 0xf7be, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xe73c, 0x39c7, 0x18c3, 0x18c3, 0x18e3, 0x94b2, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xce79, 0x2124, 0x18c3, 0x18c3, 0x18c3, 0xc618, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0x94b2, 0x18c3, 0x18c3, 0x18c3, 0x39e7, 0xf7be, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0x5aeb, 0x18c3, 0x18c3, 0x18c3, 0x5acb, 0xf7be, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xdefb, 0x2945, 0x18c3, 0x18c3, 0x18c3, 0xad55, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xc618, 0x2104, 0x18c3, 0x18c3, 0x2104, 0xce79, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0x73ae, 0x18c3, 0x18c3, 0x18c3, 0x4a49, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffdf, 0x5acb, 0x31a6, 0x31a6, 0x31a6, 0x94b2, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xef7d, 0xe71c, 0xe71c, 0xe71c, 0xe73c, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff
};
tft.cpp
#include "header.h"
void logodraw(int logoX, int logoY) {
int logoSize = ASSET_1_WIDTH;
int logoHeight = ASSET_1_HEIGHT; // Example logo size
// Draw the logo over the QR code
for (int y = 0; y < logoHeight; y++) {
for (int x = 0; x < logoSize; x++) {
uint16_t color = logo[y * logoSize + x];
if (color != 0x0000) {
// color = 0xFFFF; // Change black to white
tft.drawPixel(logoX + x, logoY + y, color);
}
// Draw the logo pixel at the desired (logoX, logoY) position
// Adjust position by logoX and logoY
}
}
}
void textDisp(int x, int y, int font) {
tft.setTextSize(font);
tft.setTextColor(TFT_WHITE);
tft.drawString("QR Scanner", x, y);
tft.setTextColor(TFT_BLACK);
tft.setTextSize(1);
}
void tft_time_loop() {
if (targetTime < millis()) {
// Set next update for 1 second later
targetTime = millis() + 1000;
// Update NTP time once per second
timeClient.update();
// Get hours, minutes, and seconds from NTP
int hh = timeClient.getHours();
int mm = timeClient.getMinutes();
int ss = timeClient.getSeconds();
// Convert 24-hour format to 12-hour format
int displayHour = hh;
if (displayHour >= 12) {
isPM = true;
if (displayHour > 12) {
displayHour -= 12; // Convert to 12-hour format
}
} else {
isPM = false;
if (displayHour == 0) {
displayHour = 12; // Midnight case (12 AM)
}
}
int xpos = 0;
int ypos = 10; // Top left corner of clock text, about halfway down
if (omm != mm) { // Redraw hours and minutes time every minute
omm = mm;
// tft.fillScreen(TFT_BLACK); // Clear the screen before redrawing time
background();
logodraw(170, 245);
textDisp(20, 290, 1);
// Draw hours and minutes
xpos = 10;
if (displayHour < 10) xpos += tft.drawChar('0', xpos, ypos, 7);
xpos += tft.drawNumber(displayHour, xpos, ypos, 7); // Draw hours
xcolon = xpos; // Save colon coordinate for later to flash on/off later
xpos += tft.drawChar(':', xpos, ypos, 7); // Draw colon
if (mm < 10) xpos += tft.drawChar('0', xpos, ypos, 7); // Add leading zero for minutes
xpos += tft.drawNumber(mm, xpos, ypos, 7); // Draw minutes
// Draw AM/PM
if (isPM) {
tft.setTextSize(2);
xpos += tft.drawString("pm", xpos + 5, ypos + 10);
} else {
tft.setTextSize(2);
xpos += tft.drawString("am", xpos + 5, ypos + 10);
}
tft.setTextSize(1);
}
}
}
qr.cpp
#include "header.h"
void dispQR(const String &name, int mrnumber, const String &url) {
tft.fillScreen(TFT_WHITE); // Set the screen to white
String mrnumberStr = String(mrnumber);
tft.setFreeFont(&FreeSansBold9pt7b);
tft.setTextSize(1); // Set the text size for the label
tft.setTextColor(TFT_BLACK); // Set the text color to black
int nameWidth = tft.textWidth(name); // Width of the name text
int numberWidth = tft.textWidth(mrnumberStr.c_str()); // Width of the mrnumber text
// int pricewidth = tft.textWidth(price, 2);
// Calculate the starting position dynamically
int nameX = (DISPLAY_WIDTH - nameWidth) / 2; // Center the name horizontally
int numberX = (DISPLAY_WIDTH - numberWidth) / 2; // Center the number horizontally
// int priceX = (tft.width() - pricewidth) / 2;
// Set the Y position as desired
int nameY = 10;
int numberY = 40;
// Print the name and mrnumber at the dynamically calculated positions
tft.drawString(name, nameX, nameY);
tft.drawNumber(mrnumber, numberX, numberY, 1);
// Start timing QR code generation
unsigned long startTime = millis();
// Create the QR code
QRCode qrcode;
uint8_t qrcodeData[qrcode_getBufferSize(15)];
qrcode_initText(&qrcode, qrcodeData, 15, 1, url.c_str());
// Calculate QR code size
int qrSize = qrcode.size;
int scale = 2; // Size of each module (QR block)
// Calculate offset (position the QR code to the center of the screen)
int xOffset = (240 - (qrSize * scale)) / 2;
int yOffset = (320 - (qrSize * scale)) / 2; // Adjust the Y offset to leave space for the label
// Display the QR code on the TFT screen
for (uint8_t y = 0; y < qrSize; y++) {
for (uint8_t x = 0; x < qrSize; x++) {
// Get module value: black (filled) or white (empty)
if (qrcode_getModule(&qrcode, x, y)) {
tft.fillRect(xOffset + x * scale, yOffset + y * scale, scale, scale, TFT_BLACK); // Draw black block
} else {
tft.fillRect(xOffset + x * scale, yOffset + y * scale, scale, scale, TFT_WHITE); // Draw white block
}
}
}
// Add a border around the QR code
uint16_t borderColor = TFT_BLACK; // You can change this to any color you want for the border
int borderWidth = 5; // Border thickness
// Draw the border
tft.drawRect(xOffset - borderWidth, yOffset - borderWidth, (qrSize * scale) + (2 * borderWidth), (qrSize * scale) + (2 * borderWidth), borderColor);
// Add the logo in the center of the QR code
int logoSize = ASSET_1_WIDTH;
int logoHeight = ASSET_1_HEIGHT; // Example logo size
int logoX = xOffset + (qrSize * scale - logoSize) / 2; // Center the logo
int logoY = yOffset + (qrSize * scale - logoHeight) / 2;
// Draw the logo over the QR code
for (int y = 0; y < logoHeight; y++) {
for (int x = 0; x < logoSize; x++) {
uint16_t color = logo[y * logoSize + x];
if (color == 0x0000) {
color = 0xFFFF; // Change black to white
}
tft.drawPixel(logoX + x, logoY + y, color); // Draw the modified pixel
}
}
// Add the price text
tft.setTextSize(2);
tft.drawString("Rs:" + extractAmountFromUPI(url), 30, 270);
tft.setTextSize(1);
// End timing and calculate duration
unsigned long endTime = millis();
unsigned long duration = endTime - startTime; // Time taken to generate QR code
// Print the time taken to serial monitor
Serial.print("QR Code Generation Time: ");
Serial.print(duration);
Serial.println(" ms");
storeNumberAudio(extractAmountFromUPI(url).toFloat());
state = QR;
}
void drawScaledImage(int startX, int startY) {
int targetWidth = 32; // Target size for the image
int targetHeight = 32;
int scaleX = 60 / targetWidth; // Scaling factor in X direction
int scaleY = 60 / targetHeight; // Scaling factor in Y direction
// Draw the 24x24 scaled image
for (int y = 0; y < targetHeight; y++) {
for (int x = 0; x < targetWidth; x++) {
// Calculate the corresponding pixel in the original 60x60 image
int originalX = x * scaleX;
int originalY = y * scaleY;
// Calculate the 1D index for the pixel in the original array
int index = originalY * 60 + originalX;
// Get the pixel color from the original image
uint16_t color = icon[index];
if (color != 0xFFFF) { // If it's not white, draw the pixel
tft.drawPixel(startX + x, startY + y, 0x0000);
}
}
}
}
websocket.cpp
#include "header.h"
void onEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len) {
switch (type) {
case WS_EVT_CONNECT:
Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
client->text("Welcome");
break;
case WS_EVT_DISCONNECT:
Serial.printf("WebSocket client #%u disconnected\n", client->id());
break;
case WS_EVT_DATA:
websockethandle(client, arg, data, len);
break;
case WS_EVT_PONG:
Serial.printf("WebSocket client #%u ponged\n", client->id());
break;
case WS_EVT_ERROR:
Serial.printf("WebSocket client #%u error(%u): %s\n", client->id(), *((uint16_t *)arg), (char *)data);
break;
}
}
void websockethandle(AsyncWebSocketClient *client, void *arg, uint8_t *data, size_t len) {
AwsFrameInfo *info = (AwsFrameInfo *)arg;
if (info->final && info->index == 0 && info->len == len) {
// Null-terminate the received data
data[len] = 0; // Null-terminate the C-string
// Use const char* for the message
const char *message = (const char *)data;
// Print the received message for debugging
// Web .print("Received: ");
Serial.println(message);
client->text("Message Received");
// if (message[0] == '{' && message[len - 1] == '}') {
handlejson(message);
// Serial.print("Received: Json data ");
// }
}
}
void handlejson(const char *json) {
DynamicJsonDocument doc(1024);
DeserializationError error = deserializeJson(doc, json);
if (error) {
Serial.print("Failed to parse JSON: ");
Serial.println(error.f_str());
return;
}
// Check the status of the JSON and handle accordingly
int status = doc["status"]; // Get the status field
// Handle the first JSON (File 1) - expects "status", "url", "name", "mrnumber"
if (status == 300) {
const char *url = doc["url"];
const char *name = doc["name"];
int mrnumber = doc["mrnumber"];
/*
Serial.print("Status: ");
Serial.println(status);
Serial.print("URL: ");
Serial.println(url);
Serial.print("Name: ");
Serial.println(name);
Serial.print("MR Number: ");
Serial.println(mrnumber);
*/
dispQR(name, mrnumber, url);
}
// Handle the second JSON (File 2) - expects "status" and "message"
else if (status == 200) {
const char *message = doc["message"];
// Serial.print("Status: ");
// Serial.println(status);
// Serial.print("Message: ");
// Serial.println(message);
successPAy(message,true);
} else if (status == 400) {
const char *message = doc["message"];
successPAy(message,false);
} else {
Serial.println("Unknown status");
}
}