26 Commits
2.05 ... 2.07

Author SHA1 Message Date
Jonas Niesner
1aeea88696 Revert release file change 2024-01-09 20:33:51 +01:00
Nic Limper
837c5de1a8 minor fix in content 2024-01-09 17:58:29 +01:00
Jonas Niesner
d4f16f74e9 Update tagotaversions.json 2024-01-09 16:48:03 +01:00
Nic Limper
fdb4a3cbf1 weather forecast template 2.9" M3 and some minor fixes 2024-01-09 16:09:43 +01:00
Jelmer
5b7c96dcc0 Added 3 Hanshow Jigs 2024-01-09 13:25:16 +01:00
Jonas Niesner
c0a2bd01e5 CI cleanup (#195)
* Update release.yml

* Update platformio.ini

* Update build-test.yml
2024-01-09 08:59:06 +01:00
atc1441
bd8965174a Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-01-09 00:10:15 +01:00
atc1441
229962165a Added SubGHz Alpha 2024-01-09 00:10:11 +01:00
jjwbruijn
4dac6ab05c M2 v0026 firmware added 2024-01-08 21:59:51 +01:00
atc1441
f95e957361 Merge branch 'master' of https://github.com/jjwbruijn/OpenEPaperLink 2024-01-08 08:09:50 +01:00
atc1441
b8161f21fa Arduino ino file renaming 2024-01-08 07:40:07 +01:00
Nic Limper
950931b9a6 smaller UI improvements
- got rid of gamma correction during dithering for quality reasons
- smaller UI improvements and textual edits
- tag grouping in the interface is now sticky across sessions
- tag auto update now shows before/after version number
2024-01-08 01:01:06 +01:00
atc1441
af5e917cb3 Arduino port of the ESP32-C6 AP Firmware added (Not PlatformIO) 2024-01-08 00:36:34 +01:00
atc1441
8005ae71fc Create TLSR_HS_35_ALPHA.bin 2024-01-07 20:10:05 +01:00
atc1441
4965c68516 Added Telink TLSR Alpha release 2024-01-07 20:07:59 +01:00
Nic Limper
96e8fe8660 geocoding and other small improvements
- separated content types for 'not configured', 'static image', 'uploaded image' and 'home assistant' (which is all the same internally, but it confused the users to always see 'static image'
- changed channel reported by the AP to the ieee801.15.4 channel instead of the WiFi channel
- added geocoding to the 'location' fields (e.g. weather forecast). Now you can choose an ambiguous location from a dropdown.
- added 'firmware update rejected' wakeup reason
2024-01-07 19:32:56 +01:00
jjwbruijn
fcff10412d added wakeup-reason for failed OTA 2024-01-07 19:23:36 +01:00
Nic Limper
23c3611872 button to restore tagDB file from backup; cleanup 2024-01-07 02:40:55 +01:00
Nic Limper
7cb7eddc22 removed u8g2 library/fonts (+ automatic substitution for compatibilty) 2024-01-07 00:03:51 +01:00
Jonas Niesner
b68cd22eb1 Updated tag OTA (#193) 2024-01-06 21:16:48 +01:00
Nic Limper
b0cfa1b2b4 new week calendar added 2024-01-06 21:09:08 +01:00
Nic Limper
29589bc5b0 content template redesign / textbox / various
- Added Signika-SB.ttf and some small bitmap fonts
- Removed calibrib50/60/80/100/120/150 bitmap fonts, as they can be better rendered using truetype. Fallback is in place to auto translate to Signika-SB.ttf with the right size in case it is still used in a json template
- Renamed confusing tag type names to 'M2 + size' and 'M3 + size'. Because the universal firmware, there is no need to tell every subtile type change apart anymore.
- added `textbox` to json templates (https://github.com/jjwbruijn/OpenEPaperLink/wiki/Json-template#paragraph-text)
- redesign of count days/hours
- redesign of RSS feed
- designed Buienradar for more tag sizes
- on a scheduled or user initiated reboot, 'REBOOTING' is sent to the error channel of the websockets just before the connection is dropped
- phased out "hwtype": [] in content_cards.json (new location is in the tagtype json, which contains a list of valid content types)

In case of problems using this commit: keep in mind the heavy caching of the tagtypes in the browser. You might still unknowingly use the old contents.
2024-01-05 13:59:31 +01:00
Nic Limper
00ce785158 use latest version 6 of ArduinoJson, not 7 for now. 2024-01-04 20:07:15 +01:00
Pablo Gonzalez
9da9ac9395 Make WebSocket connection protocol dependent (#191)
Currently, the connection to WebSockets is hardcoded to the protocol "ws://".

If the server is put behind a proxy server (like Nginx) to support "https", the connection to websockets will fail (at least in Firefox) due to insecure protocol.

This change checks the current protocol and connects to "wss" if loaded via "https", which makes it work when loaded via proxy.
2024-01-04 19:18:14 +01:00
Jonas Niesner
022f72eee7 Add simple tag ota (#190)
and renamed files
2024-01-04 17:30:42 +01:00
Nic Limper
1d03eedfd6 bugfix in WiFi connection setup; + reset wifi settings using gpio0
- in rare cases, an AP didn't connect to a WiFi network due to some tight timing
- bringing GPIO0 to LOW for more than 5 seconds now resets the wifi settings, in case you're stuck with e.g. a wrong static ip configuration
2024-01-03 15:34:09 +01:00
1143 changed files with 334269 additions and 1386 deletions

View File

@@ -40,50 +40,14 @@ jobs:
pio run --environment OpenEPaperLink_Mini_AP
pio run --target buildfs --environment OpenEPaperLink_Mini_AP
# - name: Build OpenEPaperLink_Nano_AP
# run: |
# cd ESP32_AP-Flasher
# pio run --environment OpenEPaperLink_Nano_AP
# pio run --target buildfs --environment OpenEPaperLink_Nano_AP
- name: Build OpenEPaperLink_AP_and_Flasher
run: |
cd ESP32_AP-Flasher
pio run --environment OpenEPaperLink_AP_and_Flasher
pio run --target buildfs --environment OpenEPaperLink_AP_and_Flasher
# - name: Build Wemos_d1_mini32_AP
# run: |
# cd ESP32_AP-Flasher
# pio run --environment Wemos_d1_mini32_AP
# pio run --target buildfs --environment Wemos_d1_mini32_AP
# - name: Build M5Stack_Core_ONE_AP
# run: |
# cd ESP32_AP-Flasher
# pio run --environment M5Stack_Core_ONE_AP
# pio run --target buildfs --environment M5Stack_Core_ONE_AP
- name: Build ESP32_S3_16_8_YELLOW_AP]
run: |
cd ESP32_AP-Flasher
pio run --environment ESP32_S3_16_8_YELLOW_AP
pio run --target buildfs --environment ESP32_S3_16_8_YELLOW_AP
# - name: Build Sonoff_zb_bridge_P_AP
# run: |
# cd ESP32_AP-Flasher
# pio run --environment Sonoff_zb_bridge_P_AP
# pio run --target buildfs --environment Sonoff_zb_bridge_P_AP
# - name: Build OpenEPaperLink_CC1352P
# run: |
# cd ESP32_AP-Flasher
# pio run --environment OpenEPaperLink_CC1352P
# pio run --target buildfs --environment OpenEPaperLink_CC1352P
# - name: OutdoorAP
# run: |
# cd ESP32_AP-Flasher
# pio run --environment OutdoorAP
# pio run --target buildfs --environment OutdoorAP

View File

@@ -21,11 +21,6 @@ jobs:
with:
python-version: '3.9'
# - name: Zip web files
# run: |
# cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_AP-Flasher
# python gzip_wwwfiles.py
# - name: Commit zipped files
# run: |
# git config --global user.name 'Bot'
@@ -39,19 +34,6 @@ jobs:
- name: Install intelhex
run: pip install --upgrade intelhex
# - name: Build NRF firmware
# run: |
# cd ARM_Tag_FW/Newton_M3_nRF52811
# pio run --environment Newton_M3_22_BWR
# pio run --environment Newton_M3_29_BWR
# pio run --environment Newton_M3_75_BWR
# cp Newton_M3_22_BWR-ota.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/binaries/Newton_M3_22_BWR-ota.bin
# cp Newton_M3_22_BWR-full-flash.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/binaries/Newton_M3_22_BWR-full-flash.bin
# cp Newton_M3_29_BWR-ota.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/binaries/Newton_M3_29_BWR-ota.bin
# cp Newton_M3_29_BWR-full-flash.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/binaries/Newton_M3_29_BWR-full-flash.bin
# cp Newton_M3_75_BWR-ota.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/binaries/Newton_M3_75_BWR-ota.bin
# cp Newton_M3_75_BWR-full-flash.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/binaries/Newton_M3_75_BWR-full-flash.bin
- name: Install esptool
run: pip install esptool
@@ -59,6 +41,11 @@ jobs:
run: |
mkdir espbinaries
- name: Zip web files
run: |
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_AP-Flasher
python gzip_wwwfiles.py
- name: Build firmware for Simple_AP
run: |
cd ESP32_AP-Flasher
@@ -77,42 +64,6 @@ jobs:
cp Simple_AP/firmware.bin espbinaries/Simple_AP.bin
cp Simple_AP/merged-firmware.bin espbinaries/Simple_AP_full.bin
- name: Build firmware for Wemos_d1_mini32_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment Wemos_d1_mini32_AP
pio run --target buildfs --environment Wemos_d1_mini32_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/boot_app0.bin
cp .pio/build/Wemos_d1_mini32_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/firmware.bin
cp .pio/build/Wemos_d1_mini32_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/bootloader.bin
cp .pio/build/Wemos_d1_mini32_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/partitions.bin
cp .pio/build/Wemos_d1_mini32_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/Wemos_d1_mini32_AP
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x290000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp Wemos_d1_mini32_AP/firmware.bin espbinaries/Wemos_d1_mini32_AP.bin
cp Wemos_d1_mini32_AP/merged-firmware.bin espbinaries/Wemos_d1_mini32_AP_full.bin
- name: Build firmware for M5Stack_Core_ONE_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment M5Stack_Core_ONE_AP
pio run --target buildfs --environment M5Stack_Core_ONE_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/boot_app0.bin
cp .pio/build/M5Stack_Core_ONE_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/firmware.bin
cp .pio/build/M5Stack_Core_ONE_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/bootloader.bin
cp .pio/build/M5Stack_Core_ONE_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/partitions.bin
cp .pio/build/M5Stack_Core_ONE_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/M5Stack_Core_ONE_AP
esptool.py --chip esp32 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x2B0000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp M5Stack_Core_ONE_AP/firmware.bin espbinaries/M5Stack_Core_ONE_AP.bin
cp M5Stack_Core_ONE_AP/merged-firmware.bin espbinaries/M5Stack_Core_ONE_AP_full.bin
- name: Build firmware for OpenEPaperLink_Mini_AP
run: |
cd ESP32_AP-Flasher
@@ -149,6 +100,10 @@ jobs:
cp OpenEPaperLink_Nano_AP/firmware.bin espbinaries/OpenEPaperLink_Nano_AP.bin
cp OpenEPaperLink_Nano_AP/merged-firmware.bin espbinaries/OpenEPaperLink_Nano_AP_full.bin
# - name: move files for big APs
# run: |
# cp -a binaries/ESP32-C6/. ESP32_AP-Flasher/data/
- name: Build firmware for OpenEPaperLink_AP_and_Flasher
run: |
cd ESP32_AP-Flasher
@@ -185,6 +140,24 @@ jobs:
cp ESP32_S3_16_8_YELLOW_AP/firmware.bin espbinaries/ESP32_S3_16_8_YELLOW_AP.bin
cp ESP32_S3_16_8_YELLOW_AP/merged-firmware.bin espbinaries/ESP32_S3_16_8_YELLOW_AP_full.bin
- name: Build firmware for ESP32_S3_C6_NANO_AP
run: |
cd ESP32_AP-Flasher
export PLATFORMIO_BUILD_FLAGS="-D BUILD_VERSION=${{ github.ref_name }} -D SHA=$GITHUB_SHA"
pio run --environment ESP32_S3_C6_NANO_AP
pio run --target buildfs --environment ESP32_S3_C6_NANO_AP
mkdir /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP
cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/boot_app0.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/firmware.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/firmware.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/bootloader.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/bootloader.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/partitions.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/partitions.bin
cp .pio/build/ESP32_S3_C6_NANO_AP/littlefs.bin /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP/littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink/ESP32_S3_C6_NANO_AP
esptool.py --chip esp32-s3 merge_bin -o merged-firmware.bin --flash_mode dio --flash_freq 80m --flash_size 16MB 0x0000 bootloader.bin 0x8000 partitions.bin 0xe000 boot_app0.bin 0x10000 firmware.bin 0x00910000 littlefs.bin
cd /home/runner/work/OpenEPaperLink/OpenEPaperLink
cp ESP32_S3_C6_NANO_AP/firmware.bin espbinaries/ESP32_S3_C6_NANO_AP.bin
cp ESP32_S3_C6_NANO_AP/merged-firmware.bin espbinaries/ESP32_S3_C6_NANO_AP_full.bin
- name: Build firmware for OpenEPaperLink_PoE_AP
run: |
cd ESP32_AP-Flasher
@@ -217,15 +190,6 @@ jobs:
file_glob: true
overwrite: true
# - name: Add tag bins to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: binaries/*
# tag: ${{ github.ref }}
# file_glob: true
# overwrite: true
# this is down here intentionally to be able to modify the binary folder before adding it to the Tag_Flasher later (ota binaries can be removed)
- name: Build firmware for Tag_Flasher
@@ -254,27 +218,3 @@ jobs:
tag: ${{ github.ref }}
file_glob: true
overwrite: true
# - name: Add www folder to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ESP32_AP-Flasher/data/www/*
# tag: ${{ github.ref }}
# file_glob: true
# - name: Add fonts folder to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ESP32_AP-Flasher/data/fonts/*
# tag: ${{ github.ref }}
# file_glob: true
# - name: Add data folder to release
# uses: svenstaro/upload-release-action@v2
# with:
# repo_token: ${{ secrets.GITHUB_TOKEN }}
# file: ESP32_AP-Flasher/data/*
# tag: ${{ github.ref }}
# file_glob: true

View File

@@ -0,0 +1,799 @@
// Ported to ESP32-C6 Arduino By ATC1441(ATCnetz.de) for OpenEPaperLink at ~01.2024
#include "led.h"
#include "proto.h"
#include "radio.h"
#include "subGhz.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "sdkconfig.h"
#include "second_uart.h"
#include "soc/lp_uart_reg.h"
#include "soc/uart_struct.h"
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <string.h>
const uint8_t channelList[6] = { 11, 15, 20, 25, 26, 27 };
#define DATATYPE_NOUPDATE 0
#define HW_TYPE 0xC6
#define MAX_PENDING_MACS 250
#define HOUSEKEEPING_INTERVAL 60UL
struct pendingData pendingDataArr[MAX_PENDING_MACS];
// VERSION GOES HERE!
uint16_t version = 0x0019;
#define RAW_PKT_PADDING 2
uint8_t radiotxbuffer[135];
uint8_t radiorxbuffer[135];
static uint32_t housekeepingTimer;
struct blockRequest requestedData = { 0 }; // holds which data was requested by the tag
uint8_t dstMac[8]; // target for the block transfer
uint16_t dstPan; //
static uint32_t blockStartTimer = 0; // reference that holds when the AP sends the next block
uint32_t nextBlockAttempt = 0; // reference time for when the AP can request a new block from the ESP32
uint8_t seq = 0; // holds current sequence number for transmission
uint8_t blockbuffer[BLOCK_XFER_BUFFER_SIZE + 5]; // block transfer buffer
uint8_t lastAckMac[8] = { 0 };
// these variables hold the current mac were talking to
#define CONCURRENT_REQUEST_DELAY 1200UL
uint32_t lastBlockRequest = 0;
uint8_t lastBlockMac[8];
uint8_t lastTagReturn[8];
uint8_t curChannel = 25;
uint8_t curPower = 10;
uint8_t curPendingData = 0;
uint8_t curNoUpdate = 0;
bool highspeedSerial = false;
void sendXferCompleteAck(uint8_t *dst, bool isSubGHz);
void sendCancelXfer(uint8_t *dst, bool isSubGHz);
void espNotifyAPInfo();
// tools
void addCRC(void *p, uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *)p)[c];
}
((uint8_t *)p)[0] = total;
}
bool checkCRC(void *p, uint8_t len) {
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++) {
total += ((uint8_t *)p)[c];
}
return ((uint8_t *)p)[0] == total;
}
uint8_t getPacketType(void *buffer) {
struct MacFcs *fcs = (MacFcs *)buffer;
if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0)) {
// broadcast frame
uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameBcast)];
return type;
} else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1)) {
// normal frame
uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameNormal)];
return type;
}
return 0;
}
uint8_t getBlockDataLength() {
uint8_t partNo = 0;
for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++) {
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
partNo++;
}
}
return partNo;
}
// pendingdata slot stuff
int8_t findSlotForMac(const uint8_t *mac) {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (memcmp(mac, ((uint8_t *) & (pendingDataArr[c].targetMac)), 8) == 0) {
if (pendingDataArr[c].attemptsLeft != 0) {
return c;
}
}
}
return -1;
}
int8_t findFreeSlot() {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft == 0) {
return c;
}
}
return -1;
}
int8_t findSlotForVer(const uint8_t *ver) {
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (memcmp(ver, ((uint8_t *) & (pendingDataArr[c].availdatainfo.dataVer)), 8) == 0) {
if (pendingDataArr[c].attemptsLeft != 0) return c;
}
}
return -1;
}
void deleteAllPendingDataForVer(const uint8_t *ver) {
int8_t slot = -1;
do {
slot = findSlotForVer(ver);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
} while (slot != -1);
}
void deleteAllPendingDataForMac(const uint8_t *mac) {
int8_t slot = -1;
do {
slot = findSlotForMac(mac);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
} while (slot != -1);
}
void countSlots() {
curPendingData = 0;
curNoUpdate = 0;
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft != 0) {
if (pendingDataArr[c].availdatainfo.dataType != 0) {
curPendingData++;
} else {
curNoUpdate++;
}
}
}
}
// processing serial data
#define ZBS_RX_WAIT_HEADER 0
#define ZBS_RX_WAIT_SDA 1 // send data avail
#define ZBS_RX_WAIT_CANCEL 2 // cancel traffic for mac
#define ZBS_RX_WAIT_SCP 3 // set channel power
#define ZBS_RX_WAIT_BLOCKDATA 4
bool isSame(uint8_t *in1, char *in2, int len) {
bool flag = 1;
for (int i = 0; i < len; i++) {
if (in1[i] != in2[i]) flag = 0;
}
return flag;
}
int blockPosition = 0;
void processSerial(uint8_t lastchar) {
static uint8_t cmdbuffer[4];
static uint8_t RXState = 0;
static uint8_t serialbuffer[48];
static uint8_t *serialbufferp;
static uint8_t bytesRemain = 0;
static uint32_t lastSerial = 0;
static uint32_t blockStartTime = 0;
if ((RXState != ZBS_RX_WAIT_HEADER) && ((millis() - lastSerial) > 1000)) {
RXState = ZBS_RX_WAIT_HEADER;
Serial.printf("UART Timeout\r\n");
}
lastSerial = millis();
switch (RXState) {
case ZBS_RX_WAIT_HEADER:
// shift characters in
for (uint8_t c = 0; c < 3; c++) {
cmdbuffer[c] = cmdbuffer[c + 1];
}
cmdbuffer[3] = lastchar;
if (isSame(cmdbuffer + 1, ">D>", 3)) {
pr("ACK>");
blockStartTime = millis();
Serial.printf("Starting BlkData, %lu ms after request\r\n", blockStartTime - nextBlockAttempt);
blockPosition = 0;
RXState = ZBS_RX_WAIT_BLOCKDATA;
}
if (isSame(cmdbuffer, "SDA>", 4)) {
Serial.printf("SDA In\r\n");
RXState = ZBS_RX_WAIT_SDA;
bytesRemain = sizeof(struct pendingData);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "CXD>", 4)) {
Serial.printf("CXD In\r\n");
RXState = ZBS_RX_WAIT_CANCEL;
bytesRemain = sizeof(struct pendingData);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "SCP>", 4)) {
Serial.printf("SCP In\r\n");
RXState = ZBS_RX_WAIT_SCP;
bytesRemain = sizeof(struct espSetChannelPower);
serialbufferp = serialbuffer;
break;
}
if (isSame(cmdbuffer, "NFO?", 4)) {
pr("ACK>");
Serial.printf("NFO? In\r\n");
espNotifyAPInfo();
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "RDY?", 4)) {
pr("ACK>");
Serial.printf("RDY? In\r\n");
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "RSET", 4)) {
pr("ACK>");
Serial.printf("RSET In\r\n");
delay(100);
// TODO RESET US HERE
RXState = ZBS_RX_WAIT_HEADER;
}
if (isSame(cmdbuffer, "HSPD", 4)) {
pr("ACK>");
Serial.printf("HSPD In, switching to 2000000\r\n");
delay(100);
uart_switch_speed(2000000);
delay(100);
highspeedSerial = true;
pr("ACK>");
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_BLOCKDATA:
blockbuffer[blockPosition++] = 0xAA ^ lastchar;
if (blockPosition >= 4100) {
Serial.printf("Blockdata fully received in %lu ms, %lu ms after the request\r\n", millis() - blockStartTime, millis() - nextBlockAttempt);
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_SDA:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
struct pendingData *pd = (struct pendingData *)serialbuffer;
int8_t slot = findSlotForMac(pd->targetMac);
if (slot == -1) slot = findFreeSlot();
if (slot != -1) {
memcpy(&(pendingDataArr[slot]), serialbuffer, sizeof(struct pendingData));
pr("ACK>");
} else {
pr("NOQ>");
}
} else {
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_CANCEL:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct pendingData))) {
struct pendingData *pd = (struct pendingData *)serialbuffer;
deleteAllPendingDataForMac((uint8_t *)&pd->targetMac);
pr("ACK>");
} else {
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
case ZBS_RX_WAIT_SCP:
*serialbufferp = lastchar;
serialbufferp++;
bytesRemain--;
if (bytesRemain == 0) {
if (checkCRC(serialbuffer, sizeof(struct espSetChannelPower))) {
struct espSetChannelPower *scp = (struct espSetChannelPower *)serialbuffer;
for (uint8_t c = 0; c < sizeof(channelList); c++) {
if (channelList[c] == scp->channel) goto SCPchannelFound;
}
goto SCPfailed;
SCPchannelFound:
pr("ACK>");
if (curChannel != scp->channel) {
radioSetChannel(scp->channel);
curChannel = scp->channel;
}
curPower = scp->power;
radioSetTxPower(scp->power);
Serial.printf("Set channel: %d power: %d\r\n", curChannel, curPower);
} else {
SCPfailed:
pr("NOK>");
}
RXState = ZBS_RX_WAIT_HEADER;
}
break;
}
}
// sending data to the ESP
void espBlockRequest(const struct blockRequest *br, uint8_t *src) {
struct espBlockRequest *ebr = (struct espBlockRequest *)blockbuffer;
uartTx('R');
uartTx('Q');
uartTx('B');
uartTx('>');
memcpy(&(ebr->ver), &(br->ver), 8);
memcpy(&(ebr->src), src, 8);
ebr->blockId = br->blockId;
addCRC(ebr, sizeof(struct espBlockRequest));
for (uint8_t c = 0; c < sizeof(struct espBlockRequest); c++) {
uartTx(((uint8_t *)ebr)[c]);
}
}
void espNotifyAvailDataReq(const struct AvailDataReq *adr, const uint8_t *src) {
uartTx('A');
uartTx('D');
uartTx('R');
uartTx('>');
struct espAvailDataReq eadr = { 0 };
memcpy((void *)eadr.src, (void *)src, 8);
memcpy((void *)&eadr.adr, (void *)adr, sizeof(struct AvailDataReq));
addCRC(&eadr, sizeof(struct espAvailDataReq));
for (uint8_t c = 0; c < sizeof(struct espAvailDataReq); c++) {
uartTx(((uint8_t *)&eadr)[c]);
}
}
void espNotifyXferComplete(const uint8_t *src) {
struct espXferComplete exfc;
memcpy(&exfc.src, src, 8);
uartTx('X');
uartTx('F');
uartTx('C');
uartTx('>');
addCRC(&exfc, sizeof(exfc));
for (uint8_t c = 0; c < sizeof(exfc); c++) {
uartTx(((uint8_t *)&exfc)[c]);
}
}
void espNotifyTimeOut(const uint8_t *src) {
struct espXferComplete exfc;
memcpy(&exfc.src, src, 8);
uartTx('X');
uartTx('T');
uartTx('O');
uartTx('>');
addCRC(&exfc, sizeof(exfc));
for (uint8_t c = 0; c < sizeof(exfc); c++) {
uartTx(((uint8_t *)&exfc)[c]);
}
}
void espNotifyAPInfo() {
pr("TYP>%02X", HW_TYPE);
pr("VER>%04X", version);
pr("MAC>%02X%02X", mSelfMac[0], mSelfMac[1]);
pr("%02X%02X", mSelfMac[2], mSelfMac[3]);
pr("%02X%02X", mSelfMac[4], mSelfMac[5]);
pr("%02X%02X", mSelfMac[6], mSelfMac[7]);
pr("ZCH>%02X", curChannel);
pr("ZPW>%02X", curPower);
countSlots();
pr("PEN>%02X", curPendingData);
pr("NOP>%02X", curNoUpdate);
}
void espNotifyTagReturnData(uint8_t *src, uint8_t len) {
struct tagReturnData *trd = (struct tagReturnData *)(radiorxbuffer + sizeof(struct MacFrameBcast) + 1); // oh how I'd love to pass this as an argument, but sdcc won't let me
struct espTagReturnData *etrd = (struct espTagReturnData *)radiotxbuffer;
if (memcmp((void *)&trd->dataVer, lastTagReturn, 8) == 0) {
return;
} else {
memcpy(lastTagReturn, &trd->dataVer, 8);
}
memcpy(etrd->src, src, 8);
etrd->len = len;
memcpy(&etrd->returnData, trd, len);
addCRC(etrd, len + 10);
uartTx('T');
uartTx('R');
uartTx('D');
uartTx('>');
for (uint8_t c = 0; c < len + 10; c++) {
uartTx(((uint8_t *)etrd)[c]);
}
}
// process data from tag
void processBlockRequest(const uint8_t *buffer, uint8_t forceBlockDownload, bool isSubGHz) {
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *)buffer;
struct blockRequest *blockReq = (struct blockRequest *)(buffer + sizeof(struct MacFrameNormal) + 1);
if (!checkCRC(blockReq, sizeof(struct blockRequest))) return;
// check if we're already talking to this mac
if (memcmp(rxHeader->src, lastBlockMac, 8) == 0) {
lastBlockRequest = millis();
} else {
// we weren't talking to this mac, see if there was a transfer in progress from another mac, recently
if ((millis() - lastBlockRequest) > CONCURRENT_REQUEST_DELAY) {
// mark this mac as the new current mac we're talking to
memcpy((void *)lastBlockMac, (void *)rxHeader->src, 8);
lastBlockRequest = millis();
} else {
// we're talking to another mac, let this mac know we can't accomodate another request right now
pr("BUSY!\n");
sendCancelXfer(rxHeader->src, isSubGHz);
return;
}
}
// check if we have data for this mac
if (findSlotForMac(rxHeader->src) == -1) {
// no data for this mac, politely tell it to fuck off
sendCancelXfer(rxHeader->src, isSubGHz);
return;
}
bool requestDataDownload = false;
if ((blockReq->blockId != requestedData.blockId) || (blockReq->ver != requestedData.ver)) {
// requested block isn't already in the buffer
requestDataDownload = true;
} else {
// requested block is already in the buffer
if (forceBlockDownload) {
if ((millis() - nextBlockAttempt) > 380) {
requestDataDownload = true;
pr("FORCED\n");
} else {
pr("IGNORED\n");
}
}
}
// copy blockrequest into requested data
memcpy(&requestedData, blockReq, sizeof(struct blockRequest));
struct MacFrameNormal *txHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
struct blockRequestAck *blockRequestAck = (struct blockRequestAck *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct blockRequestAck) + RAW_PKT_PADDING;
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_REQUEST_ACK;
if (blockStartTimer == 0) {
if (requestDataDownload) {
if (highspeedSerial == true) {
blockRequestAck->pleaseWaitMs = 140;
} else {
blockRequestAck->pleaseWaitMs = 550;
}
} else {
// block is already in buffer
blockRequestAck->pleaseWaitMs = 30;
}
} else {
blockRequestAck->pleaseWaitMs = 30;
}
blockStartTimer = millis() + blockRequestAck->pleaseWaitMs;
memcpy(txHeader->src, mSelfMac, 8);
memcpy(txHeader->dst, rxHeader->src, 8);
txHeader->pan = rxHeader->pan;
txHeader->fcs.frameType = 1;
txHeader->fcs.panIdCompressed = 1;
txHeader->fcs.destAddrType = 3;
txHeader->fcs.srcAddrType = 3;
txHeader->seq = seq++;
addCRC((void *)blockRequestAck, sizeof(struct blockRequestAck));
radioTx(radiotxbuffer, isSubGHz);
// save the target for the blockdata
memcpy(dstMac, rxHeader->src, 8);
dstPan = rxHeader->pan;
if (requestDataDownload) {
blockPosition = 0;
espBlockRequest(&requestedData, rxHeader->src);
nextBlockAttempt = millis();
}
}
void processAvailDataReq(uint8_t *buffer, bool isSubGHz) {
struct MacFrameBcast *rxHeader = (struct MacFrameBcast *)buffer;
struct AvailDataReq *availDataReq = (struct AvailDataReq *)(buffer + sizeof(struct MacFrameBcast) + 1);
if (!checkCRC(availDataReq, sizeof(struct AvailDataReq))) return;
// prepare tx buffer to send a response
memset(radiotxbuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct AvailDataInfo) + 2); // 120);
struct MacFrameNormal *txHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
struct AvailDataInfo *availDataInfo = (struct AvailDataInfo *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + sizeof(struct AvailDataInfo) + RAW_PKT_PADDING;
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_AVAIL_DATA_INFO;
// check to see if we have data available for this mac
bool haveData = false;
for (uint8_t c = 0; c < MAX_PENDING_MACS; c++) {
if (pendingDataArr[c].attemptsLeft) {
if (memcmp(pendingDataArr[c].targetMac, rxHeader->src, 8) == 0) {
haveData = true;
memcpy((void *)availDataInfo, &(pendingDataArr[c].availdatainfo), sizeof(struct AvailDataInfo));
break;
}
}
}
// couldn't find data for this mac
if (!haveData) availDataInfo->dataType = DATATYPE_NOUPDATE;
memcpy(txHeader->src, mSelfMac, 8);
memcpy(txHeader->dst, rxHeader->src, 8);
txHeader->pan = rxHeader->dstPan;
txHeader->fcs.frameType = 1;
txHeader->fcs.panIdCompressed = 1;
txHeader->fcs.destAddrType = 3;
txHeader->fcs.srcAddrType = 3;
txHeader->seq = seq++;
addCRC(availDataInfo, sizeof(struct AvailDataInfo));
radioTx(radiotxbuffer, isSubGHz);
memset(lastAckMac, 0, 8); // reset lastAckMac, so we can record if we've received exactly one ack packet
espNotifyAvailDataReq(availDataReq, rxHeader->src);
}
void processXferComplete(uint8_t *buffer, bool isSubGHz) {
struct MacFrameNormal *rxHeader = (struct MacFrameNormal *)buffer;
sendXferCompleteAck(rxHeader->src, isSubGHz);
if (memcmp(lastAckMac, rxHeader->src, 8) != 0) {
memcpy((void *)lastAckMac, (void *)rxHeader->src, 8);
espNotifyXferComplete(rxHeader->src);
int8_t slot = findSlotForMac(rxHeader->src);
if (slot != -1) pendingDataArr[slot].attemptsLeft = 0;
}
}
void processTagReturnData(uint8_t *buffer, uint8_t len, bool isSubGHz) {
struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buffer;
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
if (!checkCRC((buffer + sizeof(struct MacFrameBcast) + 1), len - (sizeof(struct MacFrameBcast) + 1))) {
return;
}
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_TAG_RETURN_DATA_ACK;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, rxframe->src, 8);
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
radiotxbuffer[2] = 0xCC; // normal frame
frameHeader->seq = seq++;
frameHeader->pan = rxframe->srcPan;
radioTx(radiotxbuffer, isSubGHz);
espNotifyTagReturnData(rxframe->src, len - (sizeof(struct MacFrameBcast) + 1));
}
// send block data to the tag
void sendPart(uint8_t partNo, bool isSubGHz) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
struct blockPart *blockPart = (struct blockPart *)(radiotxbuffer + sizeof(struct MacFrameNormal) + 2);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_PART;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dstMac, 8);
blockPart->blockId = requestedData.blockId;
blockPart->blockPart = partNo;
memcpy(&(blockPart->data), blockbuffer + (partNo * BLOCK_PART_DATA_SIZE), BLOCK_PART_DATA_SIZE);
addCRC(blockPart, sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer, isSubGHz);
}
void sendBlockData(bool isSubGHz) {
if (getBlockDataLength() == 0) {
pr("Invalid block request received, 0 parts..\n");
requestedData.requestedParts[0] |= 0x01;
}
pr("Sending parts:");
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS); c++) {
if (c % 10 == 0) pr(" ");
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
pr("X");
} else {
pr(".");
}
}
pr("\n");
uint8_t partNo = 0;
while (partNo < BLOCK_MAX_PARTS) {
for (uint8_t c = 0; (c < BLOCK_MAX_PARTS) && (partNo < BLOCK_MAX_PARTS); c++) {
if (requestedData.requestedParts[c / 8] & (1 << (c % 8))) {
sendPart(c, isSubGHz);
partNo++;
}
}
}
}
void sendXferCompleteAck(uint8_t *dst, bool isSubGHz) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_XFER_COMPLETE_ACK;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dst, 8);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer, isSubGHz);
}
void sendCancelXfer(uint8_t *dst, bool isSubGHz) {
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
memset(radiotxbuffer + 1, 0, sizeof(struct blockPart) + sizeof(struct MacFrameNormal));
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_CANCEL_XFER;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, dst, 8);
frameHeader->fcs.frameType = 1;
frameHeader->fcs.panIdCompressed = 1;
frameHeader->fcs.destAddrType = 3;
frameHeader->fcs.srcAddrType = 3;
frameHeader->seq = seq++;
frameHeader->pan = dstPan;
radioTx(radiotxbuffer, isSubGHz);
}
void sendPong(void *buf, bool isSubGHz) {
struct MacFrameBcast *rxframe = (struct MacFrameBcast *)buf;
struct MacFrameNormal *frameHeader = (struct MacFrameNormal *)(radiotxbuffer + 1);
radiotxbuffer[sizeof(struct MacFrameNormal) + 1] = PKT_PONG;
radiotxbuffer[sizeof(struct MacFrameNormal) + 2] = curChannel;
radiotxbuffer[0] = sizeof(struct MacFrameNormal) + 1 + 1 + RAW_PKT_PADDING;
memcpy(frameHeader->src, mSelfMac, 8);
memcpy(frameHeader->dst, rxframe->src, 8);
radiotxbuffer[1] = 0x41; // fast way to set the appropriate bits
radiotxbuffer[2] = 0xCC; // normal frame
frameHeader->seq = seq++;
frameHeader->pan = rxframe->srcPan;
radioTx(radiotxbuffer, isSubGHz);
}
extern uint8_t mSelfMac[8];
void setup() {
Serial.begin(115200);
init_led();
init_second_uart();
requestedData.blockId = 0xFF;
// clear the array with pending information
memset(pendingDataArr, 0, sizeof(pendingDataArr));
radio_init(curChannel);
radioSetTxPower(10);
pr("RES>");
pr("RDY>");
Serial.printf("C6 ready!\r\n");
housekeepingTimer = millis();
}
bool isSubGhzRx = false;
void loop() {
while ((millis() - housekeepingTimer) < ((1000 * HOUSEKEEPING_INTERVAL) - 100)) {
int8_t ret = commsRxUnencrypted(radiorxbuffer, &isSubGhzRx);
if (ret > 1) {
if (0)
{
Serial.printf("RXed packet len %u :", ret);
for (int t = 0; t < ret; t++) {
Serial.printf(" %02x", radiorxbuffer[t]);
}
Serial.printf("\n");
}
led_flash(0);
// received a packet, lets see what it is
switch (getPacketType(radiorxbuffer)) {
case PKT_AVAIL_DATA_REQ:
if (ret == 28) {
// old version of the AvailDataReq struct, set all the new fields to zero, so it will pass the CRC
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast) + sizeof(struct oldAvailDataReq), 0,
sizeof(struct AvailDataReq) - sizeof(struct oldAvailDataReq) + 2);
processAvailDataReq(radiorxbuffer, isSubGhzRx);
} else if (ret == 40) {
// new version of the AvailDataReq struct
processAvailDataReq(radiorxbuffer, isSubGhzRx);
}
break;
case PKT_BLOCK_REQUEST:
processBlockRequest(radiorxbuffer, 1, isSubGhzRx);
break;
case PKT_BLOCK_PARTIAL_REQUEST:
processBlockRequest(radiorxbuffer, 0, isSubGhzRx);
break;
case PKT_XFER_COMPLETE:
processXferComplete(radiorxbuffer, isSubGhzRx);
break;
case PKT_PING:
sendPong(radiorxbuffer, isSubGhzRx);
break;
case PKT_AVAIL_DATA_SHORTREQ:
// a short AvailDataReq is basically a very short (1 byte payload) packet that requires little preparation on the tx side, for optimal
// battery use bytes of the struct are set 0, so it passes the checksum test, and the ESP32 can detect that no interesting payload is
// sent
if (ret == 18) {
memset(radiorxbuffer + 1 + sizeof(struct MacFrameBcast), 0, sizeof(struct AvailDataReq) + 2);
processAvailDataReq(radiorxbuffer, isSubGhzRx);
}
break;
case PKT_TAG_RETURN_DATA:
processTagReturnData(radiorxbuffer, ret, isSubGhzRx);
break;
default:
Serial.printf("t=%02X\r\n", getPacketType(radiorxbuffer));
break;
}
} else if (blockStartTimer == 0) {
delay(10);
}
uint8_t curr_char;
while (getRxCharSecond(&curr_char)) processSerial(curr_char);
if (blockStartTimer) {
if (millis() > blockStartTimer) {
sendBlockData(isSubGhzRx);
blockStartTimer = 0;
}
}
}
memset(&lastTagReturn, 0, 8);
for (uint8_t cCount = 0; cCount < MAX_PENDING_MACS; cCount++) {
if (pendingDataArr[cCount].attemptsLeft == 1) {
if (pendingDataArr[cCount].availdatainfo.dataType != DATATYPE_NOUPDATE) {
espNotifyTimeOut(pendingDataArr[cCount].targetMac);
}
pendingDataArr[cCount].attemptsLeft = 0;
} else if (pendingDataArr[cCount].attemptsLeft > 1) {
pendingDataArr[cCount].attemptsLeft--;
if (pendingDataArr[cCount].availdatainfo.nextCheckIn) pendingDataArr[cCount].availdatainfo.nextCheckIn--;
}
}
housekeepingTimer = millis();
}

View File

@@ -0,0 +1,44 @@
#include "led.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "proto.h"
#include <Arduino.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUM_LEDS 2
const uint8_t led_pins[NUM_LEDS] = { LED1, LED2 };
TimerHandle_t led_timers[NUM_LEDS] = { 0 };
void led_timer_callback(TimerHandle_t xTimer) {
int led_index = (int)pvTimerGetTimerID(xTimer);
if (led_index >= 0 && led_index < NUM_LEDS) {
digitalWrite(led_pins[led_index], 0);
}
}
void init_led() {
pinMode(LED1,OUTPUT);
pinMode(LED2,OUTPUT);
for (int i = 0; i < NUM_LEDS; i++) {
led_timers[i] = xTimerCreate("led_timer", pdMS_TO_TICKS(50), pdFALSE, (void *)i, led_timer_callback);
}
}
void led_flash(int nr) {
digitalWrite(led_pins[nr], 1);
if (nr >= 0 && nr < NUM_LEDS) {
xTimerStart(led_timers[nr], 0);
}
}
void led_set(int nr, bool state) {
digitalWrite(nr, state);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <stdbool.h>
void init_led();
void led_set(int nr, bool state);
void led_flash(int nr);

View File

@@ -0,0 +1,190 @@
#ifndef _PROTO_H_
#define _PROTO_H_
#include <stdint.h>
#define LED1 22
#define LED2 23
#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used
#define RADIO_MAX_PACKET_LEN (125) // useful payload, not including the crc
#define ADDR_MODE_NONE (0)
#define ADDR_MODE_SHORT (2)
#define ADDR_MODE_LONG (3)
#define FRAME_TYPE_BEACON (0)
#define FRAME_TYPE_DATA (1)
#define FRAME_TYPE_ACK (2)
#define FRAME_TYPE_MAC_CMD (3)
#define SHORT_MAC_UNUSED (0x10000000UL) // for radioRxFilterCfg's myShortMac
struct MacFcs {
uint8_t frameType : 3;
uint8_t secure : 1;
uint8_t framePending : 1;
uint8_t ackReqd : 1;
uint8_t panIdCompressed : 1;
uint8_t rfu1 : 1;
uint8_t rfu2 : 2;
uint8_t destAddrType : 2;
uint8_t frameVer : 2;
uint8_t srcAddrType : 2;
} __attribute__((packed, aligned(1)));
struct MacFrameFromMaster {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint16_t from;
} __attribute__((packed, aligned(1)));
struct MacFrameNormal {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct MacFrameBcast {
struct MacFcs fcs;
uint8_t seq;
uint16_t dstPan;
uint16_t dstAddr;
uint16_t srcPan;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
#define PKT_TAG_RETURN_DATA 0xE1
#define PKT_TAG_RETURN_DATA_ACK 0xE2
#define PKT_AVAIL_DATA_SHORTREQ 0xE3
#define PKT_AVAIL_DATA_REQ 0xE5
#define PKT_AVAIL_DATA_INFO 0xE6
#define PKT_BLOCK_PARTIAL_REQUEST 0xE7
#define PKT_BLOCK_REQUEST_ACK 0xE9
#define PKT_BLOCK_REQUEST 0xE4
#define PKT_BLOCK_PART 0xE8
#define PKT_XFER_COMPLETE 0xEA
#define PKT_XFER_COMPLETE_ACK 0xEB
#define PKT_CANCEL_XFER 0xEC
#define PKT_PING 0xED
#define PKT_PONG 0xEE
struct AvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
uint16_t tagSoftwareVersion;
uint8_t currentChannel;
uint8_t customMode;
uint8_t reserved[8];
} __attribute__((packed, aligned(1)));
struct oldAvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
} __attribute__((packed, aligned(1)));
struct AvailDataInfo {
uint8_t checksum;
uint64_t dataVer; // MD5 of potential traffic
uint32_t dataSize;
uint8_t dataType;
uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image)
uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes
} __attribute__((packed, aligned(1)));
struct pendingData {
struct AvailDataInfo availdatainfo;
uint16_t attemptsLeft;
uint8_t targetMac[8];
} __attribute__((packed, aligned(1)));
struct blockPart {
uint8_t checksum;
uint8_t blockId;
uint8_t blockPart;
uint8_t data[];
} __attribute__((packed, aligned(1)));
struct blockData {
uint16_t size;
uint16_t checksum;
uint8_t data[];
} __attribute__((packed, aligned(1)));
#define TAG_RETURN_DATA_SIZE 90
struct tagReturnData {
uint8_t checksum;
uint8_t partId;
uint64_t dataVer;
uint8_t dataType;
uint8_t data[TAG_RETURN_DATA_SIZE];
} __attribute__((packed, aligned(1)));
#define BLOCK_PART_DATA_SIZE 99
#define BLOCK_MAX_PARTS 42
#define BLOCK_DATA_SIZE 4096UL
#define BLOCK_XFER_BUFFER_SIZE BLOCK_DATA_SIZE + sizeof(struct blockData)
#define BLOCK_REQ_PARTS_BYTES 6
struct blockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t type;
uint8_t requestedParts[BLOCK_REQ_PARTS_BYTES];
} __attribute__((packed, aligned(1)));
struct blockRequestAck {
uint8_t checksum;
uint16_t pleaseWaitMs;
} __attribute__((packed, aligned(1)));
struct espBlockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct espXferComplete {
uint8_t checksum;
uint8_t src[8];
} __attribute__((packed, aligned(1)));
struct espAvailDataReq {
uint8_t checksum;
uint8_t src[8];
struct AvailDataReq adr;
} __attribute__((packed, aligned(1)));
struct espSetChannelPower {
uint8_t checksum;
uint8_t channel;
uint8_t power;
} __attribute__((packed, aligned(1)));
struct espTagReturnData {
uint8_t checksum;
uint8_t src[8];
uint8_t len;
struct tagReturnData returnData;
} __attribute__((packed, aligned(1)));
#endif

View File

@@ -0,0 +1,155 @@
#include "radio.h"
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "led.h"
#include "subGhz.h"
#include "proto.h"
#include "sdkconfig.h"
// if you get an error about soc/lp_uart_reg.h not being found,
// you didn't choose the right build target. :-)
#include "soc/lp_uart_reg.h"
#include "soc/uart_struct.h"
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include <Arduino.h>
bool has_sub_ghz = false;
uint8_t mSelfMac[8];
volatile uint8_t isInTransmit = 0;
QueueHandle_t packet_buffer = NULL;
void esp_ieee802154_receive_done(uint8_t *frame, esp_ieee802154_frame_info_t *frame_info) {
Serial.printf("RADIO info RX %d\r\n", frame[0]);
BaseType_t xHigherPriorityTaskWoken;
static uint8_t inner_rxPKT[130];
memcpy(inner_rxPKT, &frame[0], frame[0] + 1);
xQueueSendFromISR(packet_buffer, (void *)&inner_rxPKT, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR_ARG(xHigherPriorityTaskWoken);
}
void esp_ieee802154_transmit_failed(const uint8_t *frame, esp_ieee802154_tx_error_t error) {
isInTransmit = 0;
Serial.printf("RADIO err TX Err: %d\r\n", error);
}
void esp_ieee802154_transmit_done(const uint8_t *frame, const uint8_t *ack, esp_ieee802154_frame_info_t *ack_frame_info) {
isInTransmit = 0;
Serial.printf("RADIO info TX %d\r\n", frame[0]);
}
void radio_init(uint8_t ch) {
if (packet_buffer == NULL) packet_buffer = xQueueCreate(32, 130);
// this will trigger a "IEEE802154 MAC sleep init failed" when called a second time, but it works
esp_ieee802154_enable();
esp_ieee802154_set_channel(ch);
// esp_ieee802154_set_txpower(int8_t power);
esp_ieee802154_set_panid(PROTO_PAN_ID);
esp_ieee802154_set_promiscuous(false);
esp_ieee802154_set_coordinator(false);
esp_ieee802154_set_pending_mode(ESP_IEEE802154_AUTO_PENDING_ZIGBEE);
// esp_ieee802154_set_extended_address needs the MAC in reversed byte order
esp_read_mac(mSelfMac, ESP_MAC_IEEE802154);
uint8_t eui64_rev[8] = { 0 };
for (int i = 0; i < 8; i++) {
eui64_rev[7 - i] = mSelfMac[i];
}
esp_ieee802154_set_extended_address(eui64_rev);
esp_ieee802154_get_extended_address(mSelfMac);
esp_ieee802154_set_short_address(0xFFFE);
esp_ieee802154_set_rx_when_idle(true);
esp_ieee802154_receive();
led_flash(1);
delay(100);
led_flash(0);
delay(100);
led_flash(1);
delay(100);
led_flash(0);
Serial.printf("RADIO Receiver ready, panId=0x%04x, channel=%d, long=%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, short=%04x\r\n",
esp_ieee802154_get_panid(), esp_ieee802154_get_channel(),
mSelfMac[0], mSelfMac[1], mSelfMac[2], mSelfMac[3],
mSelfMac[4], mSelfMac[5], mSelfMac[6], mSelfMac[7],
esp_ieee802154_get_short_address());
// Lets here take care of the SubGhz Init
if (!init_subGhz())
Serial.printf("Sub-GHz radio init failed\r\n");
else if (!tiRadioSetChannel(ch))
Serial.printf("SubGHz radio channel fail\r\n");
else
has_sub_ghz = true;
Serial.printf("SubGhz %s\r\n", has_sub_ghz ? "Active" : "Not Found");
if (has_sub_ghz) {
tiRadioRxFilterCfg(mSelfMac, SHORT_MAC_UNUSED, PROTO_PAN_ID, true);
tiRadioTxConfigure(mSelfMac, SHORT_MAC_UNUSED, PROTO_PAN_ID);
tiRadioRxEnable(true, false);
}
}
// uint32_t lastZbTx = 0;
bool radioTx(uint8_t *packet, bool subGhz) {
led_flash(1);
if (has_sub_ghz && subGhz) {
tiRadioTxLL(packet);
} else {
static uint8_t txPKT[130];
while (isInTransmit) {
}
// while (millis() - lastZbTx < 6) {
// }
// lastZbTx = millis();
memcpy(txPKT, packet, packet[0]);
isInTransmit = 1;
esp_ieee802154_transmit(txPKT, false);
return true;
}
}
void radioSetChannel(uint8_t ch) {
radio_init(ch);
if (has_sub_ghz)
tiRadioSetChannel(ch);
}
void radioSetTxPower(uint8_t power) {}
int8_t commsRxUnencrypted(uint8_t *data, bool *subGhzRx) {
int8_t rssi_sub_rx = 0;
uint8_t lqi_sub_rx = 0;
static uint8_t inner_rxPKT_out[135];
if (xQueueReceive(packet_buffer, (void *)&inner_rxPKT_out, pdMS_TO_TICKS(100)) == pdTRUE) {
memcpy(data, &inner_rxPKT_out[1], inner_rxPKT_out[0] + 1);
*subGhzRx = false; // This is Normal data
return inner_rxPKT_out[0] - 2;
}
if (has_sub_ghz) {
int32_t ret_sub_rx_len = tiRadioRxDequeuePkt(inner_rxPKT_out, sizeof(inner_rxPKT_out), &rssi_sub_rx, &lqi_sub_rx);
if (ret_sub_rx_len > 0)
{
//Serial.printf("Got Sub Ghz Len %i data: %i %u\r\n", ret_sub_rx, rssi_sub_rx, lqi_sub_rx);
memcpy(data, inner_rxPKT_out, ret_sub_rx_len);
*subGhzRx = true; // This is SubGHz data
return ret_sub_rx_len;
}
}
return 0;
}

View File

@@ -0,0 +1,11 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>
extern uint8_t mSelfMac[8];
void radio_init(uint8_t ch);
bool radioTx(uint8_t *packet, bool subGhz);
void radioSetChannel(uint8_t ch);
void radioSetTxPower(uint8_t power);
int8_t commsRxUnencrypted(uint8_t *data, bool *subGhzRx);

View File

@@ -0,0 +1,125 @@
#include <esp_mac.h>
#include <math.h>
#include <stdarg.h>
#include <string.h>
#include <Arduino.h>
#include "driver/gpio.h"
#include "driver/uart.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_ieee802154.h"
#include "esp_phy_init.h"
#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "nvs.h"
#include "nvs_flash.h"
#include "proto.h"
#include "sdkconfig.h"
#include "soc/uart_struct.h"
#include "soc/lp_uart_reg.h"
#include "second_uart.h"
#if defined(CONFIG_OEPL_HARDWARE_PROFILE_POE_AP)
#define CONFIG_OEPL_HARDWARE_UART_TX 5
#define CONFIG_OEPL_HARDWARE_UART_RX 18
#else
#if !defined(CONFIG_OEPL_HARDWARE_UART_TX) || !defined(CONFIG_OEPL_HARDWARE_UART_RX)
#define CONFIG_OEPL_HARDWARE_UART_TX 3
#define CONFIG_OEPL_HARDWARE_UART_RX 2
#endif
#endif
#define BUF_SIZE (1024)
#define RD_BUF_SIZE (BUF_SIZE)
static QueueHandle_t uart0_queue;
#define MAX_BUFF_POS 8000
volatile int curr_buff_pos = 0;
volatile int worked_buff_pos = 0;
volatile uint8_t buff_pos[MAX_BUFF_POS + 5];
static void uart_event_task(void *pvParameters);
void init_second_uart() {
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
ESP_ERROR_CHECK(uart_driver_install(1, BUF_SIZE * 2, BUF_SIZE * 2, 20, &uart0_queue, 0));
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(1, CONFIG_OEPL_HARDWARE_UART_TX, CONFIG_OEPL_HARDWARE_UART_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));
xTaskCreate(uart_event_task, "uart_event_task", 16384, NULL, 12, NULL);
}
void uart_switch_speed(int baudrate) {
uart_config_t uart_config = {
.baud_rate = baudrate,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_DEFAULT,
};
ESP_ERROR_CHECK(uart_param_config(1, &uart_config));
}
void uartTx(uint8_t data) {
uart_write_bytes(1, (const char *)&data, 1);
}
bool getRxCharSecond(uint8_t *newChar) {
if (curr_buff_pos != worked_buff_pos) {
*newChar = buff_pos[worked_buff_pos];
worked_buff_pos++;
worked_buff_pos %= MAX_BUFF_POS;
return true;
}
return false;
}
static void uart_event_task(void *pvParameters) {
uart_event_t event;
uint8_t *dtmp = (uint8_t *)malloc(RD_BUF_SIZE);
for (;;) {
if (xQueueReceive(uart0_queue, (void *)&event, (TickType_t)portMAX_DELAY)) {
bzero(dtmp, RD_BUF_SIZE);
switch (event.type) {
case UART_DATA:
uart_read_bytes(1, dtmp, event.size, portMAX_DELAY);
for (int i = 0; i < event.size; i++) {
buff_pos[curr_buff_pos] = dtmp[i];
curr_buff_pos++;
curr_buff_pos %= MAX_BUFF_POS;
}
break;
default:
Serial.printf("Second UART uart event type: %d\r\n", event.type);
break;
}
}
}
free(dtmp);
dtmp = NULL;
vTaskDelete(NULL);
}
void uart_printf(const char *format, ...) {
va_list args;
va_start(args, format);
char buffer[128];
int len = vsnprintf(buffer, sizeof(buffer), format, args);
va_end(args);
if (len > 0) {
uart_write_bytes(1, buffer, len);
}
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include <inttypes.h>
void init_second_uart();
void uart_switch_speed(int baudrate);
void uartTx(uint8_t data);
bool getRxCharSecond(uint8_t *newChar);
void uart_printf(const char *format, ...);
#define pr uart_printf

View File

@@ -0,0 +1,609 @@
// This code is heavily depending on Dmitrys wonderful Work !
// https://dmitry.gr/?r=05.Projects&proj=29.%20eInk%20Price%20Tags
// Ported and modified to fit the OpenEPaperLink Project by ATC1441 (ATCnetz.de) ~01.2024
#include "subGhz.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/task.h"
#include "freertos/timers.h"
#include "proto.h"
#include <Arduino.h>
#include <SPI.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SUB_GHZ_CH_OFST 11
#define SUB_GHZ_NUM_CHANNELS 25
/*
//we configure GDO_2 is for TX.has_fifo_space
//we configure GDO_0 is for RX.has_data
WIRING:
*/
#define sub_CS 4
#define sub_GD0 5
#define sub_GD2 6
#define sub_MISO 7
#define sub_CLK 0
#define sub_MOSI 1
#define CMD_SRES 0x30
#define CMD_SFSTXON 0x31
#define CMD_SXOFF 0x32
#define CMD_SCAL 0x33
#define CMD_SRX 0x34
#define CMD_STX 0x35
#define CMD_SIDLE 0x36
#define CMD_SWOR 0x38
#define CMD_SPWD 0x39
#define CMD_SFRX 0x3a
#define CMD_SFTX 0x3b
#define CMD_SWORRST 0x3c
#define CMD_SNOP 0x3d
#define REG_IOCFG2 0x00
#define REG_IOCFG1 0x01
#define REG_IOCFG0 0x02
#define REG_FIFOTHR 0x03
#define REG_SYNC1 0x04
#define REG_SYNC0 0x05
#define REG_PKTLEN 0x06
#define REG_PKTCTRL1 0x07
#define REG_PKTCTRL0 0x08
#define REG_ADDR 0x09
#define REG_CHANNR 0x0a
#define REG_FSCTRL1 0x0b
#define REG_FSCTRL0 0x0c
#define REG_FREQ2 0x0d
#define REG_FREQ1 0x0e
#define REG_FREQ0 0x0f
#define REG_MDMCFG4 0x10
#define REG_MDMCFG3 0x11
#define REG_MDMCFG2 0x12
#define REG_MDMCFG1 0x13
#define REG_MDMCFG0 0x14
#define REG_DEVIATN 0x15
#define REG_MCSM2 0x16
#define REG_MCSM1 0x17
#define REG_MCSM0 0x18
#define REG_FOCCFG 0x19
#define REG_BSCFG 0x1a
#define REG_AGCTRL2 0x1b
#define REG_AGCTRL1 0x1c
#define REG_AGCTRL0 0x1d
#define REG_WOREVT1 0x1e
#define REG_WOREVT0 0x1f
#define REG_WORCTRL 0x20
#define REG_FREND1 0x21
#define REG_FREND0 0x22
#define REG_FSCAL3 0x23
#define REG_FSCAL2 0x24
#define REG_FSCAL1 0x25
#define REG_FSCAL0 0x26
#define REG_RCCTRL1 0x27
#define REG_RCCTRL0 0x28
#define REG_FSTEST 0x29
#define REG_PTEST 0x2a
#define REG_AGCTEST 0x2b
#define REG_TEST2 0x2c
#define REG_TEST1 0x2d
#define REG_TEST0 0x2e
#define REG_PATABLE 0x3e
#define REG_FIFO 0x3f
#define REG_PARTNUM 0xf0
#define REG_VERSION 0xf1
#define REG_FREQEST 0xf2
#define REG_LQI 0xf3
#define REG_RSSI 0xf4
#define REG_MARCSTATE 0xf5
#define REG_WORTIME1 0xf6
#define REG_WORTIME0 0xf7
#define REG_PKTSTATUS 0xf8
#define REG_VCO_VC_DAC 0xf9
#define REG_TXBYTES 0xfa
#define REG_RXBYTES 0xfb
#define REG_RCCTRL1_STA 0xfc
#define REG_RCCTRL0_STA 0xfd
#define MAX_RX_PKTS 80
static volatile uint8_t mRxBufs[MAX_RX_PKTS][RADIO_MAX_PACKET_LEN + 1 /* length */ + 2 /* RSSI, LQI/STA */];
static volatile uint8_t mRxNextWrite, mRxNextRead, mRxNumFree, mRxNumGot;
static uint8_t mRxFilterLongMac[8], mTxLongMac[8];
static uint32_t mRxFilterShortMac, mTxShortMac;
static bool mRxEnabled, mAutoAck, mPromisc;
static uint16_t mRxFilterPan, mTxPan;
static volatile int16_t mLastAck;
struct MacHeaderGenericAddr {
struct MacFcs fixed;
uint8_t seq;
} __attribute__((packed));
struct MacHeaderShortAddr {
struct MacFcs fixed;
uint8_t seq;
uint16_t pan;
uint16_t shortDstAddr;
} __attribute__((packed));
struct MacHeaderLongAddr {
struct MacFcs fixed;
uint8_t seq;
uint16_t pan;
uint8_t longDstAddr[8];
} __attribute__((packed));
void tiRadioTxConfigure(const uint8_t *myLongMac, uint32_t myShortMac, uint16_t pan) {
memcpy(mTxLongMac, myLongMac, sizeof(mTxLongMac));
mTxShortMac = myShortMac;
mTxPan = pan;
}
void tiRadioRxFilterCfg(const uint8_t *myMac, uint32_t myShortMac, uint16_t myPan, bool promisc) {
mPromisc = promisc;
mRxFilterShortMac = myShortMac;
mRxFilterPan = myPan;
memcpy(mRxFilterLongMac, myMac, sizeof(mRxFilterLongMac));
}
static bool tiRadioPrvSelect(void) {
digitalWrite(sub_CS, LOW);
SPI.beginTransaction(SPISettings(6000000, MSBFIRST, SPI_MODE0));
asm volatile("nop \n nop \n nop \n");
return true;
}
static void tiRadioPrvDeselect(void) {
asm volatile("nop \n nop \n nop \n");
SPI.endTransaction();
digitalWrite(sub_CS, HIGH);
asm volatile("nop \n nop \n nop \n");
}
static void read_multiple(uint8_t *dst, uint_fast8_t rxLen) {
for (int i = 0; i < rxLen; i++) {
dst[i] = SPI.transfer(0xff);
}
}
static int_fast16_t tiRadioPrvStrobe(uint8_t cmd) //negative on error
{
if (!tiRadioPrvSelect())
return -1;
cmd = SPI.transfer(cmd);
tiRadioPrvDeselect();
return (uint_fast16_t)cmd;
}
static bool tiRadioPrvRegWrite(uint_fast8_t reg, uint_fast8_t val) {
if (!tiRadioPrvSelect())
return false;
SPI.transfer(reg);
SPI.transfer(val);
tiRadioPrvDeselect();
return true;
}
static int_fast16_t tiRadioPrvRegRead(uint_fast8_t reg) {
uint8_t read_data = 0x00;
if (!tiRadioPrvSelect())
return -1;
SPI.transfer(reg | 0x80);
read_data = SPI.transfer(0xff);
tiRadioPrvDeselect();
return (uint_fast16_t)read_data;
}
static bool tiRadioPrvRegWriteLong(uint8_t reg, const uint8_t *valP, uint8_t len) {
if (!tiRadioPrvSelect())
return false;
SPI.transfer(reg | 0x40);
for (int i = 0; i < len; i++) {
SPI.transfer(valP[i]);
}
tiRadioPrvDeselect();
return true;
}
bool tiRadioRxEnable(bool on, bool autoAck) {
bool ret = false;
if (on) {
mAutoAck = autoAck;
if (mRxEnabled) {
ret = true;
goto out;
}
if (!tiRadioPrvStrobe(CMD_SRX))
goto out;
mRxEnabled = true;
} else if (mRxEnabled) {
if (!tiRadioPrvStrobe(CMD_SIDLE))
goto out;
mRxEnabled = false;
}
ret = true;
out:
return ret;
}
static bool radioPrvMacsEqual(const uint8_t *macA, const uint8_t *macB) {
const uint32_t *a = (const uint32_t *)(const char *)macA;
const uint32_t *b = (const uint32_t *)(const char *)macB;
return a[0] == b[0] && a[1] == b[1];
}
static uint_fast8_t tiRadioPrvGetState(void) {
uint_fast8_t state;
do {
state = tiRadioPrvRegRead(REG_MARCSTATE);
} while (tiRadioPrvRegRead(REG_MARCSTATE) != state);
return state;
}
static void tiRadioPrvPacketRx(void) {
uint8_t *rxedPkt = (uint8_t *)mRxBufs[mRxNextWrite];
const struct MacHeaderShortAddr *withShortDst = (const struct MacHeaderShortAddr *)(rxedPkt + 1);
const struct MacHeaderGenericAddr *generic = (const struct MacHeaderGenericAddr *)(rxedPkt + 1);
const struct MacHeaderLongAddr *withLongDst = (const struct MacHeaderLongAddr *)(rxedPkt + 1);
bool crcOk, acceptPacket, sendAck = false;
int32_t t, lenNoCrc, lenNoMacFixed;
uint32_t nWaitCycles = 10000;
uint_fast8_t spiLen, now;
t = tiRadioPrvRegRead(REG_FIFO);
if (t < 0)
goto fail;
if (!mRxNumFree)
goto fail;
spiLen = t;
if (spiLen > RADIO_MAX_PACKET_LEN)
goto fail;
t = 0;
rxedPkt[t++] = lenNoCrc = spiLen;
now = 31; //we just read one so 31 left for sure in the FIFO
spiLen += 2; //we expect 2 more bytes
while (spiLen) {
uint8_t reg;
if (!tiRadioPrvSelect()) {
tiRadioPrvDeselect();
goto fail;
}
reg = 0xc0 | REG_FIFO; //burst read
reg = SPI.transfer(reg);
now = reg & 0x0f;
if (now > spiLen)
now = spiLen;
if (!now && !--nWaitCycles) {
tiRadioPrvDeselect();
//Serial.printf(" !!! RX timeout !!! \r\n");
goto fail;
}
read_multiple(rxedPkt + t, now);
t += now;
spiLen -= now;
tiRadioPrvDeselect();
}
rxedPkt++; //skip len;
crcOk = !!(rxedPkt[lenNoCrc + 1] & 0x80);
lenNoMacFixed = lenNoCrc - sizeof(struct MacFcs) - sizeof(uint8_t);
if (mPromisc)
acceptPacket = true;
//otherwise, we need a valid crc
else if (!crcOk) {
acceptPacket = false;
}
//packet should be big enough to contain a header
else if (lenNoMacFixed < 0)
acceptPacket = false;
else switch (generic->fixed.frameType) {
case FRAME_TYPE_ACK:
mLastAck = (uint16_t)generic->seq;
acceptPacket = false; //no need to save it as a packet
break;
case FRAME_TYPE_DATA: //we are not the coordinator, so we demand to see our address as destination...
switch (generic->fixed.destAddrType) {
case ADDR_MODE_SHORT:
acceptPacket = (withShortDst->pan == 0xffff && withShortDst->shortDstAddr == 0xffff) || (withShortDst->pan == mRxFilterPan && (withShortDst->shortDstAddr == 0xffff || ((uint32_t)withShortDst->shortDstAddr) == mRxFilterShortMac));
break;
case ADDR_MODE_LONG:
acceptPacket = withLongDst->pan == mRxFilterPan && radioPrvMacsEqual(withLongDst->longDstAddr, mRxFilterLongMac);
break;
default:
acceptPacket = false;
break;
}
sendAck = generic->fixed.ackReqd && mAutoAck;
break;
default:
//no riff-raff please
acceptPacket = false;
break;
}
if (acceptPacket) { //other checks here too plz
if (sendAck) {
static struct {
uint8_t len;
struct MacFcs mac;
uint8_t seq;
} __attribute__((packed)) ack = {
.len = sizeof(ack) + sizeof(uint16_t) - sizeof(ack.len),
.mac = {
.frameType = FRAME_TYPE_ACK,
},
};
ack.seq = generic->seq;
tiRadioTxLL(&ack);
}
mRxNumFree--;
if (++mRxNextWrite == MAX_RX_PKTS)
mRxNextWrite = 0;
mRxNumGot++;
}
out:
if (mRxEnabled && !sendAck) { //if ack is being TXed, TX irq will restart rx later
uint32_t maxWait = 100000;
uint8_t state;
(void)tiRadioPrvStrobe(CMD_SRX);
do {
state = tiRadioPrvGetState();
if (!--maxWait) {
//Serial.printf("too long wait for rx state. state is %d\n", state);
break;
}
} while (state != 13 && state != 14 && state != 15);
}
return;
fail:
(void)tiRadioPrvStrobe(CMD_SFRX);
goto out;
}
void tiRadioRxAckReset(void) {
mLastAck = -1;
}
int16_t tiRadioRxAckGetLast(void) {
return mLastAck;
}
int32_t tiRadioRxDequeuePkt(void *dstBuf, uint32_t maxLen, int8_t *rssiP, uint8_t *lqiP) {
uint32_t len, copyLen = maxLen;
if (!mRxNumGot)
return -1;
len = mRxBufs[mRxNextRead][0];
if (copyLen > len)
copyLen = len;
memcpy(dstBuf, (const void *)(mRxBufs[mRxNextRead] + 1), copyLen);
if (lqiP) {
uint32_t lqi = 296 - ((mRxBufs[mRxNextRead][len + 2] & 0x7f) * 2);
//LQI: lower is better. 48 is very good (no lower value seen), 127 is very bad (max value possible)
//we want LQI 0..255 so we scale as SATURATE(296 - 2 * val)
if (lqi > 255)
lqi = 255;
*lqiP = lqi;
}
if (rssiP)
*rssiP = ((int8_t)mRxBufs[mRxNextRead][len + 1]) / 2 - 77;
if (++mRxNextRead == MAX_RX_PKTS)
mRxNextRead = 0;
noInterrupts();
mRxNumFree++;
mRxNumGot--;
interrupts();
//ti radio never stalls RX state machine so nothing to do even if we just freed up a buffer
return len;
}
void data_input_interrupt(void) {
while (digitalRead(sub_GD0)) //while there is data (packets)
tiRadioPrvPacketRx();
}
static void tiRadioPrvIfInit(void) {
//configure pins
pinMode(sub_CS, OUTPUT);
pinMode(sub_GD0, INPUT_PULLUP);
pinMode(sub_GD2, INPUT_PULLUP);
SPI.begin(sub_CLK, sub_MISO, sub_MOSI);
tiRadioPrvDeselect();
mRxNumFree = MAX_RX_PKTS;
}
static void tiRadioPrvIrqInit(void) {
attachInterrupt(sub_GD0, data_input_interrupt, RISING);
}
bool tiRadioSetChannel(uint_fast8_t channel) {
channel -= SUB_GHZ_CH_OFST;
if (channel >= SUB_GHZ_NUM_CHANNELS)
return false;
return tiRadioPrvRegWrite(REG_CHANNR, channel * 3);
}
bool tiRadioTxLL(const void *pkt) {
const uint8_t *data = (const uint8_t *)pkt;
uint32_t len = 1 + *data, now;
bool ret = false;
if (0) {
Serial.printf("TX packet len %u :", len);
for (int t = 0; t < len; t++) {
Serial.printf(" %02x", data[1 + t]);
}
Serial.printf("\n");
}
if (tiRadioPrvStrobe(CMD_SIDLE) < 0)
goto out;
if (tiRadioPrvStrobe(CMD_SFTX) < 0)
goto out;
now = (len > 64 ? 64 : len);
if (!tiRadioPrvRegWriteLong(REG_FIFO, data, now))
goto out;
len -= now;
data += now;
if (tiRadioPrvStrobe(CMD_STX) < 0)
goto out;
while (len) {
now = 8;
if (now > len)
now = len;
while (digitalRead(sub_GD2))
; //wait till there is space
if (!tiRadioPrvRegWriteLong(REG_FIFO, data, now))
goto out;
data += now;
len -= now;
}
while (tiRadioPrvGetState() != 1)
;
if (!tiRadioPrvStrobe(mRxEnabled ? CMD_SRX : CMD_SIDLE))
goto out;
ret = true;
out:
return ret;
}
bool init_subGhz(void) {
uint8_t regsCfg[] = {
/* 0x00 */ 0x02, 0x2e, 0x01, 0x07, 0xd3, 0x91, 0x7f, 0x04,
/* 0x08 */ 0x45, 0x22, 0x00, 0x0e, 0x00, 0x22, 0xbb, 0x13,
/* 0x10 */ 0x1d, 0x3b, 0x13, 0x43, 0xa4, 0x65, 0x07, 0x30,
/* 0x18 */ 0x1d, 0x1e, 0x1c, 0xc7, 0x00, 0xb0, 0x87, 0x6b,
/* 0x20 */ 0xfb, 0xb6, 0x10, 0xea, 0x2a, 0x00, 0x1f, 0x41,
/* 0x28 */ 0x00,
};
uint8_t paTab[] = { 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0 };
tiRadioPrvIfInit();
if (tiRadioPrvRegRead(REG_PARTNUM) != 0x00) {
Serial.printf("partnum is wrong\n");
return false;
}
if (tiRadioPrvStrobe(CMD_SRES) < 0) {
Serial.printf("res reply\n");
return false;
}
delayMicroseconds(300);
if (tiRadioPrvStrobe(CMD_SIDLE) != 0x0f) {
Serial.printf("idle reply\n");
return false;
}
if (!tiRadioPrvRegWriteLong(0, regsCfg, sizeof(regsCfg))) {
Serial.printf("config issue\n");
return false;
}
if (!tiRadioPrvRegWriteLong(REG_PATABLE, paTab, sizeof(paTab))) {
Serial.printf("PAtable issue\n");
return false;
}
tiRadioPrvIrqInit();
Serial.printf("Sub-GHz radio inited\n");
tiRadioRxEnable(true, false);
Serial.printf("Sub-GHz rx is on\n");
return true;
}

View File

@@ -0,0 +1,32 @@
// This code is heavily depending on Dmitrys wonderful Work !
// https://dmitry.gr/?r=05.Projects&proj=29.%20eInk%20Price%20Tags
// Ported and modified to fit the OpenEPaperLink Project by ATC1441 (ATCnetz.de) ~01.2024
#pragma once
#include <Arduino.h>
#include <stdbool.h>
void tiRadioTxConfigure(const uint8_t *myLongMac, uint32_t myShortMac, uint16_t pan);
void tiRadioRxFilterCfg(const uint8_t *myMac, uint32_t myShortMac, uint16_t myPan, bool promisc);
static bool tiRadioPrvSelect(void);
static void tiRadioPrvDeselect(void);
static void read_multiple(uint8_t *dst, uint_fast8_t rxLen);
static int_fast16_t tiRadioPrvStrobe(uint8_t cmd);
static bool tiRadioPrvRegWrite(uint_fast8_t reg, uint_fast8_t val);
static int_fast16_t tiRadioPrvRegRead(uint_fast8_t reg);
static bool tiRadioPrvRegWriteLong(uint8_t reg, const uint8_t *valP, uint8_t len);
bool tiRadioRxEnable(bool on, bool autoAck);
static bool radioPrvMacsEqual(const uint8_t *macA, const uint8_t *macB);
static uint_fast8_t tiRadioPrvGetState(void);
static void tiRadioPrvPacketRx(void);
void tiRadioRxAckReset(void);
int16_t tiRadioRxAckGetLast(void);
int32_t tiRadioRxDequeuePkt(void* dstBuf, uint32_t maxLen, int8_t *rssiP, uint8_t *lqiP);
void data_input_interrupt(void);
static void tiRadioPrvIfInit(void);
static void tiRadioPrvIrqInit(void);
bool tiRadioSetChannel(uint_fast8_t channel);
bool tiRadioTxLL(const void* pkt);
bool init_subGhz(void);

View File

@@ -0,0 +1,5 @@
makeit.exe clean all
flashing\telink_flasher.exe 1 8258 ac
rem flashing\telink_flasher.exe 1 8258 wf 0 -s 512k -e
flashing\telink_flasher.exe 1 8258 wf 0 -i TLSR_OpenEPaperLink.bin
flashing\telink_flasher.exe 1 8258 rst -f

View File

@@ -0,0 +1,53 @@
[MCU]
TYPE 3 0x0d = 8258 \bin\dut_8258_flash_v0003.bin 40000 b010b010 End
default = 8258 End
[MODE]
MODE 0x01 = USB End
MODE 0x04 = EVK End
default = EVK End
[OBJ]
OBJ 0x01 = FLASH End
OBJ 0x02 = CORE End
OBJ 0x03 = ANALOG End
OBJ 0x04 = OTP End
default = CORE End
[SIZE]
SIZE 0x01 = 1 End
SIZE 0x02 = 2 End
SIZE 0x03 = 4 End
SIZE 0x04 = 8 End
SIZE 0x05 = 16 End
default = 1 End
[DOWNLOAD_ADDR]
DOWNLOAD 0x01 = 0 End
DOWNLOAD 0x02 = 20000 End
DOWNLOAD 0x03 = 40000 End
default = 0 End
[ERASE_ADDR]
ERASE 0x01 = 0 End
ERASE 0x02 = 20000 End
ERASE 0x03 = 40000 End
default = 0 End
[ERASE_SIZE]
SIZE 0x01 = 4 End
SIZE 0x02 = 16 End
SIZE 0x03 = 64 End
SIZE 0x04 = 128 End
SIZE 0x05 = 512 End
default = 512 End
[PAGE_DISPLAY]
PAGE 0x01 = 0 Download End
PAGE 0x02 = 1 Tdebug End
PAGE 0x03 = 2 Log windows End
default = 0 End
[SECTION]
SECTION 0x01 = .data End
SECTION 0x02 = .bss End
SECTION 0x03 = .retention_data End
SECTION 0x04 = .retention_bss End
SECTION 0x05 = .no_ret_data End
SECTION 0x06 = .no_ret_bss End
default End
[BUTTON]
[PATH]

Binary file not shown.

View File

@@ -0,0 +1,13 @@
# Add inputs and outputs from these tool invocations to the build variables
OUT_DIR += \
/platform/tc32
OBJS += \
$(OUT_PATH)/platform/tc32/div_mod.o
# Each subdirectory must supply rules for building sources it contributes
$(OUT_PATH)/platform/tc32/%.o: $(SDK_PATH)/platform/tc32/%.S
@echo 'Building file: $<'
@$(CC) $(BOOT_FLAG) $(INCLUDE_PATHS) -c -o"$@" "$<"

View File

@@ -0,0 +1,28 @@
# Add inputs and outputs from these tool invocations to the build variables
OUT_DIR += \
/platform/chip_8258 \
/platform/chip_8258/flash \
/platform/services/b85m
OBJS += \
$(OUT_PATH)/platform/chip_8258/flash.o \
$(OUT_PATH)/platform/chip_8258/adc.o \
$(OUT_PATH)/platform/chip_8258/flash/flash_mid011460c8.o \
$(OUT_PATH)/platform/chip_8258/flash/flash_mid1060c8.o \
$(OUT_PATH)/platform/chip_8258/flash/flash_mid13325e.o \
$(OUT_PATH)/platform/chip_8258/flash/flash_mid134051.o \
$(OUT_PATH)/platform/chip_8258/flash/flash_mid136085.o \
$(OUT_PATH)/platform/chip_8258/flash/flash_mid1360c8.o \
$(OUT_PATH)/platform/chip_8258/flash/flash_mid1360eb.o \
$(OUT_PATH)/platform/chip_8258/flash/flash_mid14325e.o \
$(OUT_PATH)/platform/chip_8258/flash/flash_mid1460c8.o \
$(OUT_PATH)/platform/services/b85m/irq_handler.o
# Each subdirectory must supply rules for building sources it contributes
$(OUT_PATH)/platform/%.o: $(SDK_PATH)/platform/%.c
@echo 'Building file: $<'
@$(CC) $(GCC_FLAGS) $(INCLUDE_PATHS) -c -o"$@" "$<"

View File

@@ -0,0 +1,16 @@
# Add inputs and outputs from these tool invocations to the build variables
OUT_DIR += \
/platform/boot \
/platform/boot/8258
OBJS += \
$(OUT_PATH)/platform/boot/link_cfg.o \
$(OUT_PATH)/platform/boot/8258/cstartup_8258.o
# Each subdirectory must supply rules for building sources it contributes
$(OUT_PATH)/platform/boot/%.o: $(SDK_PATH)/platform/boot/%.S
@echo 'Building file: $<'
@$(CC) $(BOOT_FLAG) $(INCLUDE_PATHS) -c -o"$@" "$<"

View File

@@ -0,0 +1,40 @@
# Add inputs and outputs from these tool invocations to the build variables
OUT_DIR += \
/proj/common \
/proj/drivers \
/proj/drivers/usb \
/proj/os
OBJS += \
$(OUT_PATH)/proj/common/list.o \
$(OUT_PATH)/proj/common/mempool.o \
$(OUT_PATH)/proj/common/string.o \
$(OUT_PATH)/proj/common/tlPrintf.o \
$(OUT_PATH)/proj/common/utility.o \
$(OUT_PATH)/proj/drivers/drv_adc.o \
$(OUT_PATH)/proj/drivers/drv_calibration.o \
$(OUT_PATH)/proj/drivers/drv_flash.o \
$(OUT_PATH)/proj/drivers/drv_gpio.o \
$(OUT_PATH)/proj/drivers/drv_hw.o \
$(OUT_PATH)/proj/drivers/drv_i2c.o \
$(OUT_PATH)/proj/drivers/drv_keyboard.o \
$(OUT_PATH)/proj/drivers/drv_nv.o \
$(OUT_PATH)/proj/drivers/drv_pm.o \
$(OUT_PATH)/proj/drivers/drv_pwm.o \
$(OUT_PATH)/proj/drivers/drv_spi.o \
$(OUT_PATH)/proj/drivers/drv_timer.o \
$(OUT_PATH)/proj/drivers/drv_uart.o \
$(OUT_PATH)/proj/os/ev.o \
$(OUT_PATH)/proj/os/ev_buffer.o \
$(OUT_PATH)/proj/os/ev_poll.o \
$(OUT_PATH)/proj/os/ev_queue.o \
$(OUT_PATH)/proj/os/ev_timer.o
# Each subdirectory must supply rules for building sources it contributes
$(OUT_PATH)/proj/%.o: $(SDK_PATH)/proj/%.c
@echo 'Building file: $<'
@$(CC) $(GCC_FLAGS) $(INCLUDE_PATHS) -c -o"$@" "$<"

View File

@@ -0,0 +1,143 @@
PROJECT_NAME := TLSR_OpenEPaperLink
ifeq ($(OS), Windows_NT)
TC32_COMPILER_PATH := "tc32_windows\\bin\\"
WINDOWS_PREFIX :=$(TC32_COMPILER_PATH)
LINUX_CHMOD :=
else
TC32_COMPILER_PATH := ./tc32_linux/bin/
WINDOWS_PREFIX :=
LINUX_CHMOD := chmod 777 -R ./tc32_linux/
endif
AS = $(TC32_COMPILER_PATH)tc32-elf-as
CC = $(TC32_COMPILER_PATH)tc32-elf-gcc
LD = $(TC32_COMPILER_PATH)tc32-elf-ld
NM = $(TC32_COMPILER_PATH)tc32-elf-nm
OBJCOPY = $(TC32_COMPILER_PATH)tc32-elf-objcopy
OBJDUMP = $(TC32_COMPILER_PATH)tc32-elf-objdump
ARCH = $(TC32_COMPILER_PATH)tc32-elf-ar
SIZE = $(TC32_COMPILER_PATH)tc32-elf-size
LIBS := -ldrivers_8258
DEVICE_TYPE = -DEND_DEVICE=1
MCU_TYPE = -DMCU_CORE_8258=1
BOOT_FLAG = -DMCU_CORE_8258 -DMCU_STARTUP_8258
SDK_PATH := ./tl_zigbee_sdk
SRC_PATH := ./src
OUT_PATH := ./out
MAKE_INCLUDES := ./make
INCLUDE_PATHS := \
-I$(SDK_PATH)/platform \
-I$(SDK_PATH)/proj/common \
-I$(SDK_PATH)/proj \
-I$(SDK_PATH)/zbhci \
-I$(SRC_PATH) \
-I./common
LS_FLAGS := $(SDK_PATH)/platform/boot/8258/boot_8258.link
GCC_FLAGS := \
-ffunction-sections \
-fdata-sections \
-Wall \
-O2 \
-fpack-struct \
-fshort-enums \
-finline-small-functions \
-std=gnu99 \
-fshort-wchar \
-fms-extensions
GCC_FLAGS += \
$(DEVICE_TYPE) \
$(MCU_TYPE) \
-D__PROJECT_TL_SWITCH__=1
OBJ_SRCS :=
S_SRCS :=
ASM_SRCS :=
C_SRCS :=
S_UPPER_SRCS :=
O_SRCS :=
FLASH_IMAGE :=
ELFS :=
OBJS :=
LST :=
SIZEDUMMY :=
RM := $(WINDOWS_PREFIX)rm -rf
# All of the sources participating in the build are defined here
-include $(MAKE_INCLUDES)/proj.mk
-include $(MAKE_INCLUDES)/platformS.mk
-include $(MAKE_INCLUDES)/div_mod.mk
-include $(MAKE_INCLUDES)/platform.mk
-include ./project.mk
# Add inputs and outputs from these tool invocations to the build variables
LST_FILE := $(OUT_PATH)/$(PROJECT_NAME).lst
BIN_FILE := $(OUT_PATH)/../$(PROJECT_NAME).bin
ELF_FILE := $(OUT_PATH)/$(PROJECT_NAME).elf
SIZEDUMMY += \
sizedummy \
# All Target
all: chmod_all pre-build main-build
# Main-build Target
main-build: $(ELF_FILE) secondary-outputs
# Tool invocations
$(ELF_FILE): $(OBJS) $(USER_OBJS)
@echo 'Building target: $@'
@echo 'Invoking: TC32 C Linker'
$(LD) --gc-sections -L $(SDK_PATH)/zigbee/lib/tc32 -L $(SDK_PATH)/platform/lib -T $(LS_FLAGS) -o "$(ELF_FILE)" $(OBJS) $(USER_OBJS) $(LIBS)
@echo 'Finished building target: $@'
@echo ' '
$(LST_FILE): $(ELF_FILE)
@echo 'Invoking: TC32 Create Extended Listing'
$(OBJDUMP) -x -D -l -S $(ELF_FILE) > $(LST_FILE)
@echo 'Finished building: $@'
@echo ' '
$(BIN_FILE): $(ELF_FILE)
@echo 'Create Flash image (binary format)'
@$(OBJCOPY) -v -O binary $(ELF_FILE) $(BIN_FILE)
@echo 'Finished building: $@'
@echo ' '
sizedummy: $(ELF_FILE)
@echo 'Invoking: Print Size'
@$(SIZE) -t $(ELF_FILE)
@echo 'Finished building: $@'
@echo ' '
clean:
-$(RM) $(FLASH_IMAGE) $(ELFS) $(OBJS) $(SIZEDUMMY) $(LST_FILE) $(ELF_FILE) $(BIN_FILE)
-@echo ' '
pre-build:
$(WINDOWS_PREFIX)mkdir -p $(foreach s,$(OUT_DIR),$(OUT_PATH)$(s))
-@echo ' '
chmod_all:
-@$(LINUX_CHMOD)
-@echo 'chmod_all'
secondary-outputs: $(BIN_FILE) $(LST_FILE) $(FLASH_IMAGE) $(SIZEDUMMY)
.PHONY: all clean dependents pre-build
.SECONDARY: main-build pre-build

Binary file not shown.

View File

@@ -0,0 +1,34 @@
# Add inputs and outputs from these tool invocations to the build variables
OUT_DIR += \
/$(SRC_PATH) \
OBJS += \
$(OUT_PATH)/$(SRC_PATH)/main.o \
$(OUT_PATH)/$(SRC_PATH)/epd_spi.o \
$(OUT_PATH)/$(SRC_PATH)/epd.o \
$(OUT_PATH)/$(SRC_PATH)/epd_bw_213.o \
$(OUT_PATH)/$(SRC_PATH)/epd_bwr_213.o \
$(OUT_PATH)/$(SRC_PATH)/epd_bwr_350.o \
$(OUT_PATH)/$(SRC_PATH)/epd_bwy_350.o \
$(OUT_PATH)/$(SRC_PATH)/epd_bw_213_ice.o \
$(OUT_PATH)/$(SRC_PATH)/epd_bwr_154.o \
$(OUT_PATH)/$(SRC_PATH)/led.o \
$(OUT_PATH)/$(SRC_PATH)/i2c.o \
$(OUT_PATH)/$(SRC_PATH)/battery.o \
$(OUT_PATH)/$(SRC_PATH)/nfc.o \
$(OUT_PATH)/$(SRC_PATH)/uart.o \
$(OUT_PATH)/$(SRC_PATH)/one_bit_display.o \
$(OUT_PATH)/$(SRC_PATH)/eeprom.o \
$(OUT_PATH)/$(SRC_PATH)/zigbee.o \
$(OUT_PATH)/$(SRC_PATH)/comms.o \
$(OUT_PATH)/$(SRC_PATH)/drawing.o \
$(OUT_PATH)/$(SRC_PATH)/syncedproto.o \
$(OUT_PATH)/$(SRC_PATH)/wdt.o \
$(OUT_PATH)/$(SRC_PATH)/powermgt.o \
# Each subdirectory must supply rules for building sources it contributes
$(OUT_PATH)/$(SRC_PATH)/%.o: $(SRC_PATH)/%.c
@echo 'Building file: $<'
@$(CC) $(GCC_FLAGS) $(INCLUDE_PATHS) -c -o"$@" "$<"

View File

@@ -0,0 +1,822 @@
//
// OneBitDisplay (OLED+LCD library)
// Copyright (c) 2020 BitBank Software, Inc.
// Written by Larry Bank (bitbank@pobox.com)
// Project started 3/23/2020
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
#ifdef _LINUX_
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// convert wire library constants into ArmbianIO values
#define OUTPUT GPIO_OUT
#define INPUT GPIO_IN
#define INPUT_PULLUP GPIO_IN_PULLUP
#define HIGH 1
#define LOW 0
void delay(int);
#else // Arduino
#include <Arduino.h>
#ifdef __AVR__
#include <avr/pgmspace.h>
#endif
#include <SPI.h>
#endif // _LINUX_
#include "OneBitDisplay.h"
// All of the drawing code is in here
#include "obd.inl"
// Initialization sequences
const unsigned char oled128_initbuf[] PROGMEM = {0x00, 0xae,0xdc,0x00,0x81,0x40,
0xa1,0xc8,0xa8,0x7f,0xd5,0x50,0xd9,0x22,0xdb,0x35,0xb0,0xda,0x12,
0xa4,0xa6,0xaf};
const unsigned char oled64x128_initbuf[] PROGMEM ={
0x00, 0xae, 0xd5, 0x51, 0x20, 0xa8, 0x3f, 0xdc, 0x00, 0xd3, 0x60, 0xad, 0x80, 0xa6, 0xa4, 0xa0, 0xc0, 0x81, 0x40, 0xd9, 0x22, 0xdb, 0x35, 0xaf
};
const unsigned char oled132_initbuf[] PROGMEM = {0x00,0xae,0x02,0x10,0x40,0x81,0xa0,0xc0,0xa6,0xa8,0x3f,0xd3,0x00,0xd5,0x80,0xd9,0xf1,0xda,0x12,0xdb,0x40,0x20,0x02,0xa4,0xa6};
const unsigned char oled64_initbuf[] PROGMEM ={0x00,0xae,0xa8,0x3f,0xd3,0x00,0x40,0xa1,0xc8,
0xda,0x12,0x81,0xff,0xa4,0xa6,0xd5,0x80,0x8d,0x14,
0xaf,0x20,0x02};
const unsigned char oled32_initbuf[] PROGMEM = {
0x00,0xae,0xd5,0x80,0xa8,0x1f,0xd3,0x00,0x40,0x8d,0x14,0xa1,0xc8,0xda,0x02,
0x81,0x7f,0xd9,0xf1,0xdb,0x40,0xa4,0xa6,0xaf};
const unsigned char oled72_initbuf[] PROGMEM ={0x00,0xae,0xa8,0x3f,0xd3,0x00,0x40,0xa1,0xc8,
0xda,0x12,0x81,0xff,0xad,0x30,0xd9,0xf1,0xa4,0xa6,0xd5,0x80,0x8d,0x14,
0xaf,0x20,0x02};
const unsigned char uc1701_initbuf[] PROGMEM = {0xe2, 0x40, 0xa0, 0xc8, 0xa2, 0x2c, 0x2e, 0x2f, 0xf8, 0x00, 0x23, 0x81, 0x28, 0xac, 0x00, 0xa6};
const unsigned char hx1230_initbuf[] PROGMEM = {0x2f, 0x90, 0xa6, 0xa4, 0xaf, 0x40, 0xb0, 0x10, 0x00};
const unsigned char nokia5110_initbuf[] PROGMEM = {0x21, 0xa4, 0xb1, 0x04,0x14,0x20,0x0c};
static void obdCachedFlush(OBDISP *pOBD, int bRender);
static void obdCachedWrite(OBDISP *pOBD, uint8_t *pData, uint8_t u8Len, int bRender);
void obdSetPosition(OBDISP *pOBD, int x, int y, int bRender);
void obdWriteCommand(OBDISP *pOBD, unsigned char c);
void obdWriteDataBlock(OBDISP *pOBD, unsigned char *ucBuf, int iLen, int bRender);
//static void SPI_BitBang(OBDISP *pOBD, uint8_t *pData, int iLen, uint8_t iMOSIPin, uint8_t iSCKPin);
//
// Draw the contents of a memory buffer onto a display
// The sub-window will be clipped if it specifies too large an area
// for the destination display. The source OBDISP structure must have
// a valid back buffer defined
// The top and bottom destination edges will be drawn on byte boundaries (8 rows)
// The source top/bot edges can be on pixel boundaries
// This can be used for partial screen updates
//
void obdDumpWindow(OBDISP *pOBDSrc, OBDISP *pOBDDest, int srcx, int srcy, int destx, int desty, int width, int height)
{
uint8_t *s,ucTemp[32]; // temp buffer to gather source pixels
int x, y, tx, i;
int iPitch;
if (pOBDSrc == NULL || pOBDDest == NULL || pOBDSrc->ucScreen == NULL)
return; // invalid pointers
if (width > pOBDDest->width)
width = pOBDDest->width;
if (height > pOBDDest->height)
height = pOBDDest->height;
iPitch = pOBDSrc->width;
for (y=0; y<height; y+=8)
{
obdSetPosition(pOBDDest, destx, (desty+y)/8, 1);
for (x=0; x<width; x+=32)
{
tx = 32;
if (width-x < 32) tx = width-x;
s = &pOBDSrc->ucScreen[((srcy+y)/8)*iPitch + srcx+x];
if (srcy & 7) // need to shift the bits to get 8 rows of src data
{
uint8_t uc, ucShift = srcy & 7;
for (i=0; i<tx; i++)
{ // combine current and next line to capture 8 pixels
uc = s[0] >> ucShift;
uc |= s[iPitch] << (7-ucShift);
ucTemp[i] = uc;
}
obdCachedWrite(pOBDDest, ucTemp, tx, 1);
}
else
{ // simpler case
obdCachedWrite(pOBDDest, s, tx, 1); // just copy it
}
} // for x
} // for y
obdCachedFlush(pOBDDest, 1);
} /* obdDumpWindow() */
//
// Write a single line to a Sharp memory LCD
// You must provide the exact number of bytes needed for a complete line
// e.g. for the 144x168 display, pSrc must provide 144 pixels (18 bytes)
//
void obdWriteLCDLine(OBDISP *pOBD, uint8_t *pSrc, int iLine)
{
int x;
uint8_t c, ucInvert, *d, ucStart;
uint8_t ucLineBuf[54]; // 400 pixels is max supported width = 50 bytes + 4
int iPitch = pOBD->width / 8;
static int iVCOM = 0;
// if (pOBD == NULL || pSrc == NULL || pOBD->type < SHARP_144x168)
// return; // invalid request
if (iLine < 0 || iLine >= pOBD->height)
return;
ucInvert = (pOBD->invert) ? 0x00 : 0xff;
digitalWrite(pOBD->iCSPin, HIGH); // active high
ucStart = 0x80; // write command
iVCOM++;
if (iVCOM & 0x100) // flip it every 256 lines
ucStart |= 0x40; // VCOM bit
ucLineBuf[1] = ucStart;
// this code assumes I2C, so the first byte is ignored
_I2CWrite(pOBD, ucLineBuf, 2); // write command(01) + vcom(02)
d = &ucLineBuf[2];
ucLineBuf[1] = pgm_read_byte(&ucMirror[iLine+1]); // current line number
for (x=0; x<iPitch; x++)
{
c = pSrc[0] ^ ucInvert; // we need to brute-force invert it
*d++ = pgm_read_byte(&ucMirror[c]);
pSrc++;
} // for x
// write this line to the display
ucLineBuf[iPitch+2] = 0; // end of line
_I2CWrite(pOBD, ucLineBuf, iPitch+3);
ucLineBuf[1] = 0;
_I2CWrite(pOBD, ucLineBuf, 2); // final transfer
digitalWrite(pOBD->iCSPin, LOW); // de-activate
} /* obdWriteLCDLine() */
//
// Turn the display on or off
//
void obdPower(OBDISP *pOBD, int bOn)
{
uint8_t ucCMD;
if (pOBD->type == LCD_NOKIA5110)
ucCMD = (bOn) ? 0x20 : 0x24;
else // all other supported displays
ucCMD = (bOn) ? 0xaf : 0xae;
obdWriteCommand(pOBD, ucCMD);
} /* obdPower() */
// Controls the LED backlight
void obdBacklight(OBDISP *pOBD, int bOn)
{
if (pOBD->iLEDPin != 0xff)
{
digitalWrite(pOBD->iLEDPin, (bOn) ? HIGH:LOW);
}
} /* obdBacklight() */
//
// Initialize the display controller on an SPI bus
//
void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int bBitBang, int32_t iSpeed)
{
} /* obdSPIInit() */
//
// Set the memory configuration to display the pixels at 0 or 180 degrees (flipped)
// Pass true (1) to flip 180, false (0) to set to 0
//
void obdSetFlip(OBDISP *pOBD, int iOnOff)
{
if (pOBD == NULL) return;
pOBD->flip = iOnOff;
if (pOBD->type == LCD_UC1701 || pOBD->type == LCD_UC1609)
{
if (iOnOff) // rotate display 180
{
obdWriteCommand(pOBD, 0xa1); // SEG direction (A1 to flip horizontal)
obdWriteCommand(pOBD, 0xc0); // COM direction (C0 to flip vert)
} else { // non-rotated
obdWriteCommand(pOBD, 0xa0);
obdWriteCommand(pOBD, 0xc8);
}
} else { // OLEDs
if (iOnOff)
{
obdWriteCommand(pOBD, 0xa0);
obdWriteCommand(pOBD, 0xc0);
} else {
obdWriteCommand(pOBD, 0xa1);
obdWriteCommand(pOBD, 0xc8);
}
}
} /* obdSetFlip() */
//
// Initializes the OLED controller into "page mode"
//
int obdI2CInit(OBDISP *pOBD, int iType, int iAddr, int bFlip, int bInvert, int bWire, int sda, int scl, int reset, int32_t iSpeed)
{
return 0;
} /* obdInit() */
//
// Sends a command to turn on or off the OLED display
//
void oledPower(OBDISP *pOBD, uint8_t bOn)
{
if (bOn)
obdWriteCommand(pOBD, 0xaf); // turn on OLED
else
obdWriteCommand(pOBD, 0xae); // turn off OLED
} /* oledPower() */
#ifdef _LINUX_
void delay(int iDelay)
{
// usleep(iDelay * 1000);
} /* delay() */
void delayMicroseconds(int iDelay)
{
//usleep(iDelay);
} /* delayMicroseconds() */
#endif // _LINUX_
//
// Bit Bang the data on GPIO pins
//
void SPI_BitBang(OBDISP *pOBD, uint8_t *pData, int iLen, uint8_t iMOSIPin, uint8_t iSCKPin)
{
int i;
uint8_t c;
// We can access the GPIO ports much quicker on AVR by directly manipulating
// the port registers
#ifdef __AVR__
volatile uint8_t *outSCK, *outMOSI; // port registers for fast I/O
uint8_t port, bitSCK, bitMOSI; // bit mask for the chosen pins
port = digitalPinToPort(iMOSIPin);
outMOSI = portOutputRegister(port);
bitMOSI = digitalPinToBitMask(iMOSIPin);
port = digitalPinToPort(iSCKPin);
outSCK = portOutputRegister(port);
bitSCK = digitalPinToBitMask(iSCKPin);
#endif
while (iLen)
{
c = *pData++;
if (pOBD->iDCPin == 0xff) // 3-wire SPI, write D/C bit first
{
#ifdef __AVR__
if (pOBD->mode == MODE_DATA)
*outMOSI |= bitMOSI;
else
*outMOSI &= ~bitMOSI;
*outSCK |= bitSCK; // toggle clock
*outSCK &= ~bitSCK; // no delay needed on SPI devices since AVR is slow
#else
digitalWrite(iMOSIPin, (pOBD->mode == MODE_DATA));
digitalWrite(iSCKPin, HIGH);
delayMicroseconds(0);
digitalWrite(iSCKPin, LOW);
#endif
}
if (c == 0 || c == 0xff) // quicker for all bits equal
{
#ifdef __AVR__
if (c & 1)
*outMOSI |= bitMOSI;
else
*outMOSI &= ~bitMOSI;
for (i=0; i<8; i++)
{
*outSCK |= bitSCK;
*outSCK &= ~bitSCK;
}
#else
digitalWrite(iMOSIPin, (c & 1));
for (i=0; i<8; i++)
{
digitalWrite(iSCKPin, HIGH);
delayMicroseconds(0);
digitalWrite(iSCKPin, LOW);
}
#endif
}
else
{
for (i=0; i<8; i++)
{
#ifdef __AVR__
if (c & 0x80) // MSB first
*outMOSI |= bitMOSI;
else
*outMOSI &= ~bitMOSI;
*outSCK |= bitSCK;
c <<= 1;
*outSCK &= ~bitSCK;
#else
digitalWrite(iMOSIPin, (c & 0x80) != 0); // MSB first
digitalWrite(iSCKPin, HIGH);
c <<= 1;
delayMicroseconds(0);
digitalWrite(iSCKPin, LOW);
#endif
}
}
iLen--;
}
} /* SPI_BitBang() */
// Sets the D/C pin to data or command mode
void obdSetDCMode(OBDISP *pOBD, int iMode)
{
if (pOBD->iDCPin == 0xff) // 9-bit SPI
pOBD->mode = (uint8_t)iMode;
else // set the GPIO line
digitalWrite(pOBD->iDCPin, (iMode == MODE_DATA));
} /* obdSetDCMode() */
static void obdWriteCommand2(OBDISP *pOBD, unsigned char c, unsigned char d)
{
unsigned char buf[4];
if (pOBD->com_mode == COM_I2C) {// I2C device
buf[0] = 0x00;
buf[1] = c;
buf[2] = d;
_I2CWrite(pOBD, buf, 3);
} else { // must be SPI
obdWriteCommand(pOBD, c);
obdWriteCommand(pOBD, d);
}
} /* obdWriteCommand2() */
//
// Sets the brightness (0=off, 255=brightest)
//
void obdSetContrast(OBDISP *pOBD, unsigned char ucContrast)
{
if (pOBD->type == LCD_HX1230)
{ // valid values are 0-31, so scale it
ucContrast >>= 3;
obdWriteCommand(pOBD, 0x80 + ucContrast);
}
else if (pOBD->type == LCD_NOKIA5110)
{
// we allow values of 0xb0-0xbf, so shrink the range
ucContrast >>= 4;
obdWriteCommand(pOBD, 0x21); // set advanced command mode
obdWriteCommand(pOBD, 0xb0 | ucContrast);
obdWriteCommand(pOBD, 0x20); // set simple command mode
}
else // OLEDs + UC1701
obdWriteCommand2(pOBD, 0x81, ucContrast);
} /* obdSetContrast() */
//
// Special case for Sharp Memory LCD
//
static void SharpDumpBuffer(OBDISP *pOBD, uint8_t *pBuffer)
{
int x, y;
uint8_t c, ucInvert, *s, *d, ucStart;
uint8_t ucLineBuf[56];
int iPitch = pOBD->width / 8;
static uint8_t ucVCOM = 0;
int iBit;
uint8_t ucMask;
ucInvert = (pOBD->invert) ? 0x00 : 0xff;
digitalWrite(pOBD->iCSPin, HIGH); // active high
ucLineBuf[0] = 0;
ucStart = 0x80; // write command
if (ucVCOM)
ucStart |= 0x40; // VCOM bit
ucLineBuf[1] = ucStart;
// this code assumes I2C, so the first byte is ignored
_I2CWrite(pOBD, ucLineBuf, 2); // write command(01) + vcom(02)
ucVCOM = !ucVCOM; // need to toggle this each transaction
// We need to flip and invert the image in code because the Sharp memory LCD
// controller only has the simplest of commands for data writing
if (pOBD->flip)
{
for (y=0; y<pOBD->height; y++) // we have to write the memory in the wrong direction
{
ucMask = 0x80 >> (y & 7);
s = &pBuffer[pOBD->width - 1 + (pOBD->width * ((pOBD->height - 1 - y) >> 3))]; // point to last line first
d = &ucLineBuf[2];
ucLineBuf[1] = pgm_read_byte(&ucMirror[y+1]); // current line number
for (x=0; x<pOBD->width/8; x++)
{
c = ucInvert; // we need to brute-force invert it
for (iBit=7; iBit>=0; iBit--)
{
if (s[0] & ucMask)
c ^= (1 << iBit);
s--;
}
*d++ = c;
} // for y
// write this line to the display
ucLineBuf[iPitch+2] = 0; // end of line
_I2CWrite(pOBD, ucLineBuf, iPitch+3);
} // for x
}
else // normal orientation
{
for (y=0; y<pOBD->height; y++) // we have to write the memory in the wrong direction
{
ucMask = 1 << (y & 7);
s = &pBuffer[pOBD->width * (y >> 3)]; // point to last line first
d = &ucLineBuf[2];
ucLineBuf[1] = pgm_read_byte(&ucMirror[y+1]); // current line number
for (x=0; x<pOBD->width/8; x++)
{
c = ucInvert;
for (iBit=7; iBit>=0; iBit--)
{
if (s[0] & ucMask)
c ^= (1 << iBit);
s++;
}
*d++ = c;
} // for y
// write this line to the display
ucLineBuf[iPitch+2] = 0; // end of line
_I2CWrite(pOBD, ucLineBuf, iPitch+3);
} // for x
}
ucLineBuf[1] = 0;
_I2CWrite(pOBD, ucLineBuf, 2); // final transfer
digitalWrite(pOBD->iCSPin, LOW); // de-activate
} /* SharpDumpBuffer() */
//
// Dump a screen's worth of data directly to the display
// Try to speed it up by comparing the new bytes with the existing buffer
//
void obdDumpBuffer(OBDISP *pOBD, uint8_t *pBuffer)
{
int x, y, iPitch;
int iLines, iCols;
uint8_t bNeedPos;
uint8_t *pSrc = pOBD->ucScreen;
iPitch = pOBD->width;
if (pOBD->type == LCD_VIRTUAL) // wrong function for this type of display
return;
if (pBuffer == NULL) // dump the internal buffer if none is given
pBuffer = pOBD->ucScreen;
if (pBuffer == NULL)
return; // no backbuffer and no provided buffer
if (pOBD->type >= SHARP_144x168) // special case for Sharp Memory LCD
{
SharpDumpBuffer(pOBD, pBuffer);
return;
}
iLines = pOBD->height >> 3;
iCols = pOBD->width >> 4;
for (y=0; y<iLines; y++)
{
bNeedPos = 1; // start of a new line means we need to set the position too
for (x=0; x<iCols; x++) // wiring library has a 32-byte buffer, so send 16 bytes so that the data prefix (0x40) can fit
{
if (pOBD->ucScreen == NULL || pBuffer == pSrc || memcmp(pSrc, pBuffer, 16) != 0) // doesn't match, need to send it
{
if (bNeedPos) // need to reposition output cursor?
{
bNeedPos = 0;
obdCachedFlush(pOBD, 1);
obdSetPosition(pOBD, x*16, y, 1);
}
obdCachedWrite(pOBD, pBuffer, 16, 1);
}
else
{
bNeedPos = 1; // we're skipping a block, so next time will need to set the new position
}
pSrc += 16;
pBuffer += 16;
} // for x
pSrc += (iPitch - pOBD->width); // for narrow displays, skip to the next line
pBuffer += (iPitch - pOBD->width);
} // for y
obdCachedFlush(pOBD, 1);
} /* obdDumpBuffer() */
//
// Menu functions are not (yet) supported on Linux
//
#ifndef _LINUX_
// A valid CW or CCW move returns 1 or -1, invalid returns 0.
static int obdMenuReadRotary(SIMPLEMENU *sm) {
static int8_t rot_enc_table[] = {0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0};
uint8_t c;
int rc = 0;
sm->prevNextCode <<= 2;
if (digitalRead(sm->u8Dn) == sm->iPressed)
sm->prevNextCode |= 0x02;
if (digitalRead(sm->u8Up) == sm->iPressed)
sm->prevNextCode |= 0x01;
sm->prevNextCode &= 0x0f;
// If valid then store as 16 bit data.
if (rot_enc_table[sm->prevNextCode]) {
sm->store <<= 4;
sm->store |= sm->prevNextCode;
c = sm->store & 0xff;
//if (store==0xd42b) return 1;
//if (store==0xe817) return -1;
if ((c & 0xf) == 2) rc = -1;
else if ((c & 0xf) == 1) rc = 1;
}
// Serial.printf("store = 0x%04x, val = %d\r\n", sm->store, rc);
return rc;
} /* obdMenuReadRotary() */
//
// Initialize the simple menu structure
//
int obdMenuInit(OBDISP *pOBD, SIMPLEMENU *sm, char **pText, int iFontSize, int bCenter, int btnUp, int btnDn, int btnEnter, int iPressedState, int bIsRotary)
{
int iLen;
if (sm == NULL || pText == NULL) return 0;
sm->pOBD = pOBD;
sm->u8Up = btnUp; // pin numbers of the action buttons
sm->u8Dn = btnDn; // or rotary A line
sm->u8Enter = btnEnter; // or rotary B line
sm->bIsRotary = bIsRotary;
sm->u8BtnState = 0; // no active buttons to start
sm->iPressed = iPressedState; // active state of a pressed button
sm->bCenter = bCenter;
sm->iFontSize = iFontSize;
sm->pMenuText = pText;
sm->iMenuIndex = 0; // start at first item
sm->iDispX = 128; // DEBUG
sm->iDispY = 64; // DEBUG
sm->bOneButton = (btnDn == -1 && btnEnter == -1); // only 1 button defined
sm->pfnCallback = NULL;
sm->prevNextCode = 0;
sm->store = 0;
iLen = 0;
while (pText[iLen] != NULL) {
iLen++;
}
sm->iMenuLen = iLen-1; // don't count the title text
return 1; // success
} /* obdMenuInit() */
//
// Get the text and centering position for
// a specific menu item
// returns the X position
//
static int obdMenuGetItem(SIMPLEMENU *sm, int iItem, char *szText)
{
int x, cx, len;
if (iItem > sm->iMenuLen)
return -1; // invalid request
if (sm->iFontSize == FONT_6x8)
cx = 6;
else if (sm->iFontSize == FONT_8x8)
cx = 8;
else cx = 16;
strcpy(szText, sm->pMenuText[iItem]);
if (sm->pfnCallback && iItem > 0) // don't add callback for menu title
{
strcat(szText, " ");
strcat(szText, (*sm->pfnCallback)(iItem-1));
}
x = 0;
if (sm->bCenter || iItem == 0) // always center the menu title
{
len = strlen(szText);
x = (sm->iDispX - (len * cx)) / 2;
}
return x;
} /* obdMenuGetItem() */
//
// Erase the display and show the given menu
//
void obdMenuShow(SIMPLEMENU *sm, int iItem)
{
int i, x, iCount, iStart = 0;
int iFirst, iLast;
char szTemp[64];
iCount = (sm->iDispY / 8) - 1; // DEBUG - number of visible menu lines
iFirst = iLast = iItem;
if (iItem == -1) // show the entire menu
{
obdFill(sm->pOBD, 0, 0);
x = obdMenuGetItem(sm, 0, szTemp); // get the title text
obdMenuShowItem(sm->pOBD, x, 0, szTemp, 0, 0, sm->iFontSize, 0); // show title
iFirst = 0;
iLast = iCount-1;
}
if (sm->iMenuIndex >= iCount) // needs to scroll up
iStart = sm->iMenuIndex - (iCount-1);
if (sm->iMenuIndex < 0 || sm->iMenuIndex+iCount > sm->iMenuLen) { // invalid
sm->iMenuIndex = 0;
iStart = 0;
}
for (i=iFirst; i<=iLast && i+iStart < sm->iMenuLen; i++) // draw the visible menu lines
{
x = obdMenuGetItem(sm, i + iStart + 1, szTemp);
if (x >= 0) // display if valid
obdMenuShowItem(sm->pOBD, x, i+1, szTemp, (i+iStart == sm->iMenuIndex), (iFirst==iLast), sm->iFontSize, (iFirst==iLast));
}
if (iItem == -1) // now the display it in one shot
obdDumpBuffer(sm->pOBD, NULL);
} /* obdMenuShow() */
//
// Set a callback function to return custom info/status
// for each menu item
//
void obdMenuSetCallback(SIMPLEMENU *sm, SIMPLECALLBACK pfnCallBack)
{
if (sm != NULL)
sm->pfnCallback = pfnCallBack;
} /* obdMenuSetCallback() */
//
// Display the text of a single menu item
// optionally erases what's under it to prevent left-over text when the length changes
//
void obdMenuShowItem(OBDISP *pOBD, int x, int y, char *szText, int bInvert, int bErase, int iFontSize, int bRender)
{
static char *szBlank = (char *)" ";
if (bErase)
obdWriteString(pOBD, 0, 0, y, szBlank, iFontSize, 0, bRender); // erase old info
obdWriteString(pOBD, 0, x, y, szText, iFontSize, bInvert, bRender);
} /* obdMenuShowItem() */
//
// Flash a menu item when it is selected
//
static void obdMenuFlash(SIMPLEMENU *sm, int iItem)
{
int x, y, i, iCount;
char szTemp[64];
iCount = (sm->iDispY / 8) - 1; // DEBUG - number of visible menu lines
y = iItem+1;
if (y > iCount) // max bottom line
y = iCount;
x = obdMenuGetItem(sm, iItem+1, szTemp);
if (x < 0) return; // invalid request
for (i=0; i<3; i++)
{
obdMenuShowItem(sm->pOBD, x, y, szTemp, 0, 0, sm->iFontSize, 1); // show non-inverted
delay(200);
obdMenuShowItem(sm->pOBD, x, y, szTemp, 1, 0, sm->iFontSize, 1); // show inverted
delay(200);
}
} /* obdMenuFlash() */
//
// Change the menu index incrementally
// redraws the minimum amount of screen to show the new info
// (this prevents flicker/flash and saves battery life)
// returns the new menu index
//
int obdMenuDelta(SIMPLEMENU *sm, int iDelta)
{
int i, x, iNewIndex, iCount;
int iStart1, iStart2;
char szTemp[64];
if (iDelta == 0) return sm->iMenuIndex; // nothing to do
iNewIndex = sm->iMenuIndex + iDelta;
if (!sm->bOneButton && (iNewIndex < 0 || iNewIndex >= sm->iMenuLen)) // no change possible, exit
return sm->iMenuIndex; // unchanged
// If we are using a single button, wrap around the ends
if (iNewIndex < 0) iNewIndex = (sm->iMenuLen - 1);
else if (iNewIndex > sm->iMenuLen-1) iNewIndex = 0;
iCount = (sm->iDispY / 8) - 1; // DEBUG - number of visible menu lines
iStart1 = iStart2 = 0;
if (sm->iMenuIndex > iCount-1)
iStart1 = sm->iMenuIndex - (iCount-1);
if (iNewIndex > iCount-1) // needs to scroll up
iStart2 = iNewIndex - (iCount-1);
if (iStart1 != iStart2) // need to redraw all items
{
for (i=0; i<iCount; i++)
{
x = obdMenuGetItem(sm, i+iStart2+1, szTemp);
if (x >= 0)
obdMenuShowItem(sm->pOBD, x, i+1, szTemp, (i+iStart2 == iNewIndex), 1, sm->iFontSize, 0);
}
obdDumpBuffer(sm->pOBD, NULL);
}
else // need to redraw only the new and old items
{
i = sm->iMenuIndex - iStart1;
x = obdMenuGetItem(sm, sm->iMenuIndex+1, szTemp);
if (x >= 0)
obdMenuShowItem(sm->pOBD, x, i+1, szTemp, 0, 0, sm->iFontSize, 1);
i = iNewIndex - iStart2;
x = obdMenuGetItem(sm, iNewIndex+1, szTemp);
if (x >= 0)
obdMenuShowItem(sm->pOBD, x, i+1, szTemp, 1, 0, sm->iFontSize, 1);
}
sm->iMenuIndex = iNewIndex;
return iNewIndex;
} /* obdMenuDelta() */
//
// With the given setup, check for button presses
// and act accordingly
// returns -1 for normal interactions and the menu item index if the user presses the ENTER button
//
// time in milliseconds for a long press
#define MENU_LONG_PRESS 600
int obdMenuRun(SIMPLEMENU *sm)
{
uint8_t buttons = 0;
unsigned long ul;
int iDelta, rc = -1;
if (sm->bIsRotary) { // read the rotary encoder
if (digitalRead(sm->u8Enter) == sm->iPressed) {
buttons |= 1; // pressed
if (buttons != sm->u8BtnState)
rc = sm->iMenuIndex; // user pressed ENTER, return current menu index
} else { // check for rotary encoder activity
iDelta = obdMenuReadRotary(sm);
obdMenuDelta(sm, iDelta);
}
sm->u8BtnState = buttons;
} else {
// check the button states
if (digitalRead(sm->u8Up) == sm->iPressed)
buttons |= 1;
if (buttons != sm->u8BtnState) // something changed
{
if (sm->bOneButton) // different logic for a single button system
{
if (sm->u8BtnState == 0 && buttons == 1) // up button just pressed
{
sm->ulPressTime = millis(); // record the press time
}
if (sm->u8BtnState == 1 && buttons == 0) // up button just released
{
ul = millis() - sm->ulPressTime;
if (ul < MENU_LONG_PRESS) // short press = navigate menu
obdMenuDelta(sm, 1);
else // treat it like a long press
rc = sm->iMenuIndex; // action
}
}
else // 3 button setup (UP/DOWN/ENTER)
{
if (digitalRead(sm->u8Dn) == sm->iPressed)
buttons |= 2;
if (digitalRead(sm->u8Enter) == sm->iPressed)
rc = sm->iMenuIndex; // user pressed ENTER, return current menu index
if ((sm->u8BtnState & 1) == 0 && (buttons & 1) == 1) // Up button pressed
{
obdMenuDelta(sm, -1);
}
if ((sm->u8BtnState & 2) == 0 && (buttons & 2) == 2) // Down button pressed
{
obdMenuDelta(sm, 1);
}
}
sm->u8BtnState = buttons; // save the latest state
}
}
if (rc != -1) // selected
obdMenuFlash(sm, sm->iMenuIndex);
return rc;
} /* obdMenuRun() */
#endif // !_LINUX_

View File

@@ -0,0 +1,390 @@
#ifndef __ONEBITDISPLAY__
#define __ONEBITDISPLAY__
// Proportional font data taken from Adafruit_GFX library
/// Font data stored PER GLYPH
#if !defined( _ADAFRUIT_GFX_H ) && !defined( _GFXFONT_H_ )
#define _GFXFONT_H_
typedef struct {
uint16_t bitmapOffset; ///< Pointer into GFXfont->bitmap
uint8_t width; ///< Bitmap dimensions in pixels
uint8_t height; ///< Bitmap dimensions in pixels
uint8_t xAdvance; ///< Distance to advance cursor (x axis)
int8_t xOffset; ///< X dist from cursor pos to UL corner
int8_t yOffset; ///< Y dist from cursor pos to UL corner
} GFXglyph;
/// Data stored for FONT AS A WHOLE
typedef struct {
uint8_t *bitmap; ///< Glyph bitmaps, concatenated
GFXglyph *glyph; ///< Glyph array
uint8_t first; ///< ASCII extents (first char)
uint8_t last; ///< ASCII extents (last char)
uint8_t yAdvance; ///< Newline distance (y axis)
} GFXfont;
#endif // _ADAFRUIT_GFX_H
typedef struct obdstruct
{
uint8_t oled_addr; // requested address or 0xff for automatic detection
uint8_t wrap, flip, invert, type;
uint8_t *ucScreen;
int iCursorX, iCursorY;
int width, height;
int iScreenOffset;
//BBI2C bbi2c;
uint8_t com_mode; // communication mode (I2C / SPI)
uint8_t mode; // data/command mode for 9-bit SPI
uint8_t iDCPin, iMOSIPin, iCLKPin, iCSPin;
uint8_t iLEDPin; // backlight
uint8_t bBitBang;
} OBDISP;
typedef char * (*SIMPLECALLBACK)(int iMenuItem);
typedef struct smenu {
uint8_t u8Up, u8Dn, u8Enter; // button pin numbers
uint8_t bIsRotary; // rotary encoder or up/down buttons?
uint8_t bCenter; // center all menu text if true
uint8_t u8BtnState; // state of all buttons
uint8_t bOneButton; // flag indicating the menu operates from a single button
uint8_t prevNextCode; // rotary encoder state machine
int iMenuIndex; // current menu index
int iMenuLen; // number of entries in the menu (calculated at startup)
char **pMenuText; // string array with menu title and text
int iFontSize;
int iPressed; // polarity of button pressed state
unsigned long ulPressTime; // time in millis when button was pressed
int iDispX, iDispY; // display width/height in pixels
SIMPLECALLBACK pfnCallback;
OBDISP *pOBD; // display structureme
uint16_t store;
} SIMPLEMENU;
// Make the Linux library interface C instead of C++
#if defined(_LINUX_) && defined(__cplusplus)
extern "C" {
#endif
#if !defined(BITBANK_LCD_MODES)
#define BITBANK_LCD_MODES
typedef enum
{
MODE_DATA = 0,
MODE_COMMAND
} DC_MODE;
#endif
typedef enum
{
COM_I2C = 0,
COM_SPI,
} COM_MODE;
typedef enum
{
ROT_0 = 0,
ROT_90,
ROT_180,
ROT_270
} FONT_ROTATION;
// These are defined the same in my SPI_LCD library
#ifndef SPI_LCD_H
// 5 possible font sizes: 8x8, 16x32, 6x8, 12x16 (stretched from 6x8 with smoothing), 16x16 (stretched from 8x8)
enum {
FONT_6x8 = 0,
FONT_8x8,
FONT_12x16,
FONT_16x16,
FONT_16x32,
FONT_COUNT
};
// For backwards compatibility, keep the old names valid
#define FONT_NORMAL FONT_8x8
#define FONT_SMALL FONT_6x8
#define FONT_STRETCHED FONT_16x16
#define FONT_LARGE FONT_16x32
#endif
// Display type for init function
enum {
OLED_128x128 = 1,
OLED_128x32,
OLED_128x64,
OLED_132x64,
OLED_64x128,
OLED_64x32,
OLED_96x16,
OLED_72x40,
LCD_UC1701,
LCD_UC1609,
LCD_HX1230,
LCD_NOKIA5110,
LCD_VIRTUAL,
SHARP_144x168,
SHARP_400x240
};
// Rotation and flip angles to draw tiles
enum {
ANGLE_0=0,
ANGLE_90,
ANGLE_180,
ANGLE_270,
ANGLE_FLIPX,
ANGLE_FLIPY
};
// Return value from obd obdI2CInit()
enum {
OLED_NOT_FOUND = -1, // no display found
OLED_SSD1306_3C, // SSD1306 found at 0x3C
OLED_SSD1306_3D, // SSD1306 found at 0x3D
OLED_SH1106_3C, // SH1106 found at 0x3C
OLED_SH1106_3D, // SH1106 found at 0x3D
OLED_SH1107_3C, // SH1107
OLED_SH1107_3D,
LCD_OK,
LCD_ERROR
};
//
// Create a virtual display of any size
// The memory buffer must be provided at the time of creation
//
void obdCreateVirtualDisplay(OBDISP *pOBD, int width, int height, uint8_t *buffer);
// Constants for the obdCopy() function
// Output format options -
#define OBD_LSB_FIRST 0x001
#define OBD_MSB_FIRST 0x002
#define OBD_VERT_BYTES 0x004
#define OBD_HORZ_BYTES 0x008
// Orientation options -
#define OBD_ROTATE_90 0x010
#define OBD_FLIP_VERT 0x020
#define OBD_FLIP_HORZ 0x040
#define OBD_INVERT 0x080
// Copy the current bitmap buffer from its native form (LSB_FIRST, VERTICAL_BYTES) to the requested form
// A copy of the same format will just do a memcpy
int obdCopy(OBDISP *pOBD, int iFlags, uint8_t *pDestination);
//
// Draw the contents of a memory buffer onto a display
// The sub-window will be clipped if it specifies too large an area
// for the destination display. The source OBDISP structure must have
// a valid back buffer defined
// The top and bottom destination edges will be drawn on byte boundaries (8 rows)
// The source top/bot edges can be on pixel boundaries
//
void obdDumpWindow(OBDISP *pOBDSrc, OBDISP *pOBDDest, int srcx, int srcy, int destx, int desty, int width, int height);
//
// Write a single line to a Sharp memory LCD
// You must provide the exact number of bytes needed for a complete line
// e.g. for the 144x168 display, pSrc must provide 144 pixels (18 bytes)
//
void obdWriteLCDLine(OBDISP *pOBD, uint8_t *pSrc, int iLine);
//
// Initializes the display controller into "page mode" on I2C
// If SDAPin and SCLPin are not -1, then bit bang I2C on those pins
// Otherwise use the Wire library.
// If you don't need to use a separate reset pin, set it to -1
//
int obdI2CInit(OBDISP *pOBD, int iType, int iAddr, int bFlip, int bInvert, int bWire, int iSDAPin, int iSCLPin, int iResetPin, int32_t iSpeed);
//
// Initialize an SPI version of the display
//
void obdSPIInit(OBDISP *pOBD, int iType, int iDC, int iCS, int iReset, int iMOSI, int iCLK, int iLED, int bFlip, int bInvert, int iBitBang, int32_t iSpeed);
//
// Set the memory configuration to display the pixels at 0 or 180 degrees (flipped)
// pass true (1) to flip 180, false (0) to set to 0
void obdSetFlip(OBDISP *pOBD, int iOnOff);
//
// Provide or revoke a back buffer for your OLED graphics
// This allows you to manage the RAM used by ss_oled on tiny
// embedded platforms like the ATmega series
// Pass NULL to revoke the buffer. Make sure you provide a buffer
// large enough for your display (e.g. 128x64 needs 1K - 1024 bytes)
//
void obdSetBackBuffer(OBDISP *pOBD, uint8_t *pBuffer);
//
// Sets the brightness (0=off, 255=brightest)
//
void obdSetContrast(OBDISP *pOBD, unsigned char ucContrast);
//
// Load a 1-bpp Windows bitmap
// Pass the pointer to the beginning of the BMP file
// First pass version assumes a full screen bitmap
//
int obdLoadBMP(OBDISP *pOBD, uint8_t *pBMP, int x, int y, int bInvert);
//
// Power up/down the display
// useful for low power situations
//
void obdPower(OBDISP *pOBD, int bOn);
//
// Set the current cursor position
// The column represents the pixel column (0-127)
// The row represents the text row (0-7)
//
void obdSetCursor(OBDISP *pOBD, int x, int y);
//
// Turn text wrap on or off for the obdWriteString() function
//
void obdSetTextWrap(OBDISP *pOBD, int bWrap);
//
// Draw a string of normal (8x8), small (6x8) or large (16x32) characters
// At the given col+row with the given scroll offset. The scroll offset allows you to
// horizontally scroll text which does not fit on the width of the display. The offset
// represents the pixels to skip when drawing the text. An offset of 0 starts at the beginning
// of the text.
// The system remembers where the last text was written (the cursor position)
// To continue writing from the last position, set the x,y values to -1
// The text can optionally wrap around to the next line by calling oledSetTextWrap(true);
// otherwise text which would go off the right edge will not be drawn and the cursor will
// be left "off screen" until set to a new position explicitly
//
// Returns 0 for success, -1 for invalid parameter
//
int obdWriteString(OBDISP *pOBD, int iScrollX, int x, int y, char *szMsg, int iSize, int bInvert, int bRender);
//
// Draw a string with a fractional scale in both dimensions
// the scale is a 16-bit integer with and 8-bit fraction and 8-bit mantissa
// To draw at 1x scale, set the scale factor to 256. To draw at 2x, use 512
// The output must be drawn into a memory buffer, not directly to the display
// The string can be drawn in one of 4 rotations (ROT_0, ROT_90, ROT_180, ROT_270)
//
int obdScaledString(OBDISP *pOBD, int x, int y, char *szMsg, int iSize, int bInvert, int iXScale, int iYScale, int iRotation);
//
// Draw a string in a proportional font you supply
// Requires a back buffer
//
int obdWriteStringCustom(OBDISP *pOBD, GFXfont *pFont, int x, int y, char *szMsg, uint8_t ucColor);
//
// Get the width of text in a custom font
//
void obdGetStringBox(GFXfont *pFont, char *szMsg, int *width, int *top, int *bottom);
//
// Fill the frame buffer with a byte pattern
// e.g. all off (0x00) or all on (0xff)
//
void obdFill(OBDISP *pOBD, unsigned char ucData, int bRender);
//
// Set (or clear) an individual pixel
// The local copy of the frame buffer is used to avoid
// reading data from the display controller
// (which isn't possible in most configurations)
// This function needs the USE_BACKBUFFER macro to be defined
// otherwise, new pixels will erase old pixels within the same byte
//
int obdSetPixel(OBDISP *pOBD, int x, int y, unsigned char ucColor, int bRender);
//
// Dump an entire custom buffer to the display
// useful for custom animation effects
//
void obdDumpBuffer(OBDISP *pOBD, uint8_t *pBuffer);
//
// Render a window of pixels from a provided buffer or the library's internal buffer
// to the display. The row values refer to byte rows, not pixel rows due to the memory
// layout of OLEDs. Pass a src pointer of NULL to use the internal backing buffer
// returns 0 for success, -1 for invalid parameter
//
int obdDrawGFX(OBDISP *pOBD, uint8_t *pSrc, int iSrcCol, int iSrcRow, int iDestCol, int iDestRow, int iWidth, int iHeight, int iSrcPitch);
//
// Draw a line between 2 points
//
void obdDrawLine(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, int bRender);
//
// Play a frame of animation data
// The animation data is assumed to be encoded for a full frame of the display
// Given the pointer to the start of the compressed data,
// it returns the pointer to the start of the next frame
// Frame rate control is up to the calling program to manage
// When it finishes the last frame, it will start again from the beginning
//
uint8_t * obdPlayAnimFrame(OBDISP *pOBD, uint8_t *pAnimation, uint8_t *pCurrent, int iLen);
void obdWriteCommand(OBDISP *pOBD, unsigned char c);
void obdSetPosition(OBDISP *pOBD, int x, int y, int bRender);
void obdWriteDataBlock(OBDISP *pOBD, unsigned char *ucBuf, int iLen, int bRender);
//
// Scroll the internal buffer by 1 scanline (up/down)
// width is in pixels, lines is group of 8 rows
// Returns 0 for success, -1 for invalid parameter
//
int obdScrollBuffer(OBDISP *pOBD, int iStartCol, int iEndCol, int iStartRow, int iEndRow, int bUp);
//
// Draw a sprite of any size in any position
// If it goes beyond the left/right or top/bottom edges
// it's trimmed to show the valid parts
// This function requires a back buffer to be defined
// The priority color (0 or 1) determines which color is painted
// when a 1 is encountered in the source image.
// e.g. when 0, the input bitmap acts like a mask to clear
// the destination where bits are set.
//
void obdDrawSprite(OBDISP *pOBD, uint8_t *pSprite, int cx, int cy, int iPitch, int x, int y, uint8_t iPriority);
//
// Draw a 16x16 tile in any of 4 rotated positions
// Assumes input image is laid out like "normal" graphics with
// the MSB on the left and 2 bytes per line
// On AVR, the source image is assumed to be in FLASH memory
// The function can draw the tile on byte boundaries, so the x value
// can be from 0 to 112 and y can be from 0 to 6
//
void obdDrawTile(OBDISP *pOBD, const uint8_t *pTile, int x, int y, int iRotation, int bInvert, int bRender);
//
// Draw an outline or filled ellipse
//
void obdEllipse(OBDISP *pOBD, int iCenterX, int iCenterY, int32_t iRadiusX, int32_t iRadiusY, uint8_t ucColor, uint8_t bFilled);
//
// Draw an outline or filled rectangle
//
void obdRectangle(OBDISP *pOBD, int x1, int y1, int x2, int y2, uint8_t ucColor, uint8_t bFilled);
//
// Turn the LCD backlight on or off
//
void obdBacklight(OBDISP *pODB, int bOn);
//
// Menu functions
//
// Initialize the simple menu structure
//
int obdMenuInit(OBDISP *pOBD, SIMPLEMENU *sm, char **pText, int iFontSize, int bCenter, int btnUp, int btnDn, int btnEnter, int iPressedState, int bIsRotary);
//
// Erase the display and show the given menu
//
void obdMenuShow(SIMPLEMENU *sm, int iItem);
//
// Set a callback function to return custom info/status
// for each menu item
//
void obdMenuSetCallback(SIMPLEMENU *sm, SIMPLECALLBACK pfnCallBack);
//
// Display the text of a single menu item
// optionally erases what's under it to prevent left-over text when the length changes
//
void obdMenuShowItem(OBDISP *pOBD, int x, int y, char *szText, int bInvert, int bErase, int iFontSize, int bRender);
//
// Change the menu index incrementally
// redraws the minimum amount of screen to show the new info
// (this prevents flicker/flash and saves battery life)
// returns the new menu index
//
int obdMenuDelta(SIMPLEMENU *sm, int iDelta);
//
// With the given setup, check for button presses
// and act accordingly
// returns -1 for normal interactions and the menu item index if the user presses the ENTER button
//
int obdMenuRun(SIMPLEMENU *sm);
#if defined(_LINUX_) && defined(__cplusplus)
}
#endif // _LINUX_
#endif // __ONEBITDISPLAY__

View File

@@ -0,0 +1,200 @@
// Created by http://oleddisplay.squix.ch/ Consider a donation
// In case of problems make sure that you are using the font file with the correct version!
const uint8_t Roboto_Black_80Bitmaps[] = {
// Bitmap Data:
0x00, // ' '
0xFF,0xFC,0xFF,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xFC,0x7F,0xF8,0x7F,0xF8,0x7F,0xF8,0x7F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x3F,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0xC0,0x3F,0xF0,0x7F,0xF8,0x7F,0xFC,0xFF,0xFC,0xFF,0xFE,0xFF,0xFE,0xFF,0xFE,0xFF,0xFC,0x7F,0xFC,0x7F,0xF8,0x3F,0xF0,0x0F,0xC0, // '!'
0xFF,0x83,0xFE,0xFF,0x83,0xFE,0xFF,0x83,0xFE,0xFF,0x83,0xFE,0xFF,0x83,0xFE,0xFF,0x83,0xFE,0xFF,0x83,0xFC,0xFF,0x83,0xFC,0xFF,0x83,0xFC,0xFF,0x03,0xFC,0xFF,0x03,0xFC,0xFF,0x03,0xFC,0xFF,0x03,0xFC,0xFF,0x03,0xFC,0xFF,0x03,0xFC,0xFF,0x03,0xFC,0xFF,0x03,0xF8,0xFF,0x03,0xF8,0xFF,0x03,0xF8,0xFE,0x03,0xF8,0xFE,0x03,0xF8,0xFE,0x03,0xF8, // '"'
0x00,0x01,0xFE,0x07,0xF8,0x00,0x00,0x0F,0xF0,0x3F,0xC0,0x00,0x00,0x7F,0x81,0xFE,0x00,0x00,0x03,0xFC,0x0F,0xF0,0x00,0x00,0x1F,0xC0,0x7F,0x80,0x00,0x01,0xFE,0x03,0xF8,0x00,0x00,0x0F,0xF0,0x3F,0xC0,0x00,0x00,0x7F,0x81,0xFE,0x00,0x00,0x03,0xFC,0x0F,0xF0,0x00,0x00,0x1F,0xE0,0x7F,0x80,0x00,0x00,0xFE,0x03,0xFC,0x00,0x00,0x07,0xF0,0x1F,0xC0,0x00,0x00,0x7F,0x81,0xFE,0x00,0x00,0x03,0xFC,0x0F,0xF0,0x00,0x00,0x1F,0xE0,0x7F,0x80,0x00,0x00,0xFF,0x03,0xFC,0x00,0x00,0x07,0xF8,0x1F,0xE0,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x87,0xFF,0xFF,0xFF,0xFF,0xFC,0x3F,0xFF,0xFF,0xFF,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x1F,0xE0,0x7F,0x80,0x00,0x00,0xFF,0x03,0xFC,0x00,0x00,0x07,0xF8,0x1F,0xE0,0x00,0x00,0x3F,0xC0,0xFF,0x00,0x00,0x01,0xFE,0x07,0xF8,0x00,0x00,0x0F,0xE0,0x3F,0x80,0x00,0x00,0xFF,0x03,0xFC,0x00,0x00,0x07,0xF8,0x1F,0xE0,0x00,0x00,0x3F,0xC0,0xFF,0x00,0x00,0x01,0xFE,0x07,0xF8,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x03,0xF8,0x0F,0xE0,0x00,0x00,0x3F,0xC0,0xFF,0x00,0x00,0x01,0xFE,0x07,0xF8,0x00,0x00,0x0F,0xF0,0x3F,0xC0,0x00,0x00,0x7F,0x81,0xFE,0x00,0x00,0x03,0xFC,0x0F,0xF0,0x00,0x00,0x1F,0xC0,0x7F,0x00,0x00,0x01,0xFE,0x07,0xF8,0x00,0x00,0x0F,0xF0,0x3F,0xC0,0x00,0x00,0x7F,0x81,0xFE,0x00,0x00,0x03,0xFC,0x0F,0xF0,0x00,0x00,0x1F,0xE0,0x7F,0x80,0x00,0x00,0xFE,0x03,0xF8,0x00,0x00,0x0F,0xF0,0x3F,0xC0,0x00,0x00,0x7F,0x81,0xFE,0x00,0x00,0x03,0xFC,0x0F,0xF0,0x00,0x00, // '#'
0x00,0x00,0x3F,0x80,0x00,0x00,0x00,0x1F,0xC0,0x00,0x00,0x00,0x0F,0xE0,0x00,0x00,0x00,0x07,0xF0,0x00,0x00,0x00,0x03,0xF8,0x00,0x00,0x00,0x01,0xFC,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,0x01,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xFE,0x00,0x00,0x0F,0xFF,0xFF,0xC0,0x00,0x1F,0xFF,0xFF,0xF0,0x00,0x1F,0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0xFF,0x00,0x1F,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xFF,0xF0,0x0F,0xFF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFF,0xFE,0x07,0xFF,0xF0,0x7F,0xFF,0x03,0xFF,0xF0,0x0F,0xFF,0xC3,0xFF,0xF0,0x07,0xFF,0xE1,0xFF,0xF8,0x01,0xFF,0xF0,0xFF,0xFC,0x00,0xFF,0xFC,0x7F,0xFC,0x00,0x3F,0xFE,0x3F,0xFE,0x00,0x1F,0xFF,0x1F,0xFF,0x00,0x0F,0xFF,0x8F,0xFF,0xC0,0x07,0xFF,0xC7,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xFC,0x00,0x00,0x03,0xFF,0xFF,0x80,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x00,0x3F,0xFF,0xFE,0x00,0x00,0x0F,0xFF,0xFF,0xC0,0x00,0x03,0xFF,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0xFE,0x00,0x00,0x1F,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0xE0,0x00,0x00,0x3F,0xFF,0xF8,0x00,0x00,0x07,0xFF,0xFE,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x1F,0xFF,0xBF,0xFE,0x00,0x0F,0xFF,0xDF,0xFF,0x80,0x07,0xFF,0xEF,0xFF,0xC0,0x03,0xFF,0xF3,0xFF,0xE0,0x01,0xFF,0xF9,0xFF,0xF8,0x00,0xFF,0xF8,0xFF,0xFE,0x00,0xFF,0xFC,0x3F,0xFF,0xC1,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0x80,0x3F,0xFF,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x0F,0xFF,0xFE,0x00,0x00,0x00,0x7F,0xF8,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x03,0xF0,0x00,0x00,0x00,0x01,0xF8,0x00,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x00,0x1F,0x80,0x00,0x00,0x00,0x0F,0xC0,0x00,0x00, // '$'
0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x03,0xFF,0xFE,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF8,0x00,0x00,0x00,0x03,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0xFF,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFC,0x00,0x20,0x00,0x1F,0xF8,0x7F,0xE0,0x03,0xC0,0x00,0xFF,0x81,0xFF,0x00,0x1F,0x80,0x07,0xF8,0x07,0xFC,0x01,0xFF,0x00,0x3F,0xC0,0x3F,0xE0,0x0F,0xF0,0x01,0xFE,0x01,0xFF,0x00,0xFF,0x00,0x0F,0xF0,0x0F,0xF8,0x0F,0xF0,0x00,0x7F,0x80,0x7F,0xC0,0x7F,0x80,0x03,0xFC,0x03,0xFE,0x07,0xF8,0x00,0x1F,0xE0,0x1F,0xF0,0x7F,0xC0,0x00,0xFF,0x00,0xFF,0x83,0xFC,0x00,0x07,0xFC,0x0F,0xFC,0x3F,0xC0,0x00,0x3F,0xF0,0xFF,0xC1,0xFE,0x00,0x00,0xFF,0xFF,0xFE,0x1F,0xE0,0x00,0x07,0xFF,0xFF,0xE1,0xFF,0x00,0x00,0x1F,0xFF,0xFF,0x0F,0xF0,0x00,0x00,0x7F,0xFF,0xF0,0xFF,0x00,0x00,0x01,0xFF,0xFF,0x07,0xF8,0x00,0x00,0x07,0xFF,0xE0,0x7F,0x80,0x00,0x00,0x07,0xFC,0x07,0xF8,0x00,0x00,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x00,0x00,0x03,0xFC,0x00,0x00,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x0F,0xF0,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x07,0xF8,0x3F,0xFF,0x00,0x00,0x00,0x7F,0x83,0xFF,0xFE,0x00,0x00,0x03,0xFC,0x3F,0xFF,0xF8,0x00,0x00,0x3F,0xC3,0xFF,0xFF,0xE0,0x00,0x03,0xFC,0x3F,0xFF,0xFF,0x00,0x00,0x1F,0xE1,0xFF,0xFF,0xFC,0x00,0x01,0xFE,0x1F,0xF8,0x7F,0xE0,0x00,0x1F,0xF0,0xFF,0x81,0xFF,0x80,0x00,0xFF,0x07,0xF8,0x07,0xFC,0x00,0x0F,0xF0,0x3F,0xC0,0x3F,0xE0,0x00,0x7F,0x81,0xFE,0x01,0xFF,0x00,0x07,0xF8,0x0F,0xF0,0x0F,0xF8,0x00,0x7F,0x80,0x7F,0x80,0x7F,0xC0,0x03,0xFC,0x03,0xFC,0x03,0xFE,0x00,0x3F,0xC0,0x1F,0xE0,0x1F,0xF0,0x03,0xFE,0x00,0xFF,0x00,0xFF,0x80,0x1F,0xE0,0x07,0xFC,0x07,0xFC,0x00,0x7E,0x00,0x3F,0xF0,0x7F,0xC0,0x00,0xF0,0x00,0xFF,0xFF,0xFE,0x00,0x01,0x00,0x07,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x1F,0xFF,0xFF,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x00,0x07,0xFC,0x00, // '%'
0x00,0x00,0x7F,0xC0,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFC,0x00,0x00,0x00,0x01,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x00,0x07,0xFF,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0x00,0x00,0x03,0xFF,0xE1,0xFF,0xF0,0x00,0x00,0x3F,0xFC,0x0F,0xFF,0x00,0x00,0x07,0xFF,0x80,0x7F,0xF0,0x00,0x00,0x7F,0xF8,0x07,0xFF,0x00,0x00,0x07,0xFF,0x80,0x3F,0xF0,0x00,0x00,0x7F,0xF8,0x03,0xFF,0x00,0x00,0x07,0xFF,0x80,0x7F,0xF0,0x00,0x00,0x7F,0xF8,0x07,0xFF,0x00,0x00,0x03,0xFF,0x80,0xFF,0xE0,0x00,0x00,0x3F,0xFC,0x1F,0xFE,0x00,0x00,0x03,0xFF,0xC3,0xFF,0xC0,0x00,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x1F,0xFF,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x07,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x03,0xFF,0xFE,0x00,0x00,0x00,0x00,0x7F,0xFF,0xC0,0x00,0x00,0x00,0x0F,0xFF,0xFC,0x00,0xFF,0xE0,0x01,0xFF,0xFF,0xE0,0x0F,0xFE,0x00,0x3F,0xFF,0xFF,0x00,0xFF,0xE0,0x07,0xFF,0xFF,0xF0,0x0F,0xFE,0x00,0xFF,0xFF,0xFF,0x80,0xFF,0xE0,0x1F,0xFF,0xFF,0xFC,0x0F,0xFE,0x03,0xFF,0xFF,0xFF,0xE1,0xFF,0xE0,0x3F,0xFE,0x7F,0xFF,0x1F,0xFE,0x07,0xFF,0xC3,0xFF,0xF9,0xFF,0xC0,0x7F,0xFC,0x1F,0xFF,0xFF,0xFC,0x07,0xFF,0xC1,0xFF,0xFF,0xFF,0xC0,0xFF,0xF8,0x0F,0xFF,0xFF,0xFC,0x0F,0xFF,0x80,0x7F,0xFF,0xFF,0x80,0xFF,0xF8,0x03,0xFF,0xFF,0xF8,0x0F,0xFF,0xC0,0x1F,0xFF,0xFF,0x80,0xFF,0xFC,0x00,0xFF,0xFF,0xF0,0x0F,0xFF,0xC0,0x07,0xFF,0xFF,0x00,0x7F,0xFE,0x00,0x7F,0xFF,0xE0,0x07,0xFF,0xF0,0x03,0xFF,0xFC,0x00,0x7F,0xFF,0x81,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0xF0,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x1F,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x3F,0xFF,0xFF,0xFB,0xFF,0xF0,0x00,0xFF,0xFF,0xFE,0x3F,0xFF,0x80,0x03,0xFF,0xFF,0x01,0xFF,0xFC,0x00,0x03,0xFF,0x80,0x00,0x00,0x20, // '&'
0xFF,0xDF,0xFB,0xFF,0x7F,0xEF,0xFD,0xFF,0xBF,0xF7,0xFE,0xFF,0xDF,0xFB,0xFE,0x7F,0xCF,0xF9,0xFF,0x3F,0xE7,0xFC,0xFF,0x9F,0xF3,0xFE,0x7F,0xCF,0xF9,0xFF,0x00, // '''
0x00,0x00,0x20,0x00,0x01,0xE0,0x00,0x07,0xC0,0x00,0x3F,0x80,0x00,0xFF,0x80,0x03,0xFF,0x00,0x0F,0xFF,0x00,0x1F,0xF8,0x00,0x7F,0xE0,0x01,0xFF,0x80,0x07,0xFF,0x00,0x0F,0xFC,0x00,0x3F,0xF0,0x00,0x7F,0xE0,0x01,0xFF,0x80,0x03,0xFF,0x00,0x0F,0xFC,0x00,0x1F,0xF8,0x00,0x7F,0xE0,0x00,0xFF,0xC0,0x01,0xFF,0x80,0x07,0xFE,0x00,0x0F,0xFC,0x00,0x1F,0xF8,0x00,0x7F,0xF0,0x00,0xFF,0xC0,0x01,0xFF,0x80,0x03,0xFF,0x00,0x07,0xFE,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0x7F,0xE0,0x00,0xFF,0xC0,0x01,0xFF,0x80,0x03,0xFF,0x00,0x07,0xFE,0x00,0x0F,0xFC,0x00,0x1F,0xF8,0x00,0x3F,0xF0,0x00,0x7F,0xE0,0x00,0xFF,0xC0,0x01,0xFF,0x80,0x03,0xFF,0x00,0x07,0xFE,0x00,0x0F,0xFC,0x00,0x1F,0xF8,0x00,0x3F,0xF0,0x00,0x7F,0xE0,0x00,0xFF,0xC0,0x01,0xFF,0x80,0x03,0xFF,0x80,0x07,0xFF,0x00,0x07,0xFE,0x00,0x0F,0xFC,0x00,0x1F,0xF8,0x00,0x3F,0xF0,0x00,0x7F,0xF0,0x00,0x7F,0xE0,0x00,0xFF,0xC0,0x01,0xFF,0x80,0x01,0xFF,0x80,0x03,0xFF,0x00,0x07,0xFE,0x00,0x07,0xFE,0x00,0x0F,0xFC,0x00,0x0F,0xFC,0x00,0x1F,0xF8,0x00,0x1F,0xF8,0x00,0x3F,0xF0,0x00,0x3F,0xF0,0x00,0x7F,0xF0,0x00,0x7F,0xE0,0x00,0x7F,0xE0,0x00,0x7F,0xE0,0x00,0xFF,0xF0,0x00,0xFF,0xC0,0x00,0xFF,0x80,0x00,0xFE,0x00,0x00,0x7C,0x00,0x00,0x78,0x00,0x00,0x20, // '('
0x10,0x00,0x00,0x3C,0x00,0x00,0x3E,0x00,0x00,0x3F,0x80,0x00,0x7F,0xC0,0x00,0x7F,0xE0,0x00,0xFF,0xF0,0x00,0x3F,0xF8,0x00,0x1F,0xFC,0x00,0x0F,0xFC,0x00,0x0F,0xFE,0x00,0x07,0xFF,0x00,0x03,0xFF,0x00,0x03,0xFF,0x80,0x01,0xFF,0x80,0x01,0xFF,0xC0,0x00,0xFF,0xC0,0x00,0xFF,0xE0,0x00,0x7F,0xE0,0x00,0x7F,0xF0,0x00,0x7F,0xF0,0x00,0x3F,0xF0,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x1F,0xFC,0x00,0x1F,0xFC,0x00,0x1F,0xFC,0x00,0x1F,0xFC,0x00,0x1F,0xFC,0x00,0x1F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x0F,0xFE,0x00,0x1F,0xFE,0x00,0x1F,0xFC,0x00,0x1F,0xFC,0x00,0x1F,0xFC,0x00,0x1F,0xFC,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x3F,0xF8,0x00,0x3F,0xF0,0x00,0x7F,0xF0,0x00,0x7F,0xF0,0x00,0x7F,0xE0,0x00,0xFF,0xE0,0x00,0xFF,0xC0,0x01,0xFF,0xC0,0x01,0xFF,0x80,0x03,0xFF,0x80,0x03,0xFF,0x00,0x07,0xFF,0x00,0x0F,0xFE,0x00,0x0F,0xFC,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0xFF,0xF0,0x00,0x7F,0xE0,0x00,0x7F,0xC0,0x00,0x3F,0x80,0x00,0x3F,0x00,0x00,0x3C,0x00,0x00,0x10,0x00,0x00, // ')'
0x00,0x03,0xFC,0x00,0x00,0x00,0x1F,0xE0,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x07,0xF8,0x00,0x00,0x00,0x3F,0xC0,0x00,0x00,0x01,0xFE,0x00,0x00,0x00,0x07,0xF0,0x00,0x00,0x00,0x3F,0x80,0x00,0x00,0x01,0xFC,0x00,0x01,0xC0,0x0F,0xE0,0x06,0x0F,0x80,0x7F,0x01,0xF0,0x7F,0x83,0xF8,0x3F,0x87,0xFF,0x1F,0x8F,0xFE,0x3F,0xFE,0xFD,0xFF,0xF1,0xFF,0xFF,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xF0,0x00,0x1F,0xFF,0xF8,0x00,0x00,0x0F,0xFC,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0x00,0x00,0x0F,0xF7,0xF8,0x00,0x00,0xFF,0x9F,0xE0,0x00,0x0F,0xF8,0xFF,0x80,0x00,0x7F,0xC3,0xFE,0x00,0x07,0xFC,0x0F,0xF8,0x00,0x7F,0xC0,0x7F,0xE0,0x07,0xFE,0x01,0xFF,0x00,0x1F,0xE0,0x0F,0xFC,0x00,0x3E,0x00,0x3F,0x00,0x00,0xF0,0x00,0xF0,0x00,0x01,0x00,0x06,0x00,0x00, // '*'
0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x07,0xFF,0x80,0x00, // '+'
0x0F,0xFE,0x0F,0xFE,0x0F,0xFE,0x0F,0xFE,0x0F,0xFE,0x0F,0xFE,0x0F,0xFE,0x0F,0xFE,0x0F,0xFE,0x0F,0xFE,0x0F,0xFC,0x0F,0xFC,0x0F,0xFC,0x0F,0xFC,0x1F,0xFC,0x1F,0xF8,0x1F,0xF8,0x3F,0xF0,0x3F,0xF0,0x7F,0xE0,0x7F,0xE0,0xFF,0xC0,0x7F,0x80,0x1F,0x00,0x06,0x00, // ','
0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE,0xFF,0xFF,0xFE, // '-'
0x0F,0xC0,0x7F,0xE1,0xFF,0xE7,0xFF,0xCF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xF1,0xFF,0xE1,0xFF,0x80,0xFC,0x00, // '.'
0x00,0x00,0x1F,0xF8,0x00,0x00,0x7F,0xC0,0x00,0x03,0xFF,0x00,0x00,0x0F,0xFC,0x00,0x00,0x3F,0xE0,0x00,0x00,0xFF,0x80,0x00,0x07,0xFE,0x00,0x00,0x1F,0xF0,0x00,0x00,0x7F,0xC0,0x00,0x03,0xFF,0x00,0x00,0x0F,0xF8,0x00,0x00,0x3F,0xE0,0x00,0x01,0xFF,0x80,0x00,0x07,0xFC,0x00,0x00,0x1F,0xF0,0x00,0x00,0xFF,0xC0,0x00,0x03,0xFE,0x00,0x00,0x0F,0xF8,0x00,0x00,0x7F,0xE0,0x00,0x01,0xFF,0x80,0x00,0x07,0xFC,0x00,0x00,0x1F,0xF0,0x00,0x00,0xFF,0xC0,0x00,0x03,0xFE,0x00,0x00,0x0F,0xF8,0x00,0x00,0x7F,0xE0,0x00,0x01,0xFF,0x00,0x00,0x07,0xFC,0x00,0x00,0x3F,0xF0,0x00,0x00,0xFF,0x80,0x00,0x03,0xFE,0x00,0x00,0x1F,0xF8,0x00,0x00,0x7F,0xC0,0x00,0x01,0xFF,0x00,0x00,0x0F,0xFC,0x00,0x00,0x3F,0xF0,0x00,0x00,0xFF,0x80,0x00,0x03,0xFE,0x00,0x00,0x1F,0xF8,0x00,0x00,0x7F,0xC0,0x00,0x01,0xFF,0x00,0x00,0x0F,0xFC,0x00,0x00,0x3F,0xE0,0x00,0x00,0xFF,0x80,0x00,0x07,0xFE,0x00,0x00,0x1F,0xF0,0x00,0x00,0x7F,0xC0,0x00,0x03,0xFF,0x00,0x00,0x0F,0xF8,0x00,0x00,0x3F,0xE0,0x00,0x01,0xFF,0x80,0x00,0x07,0xFE,0x00,0x00,0x1F,0xF0,0x00,0x00,0x7F,0xC0,0x00,0x03,0xFF,0x00,0x00,0x0F,0xF8,0x00,0x00,0x3F,0xE0,0x00,0x01,0xFF,0x80,0x00,0x07,0xFC,0x00,0x00,0x1F,0xF0,0x00,0x00,0xFF,0xC0,0x00,0x03,0xFE,0x00,0x00,0x00, // '/'
0x00,0x01,0xFF,0x80,0x00,0x00,0x07,0xFF,0xF8,0x00,0x00,0x0F,0xFF,0xFF,0x00,0x00,0x1F,0xFF,0xFF,0xE0,0x00,0x1F,0xFF,0xFF,0xF8,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFF,0x80,0x1F,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xFF,0xF0,0x0F,0xFF,0xFF,0xFF,0xFC,0x07,0xFF,0xE0,0xFF,0xFE,0x07,0xFF,0xE0,0x1F,0xFF,0x83,0xFF,0xE0,0x07,0xFF,0xC1,0xFF,0xF0,0x03,0xFF,0xE1,0xFF,0xF0,0x00,0xFF,0xF8,0xFF,0xF8,0x00,0x7F,0xFC,0x7F,0xFC,0x00,0x3F,0xFE,0x3F,0xFE,0x00,0x1F,0xFF,0x3F,0xFF,0x00,0x0F,0xFF,0x9F,0xFF,0x00,0x03,0xFF,0xEF,0xFF,0x80,0x01,0xFF,0xF7,0xFF,0xC0,0x00,0xFF,0xFB,0xFF,0xE0,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x1F,0xFF,0x7F,0xFC,0x00,0x0F,0xFF,0xBF,0xFE,0x00,0x07,0xFF,0xDF,0xFF,0x00,0x03,0xFF,0xEF,0xFF,0x80,0x01,0xFF,0xF7,0xFF,0xC0,0x00,0xFF,0xFB,0xFF,0xE0,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x1F,0xFF,0x7F,0xFC,0x00,0x0F,0xFF,0xBF,0xFE,0x00,0x07,0xFF,0xDF,0xFF,0x00,0x03,0xFF,0xEF,0xFF,0x80,0x01,0xFF,0xF7,0xFF,0xC0,0x00,0xFF,0xFB,0xFF,0xE0,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0x7F,0xFE,0x7F,0xFC,0x00,0x3F,0xFE,0x3F,0xFE,0x00,0x1F,0xFF,0x1F,0xFF,0x00,0x0F,0xFF,0x8F,0xFF,0x80,0x07,0xFF,0xC7,0xFF,0xC0,0x03,0xFF,0xE1,0xFF,0xF0,0x03,0xFF,0xE0,0xFF,0xF8,0x01,0xFF,0xF0,0x7F,0xFE,0x01,0xFF,0xF8,0x1F,0xFF,0xC3,0xFF,0xF8,0x0F,0xFF,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFF,0xFC,0x01,0xFF,0xFF,0xFF,0xFE,0x00,0x7F,0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0xFE,0x00,0x00,0x3F,0xFF,0xFC,0x00,0x00,0x07,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xE0,0x00,0x00, // '0'
0x00,0x00,0x00,0xE0,0x00,0x00,0x7E,0x00,0x00,0x1F,0xE0,0x00,0x0F,0xFE,0x00,0x07,0xFF,0xE0,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xE0,0x7F,0xFF,0xFE,0x3F,0xFF,0xFF,0xEF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xEF,0xFF,0x7F,0xFE,0xFF,0x87,0xFF,0xEF,0xC0,0x7F,0xFE,0xC0,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x07,0xFF,0xE0, // '1'
0x00,0x00,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xFF,0x00,0x00,0x03,0xFF,0xFF,0xF0,0x00,0x03,0xFF,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xFC,0x00,0x7F,0xFF,0xFF,0xFF,0x80,0x3F,0xFF,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xFF,0xFC,0x07,0xFF,0xFF,0xFF,0xFF,0x03,0xFF,0xFC,0x1F,0xFF,0xE0,0xFF,0xFC,0x03,0xFF,0xF8,0x7F,0xFE,0x00,0x7F,0xFE,0x1F,0xFF,0x80,0x0F,0xFF,0x87,0xFF,0xC0,0x03,0xFF,0xF3,0xFF,0xF0,0x00,0xFF,0xFC,0xFF,0xFC,0x00,0x3F,0xFF,0x3F,0xFE,0x00,0x0F,0xFF,0xCF,0xFF,0x80,0x03,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x7F,0xFF,0x00,0x00,0x00,0x3F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x7F,0xFF,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xFE,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xE0, // '2'
0x00,0x01,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xFE,0x00,0x00,0x07,0xFF,0xFF,0xF0,0x00,0x07,0xFF,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xFF,0xFF,0x80,0x7F,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFF,0xFF,0x87,0xFF,0xF8,0x1F,0xFF,0xE1,0xFF,0xFC,0x01,0xFF,0xFC,0x7F,0xFE,0x00,0x3F,0xFF,0x1F,0xFF,0x00,0x0F,0xFF,0xC7,0xFF,0xC0,0x01,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x1F,0xFF,0xFF,0xE0,0x00,0x07,0xFF,0xFF,0xF0,0x00,0x01,0xFF,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xFC,0x00,0x00,0x07,0xFF,0xFF,0x80,0x00,0x01,0xFF,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x1F,0xFF,0xFF,0xE0,0x00,0x07,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x03,0xFF,0xEF,0xFF,0x80,0x00,0xFF,0xFB,0xFF,0xE0,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x07,0xFF,0xEF,0xFF,0xE0,0x03,0xFF,0xF1,0xFF,0xFC,0x01,0xFF,0xFC,0x7F,0xFF,0x81,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0xFF,0x83,0xFF,0xFF,0xFF,0xFF,0xE0,0x7F,0xFF,0xFF,0xFF,0xF0,0x1F,0xFF,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xFF,0xFC,0x00,0x7F,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xFE,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x07,0xFF,0xFE,0x00,0x00,0x00,0x1F,0xF8,0x00,0x00, // '3'
0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x1F,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xFF,0x80,0x00,0x00,0x3F,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0xFE,0x00,0x00,0x01,0xFF,0xFF,0xC0,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x1F,0xFF,0xFF,0x00,0x00,0x03,0xFF,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0xFF,0x80,0x00,0x07,0xFF,0xFF,0xF0,0x00,0x01,0xFF,0xFF,0xFE,0x00,0x00,0x3F,0xF7,0xFF,0xC0,0x00,0x0F,0xFE,0xFF,0xF8,0x00,0x03,0xFF,0x9F,0xFF,0x00,0x00,0x7F,0xE3,0xFF,0xE0,0x00,0x1F,0xFC,0x7F,0xFC,0x00,0x03,0xFF,0x0F,0xFF,0x80,0x00,0xFF,0xE1,0xFF,0xF0,0x00,0x3F,0xF8,0x3F,0xFE,0x00,0x07,0xFF,0x07,0xFF,0xC0,0x01,0xFF,0xC0,0xFF,0xF8,0x00,0x7F,0xF0,0x1F,0xFF,0x00,0x0F,0xFE,0x03,0xFF,0xE0,0x03,0xFF,0x80,0x7F,0xFC,0x00,0x7F,0xF0,0x0F,0xFF,0x80,0x1F,0xFC,0x01,0xFF,0xF0,0x07,0xFF,0x80,0x3F,0xFE,0x00,0xFF,0xE0,0x07,0xFF,0xC0,0x3F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xF0,0x00, // '4'
0x0F,0xFF,0xFF,0xFF,0xFC,0x07,0xFF,0xFF,0xFF,0xFE,0x03,0xFF,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0xC0,0x7F,0xFF,0xFF,0xFF,0xE0,0x3F,0xFF,0xFF,0xFF,0xF0,0x1F,0xFF,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFF,0xFE,0x07,0xFF,0x80,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0x01,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xF8,0x00,0x00,0x00,0x3F,0xFC,0x00,0x00,0x00,0x1F,0xFE,0x00,0x00,0x00,0x1F,0xFE,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0x07,0xFF,0x80,0x00,0x00,0x03,0xFF,0xC3,0xFE,0x00,0x01,0xFF,0xEF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xFC,0x00,0x7F,0xFF,0xFF,0xFF,0x80,0x3F,0xFF,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0xC3,0xFF,0xF0,0x1F,0xFF,0xE0,0x1F,0xE0,0x03,0xFF,0xF0,0x00,0x60,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x7F,0xFC,0x00,0x1F,0xFF,0xBF,0xFE,0x00,0x0F,0xFF,0x9F,0xFF,0x80,0x07,0xFF,0xCF,0xFF,0xC0,0x07,0xFF,0xE3,0xFF,0xF0,0x03,0xFF,0xF1,0xFF,0xFC,0x03,0xFF,0xF0,0xFF,0xFF,0x07,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFC,0x07,0xFF,0xFF,0xFF,0xFC,0x01,0xFF,0xFF,0xFF,0xFE,0x00,0x7F,0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x03,0xFF,0xFF,0xFC,0x00,0x00,0xFF,0xFF,0xFC,0x00,0x00,0x0F,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00, // '5'
0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xFC,0x00,0x00,0x03,0xFF,0xFF,0x00,0x00,0x03,0xFF,0xFF,0xC0,0x00,0x01,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFC,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x3F,0xFF,0xFF,0xC0,0x00,0x1F,0xFF,0xFE,0x00,0x00,0x0F,0xFF,0xF8,0x00,0x00,0x07,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x07,0xF8,0x00,0x1F,0xFF,0x0F,0xFF,0xC0,0x07,0xFF,0xCF,0xFF,0xF8,0x01,0xFF,0xF7,0xFF,0xFF,0x80,0x7F,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFF,0x83,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFF,0x8F,0xFF,0xF8,0x1F,0xFF,0xE3,0xFF,0xF8,0x01,0xFF,0xFC,0xFF,0xFC,0x00,0x3F,0xFF,0x3F,0xFF,0x00,0x0F,0xFF,0xCF,0xFF,0x80,0x01,0xFF,0xFB,0xFF,0xE0,0x00,0x7F,0xFE,0xFF,0xF8,0x00,0x1F,0xFF,0xBF,0xFE,0x00,0x03,0xFF,0xEF,0xFF,0x80,0x00,0xFF,0xFB,0xFF,0xE0,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x0F,0xFF,0x9F,0xFE,0x00,0x03,0xFF,0xE7,0xFF,0xC0,0x01,0xFF,0xF9,0xFF,0xF0,0x00,0x7F,0xFE,0x7F,0xFC,0x00,0x1F,0xFF,0x0F,0xFF,0x80,0x0F,0xFF,0xC3,0xFF,0xE0,0x03,0xFF,0xF0,0xFF,0xFC,0x01,0xFF,0xF8,0x1F,0xFF,0xC1,0xFF,0xFE,0x07,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xFF,0xF0,0x00,0x7F,0xFF,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x01,0xFF,0xFF,0xFE,0x00,0x00,0x1F,0xFF,0xFE,0x00,0x00,0x01,0xFF,0xFE,0x00,0x00,0x00,0x0F,0xFC,0x00,0x00, // '6'
0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x01,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00, // '7'
0x00,0x01,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xFF,0x80,0x00,0x3F,0xFF,0xFF,0xF0,0x00,0x3F,0xFF,0xFF,0xFC,0x00,0x3F,0xFF,0xFF,0xFF,0x00,0x3F,0xFF,0xFF,0xFF,0xC0,0x3F,0xFF,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xF0,0xFF,0xFF,0x07,0xFF,0xE0,0x1F,0xFF,0x83,0xFF,0xE0,0x07,0xFF,0xC3,0xFF,0xF0,0x03,0xFF,0xF1,0xFF,0xF8,0x01,0xFF,0xF8,0xFF,0xFC,0x00,0xFF,0xFC,0x7F,0xFE,0x00,0x7F,0xFE,0x3F,0xFF,0x00,0x3F,0xFF,0x0F,0xFF,0x80,0x1F,0xFF,0x07,0xFF,0xC0,0x0F,0xFF,0x83,0xFF,0xE0,0x07,0xFF,0xC0,0xFF,0xF8,0x07,0xFF,0xC0,0x7F,0xFF,0x07,0xFF,0xE0,0x1F,0xFF,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xFF,0xE0,0x00,0x7F,0xFF,0xFF,0xE0,0x00,0x0F,0xFF,0xFF,0xE0,0x00,0x0F,0xFF,0xFF,0xF0,0x00,0x1F,0xFF,0xFF,0xFE,0x00,0x1F,0xFF,0xFF,0xFF,0x80,0x1F,0xFF,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xC0,0xFF,0xFC,0x0F,0xFF,0xC0,0x3F,0xFF,0x0F,0xFF,0xC0,0x0F,0xFF,0xC7,0xFF,0xC0,0x03,0xFF,0xE3,0xFF,0xE0,0x01,0xFF,0xF3,0xFF,0xF0,0x00,0xFF,0xF9,0xFF,0xF0,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x1F,0xFF,0x7F,0xFC,0x00,0x0F,0xFF,0xBF,0xFE,0x00,0x0F,0xFF,0xDF,0xFF,0x80,0x07,0xFF,0xEF,0xFF,0xC0,0x03,0xFF,0xF7,0xFF,0xE0,0x01,0xFF,0xF9,0xFF,0xF8,0x01,0xFF,0xF8,0xFF,0xFE,0x01,0xFF,0xFC,0x7F,0xFF,0x81,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x7F,0xFF,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x0F,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00, // '8'
0x00,0x01,0xFF,0x00,0x00,0x00,0x07,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0xFE,0x00,0x00,0x0F,0xFF,0xFF,0xC0,0x00,0x1F,0xFF,0xFF,0xF0,0x00,0x1F,0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0xFF,0x00,0x1F,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xFF,0xF0,0x0F,0xFF,0xFF,0xFF,0xF8,0x0F,0xFF,0xF0,0xFF,0xFE,0x07,0xFF,0xE0,0x1F,0xFF,0x03,0xFF,0xF0,0x07,0xFF,0xC3,0xFF,0xF0,0x03,0xFF,0xE1,0xFF,0xF0,0x00,0xFF,0xF8,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xFC,0x00,0x3F,0xFE,0x7F,0xFE,0x00,0x1F,0xFF,0x3F,0xFE,0x00,0x0F,0xFF,0x9F,0xFF,0x00,0x03,0xFF,0xEF,0xFF,0x80,0x01,0xFF,0xF7,0xFF,0xC0,0x00,0xFF,0xFB,0xFF,0xE0,0x00,0x7F,0xFD,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x1F,0xFF,0x7F,0xFE,0x00,0x0F,0xFF,0x9F,0xFF,0x80,0x0F,0xFF,0xCF,0xFF,0xC0,0x07,0xFF,0xE7,0xFF,0xF0,0x07,0xFF,0xF1,0xFF,0xFE,0x0F,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0xC0,0x3F,0xFF,0xFF,0xFF,0xE0,0x07,0xFF,0xFD,0xFF,0xF0,0x00,0xFF,0xF8,0xFF,0xF0,0x00,0x0F,0xF0,0x7F,0xF8,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x3F,0xFC,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x7F,0xFF,0x80,0x00,0x01,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xFF,0xC0,0x00,0x1F,0xFF,0xFF,0xC0,0x00,0x0F,0xFF,0xFF,0xC0,0x00,0x07,0xFF,0xFF,0xC0,0x00,0x03,0xFF,0xFF,0x80,0x00,0x01,0xFF,0xFF,0x80,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xF8,0x00,0x00,0x00,0x1F,0xC0,0x00,0x00,0x00, // '9'
0x0F,0xC0,0x7F,0xE1,0xFF,0xE7,0xFF,0xCF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xF1,0xFF,0xE1,0xFF,0x80,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x3F,0xF0,0xFF,0xF3,0xFF,0xE7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xF8,0xFF,0xF0,0xFF,0xC0,0x7E,0x00, // ':'
0x03,0xF0,0x07,0xFE,0x07,0xFF,0x87,0xFF,0xC3,0xFF,0xF1,0xFF,0xF8,0xFF,0xFC,0x7F,0xFE,0x3F,0xFF,0x1F,0xFF,0x07,0xFF,0x81,0xFF,0x80,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0x81,0xFF,0xC0,0xFF,0xE0,0x7F,0xF0,0x3F,0xF8,0x1F,0xFC,0x0F,0xFE,0x07,0xFF,0x03,0xFF,0x81,0xFF,0xC0,0xFF,0xC0,0x7F,0xE0,0x3F,0xF0,0x1F,0xF8,0x1F,0xFC,0x0F,0xFC,0x07,0xFE,0x07,0xFE,0x03,0xFF,0x03,0xFF,0x01,0xFF,0x81,0xFF,0x80,0x7F,0x80,0x0F,0x80,0x01,0x80,0x00, // ';'
0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x38,0x00,0x00,0x00,0x3F,0x00,0x00,0x00,0x1F,0xE0,0x00,0x00,0x1F,0xFC,0x00,0x00,0x0F,0xFF,0x80,0x00,0x07,0xFF,0xF0,0x00,0x07,0xFF,0xFE,0x00,0x03,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFC,0x07,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFC,0x00,0x03,0xFF,0xFC,0x00,0x00,0x7F,0xFC,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x01,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xFF,0x00,0x07,0xFF,0xFF,0xF8,0x00,0xFF,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xFF,0x80,0x3F,0xFF,0xFF,0xFE,0x01,0xFF,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xFC,0x00,0x3F,0xFF,0xFF,0x80,0x00,0xFF,0xFF,0xF0,0x00,0x07,0xFF,0xFE,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0xFF,0xF8,0x00,0x00,0x07,0xFF,0x00,0x00,0x00,0x1F,0xE0,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x03,0x80,0x00,0x00,0x00,0x10, // '<'
0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFC, // '='
0xC0,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0x00,0x00,0x0F,0xFF,0xFC,0x00,0x00,0xFF,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xFF,0x00,0x7F,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xE0,0x00,0x0F,0xFF,0xFE,0x00,0x00,0x1F,0xFF,0xE0,0x00,0x00,0x7F,0xFE,0x00,0x00,0x1F,0xFF,0xE0,0x00,0x0F,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xFE,0x01,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xF8,0x00,0x0F,0xFF,0xFC,0x00,0x00,0xFF,0xFF,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0xFF,0xE0,0x00,0x00,0x0F,0xF8,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x0F,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00, // '>'
0x00,0x03,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x0F,0xFF,0xFF,0xC0,0x00,0xFF,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xFF,0x80,0x3F,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xFE,0x07,0xFF,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xC7,0xFF,0xF8,0x7F,0xFF,0x1F,0xFF,0x80,0x7F,0xFE,0x7F,0xFE,0x01,0xFF,0xF9,0xFF,0xF0,0x03,0xFF,0xEF,0xFF,0xC0,0x0F,0xFF,0xBF,0xFF,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x7F,0xFE,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x7F,0xFE,0x00,0x00,0x03,0xFF,0xF8,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0xFF,0xFE,0x00,0x00,0x07,0xFF,0xF0,0x00,0x00,0x3F,0xFF,0x80,0x00,0x01,0xFF,0xFC,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x1F,0xFE,0x00,0x00,0x00,0x7F,0xF8,0x00,0x00,0x01,0xFF,0xC0,0x00,0x00,0x07,0xFF,0x00,0x00,0x00,0x1F,0xFC,0x00,0x00,0x00,0x7F,0xF0,0x00,0x00,0x01,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xE0,0x00,0x00,0x00,0x7F,0xE0,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x7F,0xFE,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x07,0xFF,0xF0,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0x07,0xFE,0x00,0x00,0x00,0x07,0xE0,0x00,0x00, // '?'
0x00,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x07,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x3F,0xFF,0xC0,0x07,0xFF,0xF8,0x00,0x00,0x07,0xFF,0xE0,0x00,0x07,0xFF,0xC0,0x00,0x00,0xFF,0xF0,0x00,0x00,0x1F,0xFE,0x00,0x00,0x1F,0xFE,0x00,0x00,0x00,0x7F,0xF0,0x00,0x03,0xFF,0x80,0x00,0x00,0x01,0xFF,0x80,0x00,0x7F,0xF0,0x00,0x00,0x00,0x0F,0xFC,0x00,0x0F,0xFE,0x00,0x00,0x00,0x00,0x7F,0xC0,0x00,0xFF,0xC0,0x00,0x00,0x00,0x03,0xFE,0x00,0x1F,0xF8,0x00,0x00,0x00,0x00,0x3F,0xE0,0x03,0xFF,0x00,0x00,0x7F,0x80,0x01,0xFF,0x00,0x3F,0xE0,0x00,0x3F,0xFF,0x00,0x0F,0xF0,0x07,0xFE,0x00,0x0F,0xFF,0xFC,0x00,0xFF,0x00,0x7F,0xC0,0x01,0xFF,0xFF,0xF0,0x07,0xF8,0x0F,0xFC,0x00,0x7F,0xFF,0xFF,0x80,0x7F,0x80,0xFF,0x80,0x07,0xFF,0xFF,0xF8,0x07,0xF8,0x0F,0xF8,0x00,0xFF,0xFF,0xFF,0x80,0x3F,0xC1,0xFF,0x00,0x1F,0xFF,0xFF,0xF8,0x03,0xFC,0x1F,0xF0,0x03,0xFF,0xC0,0xFF,0x80,0x3F,0xC1,0xFE,0x00,0x3F,0xF0,0x0F,0xF8,0x03,0xFC,0x3F,0xE0,0x07,0xFE,0x00,0xFF,0x00,0x3F,0xC3,0xFE,0x00,0x7F,0xE0,0x0F,0xF0,0x01,0xFC,0x3F,0xE0,0x0F,0xFC,0x01,0xFF,0x00,0x1F,0xE3,0xFC,0x00,0xFF,0x80,0x1F,0xF0,0x01,0xFE,0x7F,0xC0,0x1F,0xF8,0x01,0xFF,0x00,0x1F,0xE7,0xFC,0x01,0xFF,0x80,0x1F,0xF0,0x01,0xFE,0x7F,0xC0,0x1F,0xF0,0x01,0xFF,0x00,0x1F,0xE7,0xFC,0x01,0xFF,0x00,0x1F,0xF0,0x01,0xFE,0x7F,0x80,0x3F,0xF0,0x01,0xFF,0x00,0x1F,0xE7,0xF8,0x03,0xFF,0x00,0x1F,0xF0,0x01,0xFC,0x7F,0x80,0x3F,0xF0,0x01,0xFF,0x00,0x1F,0xC7,0xF8,0x03,0xFF,0x00,0x1F,0xE0,0x03,0xFC,0x7F,0x80,0x3F,0xE0,0x01,0xFE,0x00,0x3F,0xC7,0xF8,0x03,0xFE,0x00,0x3F,0xE0,0x03,0xFC,0x7F,0x80,0x3F,0xE0,0x03,0xFE,0x00,0x3F,0xC7,0xF8,0x03,0xFE,0x00,0x3F,0xE0,0x03,0xFC,0x7F,0x80,0x3F,0xF0,0x03,0xFE,0x00,0x7F,0x87,0xF8,0x03,0xFF,0x00,0x3F,0xE0,0x07,0xF8,0x7F,0x80,0x3F,0xF0,0x07,0xFE,0x00,0xFF,0x87,0xFC,0x03,0xFF,0x00,0xFF,0xE0,0x0F,0xF0,0x7F,0xC0,0x3F,0xF8,0x0F,0xFE,0x01,0xFF,0x07,0xFC,0x01,0xFF,0xC3,0xFF,0xF0,0x3F,0xE0,0x7F,0xC0,0x1F,0xFF,0xFF,0xFF,0x8F,0xFE,0x03,0xFC,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x3F,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x03,0xFE,0x00,0x7F,0xFF,0xEF,0xFF,0xFF,0x00,0x3F,0xE0,0x07,0xFF,0xFC,0x7F,0xFF,0xE0,0x01,0xFF,0x00,0x3F,0xFF,0x83,0xFF,0xFC,0x00,0x1F,0xF0,0x00,0xFF,0xE0,0x1F,0xFF,0x00,0x01,0xFF,0x80,0x03,0xF8,0x00,0x7F,0xC0,0x00,0x0F,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x04,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x01,0xC0,0x00,0x00,0x00,0x7F,0xFF,0xE0,0x01,0xFC,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x1F,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFC,0x00,0x00,0x00,0x00, // '@'
0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x00,0x00,0x00,0x1F,0xFF,0xE0,0x00,0x00,0x00,0x00,0x1F,0xFF,0xE0,0x00,0x00,0x00,0x00,0x1F,0xFF,0xF0,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF0,0x00,0x00,0x00,0x00,0x3F,0xFF,0xF8,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFF,0xFC,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x03,0xFF,0xEF,0xFF,0x00,0x00,0x00,0x03,0xFF,0xCF,0xFF,0x00,0x00,0x00,0x03,0xFF,0xCF,0xFF,0x80,0x00,0x00,0x07,0xFF,0xC7,0xFF,0x80,0x00,0x00,0x07,0xFF,0xC7,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0x87,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0x87,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0x83,0xFF,0xE0,0x00,0x00,0x1F,0xFF,0x03,0xFF,0xE0,0x00,0x00,0x1F,0xFF,0x03,0xFF,0xE0,0x00,0x00,0x1F,0xFF,0x01,0xFF,0xF0,0x00,0x00,0x3F,0xFE,0x01,0xFF,0xF0,0x00,0x00,0x3F,0xFE,0x01,0xFF,0xF8,0x00,0x00,0x3F,0xFE,0x00,0xFF,0xF8,0x00,0x00,0x7F,0xFC,0x00,0xFF,0xF8,0x00,0x00,0x7F,0xFC,0x00,0xFF,0xFC,0x00,0x00,0xFF,0xFC,0x00,0x7F,0xFC,0x00,0x00,0xFF,0xFC,0x00,0x7F,0xFC,0x00,0x00,0xFF,0xF8,0x00,0x7F,0xFE,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xC0,0x00,0x07,0xFF,0xE0,0x1F,0xFF,0x80,0x00,0x07,0xFF,0xE0,0x1F,0xFF,0x80,0x00,0x07,0xFF,0xF0,0x1F,0xFF,0x80,0x00,0x03,0xFF,0xF0,0x3F,0xFF,0x00,0x00,0x03,0xFF,0xF0,0x3F,0xFF,0x00,0x00,0x03,0xFF,0xF8,0x3F,0xFF,0x00,0x00,0x01,0xFF,0xF8,0x7F,0xFF,0x00,0x00,0x01,0xFF,0xF8,0x7F,0xFE,0x00,0x00,0x01,0xFF,0xFC,0xFF,0xFE,0x00,0x00,0x01,0xFF,0xFC,0xFF,0xFE,0x00,0x00,0x00,0xFF,0xFE, // 'A'
0xFF,0xFF,0xFF,0xF0,0x00,0x03,0xFF,0xFF,0xFF,0xFC,0x00,0x0F,0xFF,0xFF,0xFF,0xFE,0x00,0x3F,0xFF,0xFF,0xFF,0xFE,0x00,0xFF,0xFF,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xFC,0x3F,0xFF,0x00,0x1F,0xFF,0xF8,0xFF,0xFC,0x00,0x1F,0xFF,0xE3,0xFF,0xF0,0x00,0x3F,0xFF,0x8F,0xFF,0xC0,0x00,0x7F,0xFE,0x3F,0xFF,0x00,0x01,0xFF,0xF8,0xFF,0xFC,0x00,0x03,0xFF,0xE3,0xFF,0xF0,0x00,0x0F,0xFF,0x8F,0xFF,0xC0,0x00,0x3F,0xFE,0x3F,0xFF,0x00,0x01,0xFF,0xF8,0xFF,0xFC,0x00,0x07,0xFF,0xE3,0xFF,0xF0,0x00,0x1F,0xFF,0x0F,0xFF,0xC0,0x00,0xFF,0xFC,0x3F,0xFF,0x00,0x1F,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0xFF,0xFF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFF,0xFF,0xC0,0x3F,0xFF,0xFF,0xFF,0xFE,0x00,0xFF,0xFF,0xFF,0xFF,0xF0,0x03,0xFF,0xFF,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0xFF,0xF0,0x00,0x7F,0xFF,0x8F,0xFF,0xC0,0x00,0x7F,0xFE,0x3F,0xFF,0x00,0x00,0xFF,0xFC,0xFF,0xFC,0x00,0x03,0xFF,0xF3,0xFF,0xF0,0x00,0x07,0xFF,0xCF,0xFF,0xC0,0x00,0x1F,0xFF,0x3F,0xFF,0x00,0x00,0x7F,0xFC,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xCF,0xFF,0xC0,0x00,0x3F,0xFF,0x3F,0xFF,0x00,0x00,0xFF,0xFC,0xFF,0xFC,0x00,0x07,0xFF,0xF3,0xFF,0xF0,0x00,0x7F,0xFF,0xCF,0xFF,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,0xFF,0xF0,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x3F,0xFF,0xFF,0xFF,0xF0,0x00,0xFF,0xFF,0xFF,0xFC,0x00,0x00, // 'B'
0x00,0x00,0x1F,0xFC,0x00,0x00,0x00,0x00,0xFF,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xFF,0xFC,0x00,0x00,0x03,0xFF,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0xFF,0xE0,0x00,0x07,0xFF,0xFF,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xFF,0xFF,0xFE,0x01,0xFF,0xFF,0x01,0xFF,0xFF,0x01,0xFF,0xFE,0x00,0x3F,0xFF,0xC0,0xFF,0xFC,0x00,0x07,0xFF,0xE0,0xFF,0xFE,0x00,0x03,0xFF,0xF0,0x7F,0xFE,0x00,0x00,0xFF,0xFC,0x3F,0xFF,0x00,0x00,0x7F,0xFE,0x3F,0xFF,0x00,0x00,0x1F,0xFF,0x1F,0xFF,0x80,0x00,0x0F,0xFF,0x8F,0xFF,0xC0,0x00,0x07,0xFF,0xE7,0xFF,0xC0,0x00,0x03,0xFF,0xF7,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x7F,0xFE,0x7F,0xFE,0x00,0x00,0x3F,0xFE,0x3F,0xFF,0x00,0x00,0x1F,0xFF,0x1F,0xFF,0x80,0x00,0x1F,0xFF,0x87,0xFF,0xE0,0x00,0x0F,0xFF,0xC3,0xFF,0xF0,0x00,0x0F,0xFF,0xE0,0xFF,0xFC,0x00,0x07,0xFF,0xE0,0x7F,0xFF,0x00,0x0F,0xFF,0xF0,0x1F,0xFF,0xE0,0x1F,0xFF,0xF0,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x7F,0xFF,0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0xFF,0xFC,0x00,0x01,0xFF,0xFF,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0xFF,0xF8,0x00,0x00,0x07,0xFF,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00, // 'C'
0xFF,0xFF,0xFF,0x00,0x00,0x03,0xFF,0xFF,0xFF,0xC0,0x00,0x0F,0xFF,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xFF,0xFF,0xC0,0x00,0xFF,0xFF,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x3F,0xFF,0xFF,0xFF,0xFE,0x00,0xFF,0xFF,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFF,0xFF,0xF8,0x0F,0xFF,0xC0,0x3F,0xFF,0xF0,0x3F,0xFF,0x00,0x1F,0xFF,0xE0,0xFF,0xFC,0x00,0x3F,0xFF,0x83,0xFF,0xF0,0x00,0x7F,0xFF,0x0F,0xFF,0xC0,0x00,0xFF,0xFC,0x3F,0xFF,0x00,0x01,0xFF,0xF8,0xFF,0xFC,0x00,0x07,0xFF,0xE3,0xFF,0xF0,0x00,0x1F,0xFF,0x8F,0xFF,0xC0,0x00,0x3F,0xFF,0x3F,0xFF,0x00,0x00,0xFF,0xFC,0xFF,0xFC,0x00,0x03,0xFF,0xF3,0xFF,0xF0,0x00,0x07,0xFF,0xCF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFC,0xFF,0xFC,0x00,0x03,0xFF,0xF3,0xFF,0xF0,0x00,0x0F,0xFF,0xCF,0xFF,0xC0,0x00,0x3F,0xFF,0x3F,0xFF,0x00,0x01,0xFF,0xF8,0xFF,0xFC,0x00,0x07,0xFF,0xE3,0xFF,0xF0,0x00,0x1F,0xFF,0x8F,0xFF,0xC0,0x00,0xFF,0xFC,0x3F,0xFF,0x00,0x07,0xFF,0xF0,0xFF,0xFC,0x00,0x3F,0xFF,0x83,0xFF,0xF0,0x01,0xFF,0xFE,0x0F,0xFF,0xC0,0x3F,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x3F,0xFF,0xFF,0xFF,0xF8,0x00,0xFF,0xFF,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xFF,0xFC,0x00,0x0F,0xFF,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xFF,0xFC,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00, // 'D'
0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0x83,0xFF,0xFF,0xFF,0xFF,0xC1,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF0,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFE,0x00, // 'E'
0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xF1,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF,0xFF,0xC7,0xFF,0xFF,0xFF,0xFF,0x8F,0xFF,0xFF,0xFF,0xFF,0x1F,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xF1,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00, // 'F'
0x00,0x00,0x1F,0xFE,0x00,0x00,0x00,0x00,0x7F,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xFF,0xFE,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xC0,0x00,0x03,0xFF,0xFF,0xFF,0xF8,0x00,0x03,0xFF,0xFF,0xFF,0xFE,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xFF,0xFF,0xF0,0x03,0xFF,0xFF,0xFF,0xFF,0xFC,0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0x80,0xFF,0xFF,0x80,0xFF,0xFF,0x00,0x1F,0xFF,0xC0,0xFF,0xFF,0x00,0x07,0xFF,0xF0,0x7F,0xFF,0x00,0x01,0xFF,0xF8,0x7F,0xFF,0x00,0x00,0x7F,0xFC,0x3F,0xFF,0x80,0x00,0x3F,0xFF,0x1F,0xFF,0x80,0x00,0x1F,0xFF,0x9F,0xFF,0xC0,0x00,0x07,0xFF,0xCF,0xFF,0xC0,0x00,0x03,0xFF,0xE7,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x07,0xFF,0xFF,0xF7,0xFF,0xE0,0x03,0xFF,0xFF,0xFB,0xFF,0xF0,0x01,0xFF,0xFF,0xFD,0xFF,0xF8,0x00,0xFF,0xFF,0xFE,0xFF,0xFC,0x00,0x7F,0xFF,0xFF,0x7F,0xFE,0x00,0x3F,0xFF,0xFF,0x9F,0xFF,0x00,0x1F,0xFF,0xFF,0xCF,0xFF,0xC0,0x0F,0xFF,0xFF,0xE7,0xFF,0xE0,0x07,0xFF,0xFF,0xF3,0xFF,0xF0,0x00,0x01,0xFF,0xF9,0xFF,0xF8,0x00,0x00,0xFF,0xFC,0xFF,0xFC,0x00,0x00,0x7F,0xFE,0x7F,0xFF,0x00,0x00,0x3F,0xFF,0x1F,0xFF,0x80,0x00,0x1F,0xFF,0x8F,0xFF,0xC0,0x00,0x0F,0xFF,0xC7,0xFF,0xF0,0x00,0x07,0xFF,0xE1,0xFF,0xFC,0x00,0x03,0xFF,0xF0,0xFF,0xFF,0x00,0x01,0xFF,0xF8,0x3F,0xFF,0xC0,0x01,0xFF,0xFC,0x1F,0xFF,0xFC,0x03,0xFF,0xFE,0x07,0xFF,0xFF,0xFF,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0xFF,0xC0,0x3F,0xFF,0xFF,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF,0xE0,0x03,0xFF,0xFF,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xFF,0xC0,0x00,0x1F,0xFF,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x7F,0xFF,0xFC,0x00,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00, // 'G'
0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x7F,0xFE,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x0F,0xFF,0xDF,0xFF,0x80,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x03,0xFF,0xF7,0xFF,0xE0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0xFF,0xFD,0xFF,0xF8,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x7F,0xFE,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x0F,0xFF,0xDF,0xFF,0x80,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x03,0xFF,0xF7,0xFF,0xE0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0xFF,0xFD,0xFF,0xF8,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x7F,0xFE,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x0F,0xFF,0xDF,0xFF,0x80,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x03,0xFF,0xF7,0xFF,0xE0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFE,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x0F,0xFF,0xDF,0xFF,0x80,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x03,0xFF,0xF7,0xFF,0xE0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0xFF,0xFD,0xFF,0xF8,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x7F,0xFE,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x0F,0xFF,0xDF,0xFF,0x80,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x03,0xFF,0xF7,0xFF,0xE0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0xFF,0xFD,0xFF,0xF8,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x7F,0xFE,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x0F,0xFF,0xDF,0xFF,0x80,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x03,0xFF,0xF7,0xFF,0xE0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0xFF,0xFD,0xFF,0xF8,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x00, // 'H'
0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFC, // 'I'
0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x7F,0xFE,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x0F,0xFF,0x8F,0xFF,0x80,0x0F,0xFF,0xC7,0xFF,0xE0,0x07,0xFF,0xE3,0xFF,0xF0,0x03,0xFF,0xF1,0xFF,0xFC,0x03,0xFF,0xF0,0xFF,0xFF,0x07,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFC,0x07,0xFF,0xFF,0xFF,0xFC,0x01,0xFF,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0xFC,0x00,0x01,0xFF,0xFF,0xF8,0x00,0x00,0x1F,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xC0,0x00,0x00, // 'J'
0xFF,0xFC,0x00,0x01,0xFF,0xFF,0x7F,0xFE,0x00,0x01,0xFF,0xFF,0x3F,0xFF,0x00,0x01,0xFF,0xFF,0x1F,0xFF,0x80,0x00,0xFF,0xFF,0x0F,0xFF,0xC0,0x00,0xFF,0xFF,0x07,0xFF,0xE0,0x00,0xFF,0xFF,0x83,0xFF,0xF0,0x00,0xFF,0xFF,0x81,0xFF,0xF8,0x00,0x7F,0xFF,0x80,0xFF,0xFC,0x00,0x7F,0xFF,0x80,0x7F,0xFE,0x00,0x7F,0xFF,0xC0,0x3F,0xFF,0x00,0x3F,0xFF,0xC0,0x1F,0xFF,0x80,0x3F,0xFF,0xC0,0x0F,0xFF,0xC0,0x3F,0xFF,0xC0,0x07,0xFF,0xE0,0x1F,0xFF,0xE0,0x03,0xFF,0xF0,0x1F,0xFF,0xE0,0x01,0xFF,0xF8,0x1F,0xFF,0xE0,0x00,0xFF,0xFC,0x0F,0xFF,0xE0,0x00,0x7F,0xFE,0x0F,0xFF,0xF0,0x00,0x3F,0xFF,0x0F,0xFF,0xF0,0x00,0x1F,0xFF,0x87,0xFF,0xF0,0x00,0x0F,0xFF,0xC7,0xFF,0xF0,0x00,0x07,0xFF,0xE7,0xFF,0xF8,0x00,0x03,0xFF,0xF3,0xFF,0xF8,0x00,0x01,0xFF,0xFB,0xFF,0xF8,0x00,0x00,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0xFF,0xFE,0x00,0x00,0x1F,0xFF,0xFF,0xFF,0x80,0x00,0x0F,0xFF,0xFF,0xFF,0xE0,0x00,0x07,0xFF,0xFF,0xFF,0xF0,0x00,0x03,0xFF,0xFF,0xFF,0xFC,0x00,0x01,0xFF,0xFF,0xFF,0xFE,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0xFF,0xFF,0xE0,0x00,0x3F,0xFF,0xFF,0xFF,0xF0,0x00,0x1F,0xFF,0xFF,0xFF,0xFC,0x00,0x0F,0xFF,0xFE,0xFF,0xFF,0x00,0x07,0xFF,0xFE,0x3F,0xFF,0x80,0x03,0xFF,0xFE,0x1F,0xFF,0xE0,0x01,0xFF,0xFE,0x07,0xFF,0xF0,0x00,0xFF,0xFE,0x03,0xFF,0xFC,0x00,0x7F,0xFE,0x00,0xFF,0xFF,0x00,0x3F,0xFF,0x00,0x7F,0xFF,0x80,0x1F,0xFF,0x80,0x1F,0xFF,0xE0,0x0F,0xFF,0xC0,0x07,0xFF,0xF0,0x07,0xFF,0xE0,0x03,0xFF,0xFC,0x03,0xFF,0xF0,0x00,0xFF,0xFF,0x01,0xFF,0xF8,0x00,0x7F,0xFF,0x80,0xFF,0xFC,0x00,0x1F,0xFF,0xE0,0x7F,0xFE,0x00,0x0F,0xFF,0xF0,0x3F,0xFF,0x00,0x03,0xFF,0xFC,0x1F,0xFF,0x80,0x00,0xFF,0xFF,0x0F,0xFF,0xC0,0x00,0x7F,0xFF,0x87,0xFF,0xE0,0x00,0x1F,0xFF,0xE3,0xFF,0xF0,0x00,0x0F,0xFF,0xF1,0xFF,0xF8,0x00,0x03,0xFF,0xFC,0xFF,0xFC,0x00,0x01,0xFF,0xFF,0x00, // 'K'
0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFC, // 'L'
0xFF,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0xFD,0xFF,0xFF,0xC0,0x00,0x00,0x3F,0xFF,0xFB,0xFF,0xFF,0x80,0x00,0x00,0x7F,0xFF,0xF7,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xEF,0xFF,0xFF,0x00,0x00,0x03,0xFF,0xFF,0xDF,0xFF,0xFE,0x00,0x00,0x07,0xFF,0xFF,0xBF,0xFF,0xFC,0x00,0x00,0x0F,0xFF,0xFF,0x7F,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0xFE,0xFF,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0xFD,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFB,0xFF,0xFF,0xF0,0x00,0x03,0xFF,0xFF,0xF7,0xFF,0xFF,0xE0,0x00,0x07,0xFF,0xFF,0xEF,0xFF,0xFF,0xC0,0x00,0x0F,0xFF,0xFF,0xDF,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xFF,0xBF,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0xFF,0x7F,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xFD,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xFB,0xFF,0xFF,0xFC,0x00,0x0F,0xFF,0xFF,0xF7,0xFF,0xDF,0xFC,0x00,0x3F,0xFB,0xFF,0xEF,0xFF,0xBF,0xF8,0x00,0x7F,0xF7,0xFF,0xDF,0xFF,0x7F,0xF0,0x00,0xFF,0xEF,0xFF,0xBF,0xFE,0x7F,0xF0,0x03,0xFF,0x9F,0xFF,0x7F,0xFC,0xFF,0xE0,0x07,0xFF,0x3F,0xFE,0xFF,0xF9,0xFF,0xC0,0x0F,0xFE,0x7F,0xFD,0xFF,0xF1,0xFF,0x80,0x3F,0xF8,0xFF,0xFB,0xFF,0xE3,0xFF,0x80,0x7F,0xF1,0xFF,0xF7,0xFF,0xC7,0xFF,0x00,0xFF,0xE3,0xFF,0xEF,0xFF,0x87,0xFE,0x01,0xFF,0x87,0xFF,0xDF,0xFF,0x0F,0xFE,0x07,0xFF,0x0F,0xFF,0xBF,0xFE,0x1F,0xFC,0x0F,0xFE,0x1F,0xFF,0x7F,0xFC,0x1F,0xF8,0x1F,0xF8,0x3F,0xFE,0xFF,0xF8,0x3F,0xF8,0x7F,0xF0,0xFF,0xFD,0xFF,0xF8,0x7F,0xF0,0xFF,0xE1,0xFF,0xFB,0xFF,0xF0,0x7F,0xE1,0xFF,0x83,0xFF,0xF7,0xFF,0xE0,0xFF,0xE7,0xFF,0x07,0xFF,0xEF,0xFF,0xC0,0xFF,0xCF,0xFE,0x0F,0xFF,0xDF,0xFF,0x81,0xFF,0x9F,0xF8,0x1F,0xFF,0xBF,0xFF,0x03,0xFF,0xFF,0xF0,0x3F,0xFF,0x7F,0xFE,0x03,0xFF,0xFF,0xC0,0x7F,0xFE,0xFF,0xFC,0x07,0xFF,0xFF,0x80,0xFF,0xFD,0xFF,0xF8,0x0F,0xFF,0xFF,0x01,0xFF,0xFB,0xFF,0xF0,0x0F,0xFF,0xFC,0x03,0xFF,0xF7,0xFF,0xE0,0x1F,0xFF,0xF8,0x07,0xFF,0xEF,0xFF,0xC0,0x3F,0xFF,0xF0,0x0F,0xFF,0xDF,0xFF,0x80,0x3F,0xFF,0xC0,0x1F,0xFF,0xBF,0xFF,0x00,0x7F,0xFF,0x80,0x3F,0xFF,0x7F,0xFE,0x00,0xFF,0xFF,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0xFF,0xFC,0x00,0xFF,0xFD,0xFF,0xF8,0x01,0xFF,0xF8,0x01,0xFF,0xFB,0xFF,0xF0,0x03,0xFF,0xF0,0x03,0xFF,0xF7,0xFF,0xE0,0x03,0xFF,0xC0,0x07,0xFF,0xEF,0xFF,0xC0,0x07,0xFF,0x80,0x0F,0xFF,0xDF,0xFF,0x80,0x0F,0xFF,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x0F,0xFC,0x00,0x3F,0xFF,0x7F,0xFE,0x00,0x1F,0xF8,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x3F,0xF0,0x00,0xFF,0xFC, // 'M'
0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x7F,0xFF,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x80,0x00,0x0F,0xFF,0xDF,0xFF,0xE0,0x00,0x07,0xFF,0xEF,0xFF,0xF0,0x00,0x03,0xFF,0xF7,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xFF,0x00,0x00,0xFF,0xFD,0xFF,0xFF,0x80,0x00,0x7F,0xFE,0xFF,0xFF,0xE0,0x00,0x3F,0xFF,0x7F,0xFF,0xF0,0x00,0x1F,0xFF,0xBF,0xFF,0xFC,0x00,0x0F,0xFF,0xDF,0xFF,0xFE,0x00,0x07,0xFF,0xEF,0xFF,0xFF,0x80,0x03,0xFF,0xF7,0xFF,0xFF,0xE0,0x01,0xFF,0xFB,0xFF,0xFF,0xF0,0x00,0xFF,0xFD,0xFF,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFF,0xFE,0x00,0x3F,0xFF,0x7F,0xFF,0xFF,0x80,0x1F,0xFF,0xBF,0xFF,0xFF,0xC0,0x0F,0xFF,0xDF,0xFF,0xFF,0xF0,0x07,0xFF,0xEF,0xFF,0xFF,0xFC,0x03,0xFF,0xF7,0xFF,0xFF,0xFE,0x01,0xFF,0xFB,0xFF,0xFF,0xFF,0x80,0xFF,0xFD,0xFF,0xFB,0xFF,0xC0,0x7F,0xFE,0xFF,0xFC,0xFF,0xF0,0x3F,0xFF,0x7F,0xFE,0x7F,0xF8,0x1F,0xFF,0xBF,0xFF,0x1F,0xFE,0x0F,0xFF,0xDF,0xFF,0x8F,0xFF,0x07,0xFF,0xEF,0xFF,0xC3,0xFF,0xC3,0xFF,0xF7,0xFF,0xE1,0xFF,0xF1,0xFF,0xFB,0xFF,0xF0,0x7F,0xF8,0xFF,0xFD,0xFF,0xF8,0x1F,0xFE,0x7F,0xFE,0xFF,0xFC,0x0F,0xFF,0x3F,0xFF,0x7F,0xFE,0x03,0xFF,0xDF,0xFF,0xBF,0xFF,0x01,0xFF,0xEF,0xFF,0xDF,0xFF,0x80,0x7F,0xFF,0xFF,0xEF,0xFF,0xC0,0x3F,0xFF,0xFF,0xF7,0xFF,0xE0,0x0F,0xFF,0xFF,0xFB,0xFF,0xF0,0x03,0xFF,0xFF,0xFD,0xFF,0xF8,0x01,0xFF,0xFF,0xFE,0xFF,0xFC,0x00,0x7F,0xFF,0xFF,0x7F,0xFE,0x00,0x3F,0xFF,0xFF,0xBF,0xFF,0x00,0x0F,0xFF,0xFF,0xDF,0xFF,0x80,0x07,0xFF,0xFF,0xEF,0xFF,0xC0,0x01,0xFF,0xFF,0xF7,0xFF,0xE0,0x00,0x7F,0xFF,0xFB,0xFF,0xF0,0x00,0x3F,0xFF,0xFD,0xFF,0xF8,0x00,0x0F,0xFF,0xFE,0xFF,0xFC,0x00,0x07,0xFF,0xFF,0x7F,0xFE,0x00,0x01,0xFF,0xFF,0xBF,0xFF,0x00,0x00,0xFF,0xFF,0xDF,0xFF,0x80,0x00,0x3F,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xF7,0xFF,0xE0,0x00,0x07,0xFF,0xFB,0xFF,0xF0,0x00,0x01,0xFF,0xFD,0xFF,0xF8,0x00,0x00,0xFF,0xFE,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x00, // 'N'
0x00,0x00,0x1F,0xFC,0x00,0x00,0x00,0x00,0x3F,0xFF,0xE0,0x00,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xE0,0x00,0x00,0x3F,0xFF,0xFF,0xFE,0x00,0x00,0x1F,0xFF,0xFF,0xFF,0xC0,0x00,0x0F,0xFF,0xFF,0xFF,0xF8,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x3F,0xFF,0xE0,0x3F,0xFF,0xE0,0x1F,0xFF,0xE0,0x03,0xFF,0xFC,0x07,0xFF,0xF0,0x00,0x7F,0xFF,0x03,0xFF,0xF8,0x00,0x0F,0xFF,0xE0,0xFF,0xFC,0x00,0x01,0xFF,0xF8,0x7F,0xFF,0x00,0x00,0x7F,0xFE,0x1F,0xFF,0x80,0x00,0x0F,0xFF,0xC7,0xFF,0xE0,0x00,0x03,0xFF,0xF1,0xFF,0xF8,0x00,0x00,0xFF,0xFC,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xF9,0xFF,0xF8,0x00,0x00,0xFF,0xFC,0x7F,0xFE,0x00,0x00,0x3F,0xFF,0x1F,0xFF,0x80,0x00,0x0F,0xFF,0xC7,0xFF,0xF0,0x00,0x07,0xFF,0xF0,0xFF,0xFC,0x00,0x01,0xFF,0xF8,0x3F,0xFF,0x80,0x00,0xFF,0xFE,0x07,0xFF,0xF0,0x00,0x7F,0xFF,0x01,0xFF,0xFE,0x00,0x3F,0xFF,0xC0,0x3F,0xFF,0xE0,0x3F,0xFF,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x3F,0xFF,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x1F,0xFF,0xFF,0xFF,0xC0,0x00,0x03,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x7F,0xFF,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x3F,0xFF,0xE0,0x00,0x00,0x00,0x01,0xFF,0xC0,0x00,0x00, // 'O'
0xFF,0xFF,0xFF,0xF0,0x00,0x03,0xFF,0xFF,0xFF,0xFC,0x00,0x0F,0xFF,0xFF,0xFF,0xFE,0x00,0x3F,0xFF,0xFF,0xFF,0xFE,0x00,0xFF,0xFF,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,0xC0,0x03,0xFF,0xFE,0x3F,0xFF,0x00,0x03,0xFF,0xFC,0xFF,0xFC,0x00,0x07,0xFF,0xF3,0xFF,0xF0,0x00,0x0F,0xFF,0xCF,0xFF,0xC0,0x00,0x3F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0xFF,0xFE,0xFF,0xFC,0x00,0x07,0xFF,0xF3,0xFF,0xF0,0x00,0x3F,0xFF,0xCF,0xFF,0xC0,0x03,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,0xFE,0x03,0xFF,0xFF,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xFF,0xFE,0x00,0x3F,0xFF,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xF8,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00, // 'P'
0x00,0x00,0x1F,0xFC,0x00,0x00,0x00,0x00,0x3F,0xFF,0xE0,0x00,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xE0,0x00,0x00,0x3F,0xFF,0xFF,0xFE,0x00,0x00,0x1F,0xFF,0xFF,0xFF,0xC0,0x00,0x0F,0xFF,0xFF,0xFF,0xF8,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x3F,0xFF,0xE0,0x3F,0xFF,0xE0,0x1F,0xFF,0xE0,0x03,0xFF,0xFC,0x07,0xFF,0xF0,0x00,0x7F,0xFF,0x03,0xFF,0xF8,0x00,0x0F,0xFF,0xE0,0xFF,0xFC,0x00,0x01,0xFF,0xF8,0x7F,0xFF,0x00,0x00,0x7F,0xFF,0x1F,0xFF,0x80,0x00,0x0F,0xFF,0xC7,0xFF,0xE0,0x00,0x03,0xFF,0xF1,0xFF,0xF8,0x00,0x00,0xFF,0xFC,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x01,0xFF,0xF9,0xFF,0xF8,0x00,0x00,0xFF,0xFC,0x7F,0xFE,0x00,0x00,0x3F,0xFF,0x1F,0xFF,0x80,0x00,0x0F,0xFF,0xC3,0xFF,0xF0,0x00,0x07,0xFF,0xF0,0xFF,0xFC,0x00,0x01,0xFF,0xF8,0x3F,0xFF,0x80,0x00,0xFF,0xFE,0x07,0xFF,0xF0,0x00,0x7F,0xFF,0x01,0xFF,0xFE,0x00,0x3F,0xFF,0xC0,0x3F,0xFF,0xE0,0x3F,0xFF,0xE0,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0xFF,0xFC,0x00,0x3F,0xFF,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x1F,0xFF,0xFF,0xFF,0xC0,0x00,0x03,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x3F,0xFF,0xFF,0xFE,0x00,0x00,0x07,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x3F,0xFF,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x00,0x1F,0xFF,0xF0,0x00,0x00,0x00,0x03,0xFF,0xFF,0x00,0x00,0x00,0x00,0x7F,0xFF,0xE0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x00,0xFF,0xF0,0x00,0x00,0x00,0x00,0x1F,0xF8,0x00,0x00,0x00,0x00,0x03,0xFC,0x00,0x00,0x00,0x00,0x00,0x3E,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00, // 'Q'
0xFF,0xFF,0xFF,0xF8,0x00,0x01,0xFF,0xFF,0xFF,0xFF,0x00,0x03,0xFF,0xFF,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xFF,0xFF,0xC0,0x3F,0xFF,0xFF,0xFF,0xFF,0xC0,0x7F,0xFF,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0xC1,0xFF,0xFF,0xFF,0xFF,0xFF,0x83,0xFF,0xFF,0xFF,0xFF,0xFF,0x87,0xFF,0xE0,0x01,0xFF,0xFF,0x0F,0xFF,0xC0,0x00,0xFF,0xFF,0x1F,0xFF,0x80,0x00,0xFF,0xFE,0x3F,0xFF,0x00,0x00,0xFF,0xFC,0x7F,0xFE,0x00,0x01,0xFF,0xF8,0xFF,0xFC,0x00,0x03,0xFF,0xF1,0xFF,0xF8,0x00,0x07,0xFF,0xE3,0xFF,0xF0,0x00,0x0F,0xFF,0xC7,0xFF,0xE0,0x00,0x1F,0xFF,0x8F,0xFF,0xC0,0x00,0x3F,0xFF,0x1F,0xFF,0x80,0x00,0x7F,0xFE,0x3F,0xFF,0x00,0x00,0xFF,0xFC,0x7F,0xFE,0x00,0x03,0xFF,0xF0,0xFF,0xFC,0x00,0x0F,0xFF,0xE1,0xFF,0xF8,0x00,0x7F,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xFF,0x07,0xFF,0xFF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xE0,0x3F,0xFF,0xFF,0xFF,0xFF,0x80,0x7F,0xFF,0xFF,0xFF,0xFE,0x00,0xFF,0xFF,0xFF,0xFF,0xF0,0x01,0xFF,0xFF,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xFF,0xFF,0x80,0x07,0xFF,0xFF,0xFF,0xFF,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0x00,0x1F,0xFF,0x80,0x7F,0xFE,0x00,0x3F,0xFF,0x00,0xFF,0xFE,0x00,0x7F,0xFE,0x00,0xFF,0xFC,0x00,0xFF,0xFC,0x01,0xFF,0xFC,0x01,0xFF,0xF8,0x01,0xFF,0xF8,0x03,0xFF,0xF0,0x03,0xFF,0xF8,0x07,0xFF,0xE0,0x03,0xFF,0xF0,0x0F,0xFF,0xC0,0x07,0xFF,0xF0,0x1F,0xFF,0x80,0x07,0xFF,0xE0,0x3F,0xFF,0x00,0x0F,0xFF,0xE0,0x7F,0xFE,0x00,0x0F,0xFF,0xC0,0xFF,0xFC,0x00,0x1F,0xFF,0xC1,0xFF,0xF8,0x00,0x1F,0xFF,0x83,0xFF,0xF0,0x00,0x3F,0xFF,0x87,0xFF,0xE0,0x00,0x3F,0xFF,0x0F,0xFF,0xC0,0x00,0x7F,0xFF,0x1F,0xFF,0x80,0x00,0x7F,0xFF,0x3F,0xFF,0x00,0x00,0xFF,0xFE,0x7F,0xFE,0x00,0x00,0xFF,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFC, // 'R'
0x00,0x00,0x3F,0xF8,0x00,0x00,0x00,0x0F,0xFF,0xFE,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x00,0xFF,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xFF,0xFC,0x00,0x3F,0xFF,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0xFF,0xF0,0x0F,0xFF,0xFF,0xFF,0xFF,0xE0,0x3F,0xFF,0xFF,0xFF,0xFF,0x81,0xFF,0xFF,0x01,0xFF,0xFF,0x07,0xFF,0xF0,0x01,0xFF,0xFC,0x1F,0xFF,0x80,0x03,0xFF,0xF0,0xFF,0xFC,0x00,0x07,0xFF,0xE3,0xFF,0xF0,0x00,0x1F,0xFF,0x8F,0xFF,0xC0,0x00,0x7F,0xFE,0x3F,0xFF,0x00,0x00,0xFF,0xF8,0xFF,0xFC,0x00,0x03,0xFF,0xE3,0xFF,0xF0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0x00,0x7F,0xFF,0xC0,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,0x00,0x03,0xFF,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0xFF,0xE0,0x00,0x00,0x3F,0xFF,0xFF,0xF0,0x00,0x00,0x3F,0xFF,0xFF,0xF0,0x00,0x00,0x7F,0xFF,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0xFF,0xC0,0x00,0x00,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x00,0x7F,0xFF,0xFE,0x00,0x00,0x00,0x3F,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFF,0xF0,0x00,0x00,0x00,0x3F,0xFF,0xC0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xF9,0xFF,0xF0,0x00,0x07,0xFF,0xE7,0xFF,0xC0,0x00,0x0F,0xFF,0x9F,0xFF,0x80,0x00,0x3F,0xFE,0x7F,0xFE,0x00,0x01,0xFF,0xF9,0xFF,0xFC,0x00,0x07,0xFF,0xE3,0xFF,0xF0,0x00,0x1F,0xFF,0x8F,0xFF,0xF0,0x00,0xFF,0xFE,0x1F,0xFF,0xF0,0x0F,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xFF,0xFF,0xC0,0x07,0xFF,0xFF,0xFF,0xFE,0x00,0x0F,0xFF,0xFF,0xFF,0xF0,0x00,0x0F,0xFF,0xFF,0xFF,0x80,0x00,0x0F,0xFF,0xFF,0xF8,0x00,0x00,0x0F,0xFF,0xFF,0x00,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00, // 'S'
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00, // 'T'
0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x07,0xFF,0xE7,0xFF,0xE0,0x00,0x3F,0xFF,0x1F,0xFF,0x80,0x00,0xFF,0xFC,0x7F,0xFF,0x00,0x07,0xFF,0xF1,0xFF,0xFE,0x00,0x3F,0xFF,0xC3,0xFF,0xFE,0x03,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFF,0xC0,0x7F,0xFF,0xFF,0xFF,0xFE,0x00,0xFF,0xFF,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xFF,0xF0,0x00,0x07,0xFF,0xFF,0xFF,0x00,0x00,0x0F,0xFF,0xFF,0xF8,0x00,0x00,0x07,0xFF,0xFF,0x00,0x00,0x00,0x01,0xFF,0xC0,0x00,0x00, // 'U'
0xFF,0xFE,0x00,0x00,0x03,0xFF,0xFB,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xE7,0xFF,0xF0,0x00,0x00,0x7F,0xFF,0x1F,0xFF,0xC0,0x00,0x01,0xFF,0xFC,0x7F,0xFF,0x00,0x00,0x07,0xFF,0xF0,0xFF,0xFE,0x00,0x00,0x3F,0xFF,0x83,0xFF,0xF8,0x00,0x00,0xFF,0xFE,0x0F,0xFF,0xE0,0x00,0x03,0xFF,0xF8,0x1F,0xFF,0x80,0x00,0x1F,0xFF,0xC0,0x7F,0xFF,0x00,0x00,0x7F,0xFF,0x01,0xFF,0xFC,0x00,0x01,0xFF,0xFC,0x03,0xFF,0xF0,0x00,0x07,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0x3F,0xFF,0x80,0x3F,0xFF,0x80,0x00,0xFF,0xFE,0x00,0x7F,0xFE,0x00,0x03,0xFF,0xF0,0x01,0xFF,0xF8,0x00,0x0F,0xFF,0xC0,0x07,0xFF,0xF0,0x00,0x7F,0xFF,0x00,0x0F,0xFF,0xC0,0x01,0xFF,0xF8,0x00,0x3F,0xFF,0x00,0x07,0xFF,0xE0,0x00,0xFF,0xFC,0x00,0x3F,0xFF,0x80,0x01,0xFF,0xF8,0x00,0xFF,0xFC,0x00,0x07,0xFF,0xE0,0x03,0xFF,0xF0,0x00,0x1F,0xFF,0x80,0x0F,0xFF,0xC0,0x00,0x3F,0xFF,0x00,0x7F,0xFE,0x00,0x00,0xFF,0xFC,0x01,0xFF,0xF8,0x00,0x03,0xFF,0xF0,0x07,0xFF,0xE0,0x00,0x07,0xFF,0xC0,0x1F,0xFF,0x00,0x00,0x1F,0xFF,0x80,0xFF,0xFC,0x00,0x00,0x7F,0xFE,0x03,0xFF,0xF0,0x00,0x00,0xFF,0xF8,0x0F,0xFF,0x80,0x00,0x03,0xFF,0xE0,0x7F,0xFE,0x00,0x00,0x0F,0xFF,0xC1,0xFF,0xF8,0x00,0x00,0x1F,0xFF,0x07,0xFF,0xC0,0x00,0x00,0x7F,0xFC,0x1F,0xFF,0x00,0x00,0x01,0xFF,0xF8,0xFF,0xFC,0x00,0x00,0x03,0xFF,0xE3,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0x8F,0xFF,0x80,0x00,0x00,0x3F,0xFE,0x3F,0xFC,0x00,0x00,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF7,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xDF,0xFE,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFF,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x01,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x1F,0xFF,0xFF,0x80,0x00,0x00,0x00,0x3F,0xFF,0xFE,0x00,0x00,0x00,0x00,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x03,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x07,0xFF,0xFF,0x00,0x00,0x00,0x00,0x1F,0xFF,0xFC,0x00,0x00,0x00,0x00,0x7F,0xFF,0xE0,0x00,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,0x00,0x00,0x03,0xFF,0xFE,0x00,0x00,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x00,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00, // 'V'
0xFF,0xFC,0x00,0x0F,0xFF,0x00,0x03,0xFF,0xF7,0xFF,0xE0,0x00,0x7F,0xF8,0x00,0x1F,0xFF,0x1F,0xFF,0x00,0x07,0xFF,0xC0,0x00,0xFF,0xF8,0xFF,0xF8,0x00,0x3F,0xFE,0x00,0x0F,0xFF,0xC7,0xFF,0xC0,0x01,0xFF,0xF8,0x00,0x7F,0xFE,0x3F,0xFF,0x00,0x0F,0xFF,0xC0,0x03,0xFF,0xF1,0xFF,0xF8,0x00,0x7F,0xFE,0x00,0x1F,0xFF,0x07,0xFF,0xC0,0x07,0xFF,0xF0,0x00,0xFF,0xF8,0x3F,0xFE,0x00,0x3F,0xFF,0xC0,0x07,0xFF,0xC1,0xFF,0xF0,0x01,0xFF,0xFE,0x00,0x7F,0xFE,0x0F,0xFF,0xC0,0x0F,0xFF,0xF0,0x03,0xFF,0xE0,0x7F,0xFE,0x00,0xFF,0xFF,0x80,0x1F,0xFF,0x01,0xFF,0xF0,0x07,0xFF,0xFC,0x00,0xFF,0xF8,0x0F,0xFF,0x80,0x3F,0xFF,0xF0,0x07,0xFF,0xC0,0x7F,0xFC,0x01,0xFF,0xFF,0x80,0x7F,0xFE,0x03,0xFF,0xF0,0x0F,0xFF,0xFC,0x03,0xFF,0xE0,0x0F,0xFF,0x80,0xFF,0xFF,0xE0,0x1F,0xFF,0x00,0x7F,0xFC,0x07,0xFF,0xFF,0x80,0xFF,0xF8,0x03,0xFF,0xE0,0x3F,0xFF,0xFC,0x07,0xFF,0xC0,0x1F,0xFF,0x01,0xFF,0xFF,0xE0,0x3F,0xFE,0x00,0xFF,0xF8,0x0F,0xFF,0xFF,0x03,0xFF,0xE0,0x03,0xFF,0xE0,0xFF,0xFF,0xF8,0x1F,0xFF,0x00,0x1F,0xFF,0x07,0xFF,0xFF,0xE0,0xFF,0xF8,0x00,0xFF,0xF8,0x3F,0xFF,0xFF,0x07,0xFF,0xC0,0x07,0xFF,0xC1,0xFF,0xFF,0xF8,0x3F,0xFE,0x00,0x3F,0xFE,0x1F,0xFF,0xFF,0xC3,0xFF,0xE0,0x00,0xFF,0xF8,0xFF,0xEF,0xFF,0x1F,0xFF,0x00,0x07,0xFF,0xC7,0xFF,0x3F,0xF8,0xFF,0xF8,0x00,0x3F,0xFE,0x3F,0xF9,0xFF,0xC7,0xFF,0xC0,0x01,0xFF,0xF1,0xFF,0xCF,0xFE,0x3F,0xFC,0x00,0x07,0xFF,0x9F,0xFC,0x7F,0xF1,0xFF,0xE0,0x00,0x3F,0xFC,0xFF,0xE3,0xFF,0xDF,0xFF,0x00,0x01,0xFF,0xF7,0xFF,0x0F,0xFE,0xFF,0xF8,0x00,0x0F,0xFF,0xBF,0xF8,0x7F,0xF7,0xFF,0xC0,0x00,0x7F,0xFF,0xFF,0xC3,0xFF,0xBF,0xFC,0x00,0x01,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xE0,0x00,0x0F,0xFF,0xFF,0xE0,0x7F,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0xFF,0x03,0xFF,0xFF,0xF8,0x00,0x03,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xC0,0x00,0x1F,0xFF,0xFF,0x80,0xFF,0xFF,0xFC,0x00,0x00,0x7F,0xFF,0xFC,0x03,0xFF,0xFF,0xE0,0x00,0x03,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0x00,0x00,0x1F,0xFF,0xFF,0x00,0xFF,0xFF,0xF8,0x00,0x00,0xFF,0xFF,0xF0,0x07,0xFF,0xFF,0x80,0x00,0x07,0xFF,0xFF,0x80,0x3F,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0xFC,0x00,0xFF,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0x00,0x00,0x07,0xFF,0xFF,0x00,0x3F,0xFF,0xF8,0x00,0x00,0x3F,0xFF,0xF0,0x01,0xFF,0xFF,0x80,0x00,0x00,0xFF,0xFF,0x80,0x07,0xFF,0xFC,0x00,0x00,0x07,0xFF,0xFC,0x00,0x3F,0xFF,0xE0,0x00,0x00,0x3F,0xFF,0xE0,0x01,0xFF,0xFF,0x00,0x00,0x01,0xFF,0xFE,0x00,0x0F,0xFF,0xF8,0x00,0x00,0x0F,0xFF,0xF0,0x00,0x3F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x80,0x01,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xFC,0x00,0x0F,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x7F,0xFF,0x00,0x00, // 'W'
0x7F,0xFF,0x00,0x00,0x1F,0xFF,0xC7,0xFF,0xF8,0x00,0x03,0xFF,0xFC,0x3F,0xFF,0x80,0x00,0x3F,0xFF,0x81,0xFF,0xFC,0x00,0x07,0xFF,0xF8,0x1F,0xFF,0xC0,0x00,0x7F,0xFF,0x00,0xFF,0xFE,0x00,0x0F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0xFF,0xFE,0x00,0x7F,0xFF,0x00,0x1F,0xFF,0xC0,0x07,0xFF,0xF0,0x01,0xFF,0xFC,0x00,0x3F,0xFF,0x80,0x3F,0xFF,0x80,0x03,0xFF,0xF8,0x03,0xFF,0xF8,0x00,0x1F,0xFF,0xC0,0x7F,0xFF,0x00,0x00,0xFF,0xFC,0x07,0xFF,0xE0,0x00,0x0F,0xFF,0xE0,0xFF,0xFE,0x00,0x00,0x7F,0xFE,0x0F,0xFF,0xC0,0x00,0x07,0xFF,0xF1,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x1F,0xFF,0x80,0x00,0x03,0xFF,0xFB,0xFF,0xF8,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x3F,0xFF,0xFF,0x80,0x00,0x00,0x03,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x1F,0xFF,0xFF,0x00,0x00,0x00,0x01,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x0F,0xFF,0xFE,0x00,0x00,0x00,0x00,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x0F,0xFF,0xFE,0x00,0x00,0x00,0x01,0xFF,0xFF,0xF0,0x00,0x00,0x00,0x1F,0xFF,0xFF,0x00,0x00,0x00,0x03,0xFF,0xFF,0xF8,0x00,0x00,0x00,0x7F,0xFF,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x00,0x01,0xFF,0xFF,0xFF,0xF0,0x00,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x00,0x03,0xFF,0xFB,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0x1F,0xFF,0xC0,0x00,0x07,0xFF,0xF1,0xFF,0xFC,0x00,0x00,0xFF,0xFE,0x0F,0xFF,0xE0,0x00,0x0F,0xFF,0xE0,0xFF,0xFE,0x00,0x01,0xFF,0xFC,0x07,0xFF,0xF0,0x00,0x1F,0xFF,0xC0,0x7F,0xFF,0x00,0x03,0xFF,0xF8,0x03,0xFF,0xF8,0x00,0x3F,0xFF,0x80,0x3F,0xFF,0xC0,0x07,0xFF,0xF0,0x01,0xFF,0xFC,0x00,0xFF,0xFF,0x00,0x1F,0xFF,0xE0,0x0F,0xFF,0xE0,0x00,0xFF,0xFE,0x01,0xFF,0xFE,0x00,0x0F,0xFF,0xF0,0x1F,0xFF,0xC0,0x00,0x7F,0xFF,0x03,0xFF,0xFC,0x00,0x07,0xFF,0xF8,0x3F,0xFF,0x80,0x00,0x3F,0xFF,0x87,0xFF,0xF8,0x00,0x03,0xFF,0xFC,0xFF,0xFF,0x00,0x00,0x1F,0xFF,0xE0, // 'X'
0xFF,0xFE,0x00,0x00,0x1F,0xFF,0xCF,0xFF,0xC0,0x00,0x03,0xFF,0xF9,0xFF,0xFC,0x00,0x00,0x7F,0xFE,0x1F,0xFF,0x80,0x00,0x1F,0xFF,0xC3,0xFF,0xF8,0x00,0x03,0xFF,0xF0,0x3F,0xFF,0x00,0x00,0xFF,0xFE,0x07,0xFF,0xE0,0x00,0x1F,0xFF,0x80,0x7F,0xFE,0x00,0x07,0xFF,0xF0,0x0F,0xFF,0xC0,0x00,0xFF,0xFC,0x00,0xFF,0xFC,0x00,0x1F,0xFF,0x80,0x1F,0xFF,0x80,0x07,0xFF,0xE0,0x01,0xFF,0xF8,0x00,0xFF,0xFC,0x00,0x3F,0xFF,0x00,0x3F,0xFF,0x00,0x03,0xFF,0xE0,0x07,0xFF,0xE0,0x00,0x7F,0xFE,0x01,0xFF,0xF8,0x00,0x07,0xFF,0xC0,0x3F,0xFF,0x00,0x00,0xFF,0xFC,0x07,0xFF,0xC0,0x00,0x0F,0xFF,0x81,0xFF,0xF8,0x00,0x01,0xFF,0xF0,0x3F,0xFE,0x00,0x00,0x1F,0xFF,0x0F,0xFF,0xC0,0x00,0x03,0xFF,0xE1,0xFF,0xF0,0x00,0x00,0x3F,0xFE,0x7F,0xFE,0x00,0x00,0x07,0xFF,0xCF,0xFF,0x80,0x00,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x1F,0xFF,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xFF,0xFC,0x00,0x00,0x00,0x3F,0xFF,0xFF,0x00,0x00,0x00,0x03,0xFF,0xFF,0xE0,0x00,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x00,0x07,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xC0,0x00,0x00,0x00,0x0F,0xFF,0xF8,0x00,0x00,0x00,0x01,0xFF,0xFE,0x00,0x00,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00, // 'Y'
0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xE3,0xFF,0xFF,0xFF,0xFF,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x00,0x00,0x3F,0xFF,0x80,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x0F,0xFF,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFF,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xFF,0xF8, // 'Z'
0xFF,0xFF,0xDF,0xFF,0xFB,0xFF,0xFF,0x7F,0xFF,0xEF,0xFF,0xFD,0xFF,0xFF,0xBF,0xFF,0xF7,0xFF,0xFE,0xFF,0xFF,0xDF,0xFF,0xFB,0xFF,0xE0,0x7F,0xFC,0x0F,0xFF,0x81,0xFF,0xF0,0x3F,0xFE,0x07,0xFF,0xC0,0xFF,0xF8,0x1F,0xFF,0x03,0xFF,0xE0,0x7F,0xFC,0x0F,0xFF,0x81,0xFF,0xF0,0x3F,0xFE,0x07,0xFF,0xC0,0xFF,0xF8,0x1F,0xFF,0x03,0xFF,0xE0,0x7F,0xFC,0x0F,0xFF,0x81,0xFF,0xF0,0x3F,0xFE,0x07,0xFF,0xC0,0xFF,0xF8,0x1F,0xFF,0x03,0xFF,0xE0,0x7F,0xFC,0x0F,0xFF,0x81,0xFF,0xF0,0x3F,0xFE,0x07,0xFF,0xC0,0xFF,0xF8,0x1F,0xFF,0x03,0xFF,0xE0,0x7F,0xFC,0x0F,0xFF,0x81,0xFF,0xF0,0x3F,0xFE,0x07,0xFF,0xC0,0xFF,0xF8,0x1F,0xFF,0x03,0xFF,0xE0,0x7F,0xFC,0x0F,0xFF,0x81,0xFF,0xF0,0x3F,0xFE,0x07,0xFF,0xC0,0xFF,0xF8,0x1F,0xFF,0x03,0xFF,0xE0,0x7F,0xFC,0x0F,0xFF,0x81,0xFF,0xF0,0x3F,0xFE,0x07,0xFF,0xC0,0xFF,0xF8,0x1F,0xFF,0x03,0xFF,0xE0,0x7F,0xFC,0x0F,0xFF,0x81,0xFF,0xF0,0x3F,0xFE,0x07,0xFF,0xFE,0xFF,0xFF,0xDF,0xFF,0xFB,0xFF,0xFF,0x7F,0xFF,0xEF,0xFF,0xFD,0xFF,0xFF,0xBF,0xFF,0xF7,0xFF,0xFE,0xFF,0xFF,0xC0, // '['
0xFF,0xFC,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x7F,0xFE,0x00,0x00,0x00,0xFF,0xFC,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0x80, // '\'
0xFF,0xFF,0xBF,0xFF,0xEF,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF,0xBF,0xFF,0xEF,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF,0xBF,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xF8,0x3F,0xFE,0x0F,0xFF,0x83,0xFF,0xE0,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF,0xBF,0xFF,0xEF,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF,0xBF,0xFF,0xEF,0xFF,0xFB,0xFF,0xFE,0xFF,0xFF,0x80, // ']'
0x00,0x1F,0xF8,0x00,0x00,0x07,0xFF,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0x00,0x00,0x1F,0xFF,0x80,0x00,0x0F,0xFF,0xF0,0x00,0x03,0xFF,0xFC,0x00,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0xE0,0x00,0x1F,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0x00,0x03,0xFE,0x7F,0xC0,0x00,0xFF,0x9F,0xF8,0x00,0x7F,0xE3,0xFE,0x00,0x1F,0xF0,0xFF,0x80,0x0F,0xFC,0x3F,0xF0,0x03,0xFE,0x07,0xFC,0x01,0xFF,0x81,0xFF,0x80,0x7F,0xE0,0x7F,0xE0,0x1F,0xF0,0x0F,0xF8,0x0F,0xFC,0x03,0xFF,0x03,0xFF,0x00,0x7F,0xC1,0xFF,0x80,0x1F,0xF8,0x7F,0xE0,0x07,0xFE,0x1F,0xF0,0x00,0xFF,0xCF,0xFC,0x00,0x3F,0xF3,0xFF,0x00,0x07,0xFE, // '^'
0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE, // '_'
0xFF,0xFC,0x00,0xFF,0xFC,0x00,0xFF,0xFC,0x00,0xFF,0xF8,0x00,0xFF,0xF8,0x00,0xFF,0xF8,0x00,0xFF,0xF0,0x00,0xFF,0xF0,0x00,0xFF,0xF0,0x00,0xFF,0xE0,0x00,0xFF,0xE0,0x00,0xFF,0xE0, // '`'
0x00,0x03,0xFF,0x80,0x00,0x00,0x3F,0xFF,0xF0,0x00,0x00,0xFF,0xFF,0xFC,0x00,0x03,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xFF,0xC0,0x1F,0xFF,0xFF,0xFF,0xC0,0x3F,0xFF,0xFF,0xFF,0xE0,0x3F,0xFF,0xFF,0xFF,0xF0,0x7F,0xFF,0x07,0xFF,0xF0,0x7F,0xFE,0x03,0xFF,0xF0,0x7F,0xFC,0x01,0xFF,0xF8,0x7F,0xFC,0x01,0xFF,0xF8,0x7F,0xFC,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x07,0xFF,0xFF,0xF8,0x00,0x7F,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xF8,0x7F,0xFF,0x80,0xFF,0xF8,0xFF,0xFE,0x00,0xFF,0xF8,0xFF,0xFC,0x00,0xFF,0xF8,0xFF,0xF8,0x00,0xFF,0xF8,0xFF,0xF8,0x00,0xFF,0xF8,0xFF,0xF8,0x00,0xFF,0xF8,0xFF,0xF8,0x00,0xFF,0xF8,0xFF,0xF8,0x01,0xFF,0xF8,0xFF,0xFC,0x03,0xFF,0xF8,0xFF,0xFE,0x0F,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xF8,0x7F,0xFF,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFC,0x0F,0xFF,0xFE,0xFF,0xFC,0x07,0xFF,0xFC,0x7F,0xFC,0x01,0xFF,0xF8,0x7F,0xFE,0x00,0x3F,0xC0,0x00,0x00, // 'a'
0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x1F,0xE0,0x00,0xFF,0xF8,0xFF,0xFC,0x00,0xFF,0xF9,0xFF,0xFE,0x00,0xFF,0xFB,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0x03,0xFF,0xF8,0xFF,0xFC,0x01,0xFF,0xFC,0xFF,0xFC,0x00,0xFF,0xFC,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x7F,0xFE,0xFF,0xF8,0x00,0x7F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x7F,0xFE,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0xFF,0xFC,0xFF,0xFC,0x01,0xFF,0xFC,0xFF,0xFF,0x03,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xF7,0xFF,0xFF,0xC0,0xFF,0xF3,0xFF,0xFF,0x80,0xFF,0xF1,0xFF,0xFE,0x00,0xFF,0xF0,0xFF,0xFC,0x00,0x00,0x00,0x1F,0xE0,0x00, // 'b'
0x00,0x01,0xFF,0x80,0x00,0x00,0x1F,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x07,0xFF,0xFF,0xF8,0x00,0x1F,0xFF,0xFF,0xF8,0x00,0x7F,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xFF,0xF0,0x0F,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xE0,0xFF,0xFE,0x0F,0xFF,0xE1,0xFF,0xF8,0x07,0xFF,0xC3,0xFF,0xE0,0x0F,0xFF,0x8F,0xFF,0x80,0x0F,0xFF,0x9F,0xFF,0x00,0x1F,0xFF,0x3F,0xFE,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x3F,0xFD,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xF0,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xC0,0x03,0xFF,0xCF,0xFF,0x80,0x0F,0xFF,0x9F,0xFF,0x00,0x1F,0xFF,0x1F,0xFF,0x00,0x3F,0xFE,0x3F,0xFF,0x00,0xFF,0xF8,0x7F,0xFF,0x07,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xE0,0x7F,0xFF,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0x00,0xFF,0xFF,0xFF,0xFC,0x00,0xFF,0xFF,0xFF,0xF0,0x00,0xFF,0xFF,0xFF,0xC0,0x00,0xFF,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x3F,0xFF,0xC0,0x00,0x00,0x0F,0xFC,0x00,0x00, // 'c'
0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x0F,0xF0,0x3F,0xFE,0x00,0x7F,0xFC,0x3F,0xFE,0x00,0xFF,0xFF,0x3F,0xFE,0x03,0xFF,0xFF,0xBF,0xFE,0x07,0xFF,0xFF,0xFF,0xFE,0x07,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xC1,0xFF,0xFE,0x7F,0xFF,0x00,0xFF,0xFE,0x7F,0xFE,0x00,0x7F,0xFE,0x7F,0xFE,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x3F,0xFE,0x7F,0xFE,0x00,0x7F,0xFE,0x7F,0xFF,0x00,0xFF,0xFE,0x3F,0xFF,0x81,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFE,0x07,0xFF,0xFF,0xFF,0xFE,0x07,0xFF,0xFF,0xDF,0xFE,0x01,0xFF,0xFF,0x9F,0xFE,0x00,0xFF,0xFF,0x1F,0xFE,0x00,0x7F,0xFC,0x1F,0xFE,0x00,0x0F,0xF0,0x00,0x00, // 'd'
0x00,0x00,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xFC,0x00,0x00,0x0F,0xFF,0xFF,0x80,0x00,0x0F,0xFF,0xFF,0xE0,0x00,0x1F,0xFF,0xFF,0xFC,0x00,0x1F,0xFF,0xFF,0xFF,0x00,0x1F,0xFF,0xFF,0xFF,0xC0,0x0F,0xFF,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xFF,0xFE,0x07,0xFF,0xF0,0x3F,0xFF,0x07,0xFF,0xF0,0x0F,0xFF,0x83,0xFF,0xF0,0x03,0xFF,0xE1,0xFF,0xF0,0x01,0xFF,0xF1,0xFF,0xF8,0x00,0x7F,0xF8,0xFF,0xF8,0x00,0x3F,0xFC,0x7F,0xFC,0x00,0x1F,0xFF,0x3F,0xFE,0x00,0x0F,0xFF,0x9F,0xFF,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0x9F,0xFF,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xF0,0x00,0x04,0x00,0xFF,0xFC,0x00,0x03,0x00,0x7F,0xFE,0x00,0x03,0xC0,0x3F,0xFF,0xC0,0x07,0xE0,0x0F,0xFF,0xF8,0x0F,0xF8,0x07,0xFF,0xFF,0xFF,0xFE,0x01,0xFF,0xFF,0xFF,0xFF,0x80,0x7F,0xFF,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0xFF,0xE0,0x01,0xFF,0xFF,0xFF,0xE0,0x00,0x7F,0xFF,0xFF,0xE0,0x00,0x0F,0xFF,0xFF,0xC0,0x00,0x01,0xFF,0xFF,0x80,0x00,0x00,0x0F,0xFC,0x00,0x00, // 'e'
0x00,0x00,0x3F,0xE0,0x00,0x07,0xFF,0xE0,0x00,0x7F,0xFF,0x80,0x07,0xFF,0xFE,0x00,0x3F,0xFF,0xF8,0x00,0xFF,0xFF,0xE0,0x07,0xFF,0xFF,0x80,0x3F,0xFF,0xFE,0x00,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xE0,0x1F,0xFF,0xE0,0x00,0x7F,0xFE,0x00,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x3F,0xFF,0xFF,0xFC,0xFF,0xFF,0xFF,0xF3,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFC,0xFF,0xFF,0xFF,0xF3,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0x3F,0xFF,0xFF,0xFC,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xF0,0x00,0x07,0xFF,0xC0,0x00,0x1F,0xFF,0x00,0x00,0x7F,0xFC,0x00,0x01,0xFF,0xF0,0x00, // 'f'
0x00,0x07,0xF8,0x00,0x00,0x00,0x1F,0xFF,0x87,0xFF,0x80,0x1F,0xFF,0xF3,0xFF,0xC0,0x3F,0xFF,0xFD,0xFF,0xE0,0x3F,0xFF,0xFF,0xFF,0xF0,0x3F,0xFF,0xFF,0xFF,0xF8,0x3F,0xFF,0xFF,0xFF,0xFC,0x1F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFF,0x0F,0xFF,0xFF,0xFF,0xFF,0x8F,0xFF,0xF0,0x3F,0xFF,0xC7,0xFF,0xF0,0x07,0xFF,0xE7,0xFF,0xF0,0x01,0xFF,0xF3,0xFF,0xF0,0x00,0xFF,0xF9,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x1F,0xFF,0x7F,0xFE,0x00,0x0F,0xFF,0xBF,0xFF,0x00,0x07,0xFF,0xDF,0xFF,0x00,0x03,0xFF,0xEF,0xFF,0x80,0x01,0xFF,0xF7,0xFF,0xC0,0x00,0xFF,0xFB,0xFF,0xE0,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x1F,0xFF,0x7F,0xFE,0x00,0x0F,0xFF,0xBF,0xFF,0x00,0x07,0xFF,0xCF,0xFF,0x80,0x03,0xFF,0xE7,0xFF,0xC0,0x01,0xFF,0xF3,0xFF,0xF0,0x00,0xFF,0xF9,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xFE,0x00,0x3F,0xFE,0x3F,0xFF,0x80,0x3F,0xFF,0x1F,0xFF,0xE0,0x7F,0xFF,0x87,0xFF,0xFF,0xFF,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF0,0x7F,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xFC,0x07,0xFF,0xFF,0xFF,0xFE,0x01,0xFF,0xFF,0xDF,0xFF,0x00,0x3F,0xFF,0xCF,0xFF,0x80,0x0F,0xFF,0xC7,0xFF,0xC0,0x00,0xFF,0x03,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x01,0xFF,0xF8,0x02,0x00,0x00,0xFF,0xFC,0x03,0x80,0x00,0xFF,0xFC,0x01,0xF0,0x00,0xFF,0xFE,0x01,0xFE,0x01,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0x80,0x3F,0xFF,0xFF,0xFF,0x80,0x0F,0xFF,0xFF,0xFF,0x80,0x03,0xFF,0xFF,0xFF,0x80,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x0F,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xE0,0x00,0x00, // 'g'
0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x07,0xFF,0xC0,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x7F,0xFC,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xF0,0x0F,0xF0,0x03,0xFF,0xE0,0xFF,0xF8,0x07,0xFF,0xC7,0xFF,0xFC,0x0F,0xFF,0x9F,0xFF,0xFC,0x1F,0xFF,0x7F,0xFF,0xFC,0x3F,0xFF,0xFF,0xFF,0xFC,0x7F,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xF8,0x1F,0xFF,0xEF,0xFF,0xC0,0x0F,0xFF,0xDF,0xFF,0x80,0x1F,0xFF,0xBF,0xFE,0x00,0x1F,0xFF,0x7F,0xFC,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0xFF,0xFB,0xFF,0xE0,0x01,0xFF,0xF7,0xFF,0xC0,0x03,0xFF,0xEF,0xFF,0x80,0x07,0xFF,0xDF,0xFF,0x00,0x0F,0xFF,0xBF,0xFE,0x00,0x1F,0xFF,0x7F,0xFC,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0xFF,0xFB,0xFF,0xE0,0x01,0xFF,0xF7,0xFF,0xC0,0x03,0xFF,0xEF,0xFF,0x80,0x07,0xFF,0xDF,0xFF,0x00,0x0F,0xFF,0xBF,0xFE,0x00,0x1F,0xFF,0x7F,0xFC,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0xFF,0xFB,0xFF,0xE0,0x01,0xFF,0xF7,0xFF,0xC0,0x03,0xFF,0xEF,0xFF,0x80,0x07,0xFF,0xDF,0xFF,0x00,0x0F,0xFF,0xBF,0xFE,0x00,0x1F,0xFF,0x7F,0xFC,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0xFF,0xFB,0xFF,0xE0,0x01,0xFF,0xF7,0xFF,0xC0,0x03,0xFF,0xE0, // 'h'
0x0F,0xC0,0x7F,0xE1,0xFF,0xE7,0xFF,0xCF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xF9,0xFF,0xE1,0xFF,0x80,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xE0, // 'i'
0x00,0x0F,0xC0,0x00,0x7F,0xE0,0x01,0xFF,0xE0,0x03,0xFF,0xE0,0x0F,0xFF,0xC0,0x1F,0xFF,0x80,0x3F,0xFF,0x00,0x7F,0xFE,0x00,0xFF,0xFC,0x00,0xFF,0xF8,0x01,0xFF,0xE0,0x01,0xFF,0x80,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0xFF,0xF0,0x03,0xFF,0xE0,0x07,0xFF,0xC0,0x0F,0xFF,0x80,0x1F,0xFF,0x00,0x3F,0xFE,0x00,0x7F,0xFC,0x00,0xFF,0xF8,0x01,0xFF,0xF0,0x03,0xFF,0xE0,0x07,0xFF,0xC0,0x0F,0xFF,0x80,0x1F,0xFF,0x00,0x3F,0xFE,0x00,0x7F,0xFC,0x00,0xFF,0xF8,0x01,0xFF,0xF0,0x03,0xFF,0xE0,0x07,0xFF,0xC0,0x0F,0xFF,0x80,0x1F,0xFF,0x00,0x3F,0xFE,0x00,0x7F,0xFC,0x00,0xFF,0xF8,0x01,0xFF,0xF0,0x03,0xFF,0xE0,0x07,0xFF,0xC0,0x0F,0xFF,0x80,0x1F,0xFF,0x00,0x3F,0xFE,0x00,0x7F,0xFC,0x00,0xFF,0xF8,0x01,0xFF,0xF0,0x03,0xFF,0xE0,0x07,0xFF,0xC0,0x0F,0xFF,0x80,0x1F,0xFF,0x00,0x3F,0xFE,0x00,0x7F,0xFC,0x00,0xFF,0xF8,0x01,0xFF,0xF0,0x03,0xFF,0xE0,0x07,0xFF,0xC0,0x0F,0xFF,0x80,0x1F,0xFF,0x00,0x3F,0xFE,0x00,0xFF,0xFC,0x01,0xFF,0xF8,0x0F,0xFF,0xE7,0xFF,0xFF,0xCF,0xFF,0xFF,0x9F,0xFF,0xFE,0x3F,0xFF,0xFC,0x7F,0xFF,0xF0,0xFF,0xFF,0xC1,0xFF,0xFF,0x03,0xFF,0xFC,0x07,0xFF,0xE0,0x07,0xFE,0x00,0x00, // 'j'
0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x0F,0xFF,0x80,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x0F,0xFF,0x80,0x0F,0xFF,0xF3,0xFF,0xE0,0x07,0xFF,0xF8,0xFF,0xF8,0x03,0xFF,0xFC,0x3F,0xFE,0x01,0xFF,0xFE,0x0F,0xFF,0x80,0x7F,0xFF,0x03,0xFF,0xE0,0x3F,0xFF,0x80,0xFF,0xF8,0x1F,0xFF,0xC0,0x3F,0xFE,0x0F,0xFF,0xF0,0x0F,0xFF,0x87,0xFF,0xF8,0x03,0xFF,0xE1,0xFF,0xFC,0x00,0xFF,0xF8,0xFF,0xFE,0x00,0x3F,0xFE,0x7F,0xFF,0x00,0x0F,0xFF,0xBF,0xFF,0x80,0x03,0xFF,0xFF,0xFF,0xC0,0x00,0xFF,0xFF,0xFF,0xF0,0x00,0x3F,0xFF,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0xFC,0x00,0x03,0xFF,0xFF,0xFE,0x00,0x00,0xFF,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xFF,0xF8,0x00,0x0F,0xFF,0xFF,0xFE,0x00,0x03,0xFF,0xFF,0xFF,0xC0,0x00,0xFF,0xFF,0xFF,0xF8,0x00,0x3F,0xFF,0xFF,0xFE,0x00,0x0F,0xFF,0xFF,0xFF,0xC0,0x03,0xFF,0xFF,0xFF,0xF0,0x00,0xFF,0xFF,0xFF,0xFE,0x00,0x3F,0xFF,0xDF,0xFF,0xC0,0x0F,0xFF,0xE3,0xFF,0xF0,0x03,0xFF,0xF0,0x7F,0xFE,0x00,0xFF,0xF8,0x1F,0xFF,0xC0,0x3F,0xFE,0x03,0xFF,0xF0,0x0F,0xFF,0x80,0xFF,0xFE,0x03,0xFF,0xE0,0x1F,0xFF,0xC0,0xFF,0xF8,0x07,0xFF,0xF0,0x3F,0xFE,0x00,0xFF,0xFE,0x0F,0xFF,0x80,0x1F,0xFF,0x83,0xFF,0xE0,0x07,0xFF,0xF0,0xFF,0xF8,0x00,0xFF,0xFE,0x3F,0xFE,0x00,0x3F,0xFF,0x8F,0xFF,0x80,0x07,0xFF,0xF3,0xFF,0xE0,0x00,0xFF,0xFE, // 'k'
0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xEF,0xFF,0xDF,0xFF,0xBF,0xFF,0x7F,0xFE,0xFF,0xFD,0xFF,0xFB,0xFF,0xF7,0xFF,0xE0, // 'l'
0x00,0x00,0x07,0xF8,0x00,0x0F,0xF0,0x03,0xFF,0xC0,0xFF,0xF8,0x01,0xFF,0xF8,0x0F,0xFF,0x0F,0xFF,0xF8,0x1F,0xFF,0xF0,0x3F,0xFC,0x7F,0xFF,0xF0,0xFF,0xFF,0xE0,0xFF,0xFB,0xFF,0xFF,0xC7,0xFF,0xFF,0xC3,0xFF,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0x8F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF3,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xCF,0xFF,0xF0,0x7F,0xFF,0xF0,0x3F,0xFF,0xBF,0xFF,0x80,0x7F,0xFF,0x80,0x7F,0xFE,0xFF,0xFC,0x01,0xFF,0xFC,0x01,0xFF,0xFB,0xFF,0xE0,0x03,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0x80,0x0F,0xFF,0x80,0x0F,0xFF,0xBF,0xFE,0x00,0x3F,0xFE,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xE0,0x03,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0x80,0x0F,0xFF,0x80,0x0F,0xFF,0xBF,0xFE,0x00,0x3F,0xFE,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xE0,0x03,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0x80,0x0F,0xFF,0x80,0x0F,0xFF,0xBF,0xFE,0x00,0x3F,0xFE,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xE0,0x03,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0x80,0x0F,0xFF,0x80,0x0F,0xFF,0xBF,0xFE,0x00,0x3F,0xFE,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xE0,0x03,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0x80,0x0F,0xFF,0x80,0x0F,0xFF,0xBF,0xFE,0x00,0x3F,0xFE,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xE0,0x03,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0x80,0x0F,0xFF,0x80,0x0F,0xFF,0xBF,0xFE,0x00,0x3F,0xFE,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xE0,0x03,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0x80,0x0F,0xFF,0x80,0x0F,0xFF,0xBF,0xFE,0x00,0x3F,0xFE,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xE0,0x03,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0x80,0x0F,0xFF,0x80,0x0F,0xFF,0x80, // 'm'
0x00,0x00,0x07,0xF8,0x01,0xFF,0xF0,0x7F,0xFE,0x03,0xFF,0xE1,0xFF,0xFF,0x07,0xFF,0xCF,0xFF,0xFF,0x0F,0xFF,0xBF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xFC,0xFF,0xFF,0xFF,0xFF,0xF9,0xFF,0xFF,0xFF,0xFF,0xFB,0xFF,0xFE,0x0F,0xFF,0xF7,0xFF,0xF0,0x07,0xFF,0xEF,0xFF,0xC0,0x07,0xFF,0xDF,0xFF,0x80,0x0F,0xFF,0xBF,0xFF,0x00,0x1F,0xFF,0x7F,0xFE,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x7F,0xFD,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xF0,0x01,0xFF,0xF7,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0xC0,0x07,0xFF,0xDF,0xFF,0x80,0x0F,0xFF,0xBF,0xFF,0x00,0x1F,0xFF,0x7F,0xFE,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x7F,0xFD,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xF0,0x01,0xFF,0xF7,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0xC0,0x07,0xFF,0xDF,0xFF,0x80,0x0F,0xFF,0xBF,0xFF,0x00,0x1F,0xFF,0x7F,0xFE,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x7F,0xFD,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xF0,0x01,0xFF,0xF7,0xFF,0xE0,0x03,0xFF,0xEF,0xFF,0xC0,0x07,0xFF,0xDF,0xFF,0x80,0x0F,0xFF,0xBF,0xFF,0x00,0x1F,0xFF,0x7F,0xFE,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x7F,0xFD,0xFF,0xF8,0x00,0xFF,0xFB,0xFF,0xF0,0x01,0xFF,0xF0, // 'n'
0x00,0x01,0xFF,0x80,0x00,0x00,0x03,0xFF,0xFE,0x00,0x00,0x03,0xFF,0xFF,0xE0,0x00,0x03,0xFF,0xFF,0xFE,0x00,0x01,0xFF,0xFF,0xFF,0xC0,0x00,0xFF,0xFF,0xFF,0xF8,0x00,0x7F,0xFF,0xFF,0xFF,0x00,0x3F,0xFF,0xFF,0xFF,0xE0,0x1F,0xFF,0xFF,0xFF,0xF8,0x07,0xFF,0xFF,0xFF,0xFF,0x03,0xFF,0xFC,0x1F,0xFF,0xC0,0xFF,0xFC,0x01,0xFF,0xF8,0x3F,0xFE,0x00,0x3F,0xFE,0x1F,0xFF,0x80,0x0F,0xFF,0xC7,0xFF,0xC0,0x01,0xFF,0xF1,0xFF,0xF0,0x00,0x7F,0xFC,0xFF,0xFC,0x00,0x1F,0xFF,0x3F,0xFE,0x00,0x07,0xFF,0xEF,0xFF,0x80,0x01,0xFF,0xFB,0xFF,0xE0,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x0F,0xFF,0xBF,0xFE,0x00,0x03,0xFF,0xEF,0xFF,0x80,0x00,0xFF,0xFB,0xFF,0xE0,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x0F,0xFF,0xBF,0xFE,0x00,0x07,0xFF,0xEF,0xFF,0x80,0x01,0xFF,0xFB,0xFF,0xF0,0x00,0x7F,0xFC,0x7F,0xFC,0x00,0x1F,0xFF,0x1F,0xFF,0x00,0x07,0xFF,0xC7,0xFF,0xE0,0x03,0xFF,0xF1,0xFF,0xF8,0x00,0xFF,0xF8,0x3F,0xFF,0x00,0x7F,0xFE,0x0F,0xFF,0xF0,0x7F,0xFF,0x81,0xFF,0xFF,0xFF,0xFF,0xC0,0x7F,0xFF,0xFF,0xFF,0xE0,0x0F,0xFF,0xFF,0xFF,0xF8,0x01,0xFF,0xFF,0xFF,0xFC,0x00,0x3F,0xFF,0xFF,0xFE,0x00,0x07,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0x80,0x00,0x0F,0xFF,0xFF,0x80,0x00,0x00,0xFF,0xFF,0x80,0x00,0x00,0x07,0xFF,0x00,0x00, // 'o'
0x00,0x00,0x1F,0xE0,0x00,0xFF,0xF0,0xFF,0xF8,0x00,0xFF,0xF1,0xFF,0xFE,0x00,0xFF,0xF3,0xFF,0xFF,0x00,0xFF,0xF7,0xFF,0xFF,0x80,0xFF,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0x03,0xFF,0xF8,0xFF,0xFC,0x01,0xFF,0xF8,0xFF,0xF8,0x00,0xFF,0xFC,0xFF,0xF8,0x00,0xFF,0xFC,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x7F,0xFE,0xFF,0xF8,0x00,0x7F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x7F,0xFE,0xFF,0xF8,0x00,0x7F,0xFE,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0x7F,0xFC,0xFF,0xF8,0x00,0xFF,0xFC,0xFF,0xFC,0x00,0xFF,0xFC,0xFF,0xFC,0x01,0xFF,0xF8,0xFF,0xFF,0x03,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xF8,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xF0,0xFF,0xFF,0xFF,0xFF,0xE0,0xFF,0xFF,0xFF,0xFF,0xC0,0xFF,0xFF,0xFF,0xFF,0x80,0xFF,0xFB,0xFF,0xFF,0x00,0xFF,0xF9,0xFF,0xFE,0x00,0xFF,0xF8,0xFF,0xF8,0x00,0xFF,0xF8,0x1F,0xE0,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00, // 'p'
0x00,0x0F,0xF0,0x00,0x00,0x00,0x3F,0xFE,0x0F,0xFE,0x00,0xFF,0xFF,0x0F,0xFE,0x01,0xFF,0xFF,0x9F,0xFE,0x07,0xFF,0xFF,0xDF,0xFE,0x07,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0x81,0xFF,0xFE,0x7F,0xFF,0x00,0x7F,0xFE,0x7F,0xFE,0x00,0x7F,0xFE,0x7F,0xFE,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xF8,0x00,0x3F,0xFE,0xFF,0xFC,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x3F,0xFE,0x7F,0xFE,0x00,0x3F,0xFE,0x7F,0xFE,0x00,0x7F,0xFE,0x3F,0xFF,0x00,0xFF,0xFE,0x3F,0xFF,0x81,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xFF,0xFE,0x07,0xFF,0xFF,0xFF,0xFE,0x03,0xFF,0xFF,0xFF,0xFE,0x01,0xFF,0xFF,0xBF,0xFE,0x00,0xFF,0xFF,0x3F,0xFE,0x00,0x3F,0xFE,0x3F,0xFE,0x00,0x0F,0xF0,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFE, // 'q'
0x00,0x00,0x1F,0xBF,0xFC,0x1F,0xEF,0xFF,0x1F,0xFB,0xFF,0xCF,0xFE,0xFF,0xF3,0xFF,0xBF,0xFD,0xFF,0xEF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFE,0xFF,0xFF,0x80,0x3F,0xFF,0x80,0x0F,0xFF,0xC0,0x03,0xFF,0xE0,0x00,0xFF,0xF8,0x00,0x3F,0xFE,0x00,0x0F,0xFF,0x80,0x03,0xFF,0xE0,0x00,0xFF,0xF8,0x00,0x3F,0xFE,0x00,0x0F,0xFF,0x80,0x03,0xFF,0xE0,0x00,0xFF,0xF8,0x00,0x3F,0xFE,0x00,0x0F,0xFF,0x80,0x03,0xFF,0xE0,0x00,0xFF,0xF8,0x00,0x3F,0xFE,0x00,0x0F,0xFF,0x80,0x03,0xFF,0xE0,0x00,0xFF,0xF8,0x00,0x3F,0xFE,0x00,0x0F,0xFF,0x80,0x03,0xFF,0xE0,0x00,0xFF,0xF8,0x00,0x3F,0xFE,0x00,0x0F,0xFF,0x80,0x03,0xFF,0xE0,0x00,0xFF,0xF8,0x00,0x3F,0xFE,0x00,0x0F,0xFF,0x80,0x00, // 'r'
0x00,0x03,0xFF,0x00,0x00,0x00,0x7F,0xFF,0xE0,0x00,0x03,0xFF,0xFF,0xF0,0x00,0x0F,0xFF,0xFF,0xF8,0x00,0x3F,0xFF,0xFF,0xF8,0x00,0xFF,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xFF,0xF8,0x0F,0xFF,0xFF,0xFF,0xF8,0x1F,0xFF,0xFF,0xFF,0xF0,0x7F,0xFF,0x07,0xFF,0xF0,0xFF,0xF8,0x07,0xFF,0xE1,0xFF,0xE0,0x07,0xFF,0xC3,0xFF,0xC0,0x0F,0xFF,0x87,0xFF,0x80,0x1F,0xFF,0x8F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0x80,0x00,0x00,0x3F,0xFF,0xC0,0x00,0x00,0x7F,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0xFF,0xC0,0x00,0xFF,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xFF,0xF0,0x00,0x7F,0xFF,0xFF,0xF0,0x00,0x7F,0xFF,0xFF,0xF0,0x00,0x3F,0xFF,0xFF,0xF0,0x00,0x0F,0xFF,0xFF,0xE0,0x00,0x01,0xFF,0xFF,0xE0,0x00,0x00,0x7F,0xFF,0xC0,0x00,0x00,0x1F,0xFF,0x9F,0xFF,0x00,0x1F,0xFF,0x3F,0xFE,0x00,0x1F,0xFF,0x3F,0xFC,0x00,0x3F,0xFE,0x7F,0xFC,0x00,0x7F,0xF8,0xFF,0xF8,0x01,0xFF,0xF0,0xFF,0xFC,0x0F,0xFF,0xE1,0xFF,0xFF,0xFF,0xFF,0xC1,0xFF,0xFF,0xFF,0xFF,0x03,0xFF,0xFF,0xFF,0xFC,0x03,0xFF,0xFF,0xFF,0xF8,0x03,0xFF,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0xFF,0x00,0x01,0xFF,0xFF,0xFC,0x00,0x00,0x7F,0xFF,0xC0,0x00,0x00,0x1F,0xFC,0x00,0x00, // 's'
0x03,0xFF,0xE0,0x00,0x7F,0xFC,0x00,0x0F,0xFF,0x80,0x01,0xFF,0xF0,0x00,0x3F,0xFE,0x00,0x07,0xFF,0xC0,0x00,0xFF,0xF8,0x00,0x1F,0xFF,0x00,0x03,0xFF,0xE0,0x00,0x7F,0xFC,0x00,0x0F,0xFF,0x80,0x7F,0xFF,0xFF,0xEF,0xFF,0xFF,0xFD,0xFF,0xFF,0xFF,0xBF,0xFF,0xFF,0xF7,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xDF,0xFF,0xFF,0xFB,0xFF,0xFF,0xFF,0x7F,0xFF,0xFF,0xE0,0x3F,0xFE,0x00,0x07,0xFF,0xC0,0x00,0xFF,0xF8,0x00,0x1F,0xFF,0x00,0x03,0xFF,0xE0,0x00,0x7F,0xFC,0x00,0x0F,0xFF,0x80,0x01,0xFF,0xF0,0x00,0x3F,0xFE,0x00,0x07,0xFF,0xC0,0x00,0xFF,0xF8,0x00,0x1F,0xFF,0x00,0x03,0xFF,0xE0,0x00,0x7F,0xFC,0x00,0x0F,0xFF,0x80,0x01,0xFF,0xF0,0x00,0x3F,0xFE,0x00,0x07,0xFF,0xC0,0x00,0xFF,0xF8,0x00,0x1F,0xFF,0x00,0x03,0xFF,0xE0,0x00,0x7F,0xFC,0x00,0x0F,0xFF,0x80,0x01,0xFF,0xF8,0x00,0x3F,0xFF,0xFC,0x07,0xFF,0xFF,0x80,0xFF,0xFF,0xF0,0x0F,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x1F,0xFF,0xF8,0x01,0xFF,0xFF,0x00,0x1F,0xFF,0xE0,0x01,0xFF,0xFC,0x00,0x07,0xFE,0x00, // 't'
0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0xFF,0xFC,0x00,0x7F,0xFE,0x7F,0xFC,0x00,0x7F,0xFE,0x7F,0xFE,0x00,0xFF,0xFE,0x7F,0xFF,0x03,0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xFE,0x7F,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFE,0x3F,0xFF,0xFF,0xFF,0xFE,0x1F,0xFF,0xFF,0xFF,0xFE,0x0F,0xFF,0xFF,0xBF,0xFE,0x0F,0xFF,0xFF,0x3F,0xFE,0x03,0xFF,0xFE,0x3F,0xFE,0x01,0xFF,0xF8,0x3F,0xFE,0x00,0x3F,0xE0,0x00,0x00, // 'u'
0xFF,0xFC,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x07,0xFF,0xC7,0xFF,0xC0,0x03,0xFF,0xF1,0xFF,0xF8,0x00,0xFF,0xFC,0x7F,0xFE,0x00,0x3F,0xFE,0x0F,0xFF,0x80,0x0F,0xFF,0x83,0xFF,0xE0,0x07,0xFF,0xE0,0xFF,0xFC,0x01,0xFF,0xF0,0x1F,0xFF,0x00,0x7F,0xFC,0x07,0xFF,0xC0,0x1F,0xFF,0x01,0xFF,0xF0,0x0F,0xFF,0x80,0x3F,0xFE,0x03,0xFF,0xE0,0x0F,0xFF,0x80,0xFF,0xF8,0x03,0xFF,0xE0,0x3F,0xFE,0x00,0x7F,0xF8,0x1F,0xFF,0x00,0x1F,0xFF,0x07,0xFF,0xC0,0x07,0xFF,0xC1,0xFF,0xF0,0x00,0xFF,0xF0,0x7F,0xF8,0x00,0x3F,0xFC,0x3F,0xFE,0x00,0x0F,0xFF,0x8F,0xFF,0x80,0x01,0xFF,0xE3,0xFF,0xC0,0x00,0x7F,0xF8,0xFF,0xF0,0x00,0x1F,0xFE,0x7F,0xFC,0x00,0x03,0xFF,0xDF,0xFE,0x00,0x00,0xFF,0xF7,0xFF,0x80,0x00,0x3F,0xFD,0xFF,0xE0,0x00,0x07,0xFF,0xFF,0xF0,0x00,0x01,0xFF,0xFF,0xFC,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x0F,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0xF8,0x00,0x00,0x1F,0xFF,0xFC,0x00,0x00,0x07,0xFF,0xFF,0x00,0x00,0x01,0xFF,0xFF,0xC0,0x00,0x00,0x3F,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xF8,0x00,0x00,0x03,0xFF,0xFE,0x00,0x00,0x00,0x7F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xF0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00, // 'v'
0xFF,0xF8,0x01,0xFF,0x80,0x1F,0xFF,0x7F,0xFC,0x00,0xFF,0xC0,0x0F,0xFF,0xBF,0xFE,0x00,0x7F,0xE0,0x07,0xFF,0x8F,0xFF,0x00,0x7F,0xF0,0x03,0xFF,0xC7,0xFF,0x80,0x3F,0xFC,0x01,0xFF,0xE3,0xFF,0xC0,0x1F,0xFE,0x01,0xFF,0xF1,0xFF,0xF0,0x0F,0xFF,0x00,0xFF,0xF0,0x7F,0xF8,0x0F,0xFF,0xC0,0x7F,0xF8,0x3F,0xFC,0x07,0xFF,0xE0,0x3F,0xFC,0x1F,0xFE,0x03,0xFF,0xF0,0x1F,0xFE,0x0F,0xFF,0x01,0xFF,0xF8,0x0F,0xFF,0x03,0xFF,0x81,0xFF,0xFE,0x0F,0xFF,0x01,0xFF,0xC0,0xFF,0xFF,0x07,0xFF,0x80,0xFF,0xF0,0x7F,0xFF,0x83,0xFF,0xC0,0x7F,0xF8,0x7F,0xFF,0xC1,0xFF,0xE0,0x3F,0xFC,0x3F,0xFF,0xF0,0xFF,0xE0,0x0F,0xFE,0x1F,0xFF,0xF8,0x7F,0xF0,0x07,0xFF,0x0F,0xFF,0xFC,0x7F,0xF8,0x03,0xFF,0x8F,0xFF,0xFE,0x3F,0xFC,0x01,0xFF,0xE7,0xFC,0xFF,0x9F,0xFC,0x00,0x7F,0xF3,0xFE,0x7F,0xCF,0xFE,0x00,0x3F,0xF9,0xFF,0x3F,0xE7,0xFF,0x00,0x1F,0xFD,0xFF,0x1F,0xFB,0xFF,0x80,0x0F,0xFE,0xFF,0x87,0xFF,0xFF,0x80,0x03,0xFF,0x7F,0xC3,0xFF,0xFF,0xC0,0x01,0xFF,0xFF,0xE1,0xFF,0xFF,0xE0,0x00,0xFF,0xFF,0xE0,0x7F,0xFF,0xF0,0x00,0x7F,0xFF,0xF0,0x3F,0xFF,0xF8,0x00,0x1F,0xFF,0xF8,0x1F,0xFF,0xF8,0x00,0x0F,0xFF,0xF8,0x0F,0xFF,0xFC,0x00,0x07,0xFF,0xFC,0x03,0xFF,0xFE,0x00,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0x00,0x3F,0xFF,0x80,0x00,0x3F,0xFF,0x80,0x1F,0xFF,0xC0,0x00,0x1F,0xFF,0xC0,0x0F,0xFF,0xE0,0x00,0x0F,0xFF,0xC0,0x07,0xFF,0xE0,0x00,0x03,0xFF,0xE0,0x01,0xFF,0xF0,0x00,0x01,0xFF,0xF0,0x00,0xFF,0xF8,0x00,0x00,0xFF,0xF8,0x00,0x7F,0xFC,0x00,0x00,0x7F,0xF8,0x00,0x1F,0xFC,0x00,0x00,0x1F,0xFC,0x00,0x0F,0xFE,0x00,0x00, // 'w'
0x7F,0xFE,0x00,0x1F,0xFF,0x8F,0xFF,0xC0,0x0F,0xFF,0xC3,0xFF,0xF0,0x03,0xFF,0xE0,0x7F,0xFE,0x01,0xFF,0xF8,0x0F,0xFF,0x80,0x7F,0xFC,0x03,0xFF,0xF0,0x3F,0xFF,0x00,0x7F,0xFC,0x1F,0xFF,0x80,0x1F,0xFF,0x87,0xFF,0xE0,0x03,0xFF,0xE3,0xFF,0xF0,0x00,0xFF,0xFC,0xFF,0xF8,0x00,0x1F,0xFF,0x7F,0xFE,0x00,0x07,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xC0,0x00,0x3F,0xFF,0xFF,0xE0,0x00,0x07,0xFF,0xFF,0xF8,0x00,0x01,0xFF,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0xFF,0x00,0x00,0x07,0xFF,0xFF,0x80,0x00,0x01,0xFF,0xFF,0xE0,0x00,0x00,0x3F,0xFF,0xF0,0x00,0x00,0x0F,0xFF,0xFC,0x00,0x00,0x03,0xFF,0xFF,0x00,0x00,0x01,0xFF,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0xF8,0x00,0x00,0x3F,0xFF,0xFF,0x00,0x00,0x1F,0xFF,0xFF,0xC0,0x00,0x07,0xFF,0xFF,0xF8,0x00,0x03,0xFF,0xFF,0xFE,0x00,0x00,0xFF,0xFF,0xFF,0xC0,0x00,0x7F,0xFF,0xFF,0xF0,0x00,0x1F,0xFF,0x7F,0xFE,0x00,0x0F,0xFF,0xCF,0xFF,0x80,0x03,0xFF,0xE3,0xFF,0xF0,0x01,0xFF,0xF8,0x7F,0xFE,0x00,0xFF,0xFC,0x1F,0xFF,0x80,0x3F,0xFF,0x03,0xFF,0xF0,0x1F,0xFF,0x80,0xFF,0xFC,0x07,0xFF,0xE0,0x1F,0xFF,0x83,0xFF,0xF0,0x03,0xFF,0xE0,0xFF,0xFC,0x00,0xFF,0xFC,0x7F,0xFE,0x00,0x1F,0xFF,0x3F,0xFF,0x80,0x07,0xFF,0xE0, // 'x'
0xFF,0xFC,0x00,0x1F,0xFF,0xBF,0xFF,0x00,0x07,0xFF,0xEF,0xFF,0xC0,0x01,0xFF,0xF9,0xFF,0xF8,0x00,0xFF,0xFC,0x7F,0xFE,0x00,0x3F,0xFF,0x0F,0xFF,0x80,0x0F,0xFF,0xC3,0xFF,0xF0,0x07,0xFF,0xE0,0xFF,0xFC,0x01,0xFF,0xF8,0x1F,0xFF,0x00,0x7F,0xFE,0x07,0xFF,0xC0,0x1F,0xFF,0x01,0xFF,0xF8,0x0F,0xFF,0xC0,0x3F,0xFE,0x03,0xFF,0xE0,0x0F,0xFF,0x80,0xFF,0xF8,0x03,0xFF,0xE0,0x7F,0xFE,0x00,0x7F,0xFC,0x1F,0xFF,0x00,0x1F,0xFF,0x07,0xFF,0xC0,0x07,0xFF,0xC3,0xFF,0xF0,0x00,0xFF,0xF8,0xFF,0xF8,0x00,0x3F,0xFE,0x3F,0xFE,0x00,0x0F,0xFF,0x8F,0xFF,0x80,0x01,0xFF,0xE7,0xFF,0xC0,0x00,0x7F,0xFD,0xFF,0xF0,0x00,0x1F,0xFF,0x7F,0xFC,0x00,0x03,0xFF,0xFF,0xFE,0x00,0x00,0xFF,0xFF,0xFF,0x80,0x00,0x3F,0xFF,0xFF,0xE0,0x00,0x07,0xFF,0xFF,0xF0,0x00,0x01,0xFF,0xFF,0xFC,0x00,0x00,0x7F,0xFF,0xFF,0x00,0x00,0x0F,0xFF,0xFF,0x80,0x00,0x03,0xFF,0xFF,0xE0,0x00,0x00,0xFF,0xFF,0xF0,0x00,0x00,0x1F,0xFF,0xFC,0x00,0x00,0x07,0xFF,0xFF,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,0x00,0x3F,0xFF,0xE0,0x00,0x00,0x0F,0xFF,0xF8,0x00,0x00,0x01,0xFF,0xFC,0x00,0x00,0x00,0x7F,0xFF,0x00,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0x03,0xFF,0xE0,0x00,0x00,0x00,0xFF,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x0F,0xFF,0x00,0x00,0x00,0x03,0xFF,0xC0,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0x7F,0xF8,0x00,0x00,0x00,0x3F,0xFE,0x00,0x00,0x00,0x3F,0xFF,0x00,0x00,0x01,0xFF,0xFF,0xC0,0x00,0x00,0x7F,0xFF,0xF0,0x00,0x00,0x1F,0xFF,0xF8,0x00,0x00,0x07,0xFF,0xFE,0x00,0x00,0x01,0xFF,0xFF,0x00,0x00,0x00,0x7F,0xFF,0x80,0x00,0x00,0x1F,0xFF,0xC0,0x00,0x00,0x07,0xFF,0xE0,0x00,0x00,0x01,0xFF,0xF0,0x00,0x00,0x00,0x3F,0xE0,0x00,0x00,0x00, // 'y'
0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xCF,0xFF,0xFF,0xFF,0xF8,0x00,0x00,0x3F,0xFF,0x00,0x00,0x07,0xFF,0xF0,0x00,0x00,0xFF,0xFE,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x01,0xFF,0xF8,0x00,0x00,0x3F,0xFF,0x80,0x00,0x07,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0x00,0x00,0x0F,0xFF,0xC0,0x00,0x01,0xFF,0xFC,0x00,0x00,0x3F,0xFF,0x80,0x00,0x03,0xFF,0xF0,0x00,0x00,0x7F,0xFE,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x01,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0x80,0x00,0x03,0xFF,0xF0,0x00,0x00,0x7F,0xFF,0x00,0x00,0x0F,0xFF,0xE0,0x00,0x00,0xFF,0xFC,0x00,0x00,0x1F,0xFF,0x80,0x00,0x03,0xFF,0xF8,0x00,0x00,0x7F,0xFF,0xFF,0xFF,0xE7,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xEF,0xFF,0xFF,0xFF,0xFE, // 'z'
0x00,0x00,0x30,0x00,0x01,0xE0,0x00,0x0F,0xE0,0x00,0x3F,0xC0,0x01,0xFF,0xC0,0x07,0xFF,0x80,0x1F,0xFF,0x00,0x3F,0xFC,0x00,0xFF,0xF0,0x01,0xFF,0xC0,0x07,0xFF,0x80,0x0F,0xFE,0x00,0x1F,0xFC,0x00,0x7F,0xF8,0x00,0xFF,0xF0,0x01,0xFF,0xC0,0x03,0xFF,0x80,0x07,0xFF,0x00,0x0F,0xFE,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0x7F,0xF0,0x00,0xFF,0xE0,0x01,0xFF,0xC0,0x03,0xFF,0x80,0x07,0xFF,0x00,0x0F,0xFE,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0xFF,0xF0,0x01,0xFF,0xE0,0x03,0xFF,0x80,0x0F,0xFF,0x00,0x7F,0xFE,0x03,0xFF,0xF8,0x07,0xFF,0xE0,0x0F,0xFF,0x80,0x1F,0xFE,0x00,0x3F,0xF0,0x00,0x7F,0xF8,0x00,0xFF,0xF8,0x01,0xFF,0xF8,0x03,0xFF,0xF8,0x01,0xFF,0xF8,0x00,0xFF,0xF0,0x00,0xFF,0xE0,0x01,0xFF,0xE0,0x01,0xFF,0xC0,0x03,0xFF,0x80,0x07,0xFF,0x00,0x0F,0xFE,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0x7F,0xF0,0x00,0xFF,0xE0,0x01,0xFF,0xC0,0x03,0xFF,0x80,0x07,0xFF,0x00,0x0F,0xFE,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0x7F,0xF0,0x00,0xFF,0xF0,0x01,0xFF,0xE0,0x01,0xFF,0xC0,0x03,0xFF,0xC0,0x07,0xFF,0x80,0x07,0xFF,0x80,0x07,0xFF,0x80,0x0F,0xFF,0x80,0x0F,0xFF,0x00,0x0F,0xFE,0x00,0x0F,0xF8,0x00,0x07,0xF0,0x00,0x03,0xE0,0x00,0x01,0x80, // '{'
0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE, // '|'
0x30,0x00,0x00,0x78,0x00,0x01,0xFC,0x00,0x03,0xFE,0x00,0x0F,0xFE,0x00,0x1F,0xFE,0x00,0x3F,0xFE,0x00,0x3F,0xFC,0x00,0x3F,0xFC,0x00,0x3F,0xF8,0x00,0x7F,0xF8,0x00,0x7F,0xF0,0x00,0xFF,0xE0,0x01,0xFF,0xE0,0x03,0xFF,0xC0,0x03,0xFF,0x80,0x07,0xFF,0x00,0x0F,0xFE,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0x7F,0xF0,0x00,0xFF,0xE0,0x01,0xFF,0xC0,0x03,0xFF,0x80,0x07,0xFF,0x00,0x0F,0xFE,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0x7F,0xF0,0x00,0xFF,0xF0,0x01,0xFF,0xE0,0x01,0xFF,0xC0,0x03,0xFF,0xC0,0x07,0xFF,0xE0,0x07,0xFF,0xF0,0x07,0xFF,0xE0,0x07,0xFF,0xC0,0x07,0xFF,0x80,0x03,0xFF,0x00,0x1F,0xFE,0x00,0x7F,0xFC,0x01,0xFF,0xF8,0x07,0xFF,0xF0,0x1F,0xFF,0x80,0x3F,0xFC,0x00,0x7F,0xF0,0x01,0xFF,0xE0,0x03,0xFF,0x80,0x07,0xFF,0x00,0x0F,0xFE,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0x7F,0xF0,0x00,0xFF,0xE0,0x01,0xFF,0xC0,0x03,0xFF,0x80,0x07,0xFF,0x00,0x0F,0xFE,0x00,0x1F,0xFC,0x00,0x3F,0xF8,0x00,0x7F,0xF0,0x00,0xFF,0xE0,0x03,0xFF,0xC0,0x07,0xFF,0x80,0x0F,0xFE,0x00,0x3F,0xFC,0x00,0x7F,0xF8,0x01,0xFF,0xE0,0x07,0xFF,0x80,0x1F,0xFF,0x00,0x3F,0xFC,0x00,0x7F,0xF0,0x00,0x7F,0xC0,0x00,0xFE,0x00,0x00,0xF0,0x00,0x01,0x80,0x00,0x00 // '}'
};
const GFXglyph Roboto_Black_80Glyphs[] = {
// bitmapOffset, width, height, xAdvance, xOffset, yOffset
{ 0, 1, 1, 21, 0, 0 }, // ' '
{ 1, 16, 58, 23, 4, -57 }, // '!'
{ 117, 24, 22, 26, 1, -60 }, // '"'
{ 183, 45, 57, 47, 1, -57 }, // '#'
{ 504, 41, 75, 47, 3, -66 }, // '$'
{ 889, 53, 59, 60, 4, -58 }, // '%'
{ 1280, 52, 59, 55, 2, -58 }, // '&'
{ 1664, 11, 22, 13, 1, -60 }, // '''
{ 1695, 23, 81, 29, 5, -63 }, // '('
{ 1928, 24, 81, 29, 1, -63 }, // ')'
{ 2171, 37, 34, 38, 1, -57 }, // '*'
{ 2329, 40, 41, 44, 2, -47 }, // '+'
{ 2534, 16, 25, 23, 2, -10 }, // ','
{ 2584, 24, 10, 37, 6, -30 }, // '-'
{ 2614, 15, 13, 25, 5, -13 }, // '.'
{ 2639, 30, 62, 29, -1, -57 }, // '/'
{ 2872, 41, 59, 47, 3, -58 }, // '0'
{ 3175, 28, 57, 47, 6, -57 }, // '1'
{ 3375, 42, 58, 47, 2, -58 }, // '2'
{ 3680, 42, 59, 47, 2, -58 }, // '3'
{ 3990, 43, 57, 47, 2, -57 }, // '4'
{ 4297, 41, 58, 47, 3, -57 }, // '5'
{ 4595, 42, 59, 47, 3, -58 }, // '6'
{ 4905, 42, 57, 47, 2, -57 }, // '7'
{ 5205, 41, 59, 47, 3, -58 }, // '8'
{ 5508, 41, 59, 47, 3, -58 }, // '9'
{ 5811, 15, 44, 25, 5, -44 }, // ':'
{ 5894, 17, 59, 24, 3, -44 }, // ';'
{ 6020, 35, 39, 42, 2, -43 }, // '<'
{ 6191, 37, 27, 48, 5, -38 }, // '='
{ 6316, 36, 39, 42, 4, -43 }, // '>'
{ 6492, 38, 58, 42, 1, -58 }, // '?'
{ 6768, 68, 73, 73, 2, -55 }, // '@'
{ 7389, 56, 57, 56, 0, -57 }, // 'A'
{ 7788, 46, 57, 53, 4, -57 }, // 'B'
{ 8116, 49, 59, 54, 3, -58 }, // 'C'
{ 8478, 46, 57, 53, 4, -57 }, // 'D'
{ 8806, 41, 57, 46, 4, -57 }, // 'E'
{ 9099, 39, 57, 45, 4, -57 }, // 'F'
{ 9377, 49, 59, 56, 3, -58 }, // 'G'
{ 9739, 49, 57, 57, 4, -57 }, // 'H'
{ 10089, 15, 57, 25, 5, -57 }, // 'I'
{ 10196, 41, 58, 46, 1, -57 }, // 'J'
{ 10494, 49, 57, 52, 4, -57 }, // 'K'
{ 10844, 39, 57, 44, 4, -57 }, // 'L'
{ 11122, 63, 57, 71, 4, -57 }, // 'M'
{ 11571, 49, 57, 57, 4, -57 }, // 'N'
{ 11921, 50, 59, 56, 3, -58 }, // 'O'
{ 12290, 46, 57, 53, 4, -57 }, // 'P'
{ 12618, 50, 69, 56, 3, -58 }, // 'Q'
{ 13050, 47, 57, 53, 4, -57 }, // 'R'
{ 13385, 46, 59, 51, 2, -58 }, // 'S'
{ 13725, 49, 57, 51, 1, -57 }, // 'T'
{ 14075, 46, 58, 54, 4, -57 }, // 'U'
{ 14409, 54, 57, 54, 0, -57 }, // 'V'
{ 14794, 69, 57, 71, 1, -57 }, // 'W'
{ 15286, 52, 57, 52, 0, -57 }, // 'X'
{ 15657, 51, 57, 51, 0, -57 }, // 'Y'
{ 16021, 46, 57, 50, 2, -57 }, // 'Z'
{ 16349, 19, 81, 24, 4, -67 }, // '['
{ 16542, 39, 62, 35, -1, -57 }, // '\'
{ 16845, 18, 81, 24, 1, -67 }, // ']'
{ 17028, 34, 28, 37, 2, -57 }, // '^'
{ 17147, 36, 10, 36, 0, 0 }, // '_'
{ 17192, 23, 12, 28, 2, -60 }, // '`'
{ 17227, 40, 44, 43, 2, -43 }, // 'a'
{ 17447, 40, 61, 46, 4, -60 }, // 'b'
{ 17752, 39, 44, 43, 2, -43 }, // 'c'
{ 17967, 40, 61, 46, 2, -60 }, // 'd'
{ 18272, 41, 44, 45, 2, -43 }, // 'e'
{ 18498, 30, 61, 30, 0, -61 }, // 'f'
{ 18727, 41, 60, 47, 2, -43 }, // 'g'
{ 19035, 39, 60, 46, 3, -60 }, // 'h'
{ 19328, 15, 60, 23, 4, -60 }, // 'i'
{ 19441, 23, 77, 23, -4, -60 }, // 'j'
{ 19663, 42, 60, 45, 4, -60 }, // 'k'
{ 19978, 15, 60, 23, 4, -60 }, // 'l'
{ 20091, 62, 43, 70, 4, -43 }, // 'm'
{ 20425, 39, 43, 46, 3, -43 }, // 'n'
{ 20635, 42, 44, 46, 2, -43 }, // 'o'
{ 20866, 40, 59, 46, 4, -43 }, // 'p'
{ 21161, 40, 59, 46, 2, -43 }, // 'q'
{ 21456, 26, 43, 31, 4, -43 }, // 'r'
{ 21596, 39, 44, 42, 1, -43 }, // 's'
{ 21811, 27, 54, 28, 0, -53 }, // 't'
{ 21994, 40, 43, 46, 3, -42 }, // 'u'
{ 22209, 42, 42, 42, 0, -42 }, // 'v'
{ 22430, 57, 42, 59, 1, -42 }, // 'w'
{ 22730, 42, 42, 42, 0, -42 }, // 'x'
{ 22951, 42, 59, 42, 0, -42 }, // 'y'
{ 23261, 36, 42, 42, 3, -42 }, // 'z'
{ 23450, 23, 76, 27, 2, -62 }, // '{'
{ 23669, 8, 68, 21, 7, -57 }, // '|'
{ 23737, 23, 76, 27, 2, -62 } // '}'
};
const GFXfont Roboto_Black_80 = {
(uint8_t *)Roboto_Black_80Bitmaps,(GFXglyph *)Roboto_Black_80Glyphs,0x20, 0x7E, 95};

View File

@@ -0,0 +1,128 @@
/********************************************************************************************************
* @file app_cfg.h
*
* @brief This is the header file for app_cfg
*
* @author Zigbee Group
* @date 2021
*
* @par Copyright (c) 2021, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*******************************************************************************************************/
#pragma once
/* Enable C linkage for C++ Compilers: */
#if defined(__cplusplus)
extern "C"
{
#endif
#define ON 1
#define OFF 0
#ifndef MCU_CORE_8258
#define MCU_CORE_8258 1
#endif
#define RAM _attribute_data_retention_ // short version, this is needed to keep the values in ram after sleep
/**********************************************************************
* Version configuration
*/
#include "version_cfg.h"
/* PM */
#define PM_ENABLE ON
/* Board ID */
#define BOARD_8258_DIY 10
/* Board define */
#if (CHIP_TYPE == TLSR_8258_1M)
#define FLASH_CAP_SIZE_1M 1
#endif
#define BOARD BOARD_8258_DIY // BOARD_8258_DONGLE //BOARD_TB_04 //BOARD_8258_EVK //
#define CLOCK_SYS_CLOCK_HZ 24000000
/************************* For 512K Flash only ***************************************/
/* Flash map:
0x00000 Old Firmware bin
0x34000 NV_1
0x40000 OTA New bin storage Area
0x76000 MAC address
0x77000 C_Cfg_Info
0x78000 U_Cfg_Info
0x7A000 NV_2
0x80000 End Flash
*/
#define USER_DATA_SIZE 0x34000
#define BEGIN_USER_DATA1 0x00000
#define END_USER_DATA1 (BEGIN_USER_DATA1 + USER_DATA_SIZE)
#define BEGIN_USER_DATA2 0x40000
#define END_USER_DATA2 (BEGIN_USER_DATA2 + USER_DATA_SIZE)
// #define GEN_USER_CFG_DATA END_USER_DATA2
#define NV_ITEM_APP_USER_CFG (NV_ITEM_APP_GP_TRANS_TABLE + 1) // see sdk/proj/drivers/drv_nv.h
/* Board include */
#include "board_8258_diy.h"
/* Voltage detect module */
/* If VOLTAGE_DETECT_ENABLE is set,
* 1) if MCU_CORE_826x is defined, the DRV_ADC_VBAT_MODE mode is used by default,
* and there is no need to configure the detection IO port;
* 2) if MCU_CORE_8258 or MCU_CORE_8278 is defined, the DRV_ADC_VBAT_MODE mode is used by default,
* we need to configure the detection IO port, and the IO must be in a floating state.
* 3) if MCU_CORE_B91 is defined, the DRV_ADC_BASE_MODE mode is used by default,
* we need to configure the detection IO port, and the IO must be connected to the target under test,
* such as VCC.
*/
#define VOLTAGE_DETECT_ENABLE OFF
#if defined(MCU_CORE_826x)
#define VOLTAGE_DETECT_ADC_PIN 0
#elif defined(MCU_CORE_8258) || defined(MCU_CORE_8278)
#define VOLTAGE_DETECT_ADC_PIN GPIO_PB7
#elif defined(MCU_CORE_B91)
#define VOLTAGE_DETECT_ADC_PIN ADC_GPIO_PB0
#endif
/* Watch dog module */
#define MODULE_WATCHDOG_ENABLE OFF
/* UART module */
#define MODULE_UART_ENABLE OFF
/**********************************************************************
* EV configuration
*/
typedef enum
{
EV_POLL_ED_DETECT,
EV_POLL_HCI,
EV_POLL_IDLE,
EV_POLL_MAX,
} ev_poll_e;
enum{
CLOCK_SYS_CLOCK_1S = CLOCK_SYS_CLOCK_HZ,
CLOCK_SYS_CLOCK_1MS = (CLOCK_SYS_CLOCK_1S / 1000),
CLOCK_SYS_CLOCK_1US = (CLOCK_SYS_CLOCK_1S / 1000000),
};
/* Disable C linkage for C++ Compilers: */
#if defined(__cplusplus)
}
#endif

View File

@@ -0,0 +1,85 @@
#include <stdint.h>
#include "tl_common.h"
#include "battery.h"
RAM volatile unsigned int adc_dat_buf[8];
void adc_bat_init(void)
{
adc_power_on_sar_adc(0);
gpio_set_output_en(GPIO_PB7, 1);
gpio_set_input_en(GPIO_PB7, 0);
gpio_write(GPIO_PB7, 1);
adc_set_sample_clk(5);
adc_set_left_right_gain_bias(GAIN_STAGE_BIAS_PER100, GAIN_STAGE_BIAS_PER100);
adc_set_chn_enable_and_max_state_cnt(ADC_MISC_CHN, 2);
adc_set_state_length(240, 0, 10);
analog_write(anareg_adc_res_m, RES14 | FLD_ADC_EN_DIFF_CHN_M);
adc_set_ain_chn_misc(B7P, GND);
adc_set_ref_voltage(ADC_MISC_CHN, ADC_VREF_1P2V);
adc_set_tsample_cycle_chn_misc(SAMPLING_CYCLES_6);
adc_set_ain_pre_scaler(ADC_PRESCALER_1F8);
adc_power_on_sar_adc(1);
}
uint16_t get_battery_mv()
{
uint16_t temp;
int i, j;
adc_bat_init();
adc_reset_adc_module();
u32 t0 = clock_time();
uint16_t adc_sample[8] = {0};
u32 adc_result;
for (i = 0; i < 8; i++)
{
adc_dat_buf[i] = 0;
}
while (!clock_time_exceed(t0, 25))
;
adc_config_misc_channel_buf((uint16_t *)adc_dat_buf, 8 << 2);
dfifo_enable_dfifo2();
for (i = 0; i < 8; i++)
{
while (!adc_dat_buf[i])
;
if (adc_dat_buf[i] & BIT(13))
{
adc_sample[i] = 0;
}
else
{
adc_sample[i] = ((uint16_t)adc_dat_buf[i] & 0x1FFF);
}
if (i)
{
if (adc_sample[i] < adc_sample[i - 1])
{
temp = adc_sample[i];
adc_sample[i] = adc_sample[i - 1];
for (j = i - 1; j >= 0 && adc_sample[j] > temp; j--)
{
adc_sample[j + 1] = adc_sample[j];
}
adc_sample[j + 1] = temp;
}
}
}
dfifo_disable_dfifo2();
u32 adc_average = (adc_sample[2] + adc_sample[3] + adc_sample[4] + adc_sample[5]) / 4;
adc_result = adc_average;
return (adc_result * 1175) >> 10;
}
uint8_t get_battery_level(uint16_t battery_mv)
{
uint8_t battery_level = (battery_mv - 2200) / (31 - 22);
if (battery_level > 100)
battery_level = 100;
if (battery_mv < 2200)
battery_level = 0;
return battery_level;
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <stdint.h>
uint16_t get_battery_mv();
uint8_t get_battery_level(uint16_t battery_mv);

View File

@@ -0,0 +1,298 @@
#ifndef _BITMAPS_H_
#define _BITMAPS_H_
// images generated by https://lvgl.io/tools/imageconverter, prepended with width, height. "CF_INDEXED_1_BIT"-mode, little-endian
#include <stdint.h>
#include "screen.h"
static const uint8_t oepli[] = {
128, 26,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1c, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x9f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x38, 0x70, 0x01, 0xc0,
0x7f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x9f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x70, 0x01, 0xc0,
0x7f, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x9f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x70, 0x01, 0xc0,
0xf7, 0x80, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0xc0,
0xe3, 0x80, 0x00, 0x00, 0x00, 0x1c, 0x1c, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0xc0,
0xe3, 0x9d, 0xc1, 0xc7, 0x70, 0x1f, 0x9c, 0xe7, 0x73, 0xb8, 0x71, 0xd0, 0x38, 0x73, 0xb9, 0xc7,
0xe3, 0x9f, 0xe3, 0xe7, 0xf8, 0x1f, 0x9f, 0xef, 0xf3, 0xfc, 0xf9, 0xf0, 0x38, 0x73, 0xfd, 0xce,
0xe3, 0x9f, 0xe7, 0x77, 0xf8, 0x1f, 0x9f, 0xcf, 0xf3, 0xfd, 0xdd, 0xf0, 0x38, 0x73, 0xfd, 0xdc,
0xe3, 0x9c, 0xe7, 0xf7, 0x38, 0x1c, 0x1f, 0x8e, 0x73, 0x9d, 0xfd, 0xc0, 0x38, 0x73, 0x9d, 0xf8,
0xe3, 0x9c, 0xe7, 0xf7, 0x38, 0x1c, 0x1c, 0x0e, 0x73, 0x9d, 0xfd, 0xc0, 0x38, 0x73, 0x9d, 0xf8,
0xf7, 0x9c, 0xe7, 0x07, 0x38, 0x1c, 0x1c, 0x0e, 0x73, 0x9d, 0xc1, 0xc0, 0x38, 0x73, 0x9d, 0xdc,
0x7f, 0x1f, 0xe7, 0xf7, 0x38, 0x1f, 0x9c, 0x0f, 0xf3, 0xfd, 0xfd, 0xc0, 0x3f, 0x73, 0x9d, 0xdc,
0x7f, 0x1f, 0xe3, 0xe7, 0x38, 0x1f, 0x9c, 0x0f, 0xf3, 0xfc, 0xf9, 0xc0, 0x3f, 0x73, 0x9d, 0xce,
0x1e, 0x1d, 0xc1, 0xc7, 0x38, 0x1f, 0x9c, 0x07, 0x73, 0xb8, 0x71, 0xc0, 0x3f, 0x73, 0x9d, 0xc7,
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
};
static const uint8_t cloud[] = {
128, 50,
0x00, 0x08, 0x82, 0xa2, 0xab, 0x55, 0xbf, 0xff, 0xff, 0xff, 0x7d, 0xb4, 0x62, 0x28, 0x00, 0x00,
0x00, 0x10, 0x10, 0x11, 0x76, 0xff, 0x7b, 0xff, 0xff, 0x7f, 0xb7, 0xa9, 0x55, 0x50, 0x51, 0x00,
0x00, 0x29, 0x22, 0x96, 0x6f, 0xf7, 0xbf, 0xff, 0xff, 0xff, 0xea, 0xe6, 0x22, 0xaa, 0x08, 0x00,
0x00, 0x02, 0x54, 0x2a, 0xbf, 0x3f, 0x7f, 0xff, 0xff, 0xff, 0xfd, 0x59, 0xb4, 0x10, 0x20, 0x00,
0x00, 0x24, 0x23, 0xb5, 0xb5, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xae, 0x48, 0x55, 0x10, 0x00,
0x00, 0x88, 0x90, 0x54, 0x6a, 0xef, 0xff, 0xff, 0xff, 0xff, 0xfb, 0xf5, 0xa3, 0x82, 0x00, 0x00,
0x00, 0x01, 0x2d, 0xa3, 0xb3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6, 0xbe, 0x4e, 0x52, 0x09, 0x00,
0x04, 0x90, 0x02, 0x0d, 0x55, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xdd, 0x68, 0xa9, 0x00, 0x10,
0x00, 0x49, 0x0c, 0xfb, 0xab, 0x6f, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xeb, 0x95, 0x5a, 0x00, 0x20,
0x00, 0x12, 0x91, 0x22, 0xbf, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0x65, 0x81, 0x40, 0x40,
0x00, 0x28, 0x12, 0x7d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xef, 0xab, 0x28, 0x00, 0x00,
0x00, 0x42, 0x0a, 0x97, 0x75, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0x4a, 0xc2, 0x04, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x08, 0x02, 0x9c, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6a, 0x6a, 0x8d, 0x00, 0x20,
0x00, 0x04, 0x4d, 0x72, 0xaa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd5, 0xd5, 0x74, 0x80, 0x00,
0x02, 0x40, 0x12, 0x8e, 0xdf, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xae, 0xaa, 0x0a, 0x11, 0x20,
0x00, 0x20, 0x52, 0x5f, 0xf5, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0x72, 0x94, 0xaa, 0x24, 0x00,
0x00, 0x01, 0x0a, 0xab, 0x6f, 0x77, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xaf, 0x54, 0x54, 0x88, 0x00,
0x00, 0x04, 0x80, 0x4d, 0x95, 0xeb, 0xff, 0xff, 0xff, 0xff, 0x5b, 0x58, 0xb5, 0x51, 0x40, 0x00,
0x00, 0x08, 0x08, 0xa6, 0xb3, 0xf7, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xad, 0x4a, 0xa0, 0x10, 0x00,
0x00, 0x02, 0x96, 0x41, 0xdc, 0xae, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xbf, 0xea, 0x48, 0x02, 0x00,
0x00, 0x00, 0x09, 0x3e, 0xab, 0x75, 0xef, 0xff, 0xff, 0xff, 0xff, 0xd4, 0xb1, 0x21, 0x08, 0x00,
0x00, 0x00, 0x0a, 0xc3, 0x5d, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xef, 0xef, 0x44, 0x4a, 0x64, 0x80,
0x00, 0x00, 0xa1, 0x52, 0xa6, 0xef, 0xef, 0xff, 0xff, 0xff, 0xd6, 0xca, 0xf5, 0x10, 0x18, 0x00,
0x00, 0x00, 0x02, 0x15, 0x4b, 0xd5, 0xdf, 0xff, 0xff, 0xf7, 0xeb, 0xd4, 0xd8, 0x85, 0x00, 0x00,
};
static const uint8_t receive[] = {
56, 56,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0,
0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0xf0,
0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xf0,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xf0,
0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0,
0x00, 0x00, 0x00, 0x1f, 0xff, 0x80, 0x00,
0x00, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x01, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3f, 0xc0, 0x00, 0x03, 0xe0,
0x00, 0x00, 0x7f, 0x80, 0x00, 0x7f, 0xf0,
0x00, 0x00, 0xfe, 0x00, 0x03, 0xff, 0xf0,
0x00, 0x01, 0xfc, 0x00, 0x0f, 0xff, 0xf0,
0x00, 0x01, 0xf8, 0x00, 0x3f, 0xff, 0xf0,
0x00, 0x03, 0xf8, 0x00, 0xff, 0xff, 0x80,
0x00, 0x07, 0xf0, 0x01, 0xff, 0xe0, 0x00,
0x00, 0x0f, 0xe0, 0x03, 0xff, 0x00, 0x00,
0x00, 0x0f, 0xc0, 0x0f, 0xf8, 0x00, 0x00,
0x00, 0x1f, 0x80, 0x1f, 0xf0, 0x00, 0x00,
0x00, 0x1f, 0x80, 0x3f, 0xc0, 0x00, 0x00,
0x00, 0x3f, 0x00, 0x3f, 0x80, 0x00, 0x00,
0x00, 0x3f, 0x00, 0x7f, 0x00, 0x00, 0x00,
0x00, 0x7e, 0x00, 0xfe, 0x00, 0x07, 0xe0,
0x00, 0x7e, 0x01, 0xfc, 0x00, 0x1f, 0xf0,
0x00, 0xfc, 0x01, 0xf8, 0x00, 0x7f, 0xf0,
0x00, 0xfc, 0x03, 0xf0, 0x01, 0xff, 0xf0,
0x00, 0xf8, 0x03, 0xf0, 0x03, 0xff, 0xf0,
0x01, 0xf8, 0x07, 0xe0, 0x07, 0xff, 0x00,
0x01, 0xf8, 0x07, 0xe0, 0x0f, 0xf0, 0x00,
0x01, 0xf0, 0x0f, 0xc0, 0x1f, 0xe0, 0x00,
0x01, 0xf0, 0x0f, 0xc0, 0x3f, 0x80, 0x00,
0x03, 0xf0, 0x0f, 0x80, 0x3f, 0x00, 0x00,
0x03, 0xf0, 0x1f, 0x80, 0x7e, 0x00, 0x00,
0x03, 0xe0, 0x1f, 0x80, 0x7e, 0x00, 0x00,
0x03, 0xe0, 0x1f, 0x00, 0xfc, 0x01, 0xe0,
0x03, 0xe0, 0x1f, 0x00, 0xfc, 0x07, 0xf8,
0x03, 0xe0, 0x1f, 0x00, 0xf8, 0x0f, 0xfc,
0x03, 0xe0, 0x3f, 0x00, 0xf8, 0x0f, 0xfc,
0x03, 0xe0, 0x3f, 0x01, 0xf8, 0x1f, 0xfe,
0x03, 0xe0, 0x3f, 0x01, 0xf8, 0x1f, 0xfe,
0x03, 0xe0, 0x3f, 0x01, 0xf8, 0x1f, 0xfe,
0x03, 0xc0, 0x3e, 0x01, 0xf0, 0x1f, 0xfe,
0x01, 0xc0, 0x1e, 0x00, 0xf0, 0x0f, 0xfc,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xfc,
0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xf8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xe0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static const uint8_t failed[] = {
48, 48,
0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x03, 0xff, 0xff, 0xe0, 0x00,
0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00,
0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00,
0x00, 0x7f, 0xf0, 0x0f, 0xfe, 0x00,
0x00, 0xff, 0x80, 0x01, 0xff, 0x00,
0x01, 0xfe, 0x00, 0x00, 0x7f, 0x80,
0x03, 0xf8, 0x00, 0x00, 0x1f, 0xc0,
0x07, 0xf0, 0x00, 0x00, 0x3f, 0xe0,
0x0f, 0xe0, 0x00, 0x00, 0x7f, 0xf0,
0x0f, 0xc0, 0x00, 0x00, 0xff, 0xf0,
0x1f, 0x80, 0x00, 0x01, 0xff, 0xf8,
0x1f, 0x00, 0x00, 0x03, 0xff, 0xf8,
0x3f, 0x00, 0x00, 0x07, 0xfe, 0xfc,
0x3e, 0x00, 0x00, 0x0f, 0xfc, 0x7c,
0x7e, 0x00, 0x00, 0x1f, 0xf8, 0x7e,
0x7c, 0x00, 0x00, 0x3f, 0xf0, 0x3e,
0x7c, 0x00, 0x00, 0x7f, 0xe0, 0x3e,
0xfc, 0x00, 0x00, 0xff, 0xc0, 0x3f,
0xf8, 0x00, 0x01, 0xff, 0x80, 0x1f,
0xf8, 0x00, 0x03, 0xff, 0x00, 0x1f,
0xf8, 0x00, 0x07, 0xfe, 0x00, 0x1f,
0xf8, 0x00, 0x0f, 0xfc, 0x00, 0x1f,
0xf8, 0x00, 0x1f, 0xf8, 0x00, 0x1f,
0xf8, 0x00, 0x3f, 0xf0, 0x00, 0x1f,
0xf8, 0x00, 0x7f, 0xe0, 0x00, 0x1f,
0xf8, 0x00, 0xff, 0xc0, 0x00, 0x1f,
0xfc, 0x01, 0xff, 0x80, 0x00, 0x3f,
0x7c, 0x03, 0xff, 0x00, 0x00, 0x3e,
0x7c, 0x07, 0xfe, 0x00, 0x00, 0x3e,
0x7e, 0x0f, 0xfc, 0x00, 0x00, 0x7e,
0x3e, 0x1f, 0xf8, 0x00, 0x00, 0x7c,
0x3f, 0x3f, 0xf0, 0x00, 0x00, 0xfc,
0x3f, 0x7f, 0xe0, 0x00, 0x00, 0xfc,
0x1f, 0xff, 0xc0, 0x00, 0x01, 0xf8,
0x0f, 0xff, 0x80, 0x00, 0x03, 0xf0,
0x0f, 0xff, 0x00, 0x00, 0x07, 0xf0,
0x07, 0xfe, 0x00, 0x00, 0x0f, 0xe0,
0x03, 0xfc, 0x00, 0x00, 0x1f, 0xc0,
0x01, 0xfe, 0x00, 0x00, 0x7f, 0x80,
0x00, 0xff, 0x80, 0x01, 0xff, 0x00,
0x00, 0x7f, 0xf0, 0x0f, 0xfe, 0x00,
0x00, 0x3f, 0xff, 0xff, 0xfc, 0x00,
0x00, 0x0f, 0xff, 0xff, 0xf0, 0x00,
0x00, 0x03, 0xff, 0xff, 0xe0, 0x00,
0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xf8, 0x00, 0x00,
};
#if (SCREEN_WIDTH != 128)
static const uint8_t ant[] = {
16, 16,
0x00, 0x40,
0x02, 0x20,
0x01, 0x20,
0x11, 0x20,
0x11, 0x20,
0x12, 0x20,
0x28, 0x40,
0x28, 0x00,
0x28, 0x00,
0x44, 0x00,
0x44, 0x00,
0x44, 0x00,
0x44, 0x00,
0x82, 0x00,
0x82, 0x00,
0xfe, 0x00,
};
#else
static const uint8_t ant[] = {
// rotated 90 degrees
16,16,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x7c, 0x00,
0x82, 0x00,
0x00, 0x00,
0x38, 0x00,
0x44, 0x07,
0x00, 0x79,
0x03, 0x81,
0x1c, 0x01,
0x03, 0x81,
0x00, 0x79,
0x00, 0x07,
};
#endif
static const uint8_t cross[] = {
8,8,
0x00,
0x63,
0x77,
0x3e,
0x1c,
0x3e,
0x77,
0x63
};
#if (SCREEN_WIDTH != 128)
static const uint8_t battery[] = {
16,10,
0x00, 0x00,
0x7f, 0xfc,
0x40, 0x04,
0x58, 0x06,
0x58, 0x06,
0x58, 0x06,
0x58, 0x06,
0x40, 0x04,
0x7f, 0xfc,
0x00, 0x00,
};
#else
// this battery symbol is rotated 90'
static const uint8_t battery[] = {
16,16,
0x00, 0x00,
0x03, 0xc0,
0x0f, 0xf0,
0x08, 0x10,
0x08, 0x10,
0x08, 0x10,
0x08, 0x10,
0x08, 0x10,
0x08, 0x10,
0x08, 0x10,
0x08, 0x10,
0x0b, 0xd0,
0x0b, 0xd0,
0x08, 0x10,
0x0f, 0xf0,
0x00, 0x00,
};
#endif
#endif

View File

@@ -0,0 +1,31 @@
#ifndef _BOARD_H_
#define _BOARD_H_
#include <stdint.h>
#include "proto.h"
#include "main.h"
//eeprom map
#define EEPROM_SETTINGS_AREA_START (0x40000UL)
#define EEPROM_SETTINGS_AREA_LEN (0x03000UL)
#define EEPROM_UPDATA_AREA_START (0x43000UL)
#define EEPROM_UPDATE_AREA_LEN (0x20000UL)
#define EEPROM_IMG_START (0x43000UL)
#define EEPROM_IMG_EACH (0x7000UL)
#define EEPROM_IMG_LEN (0x20000UL)
#define EEPROM_PAGE_SIZE (0x01000)
//till end of eeprom really. do not put anything after - it will be erased at pairing time!!!
#define EEPROM_PROGRESS_BYTES (128)
#define HAS_EEPROM 1
#define HAS_SCREEN 1
#define AP_EMULATE_TAG 1
//hw types
#define HW_TYPE 0x60
#endif

View File

@@ -0,0 +1,24 @@
#ifndef SRC_INCLUDE_BOARD_8258_DIY_H_
#define SRC_INCLUDE_BOARD_8258_DIY_H_
/************************* For 512K Flash only ***************************************/
/* Flash map:
0x00000 Old Firmware bin
0x34000 NV_1
0x40000 OTA New bin storage Area
0x76000 MAC address
0x77000 C_Cfg_Info
0x78000 U_Cfg_Info
0x7A000 NV_2
0x80000 End Flash
*/
#define USER_DATA_SIZE 0x34000
#define BEGIN_USER_DATA1 0x00000
#define END_USER_DATA1 (BEGIN_USER_DATA1 + USER_DATA_SIZE)
#define BEGIN_USER_DATA2 0x40000
#define END_USER_DATA2 (BEGIN_USER_DATA2 + USER_DATA_SIZE)
#define GEN_USER_CFG_DATA END_USER_DATA2
#endif /* SRC_INCLUDE_BOARD_8258_DIY_H_ */

View File

@@ -0,0 +1,83 @@
/********************************************************************************************************
* @file comm_cfg.h
*
* @brief This is the header file for comm_cfg
*
* @author Zigbee Group
* @date 2021
*
* @par Copyright (c) 2021, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*******************************************************************************************************/
#pragma once
/**********************************************************************
* User configuration whether to use boot loader mode.
*
* NOTE:
* We do not recommend using BootLoader mode on 512K flash chips,
* because in boot loader mode, it can only support up to 196k firmware
* according to the current default Flash Map.
*
* Please refer to the drv_nv.h file, and check if the firmware size
* exceeds the maximum limit.
*
* The user can configure the CHIP_TYPE used by the corresponding
* project in the version.h file according to the actual size
* of the flash at hand.
*
* If BOOT_LOADER_MODE is 0, it means that the SDK uses Normal Mode,
* hardware multi-address (0x0000 or 0x40000) startup mode.
* If BOOT_LOADER_MODE is 1, it means that the SDK uses Boot Loader Mode.
*
* Normal mode is used by default.
*/
#define BOOT_LOADER_MODE 0
/* Boot loader address. */
#define BOOT_LOADER_IMAGE_ADDR 0x0
/* APP image address. */
#if (BOOT_LOADER_MODE)
#define APP_IMAGE_ADDR 0x8000
#else
#define APP_IMAGE_ADDR 0x0
#endif
/* Chip IDs */
#define TLSR_8267 0x00
#define TLSR_8269 0x01
#define TLSR_8258_512K 0x02
#define TLSR_8258_1M 0x03
#define TLSR_8278 0x04
#define TLSR_B91 0x05
/* Image types */
#if (BOOT_LOADER_MODE)
#define IMAGE_TYPE_BOOT_FLAG 1
#else
#define IMAGE_TYPE_BOOT_FLAG 0
#endif
#define IMAGE_TYPE_BOOTLOADER (0xFF)
#define IMAGE_TYPE_GW (0x00 | (IMAGE_TYPE_BOOT_FLAG << 7))
#define IMAGE_TYPE_LIGHT (0x01 | (IMAGE_TYPE_BOOT_FLAG << 7))
#define IMAGE_TYPE_SWITCH (0x02 | (IMAGE_TYPE_BOOT_FLAG << 7))
#define IMAGE_TYPE_CONTACT_SENSOR (0x03 | (IMAGE_TYPE_BOOT_FLAG << 7))

View File

@@ -0,0 +1,45 @@
#include <string.h>
#include <stdbool.h>
#include "tl_common.h"
#include "proto.h"
#include "zigbee.h"
#include "comms.h"
#define ADDR_MODE_NONE (0)
#define ADDR_MODE_SHORT (2)
#define ADDR_MODE_LONG (3)
#define FRAME_TYPE_BEACON (0)
#define FRAME_TYPE_DATA (1)
#define FRAME_TYPE_ACK (2)
#define FRAME_TYPE_MAC_CMD (3)
extern uint8_t mSelfMac[8];
uint8_t mLastLqi = 0;
int8_t mLastRSSI = 0;
uint8_t commsGetLastPacketLQI(void)
{
return mLastLqi;
}
int8_t commsGetLastPacketRSSI(void)
{
return mLastRSSI;
}
int8_t commsRxUnencrypted(uint8_t *data)
{
memset(data, 0, 128);
int8_t rxedLen = radioRxDequeuePkt(data, 128, &mLastRSSI, &mLastLqi);
if (rxedLen < 0)
return COMMS_RX_ERR_NO_PACKETS;
if (memcmp((void *)&data[5], mSelfMac, 8)) // Here we filter for our MAC Address... in software...
return COMMS_RX_ERR_INVALID_PACKET;
return rxedLen;
}
bool commsTxNoCpy(const void *packetp)
{
return radioTxLL(packetp);
}

View File

@@ -0,0 +1,24 @@
#ifndef _COMMS_H_
#define _COMMS_H_
#include <stdint.h>
#include <stdbool.h>
#define COMMS_MAX_RADIO_WAIT_MSEC 200
#define COMMS_RX_ERR_NO_PACKETS (-1)
#define COMMS_RX_ERR_INVALID_PACKET (-2)
#define COMMS_MAX_PACKET_SZ (127)
extern uint8_t mLastLqi;
extern int8_t mLastRSSI;
int8_t commsRxUnencrypted(uint8_t *data);
bool commsTxUnencrypted(const void *packetP, uint8_t len);
bool commsTxNoCpy(const void *packetp);
#endif

View File

@@ -0,0 +1,67 @@
#include "drawing.h"
#include <stdbool.h>
#include "tl_common.h"
#include "board.h"
#include "eeprom.h"
#include "proto.h"
#include "screen.h"
#include "epd.h"
static uint8_t mClutMap[256];
void drawImageAtAddress(uint32_t addr, uint8_t lut)
{
struct EepromImageHeader *eih = (struct EepromImageHeader *)mClutMap;
eepromRead(addr, mClutMap, sizeof(struct EepromImageHeader));
switch (eih->dataType)
{
case DATATYPE_IMG_RAW_1BPP:
printf("Doing raw 1bpp\r\n");
EPD_Display_start(1);
for (uint32_t c = 0; c < (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); c++)
{
if (c % 256 == 0)
{
eepromRead(addr + sizeof(struct EepromImageHeader) + c, mClutMap, 256);
}
EPD_Display_byte(mClutMap[c % 256]);
}
EPD_Display_color_change();
for (uint32_t c = 0; c < (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); c++)
{
EPD_Display_byte(0x00);
}
EPD_Display_end();
break;
case DATATYPE_IMG_RAW_2BPP:
printf("Doing raw 2bpp\r\n");
EPD_Display_start(1);
for (uint32_t c = 0; c < (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); c++)
{
if (c % 256 == 0)
{
eepromRead(addr + sizeof(struct EepromImageHeader) + c, mClutMap, 256);
}
EPD_Display_byte(mClutMap[c % 256]);
}
EPD_Display_color_change();
for (uint32_t c = 0; c < (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)); c++)
{
if (c % 256 == 0)
{
eepromRead(addr + sizeof(struct EepromImageHeader) + (SCREEN_HEIGHT * (SCREEN_WIDTH / 8)) + c, mClutMap, 256);
}
EPD_Display_byte(mClutMap[c % 256]);
}
EPD_Display_end();
break;
case DATATYPE_IMG_BMP:;
printf("sending BMP to EPD - ");
printf(" complete.\r\n");
break;
default: // prevent drawing from an unknown file image type
printf("Image with type 0x%02X was requested, but we don't know what to do with that currently...\r\n", eih->dataType);
return;
}
}

View File

@@ -0,0 +1,9 @@
#ifndef _DRAWING_H_
#define _DRAWING_H_
#include <stdint.h>
#include <stdbool.h>
void drawImageAtAddress(uint32_t addr, uint8_t lut);
#endif

View File

@@ -0,0 +1,52 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "zigbee.h"
#include "proto.h"
#include "comms.h"
#include "board.h"
#include "powermgt.h"
#include "eeprom.h"
#include "tl_common.h"
uint32_t eepromGetSize(void)
{
return EEPROM_IMG_LEN;
}
void eepromRead(uint32_t addr, uint8_t *dstP, uint32_t len)
{
printf("Eeprom read %X Len: %d\r\n", addr, len);
flash_read_page(addr, len, dstP);
}
bool eepromWrite(uint32_t addr, uint8_t *srcP, uint32_t len)
{
printf("Eeprom write %X Len: %d\r\n", addr, len);
flash_write_page(addr, len, srcP);
return true;
}
bool eepromErase(uint32_t addr, uint32_t len)
{
printf("Eeprom erase %X Len: %d\r\n", addr, len);
// round starting address down
if (addr % EEPROM_PAGE_SIZE)
{
len += addr % EEPROM_PAGE_SIZE;
addr = addr / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE;
}
// round length up
len = (len + EEPROM_PAGE_SIZE - 1) / EEPROM_PAGE_SIZE * EEPROM_PAGE_SIZE;
while (len)
{
uint32_t now;
flash_erase_sector(addr);
now = 0x1000;
addr += now;
len -= now;
}
return true;
}

View File

@@ -0,0 +1,31 @@
#ifndef _EEPROM_H_
#define _EEPROM_H_
#include <stdbool.h>
#include <stdint.h>
void eepromRead(uint32_t addr, uint8_t *dst, uint32_t len) ;
bool eepromWrite(uint32_t addr, uint8_t *src, uint32_t len) ;
bool eepromErase(uint32_t addr, uint32_t len) ;
uint32_t eepromGetSize(void);
#define EEPROM_IMG_VALID (0x494d4721UL)
#include "board.h"
struct EepromImageHeader { //each image space is 0x17000 bytes, we have space for ten of them
uint64_t version;
uint32_t validMarker;
uint32_t size;
uint8_t dataType;
uint32_t id;
//image data here
//we pre-erase so progress can be calculated by finding the first non-0xff byte
};
#endif

View File

@@ -0,0 +1,432 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "epd.h"
#include "epd_spi.h"
#include "eeprom.h"
#include "epd_bw_213.h"
#include "epd_bwr_213.h"
#include "epd_bwr_350.h"
#include "epd_bwy_350.h"
#include "epd_bw_213_ice.h"
#include "epd_bwr_154.h"
#include "powermgt.h"
#include "OneBitDisplay.h"
extern const uint8_t ucMirror[];
#include "Roboto_Black_80.h"
#include "font.h"
#include "font_60.h"
#include "font16.h"
#include "font30.h"
RAM uint8_t epd_model = 0; // 0 = Undetected, 1 = BW213, 2 = BWR213, 3 = BWR154, 4 = BW213ICE, 5 = BWR350
const char *epd_model_string[] = {"NC", "BW213", "BWR213", "BWR154", "213ICE", "BWR350", "BWY350"};
RAM uint8_t epd_update_state = 0;
const char *BLE_conn_string[] = {"", "B"};
RAM uint8_t epd_temperature_is_read = 0;
RAM uint8_t epd_temperature = 0;
uint8_t epd_buffer[epd_buffer_size];
uint8_t epd_temp[epd_buffer_size]; // for OneBitDisplay to draw into
OBDISP obd; // virtual display structure
// With this we can force a display if it wasnt detected correctly
void set_EPD_model(uint8_t model_nr)
{
epd_model = model_nr;
}
// Here we detect what E-Paper display is connected
void EPD_detect_model(void)
{
epd_model = 6;
return;
EPD_init();
// system power
EPD_POWER_ON();
WaitMs(10);
// Reset the EPD driver IC
gpio_write(EPD_RESET, 0);
WaitMs(10);
gpio_write(EPD_RESET, 1);
WaitMs(10);
// Here we neeed to detect it
if (EPD_BWR_213_detect())
{
epd_model = 2;
}
else if (EPD_BWR_154_detect()) // Right now this will never trigger, the 154 is same to 213BWR right now.
{
epd_model = 3;
}
else if (EPD_BW_213_ice_detect())
{
epd_model = 4;
}
else
{
epd_model = 1;
}
EPD_POWER_OFF();
}
uint8_t EPD_read_temp(void)
{
if (epd_temperature_is_read)
return epd_temperature;
if (!epd_model)
EPD_detect_model();
EPD_init();
// system power
EPD_POWER_ON();
WaitMs(5);
// Reset the EPD driver IC
gpio_write(EPD_RESET, 0);
WaitMs(10);
gpio_write(EPD_RESET, 1);
WaitMs(10);
if (epd_model == 1)
epd_temperature = EPD_BW_213_read_temp();
else if (epd_model == 2)
epd_temperature = EPD_BWR_213_read_temp();
else if (epd_model == 3)
epd_temperature = EPD_BWR_154_read_temp();
else if (epd_model == 4)
epd_temperature = EPD_BW_213_ice_read_temp();
else if (epd_model == 5)
epd_temperature = EPD_BWR_350_read_temp();
else if (epd_model == 6)
epd_temperature = EPD_BWY_350_read_temp();
EPD_POWER_OFF();
epd_temperature_is_read = 1;
return epd_temperature;
}
void EPD_Display_start(uint8_t full_or_partial)
{
if (!epd_model)
EPD_detect_model();
EPD_init();
// system power
EPD_POWER_ON();
WaitMs(5);
// Reset the EPD driver IC
gpio_write(EPD_RESET, 0);
WaitMs(20);
gpio_write(EPD_RESET, 1);
WaitMs(20);
/*if (epd_model == 1)
epd_temperature = EPD_BW_213_Display_start(full_or_partial);
else if (epd_model == 2)
epd_temperature = EPD_BWR_213_Display_start(full_or_partial);
else if (epd_model == 3)
epd_temperature = EPD_BWR_154_Display_start(full_or_partial);
else if (epd_model == 4)
epd_temperature = EPD_BW_213_ice_Display_start(full_or_partial);
else if (epd_model == 5)
epd_temperature = EPD_BWR_350_Display_start(full_or_partial);
else if (epd_model == 6)
epd_temperature = EPD_BWY_350_Display_start(full_or_partial);*/
if (epd_model == 4)
epd_temperature = EPD_BW_213_ice_Display_start(full_or_partial);
else if (epd_model == 5)
epd_temperature = EPD_BWR_350_Display_start(full_or_partial);
else if (epd_model == 6)
epd_temperature = EPD_BWY_350_Display_start(full_or_partial);
epd_temperature_is_read = 1;
epd_update_state = 1;
}
void EPD_Display_byte(uint8_t data)
{
/*if (epd_model == 1)
epd_temperature = EPD_BW_213_Display_byte(data);
else if (epd_model == 2)
epd_temperature = EPD_BWR_213_Display_byte(data);
else if (epd_model == 3)
epd_temperature = EPD_BWR_154_Display_byte(data);
else if (epd_model == 4)
epd_temperature = EPD_BW_213_ice_Display_byte(data);
else if (epd_model == 5)
epd_temperature = EPD_BWR_350_Display_byte(data);
else if (epd_model == 6)
epd_temperature = EPD_BWY_350_Display_byte(data);*/
if (epd_model == 4)
EPD_BW_213_ice_Display_byte(data);
else if (epd_model == 5)
EPD_BWR_350_Display_byte(data);
else if (epd_model == 6)
EPD_BWY_350_Display_byte(data);
}
void EPD_Display_buffer(unsigned char *image, int size)
{
/*if (epd_model == 1)
epd_temperature = EPD_BW_213_Display_buffer(image, size);
else if (epd_model == 2)
epd_temperature = EPD_BWR_213_Display_buffer(image, size);
else if (epd_model == 3)
epd_temperature = EPD_BWR_154_Display_buffer(image, size);
else if (epd_model == 4)
epd_temperature = EPD_BW_213_ice_Display_buffer(image, size);
else if (epd_model == 5)
epd_temperature = EPD_BWR_350_Display_buffer(image, size);
else if (epd_model == 6)
epd_temperature = EPD_BWY_350_Display_buffer(image, size);*/
if (epd_model == 4)
EPD_BW_213_ice_Display_buffer(image, size);
else if (epd_model == 5)
EPD_BWR_350_Display_buffer(image, size);
else if (epd_model == 6)
EPD_BWY_350_Display_buffer(image, size);
}
void EPD_Display_color_change()
{
if (epd_model == 5)
EPD_BWR_350_Display_color_change();
if (epd_model == 6)
EPD_BWY_350_Display_color_change();
}
void EPD_Display_end()
{
/*if (epd_model == 1)
epd_temperature = EPD_BW_213_Display_end();
else if (epd_model == 2)
epd_temperature = EPD_BWR_213_Display_end();
else if (epd_model == 3)
epd_temperature = EPD_BWR_154_Display_end();
else if (epd_model == 4)
epd_temperature = EPD_BW_213_ice_Display_end();
else if (epd_model == 5)
epd_temperature = EPD_BWR_350_Display_end();
else if (epd_model == 6)
epd_temperature = EPD_BWY_350_Display_end();*/
if (epd_model == 4)
EPD_BW_213_ice_Display_end();
else if (epd_model == 5)
EPD_BWR_350_Display_end();
else if (epd_model == 6)
EPD_BWY_350_Display_end();
uint32_t timeout_counter = 60; // 60 Seconds timeout
while (epd_state_handler())
{
doSleepGpio(1000, EPD_BUSY);
timeout_counter--;
if (!timeout_counter)
{
epd_set_sleep();
printf("E-Paper Refresh timeout !!!\r\n");
break;
}
}
}
void EPD_Display(unsigned char *image, int size, uint8_t full_or_partial)
{
if (!epd_model)
EPD_detect_model();
EPD_init();
// system power
EPD_POWER_ON();
WaitMs(5);
// Reset the EPD driver IC
gpio_write(EPD_RESET, 0);
WaitMs(10);
gpio_write(EPD_RESET, 1);
WaitMs(10);
if (epd_model == 1)
epd_temperature = EPD_BW_213_Display(image, size, full_or_partial);
else if (epd_model == 2)
epd_temperature = EPD_BWR_213_Display(image, size, full_or_partial);
else if (epd_model == 3)
epd_temperature = EPD_BWR_154_Display(image, size, full_or_partial);
else if (epd_model == 4)
epd_temperature = EPD_BW_213_ice_Display(image, size, full_or_partial);
else if (epd_model == 5)
epd_temperature = EPD_BWR_350_Display(image, size, full_or_partial);
else if (epd_model == 6)
epd_temperature = EPD_BWY_350_Display(image, size, full_or_partial);
epd_temperature_is_read = 1;
epd_update_state = 1;
uint32_t timeout_counter = 60; // 60 Seconds timeout
while (epd_state_handler())
{
doSleepGpio(1000, EPD_BUSY);
timeout_counter--;
if (!timeout_counter)
{
epd_set_sleep();
printf("E-Paper Refresh timeout !!!\r\n");
break;
}
}
}
void epd_set_sleep(void)
{
if (!epd_model)
EPD_detect_model();
if (epd_model == 1)
EPD_BW_213_set_sleep();
else if (epd_model == 2)
EPD_BWR_213_set_sleep();
else if (epd_model == 3)
EPD_BWR_154_set_sleep();
else if (epd_model == 4)
EPD_BW_213_ice_set_sleep();
else if (epd_model == 5)
EPD_BWR_350_set_sleep();
else if (epd_model == 6)
EPD_BWY_350_set_sleep();
EPD_POWER_OFF();
epd_update_state = 0;
}
uint8_t epd_state_handler(void)
{
switch (epd_update_state)
{
case 0:
// Nothing todo
break;
case 1: // check if refresh is done and sleep epd if so
if (epd_model == 1 || epd_model == 6)
{
if (!EPD_IS_BUSY())
epd_set_sleep();
}
else
{
if (EPD_IS_BUSY())
epd_set_sleep();
}
break;
}
return epd_update_state;
}
void FixBuffer(uint8_t *pSrc, uint8_t *pDst, uint16_t width, uint16_t height)
{
int x, y;
uint8_t *s, *d;
for (y = 0; y < (height / 8); y++)
{ // byte rows
d = &pDst[y];
s = &pSrc[y * width];
for (x = 0; x < width; x++)
{
d[x * (height / 8)] = ~ucMirror[s[width - 1 - x]]; // invert and flip
} // for x
} // for y
}
void epd_display_this()
{
// test G4 decoder
memset(epd_buffer, 0xff, epd_buffer_size); // clear to white
EPD_Display(epd_buffer, epd_buffer_size, 1);
}
void epd_display(char *str1, uint16_t battery_mv, char *ownMacStr, uint8_t full_or_partial)
{
if (epd_update_state)
return;
if (!epd_model)
{
EPD_detect_model();
}
uint16_t resolution_w = 250;
uint16_t resolution_h = 128; // 122 real pixel, but needed to have a full byte
if (epd_model == 1)
{
resolution_w = 250;
resolution_h = 128; // 122 real pixel, but needed to have a full byte
}
else if (epd_model == 2)
{
resolution_w = 250;
resolution_h = 128; // 122 real pixel, but needed to have a full byte
}
else if (epd_model == 3)
{
resolution_w = 200;
resolution_h = 200;
}
else if (epd_model == 4)
{
resolution_w = 212;
resolution_h = 104;
}
else if (epd_model == 5)
{ // Just as placeholder right now, needs a complete different driving because of RAM limits
resolution_w = 200;
resolution_h = 184;
}
else if (epd_model == 6)
{ // Just as placeholder right now, needs a complete different driving because of RAM limits
resolution_w = 210;
resolution_h = 184;
}
obdCreateVirtualDisplay(&obd, resolution_w, resolution_h, epd_temp);
obdFill(&obd, 0, 0); // fill with white
char buff[100];
sprintf(buff, "Compiled:");
obdWriteString(&obd, 0, 0, 20, (char *)buff, FONT_8x8, 0, 0);
sprintf(buff, "%s %s", __DATE__, __TIME__);
obdWriteString(&obd, 0, 0, 21, (char *)buff, FONT_8x8, 0, 0);
sprintf(buff, "Tag MAC:", ownMacStr);
// obdWriteStringCustom(&obd, FONT_8x8, 0, 18, (char *)buff, 1);
obdWriteString(&obd, 0, 0, 17, (char *)buff, FONT_8x8, 0, 0);
sprintf(buff, "%s", ownMacStr);
// obdWriteStringCustom(&obd, FONT_8x8, 0, 18, (char *)buff, 1);
obdWriteString(&obd, 0, 0, 18, (char *)buff, FONT_8x8, 0, 0);
sprintf(buff, "OpenEpaperLink");
obdWriteStringCustom(&obd, (GFXfont *)&Dialog_plain_16, 10, 50, (char *)buff, 1);
sprintf(buff, "%s", str1);
obdWriteStringCustom(&obd, (GFXfont *)&Special_Elite_Regular_30, 10, 95, (char *)buff, 1);
sprintf(buff, "Battery %dmV", battery_mv);
obdWriteStringCustom(&obd, (GFXfont *)&Dialog_plain_16, 10, 120, (char *)buff, 1);
FixBuffer(epd_temp, epd_buffer, resolution_w, resolution_h);
EPD_Display(epd_buffer, resolution_w * resolution_h / 8, full_or_partial);
}
void epd_display_char(uint8_t data)
{
int i;
for (i = 0; i < epd_buffer_size; i++)
{
epd_buffer[i] = data;
}
EPD_Display(epd_buffer, epd_buffer_size, 1);
}
void epd_clear(void)
{
memset(epd_buffer, 0x00, epd_buffer_size);
}

View File

@@ -0,0 +1,23 @@
#pragma once
#define epd_height 200
#define epd_width 200
#define epd_buffer_size ((epd_height / 8) * epd_width)
void set_EPD_model(uint8_t model_nr);
void init_epd(void);
uint8_t EPD_read_temp(void);
void EPD_Display_start(uint8_t full_or_partial);
void EPD_Display_byte(uint8_t data);
void EPD_Display_buffer(unsigned char *image, int size);
void EPD_Display_color_change();
void EPD_Display_end();
void EPD_Display(unsigned char *image, int size, uint8_t full_or_partial);
void epd_display_this();
void epd_display(char *str1, uint16_t battery_mv, char *ownMacStr, uint8_t full_or_partial);
void epd_set_sleep(void);
uint8_t epd_state_handler(void);
void epd_display_char(uint8_t data);
void epd_clear(void);

View File

@@ -0,0 +1,121 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "epd.h"
#include "epd_spi.h"
#include "epd_bw_213.h"
// UC8151C or similar EPD Controller
#define lut_bw_213_refresh_time 10
uint8_t lut_bw_213_20_part[] =
{
0x20, 0x00, lut_bw_213_refresh_time, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t lut_bw_213_22_part[] =
{
0x22, 0x80, lut_bw_213_refresh_time, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t lut_bw_213_23_part[] =
{
0x23, 0x40, lut_bw_213_refresh_time, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
uint8_t EPD_BW_213_read_temp(void)
{
uint8_t epd_temperature = 0 ;
EPD_WriteCmd(0x04);
// check BUSY pin
EPD_CheckStatus(100);
EPD_WriteCmd(0x40);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
// power off
EPD_WriteCmd(0x02);
// deep sleep
EPD_WriteCmd(0x07);
EPD_WriteData(0xa5);
return epd_temperature;
}
uint8_t EPD_BW_213_Display(unsigned char *image, int size, uint8_t full_or_partial)
{
uint8_t epd_temperature = 0 ;
// Booster soft start
EPD_WriteCmd(0x06);
EPD_WriteData(0x17);
EPD_WriteData(0x17);
EPD_WriteData(0x17);
// power on
EPD_WriteCmd(0x04);
// check BUSY pin
EPD_CheckStatus(100);
EPD_WriteCmd(0x40);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
// panel setting
EPD_WriteCmd(0x00);
if (full_or_partial)
EPD_WriteData(0b00011111);
else
EPD_WriteData(0b00111111);
EPD_WriteData(0x0f);
// resolution setting
EPD_WriteCmd(0x61);
EPD_WriteData(0x80);
EPD_WriteData(0x01);
EPD_WriteData(0x28);
// Vcom and data interval setting
EPD_WriteCmd(0X50);
EPD_WriteData(0x97);
if (!full_or_partial)
{
EPD_send_lut(lut_bw_213_20_part, sizeof(lut_bw_213_20_part));
EPD_send_empty_lut(0x21, 260);
EPD_send_lut(lut_bw_213_22_part, sizeof(lut_bw_213_22_part));
EPD_send_lut(lut_bw_213_23_part, sizeof(lut_bw_213_23_part));
EPD_send_empty_lut(0x24, 260);
EPD_WriteCmd(0x10);
int i;
for (i = 0; i < size; i++)
{
EPD_WriteData(~image[i]);
}
}
// load image data to EPD
EPD_LoadImage(image, size, 0x13);
// trigger display refresh
EPD_WriteCmd(0x12);
return epd_temperature;
}
void EPD_BW_213_set_sleep(void)
{
// Vcom and data interval setting
EPD_WriteCmd(0x50);
EPD_WriteData(0xf7);
// power off
EPD_WriteCmd(0x02);
// deep sleep
EPD_WriteCmd(0x07);
EPD_WriteData(0xa5);
}

View File

@@ -0,0 +1,5 @@
#pragma once
uint8_t EPD_BW_213_read_temp(void);
uint8_t EPD_BW_213_Display(unsigned char *image, int size, uint8_t full_or_partial);
void EPD_BW_213_set_sleep(void);

View File

@@ -0,0 +1,488 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "epd.h"
#include "epd_spi.h"
#include "epd_bw_213_ice.h"
// SSD1675 mixed with SSD1680 EPD Controller
#define BW_213_ice_Len 50
uint8_t LUT_BW_213_ice_part[] = {
0x40,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x80,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x40,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x80,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
BW_213_ice_Len,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
0x00,
};
uint8_t EPD_BW_213_ice_detect(void)
{
// SW Reset
EPD_WriteCmd(0x12);
WaitMs(10);
EPD_WriteCmd(0x2F);
if (EPD_SPI_read() != 0x01)
return 0;
return 1;
}
uint8_t EPD_BW_213_ice_read_temp(void)
{
uint8_t epd_temperature = 0;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
// Set Analog Block control
EPD_WriteCmd(0x74);
EPD_WriteData(0x54);
// Set Digital Block control
EPD_WriteCmd(0x7E);
EPD_WriteData(0x3B);
// ACVCOM Setting
EPD_WriteCmd(0x2B);
EPD_WriteData(0x04);
EPD_WriteData(0x63);
// Booster soft start
EPD_WriteCmd(0x0C);
EPD_WriteData(0x8B);
EPD_WriteData(0x9C);
EPD_WriteData(0x96);
EPD_WriteData(0x0F);
// Driver output control
EPD_WriteCmd(0x01);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x01);
// Data entry mode setting
EPD_WriteCmd(0x11);
EPD_WriteData(0x01);
// Temperature sensor control
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x00);
EPD_WriteData(0x0C);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x54);
EPD_WriteData(0x00);
// Border waveform control
EPD_WriteCmd(0x3C);
EPD_WriteData(0x01);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xA1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Temperature sensor read from register
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xB1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Display update control
EPD_WriteCmd(0x21);
EPD_WriteData(0x03);
// deep sleep
EPD_WriteCmd(0x10);
EPD_WriteData(0x01);
return epd_temperature;
}
uint8_t EPD_BW_213_ice_Display_start(uint8_t full_or_partial)
{
uint8_t epd_temperature = 0;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
// Set Analog Block control
EPD_WriteCmd(0x74);
EPD_WriteData(0x54);
// Set Digital Block control
EPD_WriteCmd(0x7E);
EPD_WriteData(0x3B);
// ACVCOM Setting
EPD_WriteCmd(0x2B);
EPD_WriteData(0x04);
EPD_WriteData(0x63);
// Booster soft start
EPD_WriteCmd(0x0C);
EPD_WriteData(0x8B);
EPD_WriteData(0x9C);
EPD_WriteData(0x96);
EPD_WriteData(0x0F);
// Driver output control
EPD_WriteCmd(0x01);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x01);
// Data entry mode setting
EPD_WriteCmd(0x11);
EPD_WriteData(0x01);
// Temperature sensor control
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x00);
EPD_WriteData(0x0C);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x54);
EPD_WriteData(0x00);
// Border waveform control
EPD_WriteCmd(0x3C);
EPD_WriteData(0x01);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xA1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Temperature sensor read from register
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xB1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Display update control
EPD_WriteCmd(0x21);
EPD_WriteData(0x03);
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x00);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0x40);
int i;
if (!full_or_partial)
{
EPD_WriteCmd(0x32);
for (i = 0; i < sizeof(LUT_BW_213_ice_part); i++)
{
EPD_WriteData(LUT_BW_213_ice_part[i]);
}
}
EPD_WriteCmd(0x24);
return epd_temperature;
}
void EPD_BW_213_ice_Display_byte(uint8_t data)
{
EPD_WriteData(data);
}
void EPD_BW_213_ice_Display_buffer(unsigned char *image, int size)
{
for (int i = 0; i < size; i++)
{
EPD_WriteData(image[i]);
}
}
void EPD_BW_213_ice_Display_end()
{
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xC7);
// Master Activation
EPD_WriteCmd(0x20);
}
uint8_t EPD_BW_213_ice_Display(unsigned char *image, int size, uint8_t full_or_partial)
{
uint8_t epd_temperature = 0;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
// Set Analog Block control
EPD_WriteCmd(0x74);
EPD_WriteData(0x54);
// Set Digital Block control
EPD_WriteCmd(0x7E);
EPD_WriteData(0x3B);
// ACVCOM Setting
EPD_WriteCmd(0x2B);
EPD_WriteData(0x04);
EPD_WriteData(0x63);
// Booster soft start
EPD_WriteCmd(0x0C);
EPD_WriteData(0x8B);
EPD_WriteData(0x9C);
EPD_WriteData(0x96);
EPD_WriteData(0x0F);
// Driver output control
EPD_WriteCmd(0x01);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x01);
// Data entry mode setting
EPD_WriteCmd(0x11);
EPD_WriteData(0x01);
// Temperature sensor control
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x00);
EPD_WriteData(0x0C);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x54);
EPD_WriteData(0x00);
// Border waveform control
EPD_WriteCmd(0x3C);
EPD_WriteData(0x01);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xA1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Temperature sensor read from register
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xB1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Display update control
EPD_WriteCmd(0x21);
EPD_WriteData(0x03);
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x00);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_LoadImage(image, size, 0x24);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0x40);
int i;
if (!full_or_partial)
{
EPD_WriteCmd(0x32);
for (i = 0; i < sizeof(LUT_BW_213_ice_part); i++)
{
EPD_WriteData(LUT_BW_213_ice_part[i]);
}
}
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xC7);
// Master Activation
EPD_WriteCmd(0x20);
return epd_temperature;
}
void EPD_BW_213_ice_set_sleep(void)
{
// deep sleep
EPD_WriteCmd(0x10);
EPD_WriteData(0x01);
}

View File

@@ -0,0 +1,12 @@
#pragma once
uint8_t EPD_BW_213_ice_detect(void);
uint8_t EPD_BW_213_ice_read_temp(void);
uint8_t EPD_BW_213_ice_Display_start(uint8_t full_or_partial);
void EPD_BW_213_ice_Display_byte(uint8_t data);
void EPD_BW_213_ice_Display_buffer(unsigned char *image, int size);
void EPD_BW_213_ice_Display_end();
uint8_t EPD_BW_213_ice_Display(unsigned char *image, int size, uint8_t full_or_partial);
void EPD_BW_213_ice_set_sleep(void);

View File

@@ -0,0 +1,226 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "epd.h"
#include "epd_spi.h"
#include "epd_bwr_154.h"
// SSD1675 mixed with SSD1680 EPD Controller
#define BWR_154_Len 50
uint8_t LUT_bwr_154_part[] = {
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
BWR_154_Len, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x00, 0x00, 0x00,
};
#define EPD_BWR_154_test_pattern 0xA5
uint8_t EPD_BWR_154_detect(void)
{
// SW Reset
EPD_WriteCmd(0x12);
WaitMs(10);
EPD_WriteCmd(0x32);
int i;
for (i = 0; i < 65; i++)// This controller has a <100 bytes LUT storage so we test if thats existing.
{
EPD_WriteData(EPD_BWR_154_test_pattern);
}
EPD_WriteCmd(0x33);
for (i = 0; i < 65; i++)
{
if(EPD_SPI_read() != EPD_BWR_154_test_pattern)
return 0;
}
return 1;
}
uint8_t EPD_BWR_154_read_temp(void)
{
uint8_t epd_temperature = 0 ;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
EPD_WriteCmd(0x01);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x01);
// Data entry mode setting
EPD_WriteCmd(0x11);
EPD_WriteData(0x01);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x00);
EPD_WriteData(0x18);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x61);
EPD_WriteData(0x00);
// Border waveform control
EPD_WriteCmd(0x3C);
EPD_WriteData(0x05);
// Temperature sensor control
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xB1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Temperature sensor read from register
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
// deep sleep
EPD_WriteCmd(0x10);
EPD_WriteData(0x01);
return epd_temperature;
}
uint8_t EPD_BWR_154_Display(unsigned char *image, int size, uint8_t full_or_partial)
{
uint8_t epd_temperature = 0 ;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
// Driver output control
EPD_WriteCmd(0x01);
EPD_WriteData(0xc7);
EPD_WriteData(0x00);
EPD_WriteData(0x01);
// Data entry mode setting
EPD_WriteCmd(0x11);
EPD_WriteData(0x01);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x00);
EPD_WriteData(0x18);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0xc7);
EPD_WriteData(0x00);
EPD_WriteData(0x00);
EPD_WriteData(0x00);
// Border waveform control
EPD_WriteCmd(0x3C);
EPD_WriteData(0x05);
// Temperature sensor control
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xB1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Temperature sensor read from register
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x00);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0xc7);
EPD_WriteData(0x00);
EPD_LoadImage(image, size, 0x24);
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x00);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0xc7);
EPD_WriteData(0x00);
EPD_WriteCmd(0x26);// RED Color TODO make something out of it :)
int i;
for (i = 0; i < size; i++)
{
EPD_WriteData(0x00);
}
if (!full_or_partial)
{
EPD_WriteCmd(0x32);
for (i = 0; i < sizeof(LUT_bwr_154_part); i++)
{
EPD_WriteData(LUT_bwr_154_part[i]);
}
}
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xC7);
// Master Activation
EPD_WriteCmd(0x20);
return epd_temperature;
}
void EPD_BWR_154_set_sleep(void)
{
// deep sleep
EPD_WriteCmd(0x10);
EPD_WriteData(0x01);
}

View File

@@ -0,0 +1,6 @@
#pragma once
uint8_t EPD_BWR_154_detect(void);
uint8_t EPD_BWR_154_read_temp(void);
uint8_t EPD_BWR_154_Display(unsigned char *image, int size, uint8_t full_or_partial);
void EPD_BWR_154_set_sleep(void);

View File

@@ -0,0 +1,265 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "epd.h"
#include "epd_spi.h"
#include "epd_bwr_213.h"
// SSD1675 mixed with SSD1680 EPD Controller
#define BWR_213_Len 50
uint8_t LUT_bwr_213_part[] = {
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
BWR_213_Len, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x00, 0x00, 0x00,
};
#define EPD_BWR_213_test_pattern 0xA5
uint8_t EPD_BWR_213_detect(void)
{
// SW Reset
EPD_WriteCmd(0x12);
WaitMs(10);
EPD_WriteCmd(0x32);
int i;
for (i = 0; i < 153; i++)// This model has a 159 bytes LUT storage so we test for that
{
EPD_WriteData(EPD_BWR_213_test_pattern);
}
EPD_WriteCmd(0x33);
for (i = 0; i < 153; i++)
{
if(EPD_SPI_read() != EPD_BWR_213_test_pattern)
return 0;
}
return 1;
}
uint8_t EPD_BWR_213_read_temp(void)
{
uint8_t epd_temperature = 0 ;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
// Set Analog Block control
EPD_WriteCmd(0x74);
EPD_WriteData(0x54);
// Set Digital Block control
EPD_WriteCmd(0x7E);
EPD_WriteData(0x3B);
// Booster soft start
EPD_WriteCmd(0x0C);
EPD_WriteData(0x8B);
EPD_WriteData(0x9C);
EPD_WriteData(0x96);
EPD_WriteData(0x0F);
// Driver output control
EPD_WriteCmd(0x01);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x01);
// Data entry mode setting
EPD_WriteCmd(0x11);
EPD_WriteData(0x01);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x00);
EPD_WriteData(0x0F);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x2E);
EPD_WriteData(0x00);
// Border waveform control
EPD_WriteCmd(0x3C);
EPD_WriteData(0x05);
// Display update control
EPD_WriteCmd(0x21);
EPD_WriteData(0x00);
EPD_WriteData(0x80);
// Temperature sensor control
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xB1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Temperature sensor read from register
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
// deep sleep
EPD_WriteCmd(0x10);
EPD_WriteData(0x01);
return epd_temperature;
}
uint8_t EPD_BWR_213_Display(unsigned char *image, int size, uint8_t full_or_partial)
{
uint8_t epd_temperature = 0 ;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
// Set Analog Block control
EPD_WriteCmd(0x74);
EPD_WriteData(0x54);
// Set Digital Block control
EPD_WriteCmd(0x7E);
EPD_WriteData(0x3B);
// Booster soft start
EPD_WriteCmd(0x0C);
EPD_WriteData(0x8B);
EPD_WriteData(0x9C);
EPD_WriteData(0x96);
EPD_WriteData(0x0F);
// Driver output control
EPD_WriteCmd(0x01);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x01);
// Data entry mode setting
EPD_WriteCmd(0x11);
EPD_WriteData(0x01);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x00);
EPD_WriteData(0x0F);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x2E);
EPD_WriteData(0x00);
// Border waveform control
EPD_WriteCmd(0x3C);
EPD_WriteData(0x05);
// Display update control
EPD_WriteCmd(0x21);
EPD_WriteData(0x00);
EPD_WriteData(0x80);
// Temperature sensor control
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xB1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Temperature sensor read from register
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x00);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_LoadImage(image, size, 0x24);
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x00);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteCmd(0x26);// RED Color TODO make something out of it :)
int i;
for (i = 0; i < size; i++)
{
EPD_WriteData(0x00);
}
if (!full_or_partial)
{
EPD_WriteCmd(0x32);
for (i = 0; i < sizeof(LUT_bwr_213_part); i++)
{
EPD_WriteData(LUT_bwr_213_part[i]);
}
}
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xC7);
// Master Activation
EPD_WriteCmd(0x20);
return epd_temperature;
}
void EPD_BWR_213_set_sleep(void)
{
// deep sleep
EPD_WriteCmd(0x10);
EPD_WriteData(0x01);
}

View File

@@ -0,0 +1,6 @@
#pragma once
uint8_t EPD_BWR_213_detect(void);
uint8_t EPD_BWR_213_read_temp(void);
uint8_t EPD_BWR_213_Display(unsigned char *image, int size, uint8_t full_or_partial);
void EPD_BWR_213_set_sleep(void);

View File

@@ -0,0 +1,363 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "epd.h"
#include "epd_spi.h"
#include "epd_bwr_350.h"
// SSD1675 mixed with SSD1680 EPD Controller
#define BWR_350_Len 50
uint8_t LUT_bwr_350_part[] = {
0x01, 0x10, 0x18, 0x01, 0x32, 0x02, 0x01, 0x10, 0x08, 0x01, 0x03, 0x02,
0x01, 0x01, 0x01, 0x0A, 0x05, 0x0A, 0x0F, 0x01, 0x01, 0x01, 0x14, 0x0F,
0x02, 0x02, 0x01, 0x14, 0x01, 0x02, 0x02, 0x04, 0x02, 0x14, 0x12, 0x01,
0x0A, 0x0F, 0x01, 0x02, 0x01, 0x01, 0x07, 0x05, 0x00, 0x22, 0x02, 0x01,
0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x50, 0x18, 0x01,
0x72, 0x02, 0x01, 0x10, 0x88, 0x01, 0x43,
0x02, 0x01, 0x01, 0x01, 0x4A, 0x85, 0x4A,
0x8F, 0x01, 0x01, 0x01, 0x94, 0x8F, 0x82,
0x42, 0x01, 0x14, 0x01, 0x82, 0x42, 0x84,
0x42, 0x14, 0x12, 0x01, 0x4A, 0x4F, 0x01,
0x02, 0x01, 0x01, 0x07, 0x85, 0x00, 0xE2,
0x02, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x50, 0x58, 0x81,
0x72, 0x02, 0x01, 0x10, 0x88, 0x01, 0x43,
0x42, 0x01, 0x01, 0x01, 0x4A, 0x85, 0x4A,
0x8F, 0x01, 0x01, 0x01, 0x94, 0x8F, 0x82,
0x42, 0x01, 0x14, 0x01, 0x82, 0x42, 0x84,
0x42, 0x14, 0x12, 0x01, 0x4A, 0x4F, 0x01,
0x02, 0x01, 0x01, 0x07, 0x85, 0x00, 0x22,
0x02, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x50, 0x58, 0x01,
0x72, 0x02, 0x01, 0x10, 0x88, 0x81, 0x43,
0x02, 0x01, 0x01, 0x01, 0x4A, 0x85, 0x4A,
0x8F, 0x01, 0x01, 0x01, 0x94, 0x8F, 0x82,
0x42, 0x01, 0x14, 0x01, 0x82, 0x42, 0x84,
0x42, 0x14, 0x12, 0x01, 0x4A, 0x4F, 0x01,
0x82, 0x01, 0x01, 0x07, 0x05, 0x00, 0x22,
0x42, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01,
0x02, 0x00, 0x00,
0x22, 0x17, 0x41, 0xA8, 0x32, 0x50};
#define EPD_BWR_350_test_pattern 0xA5
uint8_t EPD_BWR_350_detect(void)
{
// SW Reset
EPD_WriteCmd(0x12);
WaitMs(10);
EPD_WriteCmd(0x32);
int i;
for (i = 0; i < 153; i++) // This model has a 159 bytes LUT storage so we test for that
{
EPD_WriteData(EPD_BWR_350_test_pattern);
}
EPD_WriteCmd(0x33);
for (i = 0; i < 153; i++)
{
if (EPD_SPI_read() != EPD_BWR_350_test_pattern)
return 0;
}
return 1;
}
uint8_t EPD_BWR_350_read_temp(void)
{
uint8_t epd_temperature = 0;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
// Set Analog Block control
EPD_WriteCmd(0x74);
EPD_WriteData(0x54);
// Set Digital Block control
EPD_WriteCmd(0x7E);
EPD_WriteData(0x3B);
// Booster soft start
EPD_WriteCmd(0x0C);
EPD_WriteData(0x8B);
EPD_WriteData(0x9C);
EPD_WriteData(0x96);
EPD_WriteData(0x0F);
// Driver output control
EPD_WriteCmd(0x01);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x01);
// Data entry mode setting
EPD_WriteCmd(0x11);
EPD_WriteData(0x01);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x00);
EPD_WriteData(0x0F);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x2E);
EPD_WriteData(0x00);
// Border waveform control
EPD_WriteCmd(0x3C);
EPD_WriteData(0x05);
// Display update control
EPD_WriteCmd(0x21);
EPD_WriteData(0x00);
EPD_WriteData(0x80);
// Temperature sensor control
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xB1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Temperature sensor read from register
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
// deep sleep
EPD_WriteCmd(0x10);
EPD_WriteData(0x01);
return epd_temperature;
}
uint8_t EPD_BWR_350_Display_start(uint8_t full_or_partial)
{
uint8_t epd_temperature = 0;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
EPD_WriteCmd(0x3c);
EPD_WriteData(0x05);
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
EPD_WriteCmd(0x22);
EPD_WriteData(0xb1);
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
EPD_WriteCmd(0x21);
EPD_WriteData(0b00001000);
EPD_WriteData(0x00);
EPD_WriteCmd(0x11);
EPD_WriteData(0x03);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x01);
EPD_WriteData(0x17);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0x00);
EPD_WriteData(0x00);
EPD_WriteData(0x7f);
EPD_WriteData(0x01);
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x01);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0x00);
EPD_WriteData(0x00);
EPD_WriteCmd(0x24);
return epd_temperature;
}
void EPD_BWR_350_Display_byte(uint8_t data)
{
EPD_WriteData(data);
}
void EPD_BWR_350_Display_buffer(unsigned char *image, int size)
{
for (int i = 0; i < size; i++)
{
EPD_WriteData(image[i]);
}
}
void EPD_BWR_350_Display_end()
{
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xC7);
// Master Activation
EPD_WriteCmd(0x20);
}
void EPD_BWR_350_Display_color_change()
{
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x01);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0x00);
EPD_WriteData(0x00);
EPD_WriteCmd(0x26);
}
uint8_t EPD_BWR_350_Display(unsigned char *image, int size, uint8_t full_or_partial)
{
uint8_t epd_temperature = 0;
// SW Reset
EPD_WriteCmd(0x12);
EPD_CheckStatus_inverted(100);
// Set Analog Block control
EPD_WriteCmd(0x74);
EPD_WriteData(0x54);
// Set Digital Block control
EPD_WriteCmd(0x7E);
EPD_WriteData(0x3B);
// Booster soft start
EPD_WriteCmd(0x0C);
EPD_WriteData(0x8B);
EPD_WriteData(0x9C);
EPD_WriteData(0x96);
EPD_WriteData(0x0F);
// Driver output control
EPD_WriteCmd(0x01);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x01);
// Data entry mode setting
EPD_WriteCmd(0x11);
EPD_WriteData(0x01);
// Set RAM X- Address Start/End
EPD_WriteCmd(0x44);
EPD_WriteData(0x00);
EPD_WriteData(0x0F);
// Set RAM Y- Address Start/End
EPD_WriteCmd(0x45);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteData(0x2E);
EPD_WriteData(0x00);
// Border waveform control
EPD_WriteCmd(0x3C);
EPD_WriteData(0x05);
// Display update control
EPD_WriteCmd(0x21);
EPD_WriteData(0x00);
EPD_WriteData(0x80);
// Temperature sensor control
EPD_WriteCmd(0x18);
EPD_WriteData(0x80);
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xB1);
// Master Activation
EPD_WriteCmd(0x20);
EPD_CheckStatus_inverted(100);
// Temperature sensor read from register
EPD_WriteCmd(0x1B);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
WaitMs(5);
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x00);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_LoadImage(image, size, 0x24);
// Set RAM X address
EPD_WriteCmd(0x4E);
EPD_WriteData(0x00);
// Set RAM Y address
EPD_WriteCmd(0x4F);
EPD_WriteData(0x28);
EPD_WriteData(0x01);
EPD_WriteCmd(0x26); // RED Color TODO make something out of it :)
int i;
for (i = 0; i < size; i++)
{
EPD_WriteData(0x00);
}
if (!full_or_partial)
{
EPD_WriteCmd(0x32);
for (i = 0; i < sizeof(LUT_bwr_350_part); i++)
{
EPD_WriteData(LUT_bwr_350_part[i]);
}
}
// Display update control
EPD_WriteCmd(0x22);
EPD_WriteData(0xC7);
// Master Activation
EPD_WriteCmd(0x20);
return epd_temperature;
}
void EPD_BWR_350_set_sleep(void)
{
// deep sleep
EPD_WriteCmd(0x10);
EPD_WriteData(0x01);
}

View File

@@ -0,0 +1,13 @@
#pragma once
uint8_t EPD_BWR_350_detect(void);
uint8_t EPD_BWR_350_read_temp(void);
uint8_t EPD_BWR_350_Display_start(uint8_t full_or_partial);
void EPD_BWR_350_Display_byte(uint8_t data);
void EPD_BWR_350_Display_buffer(unsigned char *image, int size);
void EPD_BWR_350_Display_end();
void EPD_BWR_350_Display_color_change();
uint8_t EPD_BWR_350_Display(unsigned char *image, int size, uint8_t full_or_partial);
void EPD_BWR_350_set_sleep(void);

View File

@@ -0,0 +1,205 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "epd.h"
#include "epd_spi.h"
#include "epd_bwy_350.h"
// UC8151C or similar EPD Controller
enum PSR_FLAGS
{
RES_96x230 = 0b00000000,
RES_96x252 = 0b01000000,
RES_128x296 = 0b10000000,
RES_160x296 = 0b11000000,
LUT_OTP = 0b00000000,
LUT_REG = 0b00100000,
FORMAT_BWR = 0b00000000,
FORMAT_BW = 0b00010000,
SCAN_DOWN = 0b00000000,
SCAN_UP = 0b00001000,
SHIFT_LEFT = 0b00000000,
SHIFT_RIGHT = 0b00000100,
BOOSTER_OFF = 0b00000000,
BOOSTER_ON = 0b00000010,
RESET_SOFT = 0b00000000,
RESET_NONE = 0b00000001
};
#define lut_bwy_350_refresh_time 10
uint8_t lut_bwy_350_20_part[] =
{
0x20, 0x00, lut_bwy_350_refresh_time, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t lut_bwy_350_22_part[] =
{
0x22, 0x80, lut_bwy_350_refresh_time, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t lut_bwy_350_23_part[] =
{
0x23, 0x40, lut_bwy_350_refresh_time, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t EPD_BWY_350_detect(void)
{
// SW Reset
/*EPD_WriteCmd(0x12);
WaitMs(10);
EPD_WriteCmd(0x2F);
if (EPD_SPI_read() != 0x01)
return 0;
return 1;*/
return 0;
}
uint8_t EPD_BWY_350_read_temp(void)
{
uint8_t epd_temperature = 0;
EPD_WriteCmd(0x04);
WaitMs(1);
EPD_WriteCmd(0x40);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
// power off
EPD_WriteCmd(0x02);
// deep sleep
EPD_WriteCmd(0x07);
EPD_WriteData(0xa5);
return epd_temperature;
}
#define scan_direction (SCAN_UP | RES_160x296 | FORMAT_BWR | BOOSTER_ON | RESET_NONE | LUT_OTP | SHIFT_RIGHT)
uint8_t EPD_BWY_350_Display_start(uint8_t full_or_partial)
{
uint8_t epd_temperature = 0;
// power on
EPD_WriteCmd(0x04);
WaitMs(1);
/*EPD_WriteCmd(0X4D);
EPD_WriteData(0x55);
EPD_WriteCmd(0XF3);
EPD_WriteData(0x0A);
EPD_WriteCmd(0X50);
EPD_WriteData(0x57);*/
EPD_WriteCmd(0x00);
EPD_WriteData(scan_direction);
EPD_WriteData(0x0f);
EPD_WriteCmd(0x40);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
EPD_WriteCmd(0x10);
return epd_temperature;
}
void EPD_BWY_350_Display_byte(uint8_t data)
{
EPD_WriteData(data);
}
void EPD_BWY_350_Display_buffer(unsigned char *image, int size)
{
for (int i = 0; i < size; i++)
{
EPD_WriteData(image[i]);
}
}
void EPD_BWY_350_Display_color_change()
{
EPD_WriteCmd(0x13);
}
void EPD_BWY_350_Display_end()
{
EPD_WriteCmd(0x12);
}
uint8_t EPD_BWY_350_Display(unsigned char *image, int size, uint8_t full_or_partial)
{
uint8_t epd_temperature = 0;
// power on
EPD_WriteCmd(0x04);
WaitMs(1);
/*EPD_WriteCmd(0X4D);
EPD_WriteData(0x55);
EPD_WriteCmd(0XF3);
EPD_WriteData(0x0A);
EPD_WriteCmd(0X50);
EPD_WriteData(0x57);*/
EPD_WriteCmd(0x00);
EPD_WriteData(scan_direction); //| LUT_REG);
EPD_WriteData(0x0f);
EPD_WriteCmd(0x40);
epd_temperature = EPD_SPI_read();
EPD_SPI_read();
/*EPD_send_lut(lut_bwy_350_20_part, sizeof(lut_bwy_350_20_part));
EPD_send_empty_lut(0x21, 260);
EPD_send_lut(lut_bwy_350_22_part, sizeof(lut_bwy_350_22_part));
EPD_send_lut(lut_bwy_350_23_part, sizeof(lut_bwy_350_23_part));
EPD_send_empty_lut(0x24, 260);*/
//////////////////////// This parts clears the full screen
EPD_WriteCmd(0x10);
int i;
for (i = 0; i < 8832; i++)
{
EPD_WriteData(0);
}
EPD_WriteCmd(0x13);
for (i = 0; i < 8832; i++)
{
EPD_WriteData(0);
}
//////////////////////// This parts clears the full screen
EPD_WriteCmd(0x10);
for (i = 0; i < size; i++)
{
EPD_WriteData(~image[i]);
}
// load image data to EPD
// EPD_LoadImage(image, size, 0x13);
// EPD_WriteCmd(0XB6);
// EPD_WriteData(0x12);
// trigger display refresh
EPD_WriteCmd(0x12);
return epd_temperature;
}
void EPD_BWY_350_set_sleep(void)
{
// Vcom and data interval setting
// EPD_WriteCmd(0x50);
// EPD_WriteData(0xf7);
// power off
EPD_WriteCmd(0x02);
// deep sleep
EPD_WriteCmd(0x07);
EPD_WriteData(0xa5);
}

View File

@@ -0,0 +1,13 @@
#pragma once
uint8_t EPD_BWY_350_detect(void);
uint8_t EPD_BWY_350_read_temp(void);
uint8_t EPD_BWY_350_Display_start(uint8_t full_or_partial);
void EPD_BWY_350_Display_byte(uint8_t data);
void EPD_BWY_350_Display_buffer(unsigned char *image, int size);
void EPD_BWY_350_Display_end();
void EPD_BWY_350_Display_color_change();
uint8_t EPD_BWY_350_Display(unsigned char *image, int size, uint8_t full_or_partial);
void EPD_BWY_350_set_sleep(void);

View File

@@ -0,0 +1,152 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "epd.h"
#include "epd_spi.h"
void EPD_init(void)
{
gpio_set_func(EPD_RESET, AS_GPIO);
gpio_set_output_en(EPD_RESET, 1);
gpio_setup_up_down_resistor(EPD_RESET, PM_PIN_PULLUP_1M);
gpio_set_func(EPD_DC, AS_GPIO);
gpio_set_output_en(EPD_DC, 1);
gpio_setup_up_down_resistor(EPD_DC, PM_PIN_PULLUP_1M);
gpio_set_func(EPD_BUSY, AS_GPIO);
gpio_set_output_en(EPD_BUSY, 0);
gpio_set_input_en(EPD_BUSY, 1);
gpio_setup_up_down_resistor(EPD_BUSY, PM_PIN_PULLUP_1M);
gpio_set_func(EPD_CS, AS_GPIO);
gpio_set_output_en(EPD_CS, 1);
gpio_setup_up_down_resistor(EPD_CS, PM_PIN_PULLUP_1M);
gpio_set_func(EPD_CLK, AS_GPIO);
gpio_set_output_en(EPD_CLK, 1);
gpio_setup_up_down_resistor(EPD_CLK, PM_PIN_PULLUP_1M);
gpio_set_func(EPD_MOSI, AS_GPIO);
gpio_set_output_en(EPD_MOSI, 1);
gpio_setup_up_down_resistor(EPD_MOSI, PM_PIN_PULLUP_1M);
gpio_set_output_en(EPD_ENABLE, 0);
gpio_set_input_en(EPD_ENABLE, 1);
gpio_setup_up_down_resistor(EPD_ENABLE, PM_PIN_PULLUP_1M);
}
void EPD_SPI_Write(unsigned char value)
{
unsigned char i;
WaitUs(10);
for (i = 0; i < 8; i++)
{
gpio_write(EPD_CLK, 0);
if (value & 0x80)
{
gpio_write(EPD_MOSI, 1);
}
else
{
gpio_write(EPD_MOSI, 0);
}
value = (value << 1);
gpio_write(EPD_CLK, 1);
}
}
uint8_t EPD_SPI_read(void)
{
unsigned char i;
uint8_t value = 0;
gpio_shutdown(EPD_MOSI);
gpio_set_output_en(EPD_MOSI, 0);
gpio_set_input_en(EPD_MOSI, 1);
gpio_write(EPD_CS, 0);
EPD_ENABLE_WRITE_DATA();
WaitUs(10);
for (i = 0; i < 8; i++)
{
gpio_write(EPD_CLK, 0);
gpio_write(EPD_CLK, 1);
value <<= 1;
if (gpio_read(EPD_MOSI) != 0)
{
value |= 1;
}
}
gpio_set_output_en(EPD_MOSI, 1);
gpio_set_input_en(EPD_MOSI, 0);
gpio_write(EPD_CS, 1);
return value;
}
void EPD_WriteCmd(unsigned char cmd)
{
gpio_write(EPD_CS, 0);
EPD_ENABLE_WRITE_CMD();
EPD_SPI_Write(cmd);
gpio_write(EPD_CS, 1);
}
void EPD_WriteData(unsigned char data)
{
gpio_write(EPD_CS, 0);
EPD_ENABLE_WRITE_DATA();
EPD_SPI_Write(data);
gpio_write(EPD_CS, 1);
}
void EPD_CheckStatus(int max_ms)
{
unsigned long timeout_start = clock_time();
unsigned long timeout_ticks = max_ms * CLOCK_16M_SYS_TIMER_CLK_1MS;
WaitMs(1);
while (EPD_IS_BUSY())
{
if (clock_time() - timeout_start >= timeout_ticks)
return; // Here we had a timeout
}
}
void EPD_CheckStatus_inverted(int max_ms)
{
unsigned long timeout_start = clock_time();
unsigned long timeout_ticks = max_ms * CLOCK_16M_SYS_TIMER_CLK_1MS;
WaitMs(1);
while (!EPD_IS_BUSY())
{
if (clock_time() - timeout_start >= timeout_ticks)
return; // Here we had a timeout
}
}
void EPD_send_lut(uint8_t lut[], int len)
{
EPD_WriteCmd(lut[0]);
for (int r = 1; r <= len; r++)
{
EPD_WriteData(lut[r]);
}
}
void EPD_send_empty_lut(uint8_t lut, int len)
{
EPD_WriteCmd(lut);
for (int r = 0; r <= len; r++)
EPD_WriteData(0x00);
}
void EPD_LoadImage(unsigned char *image, int size, uint8_t cmd)
{
int i;
EPD_WriteCmd(cmd);
for (i = 0; i < size; i++)
{
EPD_WriteData(image[i]);
}
WaitMs(2);
}

View File

@@ -0,0 +1,22 @@
#pragma once
#define EPD_POWER_ON() gpio_write(EPD_ENABLE, 0)
#define EPD_POWER_OFF() gpio_write(EPD_ENABLE, 1)
#define EPD_ENABLE_WRITE_CMD() gpio_write(EPD_DC, 0)
#define EPD_ENABLE_WRITE_DATA() gpio_write(EPD_DC, 1)
#define EPD_IS_BUSY() (!gpio_read(EPD_BUSY))
void EPD_init(void);
void EPD_SPI_Write(unsigned char value);
uint8_t EPD_SPI_read(void);
void EPD_WriteCmd(unsigned char cmd);
void EPD_WriteData(unsigned char data);
void EPD_CheckStatus(int max_ms);
void EPD_CheckStatus_inverted(int max_ms);
void EPD_send_lut(uint8_t lut[], int len);
void EPD_send_empty_lut(uint8_t lut, int len);
void EPD_LoadImage(unsigned char *image, int size, uint8_t cmd);

View File

@@ -0,0 +1,259 @@
#pragma once
static const uint8_t font[256][20]={ // https://raw.githubusercontent.com/basti79/LCD-fonts/master/10x16_vertikal_MSB_1.h
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x00
{0xE0,0x01,0x30,0x03,0x50,0x02,0x28,0x05,0x28,0x04,0x28,0x04,0x28,0x05,0x50,0x02,0x30,0x03,0xE0,0x01}, // 0x01
{0xE0,0x01,0xF0,0x03,0xB0,0x03,0xD8,0x06,0xD8,0x07,0xD8,0x07,0xD8,0x06,0xB0,0x03,0xF0,0x03,0xE0,0x01}, // 0x02
{0x00,0x3E,0x80,0x7F,0xE0,0x7F,0xF0,0x7F,0xF8,0x3F,0xF8,0x3F,0xF0,0x7F,0xE0,0x7F,0x80,0x7F,0x00,0x3E}, // 0x03
{0x00,0x01,0x80,0x03,0xC0,0x0F,0xE0,0x1F,0xF8,0x7F,0xF0,0x1F,0xE0,0x0F,0xC0,0x07,0x80,0x03,0x00,0x01}, // 0x04
{0x80,0x03,0xC0,0x07,0xC0,0x07,0xC0,0x3F,0xF8,0x7F,0xB8,0x7F,0xC0,0x3F,0xC0,0x07,0xC0,0x07,0x80,0x03}, // 0x05
{0x80,0x03,0xC0,0x07,0xC0,0x0F,0xC0,0x1F,0xF8,0x3F,0xB8,0x7F,0xC0,0x1F,0xC0,0x0F,0xC0,0x07,0x80,0x03}, // 0x06
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x07
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x08
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x09
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0A
{0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x24,0x10,0x2E,0xE0,0x71,0x00,0x70,0x00,0x18}, // 0x0B
{0x00,0x00,0x00,0x1E,0x20,0x21,0xA0,0x40,0xF8,0x40,0xA0,0x40,0xA0,0x41,0x00,0x21,0x00,0x1E,0x00,0x00}, // 0x0C
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x0D
{0x06,0x00,0x0E,0x00,0x0E,0x00,0xFC,0x1F,0x00,0x18,0x30,0x10,0x70,0x30,0x70,0x20,0xE0,0x7F,0x00,0x00}, // 0x0E
{0x00,0x01,0xC0,0x0F,0xC0,0x04,0x40,0x08,0x60,0x18,0x40,0x08,0x40,0x04,0xC0,0x0C,0xC0,0x0B,0x00,0x01}, // 0x0F
{0xF8,0x0F,0xF0,0x07,0xF0,0x07,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xC0,0x01,0xC0,0x01,0x80,0x00,0x80,0x00}, // 0x10
{0x80,0x00,0x80,0x00,0xC0,0x01,0xC0,0x01,0xE0,0x03,0xE0,0x03,0xE0,0x03,0xF0,0x07,0xF0,0x07,0xF8,0x0F}, // 0x11
{0x00,0x00,0x00,0x00,0x08,0x10,0x04,0x20,0xFE,0x7F,0x04,0x20,0x08,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x12
{0x00,0x00,0x00,0x00,0xD8,0x7F,0x00,0x00,0x00,0x00,0xD8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x13
{0x00,0x00,0x00,0x38,0x00,0x7C,0x00,0x7E,0xFE,0x7F,0x00,0x40,0x00,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00}, // 0x14
{0x00,0x00,0x00,0x00,0x86,0x3B,0xC2,0x4C,0x42,0x44,0x62,0x46,0x32,0x42,0xDC,0x41,0x00,0x00,0x00,0x00}, // 0x15
{0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x00}, // 0x16
{0x00,0x00,0x00,0x00,0x11,0x10,0x09,0x20,0xFD,0x7F,0x09,0x20,0x11,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x17
{0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x20,0xFE,0x7F,0x00,0x20,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x18
{0x00,0x00,0x00,0x00,0x08,0x00,0x04,0x00,0xFE,0x7F,0x04,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x19
{0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xA0,0x02,0xC0,0x01,0x80,0x00,0x00,0x00}, // 0x1A
{0x00,0x00,0x80,0x00,0xC0,0x01,0xA0,0x02,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00}, // 0x1B
{0x00,0x00,0xF8,0x07,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00}, // 0x1C
{0x00,0x00,0x80,0x00,0xC0,0x01,0xA0,0x02,0x80,0x00,0x80,0x00,0xA0,0x02,0xC0,0x01,0x80,0x00,0x00,0x00}, // 0x1D
{0x08,0x00,0x18,0x00,0x78,0x00,0xF8,0x01,0xF8,0x03,0xF8,0x0F,0xF8,0x03,0xF8,0x00,0x38,0x00,0x08,0x00}, // 0x1E
{0x00,0x08,0x00,0x0C,0x00,0x0F,0xC0,0x0F,0xE0,0x0F,0xF8,0x0F,0xE0,0x0F,0x80,0x0F,0x00,0x0E,0x00,0x08}, // 0x1F
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x20
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x21
{0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x22
{0x80,0x00,0x98,0x04,0xE0,0x05,0x80,0x1E,0x98,0x64,0xE0,0x05,0x80,0x1E,0x80,0x64,0x80,0x04,0x00,0x00}, // 0x23
{0x00,0x00,0x00,0x00,0x18,0x38,0x08,0x64,0x08,0x42,0xFC,0xFF,0x88,0x41,0xF0,0x40,0x00,0x00,0x00,0x00}, // 0x24
{0x08,0x38,0x10,0x44,0x20,0x44,0xC0,0x44,0x00,0x39,0x70,0x02,0x88,0x0C,0x88,0x10,0x88,0x20,0x70,0x40}, // 0x25
{0xE0,0x00,0x10,0x01,0x08,0x3A,0x08,0x46,0x88,0x45,0xC8,0x4C,0x38,0x38,0x18,0x00,0x68,0x00,0x80,0x01}, // 0x26
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x27
{0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x07,0x18,0x18,0x0C,0x30,0x04,0x20,0x02,0x40,0x02,0x40,0x00,0x00}, // 0x28
{0x00,0x00,0x02,0x40,0x02,0x40,0x04,0x20,0x0C,0x30,0x18,0x18,0xE0,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x29
{0x00,0x00,0x00,0x10,0x00,0x18,0x00,0x0F,0x00,0x72,0x00,0x0F,0x00,0x18,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x2A
{0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0xF8,0x07,0x40,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00}, // 0x2B
{0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2C
{0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00}, // 0x2D
{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x2E
{0x00,0x00,0x02,0x00,0x0C,0x00,0x30,0x00,0xC0,0x00,0x00,0x03,0x00,0x0C,0x00,0x30,0x00,0x40,0x00,0x00}, // 0x2F
{0x00,0x00,0xC0,0x0F,0x30,0x30,0x08,0x40,0x08,0x40,0x08,0x40,0x30,0x30,0xC0,0x0F,0x00,0x00,0x00,0x00}, // 0x30
{0x00,0x00,0x08,0x20,0x08,0x20,0x08,0x20,0xF8,0x7F,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x31
{0x00,0x00,0x18,0x60,0x28,0x40,0x48,0x40,0x88,0x40,0x08,0x43,0x08,0x3C,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x32
{0x00,0x00,0x00,0x00,0x08,0x40,0x08,0x42,0x08,0x42,0x08,0x42,0xF0,0x3D,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x33
{0xC0,0x00,0x40,0x03,0x40,0x04,0x40,0x18,0x40,0x20,0xF8,0x7F,0x40,0x00,0x40,0x00,0x00,0x00,0x00,0x00}, // 0x34
{0x00,0x00,0x00,0x00,0x08,0x7C,0x08,0x44,0x08,0x44,0x10,0x42,0xE0,0x41,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x35
{0x00,0x00,0xE0,0x0F,0x10,0x32,0x08,0x44,0x08,0x44,0x08,0x44,0x10,0x42,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x36
{0x00,0x00,0x00,0x40,0x18,0x40,0xE0,0x40,0x00,0x43,0x00,0x4C,0x00,0x50,0x00,0x60,0x00,0x00,0x00,0x00}, // 0x37
{0x00,0x00,0xF0,0x38,0x08,0x45,0x08,0x42,0x08,0x42,0x08,0x45,0x90,0x45,0x60,0x38,0x00,0x00,0x00,0x00}, // 0x38
{0x00,0x00,0x00,0x1E,0x08,0x21,0x88,0x40,0x88,0x40,0x88,0x40,0x30,0x21,0xC0,0x1F,0x00,0x00,0x00,0x00}, // 0x39
{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x06,0x18,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3A
{0x00,0x00,0x00,0x00,0x00,0x00,0x19,0x06,0x1E,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x3B
{0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0x20,0x01,0x20,0x01,0x10,0x02,0x10,0x02,0x08,0x04,0x00,0x00}, // 0x3C
{0x00,0x00,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x20,0x01,0x00,0x00}, // 0x3D
{0x00,0x00,0x08,0x04,0x10,0x02,0x10,0x02,0x20,0x01,0x20,0x01,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00}, // 0x3E
{0x00,0x00,0x00,0x70,0x00,0x40,0xD8,0x40,0x00,0x41,0x00,0x42,0x00,0x64,0x00,0x38,0x00,0x00,0x00,0x00}, // 0x3F
{0xC0,0x0F,0x30,0x18,0x18,0x20,0xC8,0x47,0x28,0x48,0x68,0x50,0xD8,0x51,0xE0,0x3F,0x20,0x00,0x20,0x00}, // 0x40
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x0E,0x40,0x18,0x40,0x0C,0x40,0x03,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0x41
{0x00,0x00,0xF8,0x1F,0x08,0x11,0x08,0x11,0x08,0x11,0x08,0x11,0x88,0x12,0x70,0x0C,0x00,0x00,0x00,0x00}, // 0x42
{0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x18,0x00,0x00,0x00,0x00}, // 0x43
{0x00,0x00,0xF8,0x1F,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00,0x00,0x00}, // 0x44
{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x45
{0x00,0x00,0xF8,0x1F,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x00,0x10,0x00,0x00,0x00,0x00}, // 0x46
{0x00,0x00,0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x88,0x10,0x88,0x10,0xF8,0x18,0x00,0x00}, // 0x47
{0x00,0x00,0xF8,0x1F,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x48
{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xF8,0x1F,0x08,0x10,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x49
{0x00,0x00,0x00,0x00,0x08,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xF0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x4A
{0x00,0x00,0xF8,0x1F,0x00,0x01,0x80,0x01,0x40,0x02,0x20,0x04,0x20,0x08,0x10,0x10,0x08,0x00,0x00,0x00}, // 0x4B
{0x00,0x00,0xF8,0x1F,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x4C
{0xF8,0x1F,0x00,0x1C,0x80,0x07,0xE0,0x00,0x60,0x00,0x80,0x03,0x00,0x1C,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x4D
{0x00,0x00,0xF8,0x1F,0x00,0x08,0x00,0x06,0x80,0x01,0x60,0x00,0x10,0x00,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0x4E
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0x4F
{0x00,0x00,0xF8,0x1F,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x00,0x11,0x00,0x0E,0x00,0x00,0x00,0x00}, // 0x50
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x10,0x08,0x10,0x0C,0x10,0x12,0x08,0xE2,0x07,0x00,0x00}, // 0x51
{0x00,0x00,0xF8,0x1F,0x80,0x10,0x80,0x10,0xC0,0x10,0x20,0x11,0x10,0x0E,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x52
{0x00,0x00,0x18,0x0E,0x08,0x12,0x08,0x11,0x08,0x11,0x88,0x10,0x90,0x10,0x70,0x18,0x00,0x00,0x00,0x00}, // 0x53
{0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0xF8,0x1F,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00}, // 0x54
{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0x55
{0x00,0x10,0x00,0x0C,0x80,0x03,0x60,0x00,0x18,0x00,0x18,0x00,0xE0,0x00,0x00,0x03,0x00,0x0C,0x00,0x10}, // 0x56
{0x00,0x18,0xC0,0x07,0x38,0x00,0xF0,0x00,0x00,0x07,0x80,0x03,0x70,0x00,0x38,0x00,0xC0,0x07,0x00,0x18}, // 0x57
{0x08,0x10,0x10,0x08,0x20,0x04,0x40,0x02,0x80,0x01,0x80,0x01,0x40,0x02,0x20,0x04,0x10,0x08,0x08,0x10}, // 0x58
{0x00,0x10,0x00,0x08,0x00,0x06,0x00,0x01,0xF8,0x00,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10}, // 0x59
{0x00,0x00,0x18,0x10,0x28,0x10,0x48,0x10,0x88,0x10,0x08,0x11,0x08,0x12,0x08,0x14,0x08,0x18,0x00,0x00}, // 0x5A
{0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x00,0x00,0x00}, // 0x5B
{0x00,0x00,0x00,0x40,0x00,0x30,0x00,0x0C,0x00,0x03,0xC0,0x00,0x30,0x00,0x0C,0x00,0x02,0x00,0x00,0x00}, // 0x5C
{0x00,0x00,0x02,0x40,0x02,0x40,0x02,0x40,0x02,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x5D
{0x00,0x00,0x20,0x00,0xC0,0x00,0x00,0x07,0x00,0x1C,0x00,0x70,0x00,0x0E,0xC0,0x01,0x20,0x00,0x00,0x00}, // 0x5E
{0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00}, // 0x5F
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x60
{0x00,0x00,0x30,0x00,0x48,0x04,0x88,0x04,0x88,0x04,0x90,0x04,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x61
{0x00,0x00,0xF8,0x7F,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x06,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x62
{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x63
{0x00,0x00,0xE0,0x01,0x18,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x02,0xF8,0x7F,0x00,0x00,0x00,0x00}, // 0x64
{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x04,0x88,0x04,0x88,0x04,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x65
{0x00,0x00,0x00,0x04,0x00,0x04,0xF8,0x3F,0x00,0x24,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x44,0x00,0x00}, // 0x66
{0x00,0x00,0xE0,0x01,0x19,0x02,0x09,0x04,0x09,0x04,0x09,0x04,0x12,0x02,0xFC,0x07,0x00,0x00,0x00,0x00}, // 0x67
{0x00,0x00,0xF8,0x7F,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0x68
{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x64,0xF8,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x69
{0x00,0x00,0x01,0x00,0x01,0x04,0x01,0x04,0x01,0x64,0xFE,0x67,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6A
{0x00,0x00,0xF8,0x7F,0x80,0x00,0xC0,0x00,0x20,0x01,0x20,0x02,0x10,0x02,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x6B
{0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x40,0x00,0x40,0xF8,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x6C
{0xF8,0x07,0x00,0x02,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x02,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x00}, // 0x6D
{0x00,0x00,0xF8,0x07,0x00,0x03,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0x6E
{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x6F
{0x00,0x00,0xFF,0x07,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x06,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x70
{0x00,0x00,0xE0,0x01,0x18,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x02,0xFF,0x07,0x00,0x00,0x00,0x00}, // 0x71
{0x00,0x00,0x00,0x00,0xF8,0x07,0x00,0x01,0x00,0x02,0x00,0x04,0x00,0x04,0x00,0x07,0x00,0x00,0x00,0x00}, // 0x72
{0x00,0x00,0x18,0x03,0x88,0x04,0x88,0x04,0x48,0x04,0x48,0x04,0x30,0x04,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x73
{0x00,0x00,0x00,0x04,0x00,0x04,0xF0,0x1F,0x08,0x04,0x08,0x04,0x08,0x04,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x74
{0x00,0x00,0xF0,0x07,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x75
{0x00,0x04,0x80,0x03,0x60,0x00,0x18,0x00,0x08,0x00,0x30,0x00,0xC0,0x00,0x00,0x03,0x00,0x04,0x00,0x00}, // 0x76
{0x00,0x06,0xE0,0x01,0x18,0x00,0x70,0x00,0x80,0x03,0x80,0x01,0x70,0x00,0x18,0x00,0xE0,0x01,0x00,0x06}, // 0x77
{0x00,0x00,0x08,0x04,0x10,0x02,0x20,0x01,0xC0,0x00,0xC0,0x00,0x20,0x01,0x10,0x02,0x08,0x04,0x00,0x00}, // 0x78
{0x01,0x04,0x01,0x03,0xC1,0x00,0x62,0x00,0x1C,0x00,0x18,0x00,0x60,0x00,0x80,0x00,0x00,0x03,0x00,0x04}, // 0x79
{0x00,0x00,0x08,0x04,0x18,0x04,0x28,0x04,0x48,0x04,0x88,0x04,0x08,0x05,0x08,0x06,0x08,0x04,0x00,0x00}, // 0x7A
{0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x7C,0x3F,0x02,0x40,0x02,0x40,0x02,0x40,0x00,0x00,0x00,0x00}, // 0x7B
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x7F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x7C
{0x00,0x00,0x00,0x00,0x02,0x40,0x02,0x40,0x02,0x40,0x7C,0x3F,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00}, // 0x7D
{0xC0,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x80,0x00,0x80,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x80,0x01}, // 0x7E
{0x00,0x00,0xF8,0x01,0x08,0x03,0x08,0x04,0x08,0x08,0x08,0x04,0x08,0x03,0xF8,0x01,0x00,0x00,0x00,0x00}, // 0x7F
{0xC0,0x03,0x30,0x0C,0x10,0x08,0x08,0x10,0x08,0x10,0x09,0x10,0x0D,0x10,0x0B,0x18,0x00,0x00,0x00,0x00}, // 0x80
{0x00,0x00,0xF0,0x07,0x08,0x20,0x08,0x00,0x08,0x00,0x10,0x20,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x81
{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x04,0x88,0x24,0x88,0x44,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x82
{0x00,0x00,0x30,0x00,0x48,0x24,0x88,0x44,0x88,0x44,0x90,0x24,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x83
{0x00,0x00,0x30,0x00,0x48,0x24,0x88,0x04,0x88,0x04,0x90,0x24,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x84
{0x00,0x00,0x30,0x00,0x48,0x44,0x88,0x24,0x88,0x04,0x90,0x04,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x85
{0x00,0x00,0x30,0x00,0x48,0x04,0x88,0x44,0x88,0xA4,0x90,0x44,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0x86
{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x09,0x04,0x0D,0x04,0x0B,0x04,0x08,0x04,0x00,0x00,0x00,0x00}, // 0x87
{0x00,0x00,0xE0,0x01,0x90,0x22,0x88,0x44,0x88,0x44,0x88,0x24,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x88
{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x24,0x88,0x04,0x88,0x04,0x88,0x24,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x89
{0x00,0x00,0xE0,0x01,0x90,0x02,0x88,0x44,0x88,0x24,0x88,0x04,0x88,0x04,0x88,0x03,0x00,0x00,0x00,0x00}, // 0x8A
{0x00,0x00,0x00,0x04,0x00,0x24,0x00,0x04,0xF8,0x07,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8B
{0x00,0x00,0x00,0x04,0x00,0x24,0x00,0x44,0xF8,0x47,0x00,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8C
{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x44,0xF8,0x27,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x8D
{0x08,0x00,0x70,0x00,0xC0,0x81,0x40,0x0E,0x40,0x18,0x40,0x0C,0x40,0x83,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0x8E
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x4E,0x40,0xB0,0x40,0xB8,0x40,0x4F,0xC0,0x01,0x70,0x00,0x08,0x00}, // 0x8F
{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x50,0x88,0x90,0x88,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0x90
{0x70,0x04,0xC8,0x04,0x88,0x04,0x88,0x04,0xF0,0x03,0x98,0x04,0x88,0x04,0x88,0x04,0x88,0x03,0x00,0x00}, // 0x91
{0x08,0x00,0x30,0x00,0xE0,0x01,0x20,0x06,0x20,0x18,0xF8,0x1F,0x88,0x10,0x88,0x10,0x08,0x10,0x00,0x00}, // 0x92
{0x00,0x00,0xE0,0x01,0x10,0x22,0x08,0x44,0x08,0x44,0x08,0x24,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x93
{0x00,0x00,0xE0,0x01,0x10,0x22,0x08,0x04,0x08,0x04,0x08,0x24,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x94
{0x00,0x00,0xE0,0x01,0x10,0x42,0x08,0x24,0x08,0x04,0x08,0x04,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0x95
{0x00,0x00,0xF0,0x07,0x08,0x20,0x08,0x40,0x08,0x40,0x10,0x20,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x96
{0x00,0x00,0xF0,0x07,0x08,0x40,0x08,0x20,0x08,0x00,0x10,0x00,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0x97
{0x01,0x04,0x01,0x03,0xC1,0x20,0x62,0x00,0x1C,0x00,0x18,0x20,0x60,0x00,0x80,0x00,0x00,0x03,0x00,0x04}, // 0x98
{0x00,0x00,0xE0,0x07,0x10,0x88,0x08,0x10,0x08,0x10,0x08,0x10,0x08,0x90,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0x99
{0x00,0x00,0xE0,0x1F,0x18,0x80,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x80,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0x9A
{0x00,0x00,0xE8,0x01,0x10,0x02,0x28,0x04,0xC8,0x04,0x08,0x05,0x10,0x02,0xE0,0x05,0x00,0x00,0x00,0x00}, // 0x9B
{0x00,0x00,0x00,0x00,0x08,0x00,0x18,0x02,0xE8,0x3F,0x08,0x42,0x08,0x42,0x08,0x40,0x00,0x00,0x00,0x00}, // 0x9C
{0x00,0x00,0xE8,0x07,0x30,0x08,0x68,0x10,0x88,0x10,0x08,0x11,0x08,0x16,0x10,0x0C,0xE0,0x17,0x00,0x00}, // 0x9D
{0x00,0x00,0x08,0x04,0x10,0x02,0x20,0x01,0xC0,0x00,0xC0,0x00,0x20,0x01,0x10,0x02,0x08,0x04,0x00,0x00}, // 0x9E
{0x00,0x00,0x01,0x00,0x01,0x04,0x01,0x04,0xFE,0x7F,0x00,0x84,0x00,0x84,0x00,0x80,0x00,0x00,0x00,0x00}, // 0x9F
{0x00,0x00,0x30,0x00,0x48,0x04,0x88,0x04,0x88,0x24,0x90,0x44,0xF8,0x03,0x08,0x00,0x00,0x00,0x00,0x00}, // 0xA0
{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x27,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xA1
{0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x24,0x08,0x44,0x10,0x02,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0xA2
{0x00,0x00,0xF0,0x07,0x08,0x00,0x08,0x00,0x08,0x20,0x10,0x40,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xA3
{0x00,0x00,0xF8,0x07,0x00,0x23,0x00,0x42,0x00,0x24,0x00,0x24,0x00,0x44,0xF8,0x03,0x00,0x00,0x00,0x00}, // 0xA4
{0x00,0x00,0xF8,0x1F,0x00,0x48,0x00,0x86,0x80,0xC1,0x60,0x40,0x10,0x80,0xF8,0x1F,0x00,0x00,0x00,0x00}, // 0xA5
{0x00,0x00,0x00,0x00,0x00,0x4C,0x00,0x52,0x00,0x52,0x00,0x52,0x00,0x3E,0x00,0x02,0x00,0x00,0x00,0x00}, // 0xA6
{0x00,0x00,0x00,0x00,0x00,0x3C,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x42,0x00,0x3C,0x00,0x00,0x00,0x00}, // 0xA7
{0x00,0x00,0x0E,0x00,0x13,0x00,0x11,0x00,0x21,0x00,0xC1,0x06,0x01,0x00,0x07,0x00,0x00,0x00,0x00,0x00}, // 0xA8
{0x00,0x00,0x00,0x1C,0x00,0x22,0x00,0x5D,0x00,0x55,0x00,0x5D,0x00,0x22,0x00,0x1C,0x00,0x00,0x00,0x00}, // 0xA9
{0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0xE0,0x01,0x00,0x00}, // 0xAA
{0x08,0x40,0x30,0x7E,0x40,0x00,0x80,0x01,0x00,0x06,0x00,0x08,0x08,0x31,0x38,0x41,0x28,0x01,0xC8,0x00}, // 0xAB
{0x08,0x40,0x30,0x7E,0x40,0x00,0x80,0x01,0x00,0x06,0x60,0x08,0xA0,0x30,0x20,0x41,0xF8,0x01,0x20,0x00}, // 0xAC
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xAD
{0x00,0x00,0x80,0x00,0x40,0x01,0x20,0x02,0x10,0x04,0x80,0x00,0x40,0x01,0x20,0x02,0x10,0x04,0x00,0x00}, // 0xAE
{0x00,0x00,0x10,0x04,0x20,0x02,0x40,0x01,0x80,0x00,0x10,0x04,0x20,0x02,0x40,0x01,0x80,0x00,0x00,0x00}, // 0xAF
{0x36,0xDB,0x36,0xDB,0x00,0x00,0x36,0xDB,0x36,0xDB,0x00,0x00,0x36,0xDB,0x36,0xDB,0x00,0x00,0x00,0x00}, // 0xB0
{0xDB,0x36,0xDB,0x36,0x36,0xDB,0xFF,0xFF,0xDB,0x36,0x36,0xDB,0xFF,0xFF,0xDB,0x36,0x36,0xDB,0x36,0xDB}, // 0xB1
{0xFF,0xFF,0xFF,0xFF,0x36,0xDB,0xFF,0xFF,0xFF,0xFF,0x36,0xDB,0xFF,0xFF,0xFF,0xFF,0x36,0xDB,0x36,0xDB}, // 0xB2
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB3
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB4
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x0E,0x40,0x58,0x40,0x8C,0x40,0x03,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xB5
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x4E,0x40,0x98,0x40,0x8C,0x40,0x43,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xB6
{0x08,0x00,0x70,0x00,0xC0,0x01,0x40,0x8E,0x40,0x58,0x40,0x0C,0x40,0x03,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xB7
{0xC0,0x0F,0x30,0x30,0x98,0x67,0xC8,0x4C,0x48,0x48,0x48,0x48,0x58,0x68,0x30,0x30,0xC0,0x0F,0x00,0x00}, // 0xB8
{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xB9
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBA
{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0x01,0x00,0x01,0xFF,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBB
{0x40,0x01,0x40,0x01,0x40,0x01,0x40,0xFF,0x40,0x00,0xC0,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBC
{0x00,0x00,0xC0,0x0F,0x20,0x10,0x30,0x20,0x10,0x20,0xF8,0x7F,0x10,0x20,0x10,0x20,0x00,0x00,0x00,0x00}, // 0xBD
{0x00,0x40,0x00,0x20,0x20,0x19,0x20,0x05,0xF8,0x03,0x20,0x05,0x20,0x09,0x00,0x10,0x00,0x20,0x00,0x40}, // 0xBE
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xBF
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC0
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC1
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC2
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC3
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC4
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0xFF,0xFF,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xC5
{0x00,0x00,0x30,0x00,0x48,0x24,0x88,0x44,0x88,0x24,0x90,0x24,0xF8,0x43,0x08,0x00,0x00,0x00,0x00,0x00}, // 0xC6
{0x08,0x00,0x70,0x00,0xC0,0x41,0x40,0x8E,0x40,0xD8,0x40,0x4C,0x40,0x83,0xC0,0x00,0x30,0x00,0x08,0x00}, // 0xC7
{0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xFF,0x40,0x00,0x40,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xC8
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x01,0x00,0x01,0x7F,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xC9
{0x40,0x01,0x40,0x01,0x40,0x01,0x40,0xFF,0x40,0x00,0x40,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCA
{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0x01,0x00,0x01,0x7F,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCB
{0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0x00,0x00,0x7F,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCC
{0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCD
{0x40,0x01,0x40,0x01,0x40,0x01,0x7F,0xFF,0x00,0x00,0x7F,0xFF,0x40,0x01,0x40,0x01,0x40,0x01,0x40,0x01}, // 0xCE
{0x00,0x00,0x20,0x10,0xC0,0x0F,0x40,0x08,0x40,0x08,0x40,0x08,0x40,0x08,0xC0,0x0F,0x20,0x10,0x00,0x00}, // 0xCF
{0x00,0x00,0xE0,0x41,0x10,0x52,0x08,0x74,0x08,0x24,0x08,0x54,0x10,0x0E,0xE0,0x03,0x00,0x00,0x00,0x00}, // 0xD0
{0x00,0x01,0xF8,0x1F,0x08,0x11,0x08,0x11,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00,0x00,0x00}, // 0xD1
{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x50,0x88,0x90,0x88,0x90,0x88,0x50,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD2
{0x00,0x00,0xF8,0x1F,0x88,0x90,0x88,0x10,0x88,0x10,0x88,0x10,0x88,0x90,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD3
{0x00,0x00,0xF8,0x1F,0x88,0x10,0x88,0x10,0x88,0x90,0x88,0x50,0x88,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD4
{0x00,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0xF8,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xD5
{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x10,0xF8,0x5F,0x08,0x90,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD6
{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x50,0xF8,0x9F,0x08,0x90,0x08,0x50,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD7
{0x00,0x00,0x08,0x10,0x08,0x90,0x08,0x10,0xF8,0x1F,0x08,0x10,0x08,0x90,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xD8
{0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xD9
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00}, // 0xDA
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, // 0xDB
{0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00}, // 0xDC
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xDD
{0x00,0x00,0x08,0x10,0x08,0x10,0x08,0x90,0xF8,0x5F,0x08,0x10,0x08,0x10,0x08,0x10,0x00,0x00,0x00,0x00}, // 0xDE
{0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF,0x00,0xFF}, // 0xDF
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x10,0x08,0x50,0x08,0x90,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE0
{0x00,0x00,0xF8,0x3F,0x00,0x40,0x00,0x40,0x08,0x47,0x88,0x38,0x48,0x00,0x30,0x00,0x00,0x00,0x00,0x00}, // 0xE1
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x50,0x08,0x90,0x08,0x90,0x08,0x50,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE2
{0x00,0x00,0xE0,0x07,0x10,0x08,0x08,0x90,0x08,0x50,0x08,0x10,0x08,0x10,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE3
{0x00,0x00,0xE0,0x01,0x10,0x22,0x08,0x44,0x08,0x24,0x08,0x24,0x10,0x42,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0xE4
{0x00,0x00,0xE0,0x07,0x10,0x48,0x08,0x90,0x08,0xD0,0x08,0x50,0x08,0x90,0x10,0x08,0xE0,0x07,0x00,0x00}, // 0xE5
{0x00,0x00,0xFF,0x07,0x10,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x10,0x00,0xF8,0x07,0x00,0x00,0x00,0x00}, // 0xE6
{0x00,0x00,0xFF,0x7F,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x04,0x10,0x06,0xE0,0x01,0x00,0x00,0x00,0x00}, // 0xE7
{0x00,0x00,0xF8,0x1F,0x20,0x04,0x20,0x04,0x20,0x04,0x20,0x04,0x40,0x04,0x80,0x03,0x00,0x00,0x00,0x00}, // 0xE8
{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x00,0x08,0x40,0x08,0x80,0x10,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xE9
{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x40,0x08,0x80,0x08,0x80,0x10,0x40,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xEA
{0x00,0x00,0xE0,0x1F,0x18,0x00,0x08,0x80,0x08,0x40,0x08,0x00,0x10,0x00,0xE0,0x1F,0x00,0x00,0x00,0x00}, // 0xEB
{0x01,0x04,0x01,0x03,0xC1,0x00,0x62,0x00,0x1C,0x20,0x18,0x40,0x60,0x00,0x80,0x00,0x00,0x03,0x00,0x04}, // 0xEC
{0x00,0x10,0x00,0x08,0x00,0x06,0x00,0x01,0xF8,0x40,0x00,0x81,0x00,0x02,0x00,0x04,0x00,0x08,0x00,0x10}, // 0xED
{0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80}, // 0xEE
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xEF
{0x00,0x00,0x00,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x80,0x00,0x00,0x00,0x00,0x00}, // 0xF0
{0x00,0x00,0x08,0x01,0x08,0x01,0x08,0x01,0x08,0x01,0xC8,0x07,0x08,0x01,0x08,0x01,0x08,0x01,0x00,0x00}, // 0xF1
{0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0x05,0x00}, // 0xF2
{0x08,0x42,0x10,0x52,0x20,0x5A,0xC0,0x6C,0x00,0x01,0x60,0x02,0xA0,0x0C,0x20,0x11,0xF8,0x21,0x20,0x40}, // 0xF3
{0x00,0x00,0x00,0x38,0x00,0x7C,0x00,0x7E,0xFE,0x7F,0x00,0x40,0x00,0x40,0xFE,0x7F,0x00,0x00,0x00,0x00}, // 0xF4
{0x00,0x00,0x00,0x00,0x86,0x3B,0xC2,0x4C,0x42,0x44,0x62,0x46,0x32,0x42,0xDC,0x41,0x00,0x00,0x00,0x00}, // 0xF5
{0x00,0x00,0x40,0x00,0x40,0x00,0x40,0x00,0x58,0x06,0x58,0x06,0x40,0x00,0x40,0x00,0x40,0x00,0x00,0x00}, // 0xF6
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x05,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF7
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x48,0x00,0x48,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF8
{0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xF9
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFA
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFB
{0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x52,0x00,0x52,0x00,0x52,0x00,0x6C,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFC
{0x00,0x00,0x00,0x00,0x00,0x42,0x00,0x46,0x00,0x4A,0x00,0x4A,0x00,0x32,0x00,0x00,0x00,0x00,0x00,0x00}, // 0xFD
{0x00,0x00,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0xF8,0x07,0x00,0x00}, // 0xFE
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // 0xFF
};

View File

@@ -0,0 +1,199 @@
// Created by http://oleddisplay.squix.ch/ Consider a donation
// In case of problems make sure that you are using the font file with the correct version!
const uint8_t Dialog_plain_16Bitmaps[] = {
// Bitmap Data:
0x00, // ' '
0xAA,0xAA,0x0A, // '!'
0x94,0xA5,0x20, // '"'
0x0C,0x80,0x88,0x09,0x87,0xFE,0x19,0x01,0x10,0x13,0x0F,0xFC,0x32,0x02,0x20,0x26,0x00, // '#'
0x10,0x10,0x7C,0xD2,0x90,0x90,0x70,0x1C,0x12,0x12,0x96,0x7C,0x10,0x10, // '$'
0x70,0x42,0x21,0x08,0x88,0x22,0x60,0x89,0x01,0xC8,0x00,0x27,0x01,0x22,0x0C,0x88,0x22,0x21,0x08,0x84,0x1C, // '%'
0x3C,0x06,0x20,0x40,0x04,0x00,0x20,0x05,0x00,0x88,0x48,0x44,0x82,0x48,0x18,0x41,0x83,0xE4, // '&'
0xAA, // '''
0x33,0x10,0x88,0x42,0x10,0x84,0x10,0x86,0x18, // '('
0xC3,0x08,0x41,0x08,0x42,0x10,0x88,0x46,0x60, // ')'
0x10,0x10,0x92,0x7C,0x38,0xD6,0x10,0x10, // '*'
0x08,0x02,0x00,0x80,0x20,0xFF,0x82,0x00,0x80,0x20,0x08,0x00, // '+'
0x49,0x40, // ','
0xF0, // '-'
0xA0, // '.'
0x08,0x21,0x04,0x10,0x82,0x08,0x41,0x04,0x30,0x80, // '/'
0x3C,0x21,0x10,0x90,0x28,0x14,0x0A,0x05,0x02,0x81,0x21,0x10,0x87,0x80, // '0'
0x70,0xD0,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0xFE, // '1'
0x78,0xC4,0x82,0x02,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xFE, // '2'
0x7C,0x41,0x80,0x40,0x20,0x31,0xE0,0x0C,0x02,0x01,0x00,0xA0,0x8F,0x80, // '3'
0x06,0x02,0x80,0xA0,0x48,0x22,0x10,0x84,0x22,0x08,0xFF,0x80,0x80,0x20,0x08, // '4'
0x7E,0x20,0x10,0x08,0x07,0xC2,0x10,0x04,0x02,0x01,0x00,0xA0,0x8F,0x80, // '5'
0x1C,0x31,0x10,0x10,0x0B,0xC6,0x12,0x05,0x02,0x81,0x40,0x90,0x87,0x80, // '6'
0xFF,0x00,0x80,0x80,0x40,0x40,0x20,0x20,0x10,0x08,0x08,0x04,0x04,0x00, // '7'
0x3C,0x61,0xA0,0x50,0x2C,0x31,0xE3,0x0D,0x02,0x81,0x40,0x90,0x87,0x80, // '8'
0x3C,0x21,0x20,0x90,0x28,0x14,0x09,0x0C,0x7A,0x01,0x01,0x11,0x87,0x00, // '9'
0xA0,0x0A, // ':'
0x48,0x00,0x12,0x50, // ';'
0x00,0x40,0x70,0x70,0x38,0x08,0x00,0xE0,0x07,0x00,0x1C,0x00,0x40, // '<'
0xFF,0xC0,0x00,0x00,0x7F,0xE0, // '='
0x80,0x0E,0x00,0x38,0x01,0xC0,0x04,0x07,0x03,0x83,0x80,0x80,0x00, // '>'
0x79,0x08,0x10,0x20,0xC3,0x0C,0x10,0x20,0x00,0x81,0x00, // '?'
0x0F,0xC0,0x30,0x60,0x80,0x62,0x3D,0x4C,0x86,0x52,0x04,0xA4,0x09,0x48,0x12,0x90,0x25,0x90,0xD1,0x1E,0xC1,0x00,0x01,0x83,0x00,0xFC,0x00, // '@'
0x04,0x00,0x40,0x0A,0x00,0xA0,0x11,0x01,0x10,0x20,0x82,0x08,0x3F,0x84,0x04,0x40,0x48,0x02, // 'A'
0xFE,0x20,0x68,0x0A,0x02,0x81,0xBF,0xC8,0x1A,0x02,0x80,0xA0,0x28,0x13,0xF8, // 'B'
0x1F,0x08,0x64,0x02,0x00,0x80,0x20,0x08,0x02,0x00,0x80,0x10,0x02,0x18,0x7C, // 'C'
0xFE,0x10,0x62,0x02,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x12,0x0C,0x7F,0x00, // 'D'
0xFF,0x40,0x20,0x10,0x08,0x07,0xFA,0x01,0x00,0x80,0x40,0x20,0x1F,0xE0, // 'E'
0xFE,0x80,0x80,0x80,0x80,0xFC,0x80,0x80,0x80,0x80,0x80,0x80, // 'F'
0x1F,0x84,0x19,0x01,0x40,0x08,0x01,0x00,0x20,0xF4,0x02,0x80,0x48,0x08,0x81,0x0F,0xC0, // 'G'
0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0xFF,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x20, // 'H'
0xAA,0xAA,0xAA, // 'I'
0x22,0x22,0x22,0x22,0x22,0x22,0x22,0xC0, // 'J'
0x81,0x20,0x88,0x42,0x20,0x90,0x38,0x0A,0x02,0x40,0x88,0x21,0x08,0x22,0x04, // 'K'
0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0xFE, // 'L'
0xC0,0x6C,0x06,0xA0,0xAA,0x0A,0xA0,0xA9,0x12,0x91,0x28,0xA2,0x8A,0x28,0x42,0x80,0x28,0x02, // 'M'
0xC0,0x54,0x0A,0x81,0x48,0x28,0x85,0x10,0xA1,0x14,0x12,0x82,0x50,0x2A,0x05,0x40,0x60, // 'N'
0x1F,0x02,0x08,0x40,0x48,0x02,0x80,0x28,0x02,0x80,0x28,0x02,0x80,0x24,0x04,0x20,0x81,0xF0, // 'O'
0xFC,0x41,0x20,0x50,0x28,0x14,0x13,0xF1,0x00,0x80,0x40,0x20,0x10,0x00, // 'P'
0x1F,0x02,0x08,0x40,0x48,0x02,0x80,0x28,0x02,0x80,0x28,0x02,0x80,0x24,0x04,0x20,0xC1,0xF0,0x00,0x80,0x04, // 'Q'
0xFC,0x10,0x42,0x04,0x40,0x88,0x11,0x04,0x3F,0x84,0x10,0x81,0x10,0x22,0x02,0x40,0x40, // 'R'
0x3C,0x63,0x20,0x10,0x08,0x03,0x80,0x78,0x06,0x01,0x40,0xB0,0xCF,0x80, // 'S'
0xFF,0x82,0x00,0x80,0x20,0x08,0x02,0x00,0x80,0x20,0x08,0x02,0x00,0x80,0x20, // 'T'
0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x09,0x02,0x1F,0x80, // 'U'
0x80,0x28,0x02,0x40,0x44,0x04,0x20,0x82,0x08,0x11,0x01,0x10,0x11,0x00,0xA0,0x0A,0x00,0x40, // 'V'
0x81,0x02,0x81,0x02,0x42,0x84,0x42,0x84,0x42,0x84,0x22,0x88,0x24,0x48,0x24,0x48,0x14,0x50,0x14,0x50,0x08,0x20,0x08,0x20, // 'W'
0xC1,0x90,0x42,0x20,0x88,0x14,0x02,0x00,0x80,0x50,0x22,0x08,0x84,0x12,0x02, // 'X'
0x80,0x90,0x42,0x20,0x88,0x14,0x02,0x00,0x80,0x20,0x08,0x02,0x00,0x80,0x20, // 'Y'
0xFF,0xC0,0x08,0x02,0x00,0x80,0x20,0x08,0x02,0x00,0x80,0x20,0x08,0x02,0x00,0x7F,0xE0, // 'Z'
0xE8,0x88,0x88,0x88,0x88,0x88,0x8E, // '['
0x83,0x04,0x10,0x40,0x82,0x08,0x10,0x41,0x02,0x08, // '\'
0xE2,0x22,0x22,0x22,0x22,0x22,0x2E, // ']'
0x0C,0x03,0xC0,0x84,0x20,0x40, // '^'
0xFF,0x00, // '_'
0xC3,0x0C, // '`'
0x3C,0x46,0x02,0x7E,0xC2,0x82,0x82,0xC6,0x7A, // 'a'
0x80,0x40,0x20,0x17,0x8C,0x24,0x0A,0x05,0x02,0x81,0x40,0xB0,0x97,0x80, // 'b'
0x3C,0x42,0x80,0x80,0x80,0x80,0x80,0x42,0x3C, // 'c'
0x01,0x00,0x80,0x47,0xA4,0x34,0x0A,0x05,0x02,0x81,0x40,0x90,0xC7,0xA0, // 'd'
0x38,0x44,0x82,0x82,0xFE,0x80,0x80,0x42,0x3C, // 'e'
0x39,0x04,0x3C,0x41,0x04,0x10,0x41,0x04,0x10, // 'f'
0x3D,0x21,0xA0,0x50,0x28,0x14,0x0A,0x04,0x86,0x3D,0x00,0x90,0x87,0x80, // 'g'
0x80,0x40,0x20,0x17,0x8C,0x24,0x0A,0x05,0x02,0x81,0x40,0xA0,0x50,0x20, // 'h'
0xA2,0xAA,0xAA, // 'i'
0x22,0x02,0x22,0x22,0x22,0x22,0x22,0xC0, // 'j'
0x80,0x40,0x20,0x10,0x48,0x44,0x42,0x41,0xC0,0x90,0x44,0x21,0x10,0x40, // 'k'
0xAA,0xAA,0xAA, // 'l'
0xBC,0xF3,0x1C,0x68,0x20,0xA0,0x82,0x82,0x0A,0x08,0x28,0x20,0xA0,0x82,0x82,0x08, // 'm'
0xBC,0x61,0x20,0x50,0x28,0x14,0x0A,0x05,0x02,0x81,0x00, // 'n'
0x3C,0x21,0x20,0x50,0x28,0x14,0x0A,0x04,0x84,0x3C,0x00, // 'o'
0xBC,0x61,0x20,0x50,0x28,0x14,0x0A,0x05,0x84,0xBC,0x40,0x20,0x10,0x00, // 'p'
0x3D,0x21,0xA0,0x50,0x28,0x14,0x0A,0x04,0x86,0x3D,0x00,0x80,0x40,0x20, // 'q'
0xBB,0x08,0x20,0x82,0x08,0x20,0x80, // 'r'
0x7C,0x82,0x80,0xC0,0x78,0x06,0x02,0x82,0x7C, // 's'
0x41,0x0F,0x90,0x41,0x04,0x10,0x41,0x03,0x80, // 't'
0x81,0x40,0xA0,0x50,0x28,0x14,0x0A,0x04,0x86,0x3D,0x00, // 'u'
0x80,0x90,0x11,0x04,0x20,0x82,0x20,0x44,0x05,0x00,0xE0,0x08,0x00, // 'v'
0x82,0x0A,0x08,0x24,0x51,0x11,0x44,0x48,0x90,0xA2,0x82,0x8A,0x04,0x10,0x10,0x40, // 'w'
0xC3,0x21,0x09,0x04,0x81,0x81,0x20,0x90,0x84,0xC3,0x00, // 'x'
0x80,0x90,0x44,0x10,0x84,0x22,0x08,0x81,0x40,0x50,0x0C,0x02,0x00,0x81,0xC0, // 'y'
0xFE,0x02,0x04,0x08,0x10,0x20,0x40,0x80,0xFE, // 'z'
0x18,0x82,0x08,0x20,0x82,0x30,0x20,0x82,0x08,0x20,0x81,0x80, // '{'
0xAA,0xAA,0xAA,0xAA, // '|'
0xC0,0x82,0x08,0x20,0x82,0x06,0x20,0x82,0x08,0x20,0x8C,0x00 // '}'
};
const GFXglyph Dialog_plain_16Glyphs[] = {
// bitmapOffset, width, height, xAdvance, xOffset, yOffset
{ 0, 1, 1, 6, 0, 0 }, // ' '
{ 1, 2, 12, 7, 2, -12 }, // '!'
{ 4, 5, 4, 7, 1, -12 }, // '"'
{ 7, 12, 11, 14, 1, -11 }, // '#'
{ 24, 8, 14, 11, 2, -12 }, // '$'
{ 38, 14, 12, 16, 1, -12 }, // '%'
{ 59, 12, 12, 13, 1, -12 }, // '&'
{ 77, 2, 4, 4, 1, -12 }, // '''
{ 78, 5, 14, 7, 1, -12 }, // '('
{ 87, 5, 14, 7, 1, -12 }, // ')'
{ 96, 8, 8, 9, 1, -12 }, // '*'
{ 104, 10, 9, 14, 2, -9 }, // '+'
{ 116, 3, 4, 6, 1, -2 }, // ','
{ 118, 5, 1, 7, 1, -5 }, // '-'
{ 119, 2, 2, 6, 2, -2 }, // '.'
{ 120, 6, 13, 6, 0, -12 }, // '/'
{ 130, 9, 12, 11, 1, -12 }, // '0'
{ 144, 8, 12, 11, 2, -12 }, // '1'
{ 156, 8, 12, 11, 1, -12 }, // '2'
{ 168, 9, 12, 11, 1, -12 }, // '3'
{ 182, 10, 12, 11, 1, -12 }, // '4'
{ 197, 9, 12, 11, 1, -12 }, // '5'
{ 211, 9, 12, 11, 1, -12 }, // '6'
{ 225, 9, 12, 11, 1, -12 }, // '7'
{ 239, 9, 12, 11, 1, -12 }, // '8'
{ 253, 9, 12, 11, 1, -12 }, // '9'
{ 267, 2, 8, 6, 2, -8 }, // ':'
{ 269, 3, 10, 6, 1, -8 }, // ';'
{ 273, 11, 9, 14, 2, -9 }, // '<'
{ 286, 11, 4, 14, 2, -7 }, // '='
{ 292, 11, 9, 14, 2, -9 }, // '>'
{ 305, 7, 12, 10, 1, -12 }, // '?'
{ 316, 15, 14, 17, 1, -12 }, // '@'
{ 343, 12, 12, 12, 0, -12 }, // 'A'
{ 361, 10, 12, 12, 1, -12 }, // 'B'
{ 376, 10, 12, 12, 1, -12 }, // 'C'
{ 391, 11, 12, 13, 1, -12 }, // 'D'
{ 408, 9, 12, 11, 1, -12 }, // 'E'
{ 422, 8, 12, 10, 1, -12 }, // 'F'
{ 434, 11, 12, 13, 1, -12 }, // 'G'
{ 451, 11, 12, 13, 1, -12 }, // 'H'
{ 468, 2, 12, 6, 2, -12 }, // 'I'
{ 471, 4, 15, 6, 0, -12 }, // 'J'
{ 479, 10, 12, 11, 1, -12 }, // 'K'
{ 494, 8, 12, 10, 1, -12 }, // 'L'
{ 506, 12, 12, 14, 1, -12 }, // 'M'
{ 524, 11, 12, 13, 1, -12 }, // 'N'
{ 541, 12, 12, 14, 1, -12 }, // 'O'
{ 559, 9, 12, 11, 1, -12 }, // 'P'
{ 573, 12, 14, 14, 1, -12 }, // 'Q'
{ 594, 11, 12, 12, 1, -12 }, // 'R'
{ 611, 9, 12, 11, 1, -12 }, // 'S'
{ 625, 10, 12, 10, 0, -12 }, // 'T'
{ 640, 11, 12, 13, 1, -12 }, // 'U'
{ 657, 12, 12, 12, 0, -12 }, // 'V'
{ 675, 16, 12, 18, 1, -12 }, // 'W'
{ 699, 10, 12, 12, 1, -12 }, // 'X'
{ 714, 10, 12, 10, 0, -12 }, // 'Y'
{ 729, 11, 12, 13, 1, -12 }, // 'Z'
{ 746, 4, 14, 7, 1, -12 }, // '['
{ 753, 6, 13, 6, 0, -12 }, // '\'
{ 763, 4, 14, 7, 2, -12 }, // ']'
{ 770, 11, 4, 14, 2, -12 }, // '^'
{ 776, 9, 1, 9, 0, 3 }, // '_'
{ 778, 5, 3, 9, 1, -13 }, // '`'
{ 780, 8, 9, 10, 1, -9 }, // 'a'
{ 789, 9, 12, 11, 1, -12 }, // 'b'
{ 803, 8, 9, 10, 1, -9 }, // 'c'
{ 812, 9, 12, 11, 1, -12 }, // 'd'
{ 826, 8, 9, 10, 1, -9 }, // 'e'
{ 835, 6, 12, 7, 1, -12 }, // 'f'
{ 844, 9, 12, 11, 1, -9 }, // 'g'
{ 858, 9, 12, 11, 1, -12 }, // 'h'
{ 872, 2, 12, 4, 1, -12 }, // 'i'
{ 875, 4, 15, 4, -1, -12 }, // 'j'
{ 883, 9, 12, 10, 1, -12 }, // 'k'
{ 897, 2, 12, 4, 1, -12 }, // 'l'
{ 900, 14, 9, 16, 1, -9 }, // 'm'
{ 916, 9, 9, 11, 1, -9 }, // 'n'
{ 927, 9, 9, 11, 1, -9 }, // 'o'
{ 938, 9, 12, 11, 1, -9 }, // 'p'
{ 952, 9, 12, 11, 1, -9 }, // 'q'
{ 966, 6, 9, 8, 1, -9 }, // 'r'
{ 973, 8, 9, 10, 1, -9 }, // 's'
{ 982, 6, 11, 7, 0, -11 }, // 't'
{ 991, 9, 9, 11, 1, -9 }, // 'u'
{ 1002, 11, 9, 10, 0, -9 }, // 'v'
{ 1015, 14, 9, 14, 0, -9 }, // 'w'
{ 1031, 9, 9, 11, 1, -9 }, // 'x'
{ 1042, 10, 12, 10, 0, -9 }, // 'y'
{ 1057, 8, 9, 10, 1, -9 }, // 'z'
{ 1066, 6, 15, 11, 2, -12 }, // '{'
{ 1078, 2, 16, 6, 2, -12 }, // '|'
{ 1082, 6, 15, 11, 2, -12 } // '}'
};
const GFXfont Dialog_plain_16 = {
(uint8_t *)Dialog_plain_16Bitmaps,(GFXglyph *)Dialog_plain_16Glyphs,0x20, 0x7E, 19};

View File

@@ -0,0 +1,199 @@
// Created by http://oleddisplay.squix.ch/ Consider a donation
// In case of problems make sure that you are using the font file with the correct version!
const uint8_t Special_Elite_Regular_30Bitmaps[] = {
// Bitmap Data:
0x00, // ' '
0x63,0xBD,0xE7,0x39,0xCE,0x73,0x98,0xC6,0x31,0x84,0x01,0x39,0xE6,0x00, // '!'
0x67,0x73,0x99,0xCC,0xE6,0x23,0x19,0x8C,0x44, // '"'
0x03,0x8C,0x03,0x9C,0x03,0x18,0x03,0x18,0x03,0x18,0x06,0x10,0x06,0x30,0x3E,0xF4,0x7F,0xFE,0x0C,0x60,0x0C,0x60,0x0C,0x40,0xFF,0xFC,0xFF,0xE8,0x10,0x80,0x31,0x80,0x31,0x80,0x71,0x80,0x63,0x00,0x63,0x00,0x63,0x00, // '#'
0x02,0x00,0x06,0x00,0x0C,0x00,0x38,0x00,0x30,0x00,0x60,0x00,0xC0,0x01,0x80,0x1F,0xE0,0xF6,0xF1,0x8C,0x62,0x19,0xCC,0x33,0x98,0x46,0x30,0x80,0x39,0x00,0x3F,0x00,0x0F,0xE0,0x08,0xE0,0x10,0x6E,0x20,0xDE,0x61,0xB0,0xC3,0x61,0x8C,0x73,0x38,0x7F,0xE0,0x3E,0x00,0x18,0x00,0x30,0x00,0x60,0x00,0xC0,0x01,0x80,0x03,0x00,0x06,0x00, // '$'
0x00,0x01,0xC0,0x00,0x78,0x00,0x1F,0x00,0x07,0xC0,0x01,0xF0,0x00,0xFE,0x07,0xFD,0x81,0xFC,0x70,0x31,0x8C,0x0E,0x33,0x01,0x86,0x60,0x31,0xD8,0x06,0x32,0x00,0xFC,0xC0,0x0F,0x10,0x00,0x06,0x00,0x01,0xCE,0x00,0x33,0xE0,0x0C,0xC4,0x01,0xB0,0xC0,0x66,0x18,0x0C,0xC7,0x03,0x18,0xC0,0x63,0xF0,0x18,0x3C,0x03,0x00,0x00,0xC0,0x00,0x38,0x00,0x06,0x00,0x01,0xC0,0x00,0x38,0x00,0x02,0x00,0x00, // '%'
0x03,0xC0,0x00,0xFC,0x00,0x39,0xC0,0x0E,0x18,0x01,0xC3,0x00,0x18,0xE0,0x03,0x98,0x00,0x36,0x00,0x07,0x83,0x81,0xE1,0xF8,0xF6,0x3F,0x38,0xC6,0xCE,0x0C,0x81,0x81,0xB0,0x20,0x1E,0x06,0x03,0x82,0xE0,0x30,0xCC,0x0F,0x19,0xFF,0x7F,0x1F,0xFF,0xC1,0xF8,0x70, // '&'
0x6E,0x66,0x66,0x62, // '''
0x18,0xE3,0x9C,0x71,0x86,0x30,0xC3,0x0C,0x30,0xC3,0x0C,0x30,0xC3,0x06,0x18,0x60,0x83,0x04,0x18, // '('
0xE1,0xC1,0xC3,0x83,0x87,0x06,0x0E,0x1C,0x18,0x70,0x60,0xC1,0x83,0x0C,0x18,0x30,0x40,0xC3,0x06,0x18,0x70,0x40, // ')'
0x18,0x60,0x38,0xC0,0x73,0x80,0x66,0x00,0x78,0x1F,0xFF,0xBF,0xFF,0x03,0xC0,0x0D,0x80,0x39,0x80,0x63,0x80,0xC7,0x00,0x04,0x00, // '*'
0x02,0x00,0x0C,0x00,0x30,0x00,0xC0,0x03,0x03,0xFF,0xCF,0xFF,0x80,0xC0,0x03,0x00,0x0C,0x00,0x30,0x01,0xC0,0x03,0x00, // '+'
0x08,0x3E,0x1F,0x0F,0xC7,0xF3,0xF9,0xF8,0x5C,0x0E,0x0E,0x0E,0x0F,0x0F,0x03,0x00, // ','
0xCA,0x94,0xBF,0xFE,0xFF,0xFE,0x00,0x0C, // '-'
0x7C,0xF8,0xFE,0xFE,0xFC,0xFC,0x78, // '.'
0x00,0x06,0x00,0x0E,0x00,0x1C,0x00,0x1C,0x00,0x38,0x00,0x30,0x00,0x70,0x00,0x60,0x00,0xE0,0x00,0xC0,0x01,0xC0,0x01,0x80,0x03,0x00,0x03,0x00,0x06,0x00,0x0E,0x00,0x0C,0x00,0x18,0x00,0x38,0x00,0x38,0x00,0x70,0x00,0xE0,0x00,0xE0,0x00,0xC0,0x00, // '/'
0x01,0x00,0x1F,0xE0,0x3C,0x70,0x70,0x38,0x60,0x18,0x60,0x0C,0xC0,0x0C,0xC0,0x04,0x80,0x04,0xC0,0x06,0x80,0x04,0x80,0x06,0x80,0x0C,0xC0,0x0E,0xC0,0x0C,0xC0,0x0C,0xC0,0x1C,0x60,0x1C,0x70,0x30,0x3F,0xF0,0x1F,0xE0,0x07,0xC0, // '0'
0x7F,0x80,0x7F,0xC0,0x12,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x80,0x01,0x80,0x00,0xC0,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x80,0x00,0xC0,0x10,0xF3,0x9F,0xFF,0xEF,0xFF,0xF0, // '1'
0x1F,0xE0,0xF0,0xC1,0x00,0xC6,0x00,0xCE,0x01,0x9E,0x07,0x3C,0x0E,0x00,0x38,0x00,0xE0,0x07,0x80,0x3E,0x01,0xF0,0x03,0x80,0x0E,0x00,0x38,0x00,0x60,0x00,0xFE,0x0D,0xEF,0x1B,0x8F,0xF6,0x07,0x84,0x00,0x00, // '2'
0x01,0xF8,0x7F,0xF1,0xC0,0xC3,0x03,0x82,0x0C,0x0C,0x30,0x00,0xE0,0x03,0xC0,0x0F,0xC0,0x37,0xE0,0x60,0xE0,0x00,0xC0,0x00,0xC0,0x01,0x98,0x03,0x78,0x06,0xF0,0x1D,0xC0,0x39,0x81,0xE3,0xFF,0x83,0xFF,0x00,0xF0,0x00, // '3'
0x00,0x38,0x00,0x1E,0x00,0x0F,0x80,0x03,0x60,0x01,0x98,0x00,0xE6,0x00,0x71,0x80,0x38,0x60,0x1C,0x18,0x07,0x06,0x03,0x81,0x81,0xC0,0x60,0x70,0x18,0x3F,0xFF,0xE7,0xFF,0xF8,0x00,0x60,0x00,0x18,0x00,0x0E,0x00,0x0F,0xF8,0x07,0xFE,0x01,0x3B,0x00, // '4'
0x30,0x20,0xFF,0xE1,0x8F,0x03,0x00,0x02,0x00,0x0E,0x00,0x0C,0x00,0x3B,0xE0,0x7F,0xE0,0xF0,0xE0,0xC0,0xE0,0x00,0xE0,0x00,0xC0,0x01,0x9C,0x03,0x78,0x06,0x70,0x18,0xE0,0x70,0xE1,0xC1,0xFF,0x00,0xFC,0x00, // '5'
0x01,0xF0,0x0F,0xF8,0x0E,0x1C,0x18,0x1E,0x30,0x3C,0x70,0x1C,0x60,0x00,0x60,0x00,0x67,0xC0,0x6F,0xF8,0x78,0x3C,0xF0,0x1E,0xE0,0x0E,0x60,0x06,0x60,0x06,0x60,0x0E,0x30,0x0E,0x38,0x1E,0x3C,0x7C,0x0F,0xF8,0x07,0xC0, // '6'
0x03,0xC0,0x1F,0xFB,0x8F,0xFF,0xCE,0x3F,0xE7,0x00,0x73,0x00,0x33,0x80,0x38,0x80,0x18,0x00,0x18,0x00,0x1C,0x00,0x0C,0x00,0x0E,0x00,0x06,0x00,0x07,0x00,0x03,0x00,0x01,0x80,0x01,0xC0,0x00,0xE0,0x00,0xF0,0x00,0x30,0x00,0x38,0x00,0x18,0x00,0x04,0x00, // '7'
0x03,0x00,0x1F,0xE0,0x3C,0xF0,0x70,0x38,0xE0,0x1C,0xE0,0x0C,0xE0,0x0C,0x60,0x18,0x70,0x18,0x3F,0xF8,0x3F,0xF0,0x78,0x70,0xE0,0x1C,0xC0,0x1C,0xC0,0x0C,0xC0,0x0E,0xC0,0x0C,0xE0,0x1C,0xF0,0x3C,0xFF,0xF8,0x7F,0xF0,0x0F,0x80, // '8'
0x0F,0xE0,0x1C,0xF0,0x30,0x38,0x60,0x10,0x60,0x0C,0x60,0x0C,0xC0,0x0E,0x60,0x0E,0x60,0x1E,0x78,0x1E,0x1F,0xFE,0x0F,0xEE,0x01,0x0E,0x00,0x0C,0x30,0x0C,0x78,0x18,0x68,0x18,0x7C,0xF0,0x3F,0xE0,0x1F,0xC0,0x0F,0x00, // '9'
0x20,0x78,0xFC,0xE8,0xFC,0x78,0x10,0x00,0x00,0x7C,0xF8,0xFE,0xFE,0xFC,0xFC,0x78, // ':'
0x10,0x1E,0x1F,0x8F,0x87,0xE1,0xE0,0x40,0x00,0x08,0x3F,0x1F,0x8F,0xC7,0xF3,0xF9,0xF8,0x5C,0x0E,0x0E,0x0E,0x0F,0x0F,0x03,0x00, // ';'
0x00,0xE0,0x1E,0x03,0xC0,0xF0,0x3E,0x07,0x80,0xF0,0x0E,0x00,0x70,0x03,0xE0,0x0F,0x00,0x3E,0x00,0xE0, // '<'
0xFF,0xFE,0xFF,0xFE,0x7F,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x5E,0xFF,0xFE,0xFF,0xFE, // '='
0xE0,0x0F,0x00,0x78,0x01,0xE0,0x0F,0x00,0x3C,0x01,0xE0,0x0E,0x01,0xC0,0xF8,0x3E,0x0F,0x80,0xE0,0x00, // '>'
0x0E,0x01,0xFC,0x1C,0x79,0xC0,0x4E,0x03,0x78,0x19,0xE0,0xCF,0x06,0x78,0x60,0x0F,0x01,0xE0,0x1E,0x00,0xE0,0x07,0x00,0x38,0x00,0xC0,0x00,0x00,0x00,0x03,0x00,0x3C,0x00,0xF0,0x07,0x00, // '?'
0x07,0xF8,0x01,0xE3,0x80,0x70,0x18,0x1C,0x01,0x83,0x0C,0x30,0xC7,0xFB,0x18,0xC7,0x63,0x38,0xCC,0xE6,0x19,0x9D,0xC2,0x33,0xB8,0xC6,0x77,0x18,0xC6,0xE7,0x30,0xCF,0xFC,0x18,0xE7,0x31,0x80,0x04,0x38,0x01,0x83,0x80,0xE0,0x1F,0x78,0x00,0xFC,0x00, // '@'
0x01,0xC0,0x00,0xF8,0x00,0x3E,0x00,0x0F,0x80,0x07,0xE0,0x01,0xF8,0x00,0x76,0x00,0x19,0xC0,0x0E,0x70,0x01,0x8C,0x00,0xE3,0x00,0x38,0xC0,0x0E,0x38,0x03,0xFE,0x00,0xFF,0x80,0x7A,0x60,0x1C,0x18,0x07,0x02,0x01,0x81,0xC1,0xF8,0xFE,0xFE,0x3F,0x00, // 'A'
0xFF,0xF0,0x7F,0xFC,0x0F,0x8F,0x03,0x01,0xC1,0x80,0x60,0xC0,0x30,0x60,0x18,0x30,0x1C,0x1C,0x3C,0x0F,0xFE,0x07,0xFF,0x03,0x83,0x81,0x80,0xE0,0xC0,0x38,0x60,0x1C,0x30,0x0E,0x18,0x04,0x0C,0x07,0x0E,0x07,0x0F,0xFF,0x07,0xFE,0x00, // 'B'
0x07,0xCC,0x1F,0xFE,0x3F,0xFE,0x38,0x7E,0x70,0x1E,0x70,0x1E,0x60,0x0E,0x60,0x06,0x60,0x0C,0x60,0x00,0xE0,0x00,0xE0,0x0C,0xE0,0x0E,0x60,0x0E,0x60,0x0E,0x60,0x1C,0x30,0x1C,0x30,0x78,0x1F,0xF8,0x0F,0xF0,0x07,0xC0, // 'C'
0x7F,0xE0,0x7F,0xF8,0x3F,0xFF,0x07,0x83,0x81,0xC0,0xE0,0xE0,0x30,0x70,0x1C,0x38,0x0E,0x1C,0x07,0x0E,0x01,0x87,0x00,0xC3,0x80,0x61,0xC0,0x30,0xE0,0x38,0x70,0x1C,0x30,0x0E,0x18,0x0E,0x0E,0x0F,0x07,0x9F,0x0F,0xFF,0x07,0xFF,0x00, // 'D'
0x0E,0xFE,0x3F,0xFF,0xC7,0xFF,0xB0,0xC0,0x0C,0x10,0x03,0x04,0x00,0xC1,0x06,0x38,0x41,0x04,0x10,0x60,0x07,0xF8,0x01,0x7C,0x00,0x7F,0x80,0x18,0x60,0x06,0x18,0xC1,0x86,0x30,0x60,0x0E,0x18,0x03,0x04,0x00,0xC3,0x80,0x71,0xFF,0xFC,0x7F,0xFE,0x00, // 'E'
0x7F,0xFE,0x3F,0xFF,0xC3,0xC7,0xF0,0x60,0x0C,0x18,0x03,0x86,0x18,0xE1,0x86,0x38,0x61,0x80,0x18,0xE0,0x07,0xF8,0x01,0xFE,0x00,0x7F,0x80,0x18,0x60,0x06,0x18,0x01,0x86,0x00,0x61,0x00,0x18,0x00,0x06,0x00,0x07,0xE0,0x03,0xFC,0x00,0xFF,0x00,0x00, // 'F'
0x07,0xC4,0x07,0xFF,0x03,0xC7,0xC0,0xE0,0x70,0x70,0x1C,0x18,0x03,0x86,0x00,0xC1,0x80,0x10,0x60,0x00,0x38,0x00,0x0E,0x03,0xF1,0x80,0xFE,0x60,0x1E,0x18,0x03,0x86,0x00,0xE1,0x80,0x38,0x30,0x1E,0x0E,0x07,0x81,0xC7,0xE0,0x3F,0xF8,0x03,0xC6,0x00, // 'G'
0x74,0x23,0x1F,0xC7,0xF1,0xF0,0x7C,0x0C,0x03,0x01,0x80,0x60,0x30,0x0C,0x06,0x01,0x80,0xC0,0x30,0x18,0x06,0x03,0xF9,0xC0,0x7F,0xF8,0x0F,0xE7,0x01,0x80,0x60,0x30,0x0C,0x06,0x01,0x80,0xC0,0x30,0x18,0x06,0x03,0x00,0xC0,0x70,0x18,0x7F,0x9F,0xCF,0xF3,0xFC,0x00,0x10,0x00, // 'H'
0x7F,0xFB,0xFF,0xEF,0xBF,0x01,0xC0,0x07,0x00,0x1C,0x00,0x70,0x01,0xC0,0x07,0x00,0x1C,0x00,0x70,0x00,0xC0,0x07,0x00,0x1C,0x00,0x70,0x01,0xC0,0x07,0x00,0x1C,0x00,0x70,0x3F,0xFE,0xFF,0xF9,0x00,0xC0, // 'I'
0x0F,0xFC,0x0F,0xFE,0x07,0xFE,0x00,0xE0,0x00,0xE0,0x00,0xE0,0x00,0x60,0x00,0x60,0x00,0xE0,0x00,0xE0,0x00,0x60,0x00,0x60,0x00,0xE0,0xE0,0x60,0xF0,0x60,0xF0,0x60,0xF0,0x60,0xE0,0xC0,0xE1,0x80,0x7F,0x80,0x1F,0x00, // 'J'
0xFE,0x3E,0x3F,0xDF,0xC3,0xC3,0x80,0x60,0xC0,0x18,0x60,0x06,0x38,0x01,0x9C,0x00,0x67,0x00,0x1B,0x80,0x07,0xE0,0x01,0xFC,0x00,0x73,0x80,0x18,0xE0,0x06,0x18,0x01,0x83,0x00,0x60,0xC0,0x18,0x10,0x06,0x06,0x03,0x81,0x81,0xF8,0xF8,0x7E,0x3F,0x80, // 'K'
0x02,0x00,0x7F,0xE0,0x3F,0xE0,0x13,0xC0,0x01,0xC0,0x00,0xC0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x0C,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x0C,0x38,0x06,0x1C,0x03,0x0E,0x01,0x87,0x00,0xCF,0xFF,0xE7,0xFF,0xF7,0xFF,0xF0, // 'L'
0x38,0x01,0x07,0xC0,0xFC,0x3C,0x0F,0xC3,0xE0,0xF0,0x3E,0x1F,0x03,0xE0,0xF0,0x1E,0x1F,0x81,0xF1,0xB8,0x13,0x1B,0x81,0xB1,0x90,0x1B,0x13,0x03,0xB1,0x30,0x39,0x11,0x03,0x91,0x30,0x19,0xB1,0x01,0x9F,0x10,0x19,0xF1,0x01,0x1A,0x10,0x78,0xE1,0x0F,0xCE,0x7E,0x7C,0x47,0xC0, // 'M'
0x78,0x3E,0x3F,0x1F,0xE7,0xE3,0xF0,0xF8,0x38,0x1E,0x0E,0x07,0xC3,0x81,0xB0,0xE0,0x6C,0x18,0x19,0x86,0x06,0x61,0x81,0x88,0x40,0x63,0x18,0x18,0x66,0x06,0x19,0x81,0x86,0x40,0x61,0xD0,0x18,0x36,0x06,0x07,0x81,0x81,0xE1,0xFC,0x78,0xFF,0x0C,0x00, // 'N'
0x03,0xF0,0x0F,0xFC,0x0F,0xFF,0x07,0x03,0x87,0x00,0xE3,0x80,0x31,0x80,0x19,0xC0,0x0E,0xE0,0x03,0x70,0x01,0x98,0x00,0xCC,0x00,0x66,0x00,0x33,0x00,0x19,0x80,0x0C,0xE0,0x0C,0x38,0x06,0x1E,0x07,0x0F,0x87,0x03,0xFF,0x80,0xFF,0x80,0x1F,0x00, // 'O'
0x15,0x00,0xFF,0xF0,0x3F,0xF8,0x18,0x1C,0x18,0x0E,0x18,0x0E,0x18,0x0E,0x10,0x0E,0x18,0x0C,0x1C,0xFC,0x1F,0xF8,0x1F,0xE0,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x18,0x00,0x1C,0x00,0x7E,0x00,0xFF,0x00, // 'P'
0x0F,0xE0,0x0F,0xF8,0x0E,0x0E,0x0E,0x01,0x86,0x00,0xC3,0x00,0x61,0x80,0x18,0xC0,0x0C,0xE0,0x06,0x60,0x03,0x10,0x00,0x88,0x00,0xC4,0x00,0x63,0x00,0x31,0x8E,0x18,0x6F,0xD8,0x3F,0xFC,0x1F,0x7C,0x07,0xFC,0x01,0xFE,0x00,0x1E,0x10,0x01,0x98,0x00,0xEC,0x00,0x38, // 'Q'
0x3F,0xFC,0x03,0xFF,0xE0,0x1E,0x0E,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x30,0x0C,0x03,0x00,0xC0,0x70,0x0C,0x1F,0x00,0xFF,0xE0,0x0F,0xFC,0x00,0xE1,0xC0,0x0C,0x0C,0x00,0xC0,0xE0,0x0C,0x0E,0x00,0xC0,0x60,0x0C,0x0E,0x00,0xC0,0x64,0x0F,0x07,0xE7,0xF8,0x7C,0xFF,0x03,0xC0, // 'R'
0x00,0x10,0x3F,0xE0,0xFF,0xE3,0xC1,0xC6,0x03,0x9C,0x03,0x38,0x06,0x30,0x04,0x78,0x00,0x7F,0xC0,0x3F,0xE0,0x01,0xC8,0x01,0xD0,0x01,0xB0,0x03,0x60,0x06,0xC0,0x0D,0xC0,0x7B,0xC1,0xE7,0xFF,0x0F,0xFC,0x00, // 'S'
0xFF,0xFE,0x7F,0xF3,0xB0,0x60,0xD8,0x30,0xEC,0x18,0x76,0x0C,0x1B,0x06,0x0D,0x03,0x04,0x01,0x80,0x00,0xC0,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0xC0,0x00,0xE0,0x03,0xFE,0x03,0xFF,0x01,0xF8,0x00, // 'T'
0xFE,0x7F,0xBF,0x9F,0xE3,0xC3,0xE0,0xE0,0x30,0x30,0x08,0x0C,0x03,0x03,0x00,0xC0,0xC0,0x30,0x30,0x0C,0x0C,0x03,0x03,0x00,0xC0,0xC0,0x30,0x30,0x0C,0x0E,0x03,0x03,0x80,0xC0,0x60,0x30,0x18,0x0C,0x06,0x06,0x01,0xE7,0x80,0x3E,0xC0,0x07,0xE0,0x00, // 'U'
0x00,0x07,0x1F,0xC7,0xFB,0xF8,0xFF,0x1F,0x0F,0x81,0xC0,0xE0,0x18,0x1C,0x03,0x03,0x00,0x60,0xE0,0x0C,0x1C,0x00,0xC3,0x80,0x38,0xE0,0x03,0x1C,0x00,0x63,0x80,0x0C,0x70,0x00,0xCE,0x00,0x19,0x80,0x03,0xF0,0x00,0x7E,0x00,0x0F,0x80,0x00,0xF0,0x00,0x1E,0x00,0x03,0xC0,0x00, // 'V'
0x01,0x21,0xDF,0xFF,0xF9,0xC3,0x8F,0x08,0x70,0xC1,0x0E,0x18,0x01,0xE2,0x04,0x38,0x40,0x85,0x98,0x18,0xB3,0x01,0x16,0x60,0x26,0xEC,0x06,0x99,0x80,0xD1,0xA0,0x1B,0x3C,0x03,0xC7,0x80,0x78,0xF0,0x0F,0x1E,0x00,0xE3,0xC0,0x1C,0x78,0x03,0x87,0x00,0x60,0xC0, // 'W'
0x7E,0x1F,0x3F,0x8F,0xE1,0xC1,0xC0,0x30,0x60,0x06,0x30,0x01,0x8C,0x00,0x36,0x00,0x0F,0x80,0x01,0xE0,0x00,0x70,0x00,0x1C,0x00,0x07,0x00,0x03,0xE0,0x00,0xF8,0x00,0x73,0x00,0x18,0xE0,0x0C,0x18,0x07,0x07,0x03,0xE3,0xFB,0xFC,0xFE,0xFE,0x3F,0x80, // 'X'
0x1C,0x08,0x8F,0xF7,0xFB,0xFE,0xFF,0x0F,0x87,0xC0,0x60,0xE0,0x0E,0x38,0x00,0xC6,0x00,0x1D,0xC0,0x01,0xF8,0x00,0x3E,0x00,0x03,0xC0,0x00,0x70,0x00,0x06,0x00,0x00,0xC0,0x00,0x18,0x00,0x03,0x00,0x00,0x60,0x00,0x0C,0x00,0x03,0x80,0x03,0xFF,0x01,0xFF,0xF0,0x3F,0xFE,0x00, // 'Y'
0xBF,0xF8,0xFF,0xF8,0xC0,0xF8,0xC0,0xF8,0xC0,0xF0,0xC1,0xE0,0xC1,0xE0,0x03,0xC0,0x07,0x80,0x07,0x00,0x0F,0x00,0x0E,0x00,0x3C,0x08,0x1C,0x0C,0x78,0x0E,0xF0,0x0C,0xF0,0x0E,0xF4,0x3C,0xFF,0xFC,0xFF,0xFC,0xFF,0xFC, // 'Z'
0x49,0xFB,0x86,0x0C,0x18,0x30,0x60,0xC1,0xC3,0x06,0x0E,0x18,0x38,0x70,0xC1,0xC3,0x87,0x0E,0x1C,0x30,0x78,0xF8, // '['
0xC0,0x00,0xE0,0x00,0x60,0x00,0x70,0x00,0x30,0x00,0x38,0x00,0x18,0x00,0x1C,0x00,0x0E,0x00,0x0E,0x00,0x07,0x00,0x03,0x00,0x01,0x80,0x01,0x80,0x00,0xC0,0x00,0xC0,0x00,0x60,0x00,0x60,0x00,0x30,0x00,0x38,0x00,0x1C,0x00,0x1C,0x00,0x0E,0x00,0x06, // '\'
0x24,0x7C,0x0C,0x0C,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0E,0x0C,0x7C,0xFC, // ']'
0x0E,0x00,0x78,0x07,0xC0,0x37,0x03,0x18,0x18,0x61,0x83,0x8C,0x0E,0xC0,0x36,0x01,0x80, // '^'
0x00,0x90,0xFF,0xFE,0xFF,0xFC, // '_'
0x80,0xC0,0xF0,0x38,0x0E,0x04, // '`'
0x0F,0xC0,0x1F,0xF0,0x0F,0x1C,0x0F,0x06,0x07,0x81,0x81,0xC0,0xC0,0x03,0xE0,0x3F,0xF0,0x7F,0x18,0x38,0x0C,0x38,0x06,0x18,0x07,0x0E,0x03,0xB3,0xFF,0xF8,0xFE,0x38, // 'a'
0x60,0x00,0x3E,0x00,0x07,0x80,0x00,0x60,0x00,0x18,0x00,0x06,0x00,0x01,0x84,0x00,0x3F,0xE0,0x0F,0xFE,0x07,0x81,0x81,0xC0,0x30,0x30,0x0C,0x1C,0x01,0x87,0x00,0x61,0xC0,0x30,0x20,0x0E,0x1C,0x03,0x07,0x01,0xC0,0xE0,0xE0,0x3F,0xF8,0x0B,0xFC,0x00, // 'b'
0x07,0xE0,0x7F,0xF1,0x7F,0xE3,0xC3,0xE7,0x07,0xCC,0x07,0x98,0x0E,0x70,0x00,0xE0,0x01,0xC0,0x01,0x80,0x63,0x80,0xE3,0x87,0xC3,0xFF,0x03,0xF8,0x00,0x40, // 'c'
0x00,0xE8,0x00,0x7F,0x00,0x0F,0xC0,0x00,0x70,0x00,0x1C,0x00,0x07,0x00,0x61,0xC0,0x7F,0xF0,0x3F,0xFC,0x1E,0x1F,0x07,0x01,0xC1,0x80,0x70,0xE0,0x0C,0x38,0x03,0x0E,0x01,0xC3,0x00,0x70,0x70,0x1C,0x1C,0x07,0x03,0x87,0xC0,0xFF,0xFE,0x0F,0xEF,0x80,0xE0,0x00, // 'd'
0x07,0x80,0x3F,0xC0,0xF3,0xC3,0x80,0xC6,0x00,0x9C,0x01,0x9C,0x47,0x7F,0xFE,0xF0,0x09,0xC0,0x01,0x80,0x03,0x80,0x63,0x81,0xC3,0xFF,0x03,0xFC,0x01,0xC0, // 'e'
0x01,0xF8,0x01,0xFE,0x01,0xEF,0x81,0xC3,0xC0,0xE1,0xF0,0x70,0x70,0x38,0x10,0xFF,0x80,0x7F,0xC0,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x00,0x70,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x06,0x00,0x03,0x80,0x1F,0xFC,0x0F,0xFE,0x07,0x06,0x00, // 'f'
0x00,0x06,0x07,0xEF,0x0F,0xFB,0xC7,0x0F,0xE3,0x03,0xC1,0x80,0xC0,0xC0,0xE0,0x70,0x60,0x18,0x70,0x1F,0xF0,0x1F,0xF0,0x0C,0x00,0x06,0x00,0x03,0xF7,0x01,0xFF,0xF0,0xF0,0x3C,0xE0,0x07,0x60,0x03,0xB8,0x01,0xCF,0x07,0xC3,0xFF,0x80,0x3C,0x00, // 'g'
0xF8,0x00,0x0F,0x00,0x00,0x60,0x00,0x0C,0x00,0x01,0x80,0x00,0x30,0x60,0x06,0x3F,0x00,0xFF,0xE0,0x1F,0x06,0x03,0xC0,0xC0,0x70,0x18,0x0E,0x03,0x01,0xC0,0x60,0x30,0x0C,0x03,0x00,0x80,0x60,0x10,0x1C,0x02,0x03,0x80,0xE1,0x7C,0x7F,0x3F,0x9F,0xE7,0xC1,0x00, // 'h'
0x07,0x00,0x07,0xC0,0x03,0xE0,0x00,0xE0,0x00,0x00,0x00,0x00,0x01,0xFC,0x01,0xFF,0x00,0x11,0x80,0x00,0xC0,0x00,0x60,0x00,0x38,0x00,0x1C,0x00,0x0E,0x00,0x07,0x00,0x03,0x80,0x01,0xC0,0x00,0xE0,0x12,0xFF,0x9F,0xF9,0xE7,0x80,0x20, // 'i'
0x07,0x81,0xF8,0x1F,0x03,0xA0,0x38,0x00,0x0F,0xE1,0xFE,0x01,0xC0,0x18,0x03,0x00,0x60,0x0C,0x01,0x80,0x30,0x06,0x00,0xC0,0x18,0x03,0x00,0x6E,0x0D,0xE1,0xBC,0x37,0x9E,0xF7,0x8F,0xC0,0xE0,0x00, // 'j'
0xF8,0x00,0x0F,0x00,0x00,0x60,0x00,0x0C,0x00,0x01,0x80,0x00,0x30,0x00,0x06,0x0F,0xE0,0x41,0xFC,0x08,0x38,0x01,0x0E,0x00,0x23,0x80,0x06,0xE0,0x00,0xFC,0x00,0x1F,0xC0,0x07,0x9C,0x00,0x61,0xC0,0x1C,0x18,0x07,0x83,0x83,0xFC,0xFE,0x3F,0x9F,0xE0,0x01,0xD8, // 'k'
0xFF,0x00,0x7F,0xC0,0x00,0x60,0x00,0x30,0x00,0x38,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x80,0x00,0xC0,0x00,0x60,0x00,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x80,0x01,0xC0,0x3F,0xFF,0xDF,0xFF,0xE7,0xA8,0xE0, // 'l'
0x01,0x0C,0x0E,0xFF,0xC3,0xFF,0xFC,0x1E,0x7B,0x83,0x8E,0x70,0x61,0xCE,0x0E,0x31,0xC1,0xC6,0x38,0x30,0xC3,0x06,0x18,0x60,0xE3,0x0C,0x1C,0x61,0x83,0x8C,0x70,0xF3,0xEF,0x9F,0x7B,0xF3,0x80,0x1A, // 'm'
0x20,0x70,0x3E,0x7F,0x0F,0xBF,0xC0,0xFC,0x38,0x1E,0x0E,0x07,0x01,0x81,0x80,0x60,0x60,0x38,0x18,0x0E,0x06,0x03,0x81,0x80,0xE0,0x60,0x18,0x18,0x06,0x1F,0x8F,0xEF,0xF3,0xF8,0xF8,0x28, // 'n'
0x01,0xC0,0x0F,0xF0,0x3F,0xF8,0x38,0x3C,0x70,0x0E,0x60,0x0E,0xE0,0x0E,0x60,0x0E,0xE0,0x02,0xE0,0x0E,0xE0,0x0E,0x70,0x1E,0x38,0x3C,0x1F,0xF8,0x0F,0xF0,0x03,0xE0, // 'o'
0x78,0xF0,0x7F,0xFE,0x07,0x83,0x81,0x80,0xC0,0xC0,0x30,0xE0,0x18,0x20,0x04,0x30,0x02,0x1C,0x03,0x06,0x01,0x83,0x00,0xC1,0x80,0xC0,0xF0,0xC0,0x7F,0xE0,0x23,0xC0,0x10,0x00,0x08,0x00,0x04,0x00,0x06,0x00,0x1F,0xE0,0x07,0x60,0x00, // 'p'
0x02,0x00,0x0F,0xEE,0x0F,0xFF,0x0F,0x0F,0x06,0x01,0x87,0x00,0xE3,0x80,0x71,0xC0,0x30,0xE0,0x18,0x30,0x0C,0x18,0x06,0x0E,0x07,0x03,0x87,0x80,0xFF,0xC0,0x3F,0x30,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x07,0xC0,0x07,0xF0, // 'q'
0x00,0x18,0x7E,0x7F,0x3F,0xFF,0x81,0xF9,0xE0,0xF0,0xF0,0x70,0x70,0x38,0x00,0x18,0x00,0x0C,0x00,0x06,0x00,0x03,0x00,0x01,0x80,0x00,0xE0,0x01,0xFE,0x03,0xFD,0x00, // 'r'
0x1F,0x80,0xFF,0xC7,0x3F,0x1C,0x0C,0x60,0x31,0xC0,0x47,0xFC,0x0D,0xFC,0x00,0x3B,0x00,0x66,0x01,0x98,0x06,0x70,0x79,0xFF,0xC7,0xFE,0x10,0x00, // 's'
0x04,0x00,0x0C,0x00,0x0E,0x00,0x0E,0x00,0x0C,0x00,0x0E,0x00,0x7F,0xF0,0xFF,0xF8,0x7F,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x00,0x0E,0x0E,0x0E,0x1E,0x0F,0x1C,0x0F,0x1C,0x07,0xFC,0x07,0xF8,0x01,0xE0, // 't'
0x30,0x02,0x0F,0xC3,0xE0,0x7C,0x3F,0x00,0xC0,0x70,0x0C,0x07,0x00,0xC0,0x70,0x0C,0x07,0x00,0xC0,0x60,0x0C,0x07,0x00,0xC0,0x60,0x0C,0x07,0x00,0xC0,0xE0,0x0C,0x3F,0xC0,0xFF,0xFE,0x07,0xF7,0xE0,0x38,0x1C, // 'u'
0xFF,0x3F,0xDF,0xE7,0xF8,0x70,0x38,0x06,0x06,0x00,0xC0,0xC0,0x1C,0x30,0x01,0x86,0x00,0x30,0xC0,0x07,0x38,0x00,0x66,0x00,0x0D,0xC0,0x01,0xF8,0x00,0x1E,0x00,0x03,0xC0,0x00,0x30,0x00, // 'v'
0x00,0x00,0xE7,0xF7,0xFF,0xBF,0xBE,0xFC,0xB1,0xE3,0x81,0x8F,0x18,0x06,0x78,0xC0,0x32,0x46,0x01,0x9B,0x30,0x0C,0xDB,0x80,0x6E,0xF8,0x03,0xE3,0xC0,0x0F,0x1E,0x00,0x78,0xF0,0x03,0xC7,0x80,0x0C,0x18,0x00, // 'w'
0xFF,0x9F,0xE7,0xF9,0xFE,0x07,0x0E,0x00,0x71,0xC0,0x03,0xB8,0x00,0x1F,0x00,0x00,0xF0,0x00,0x0F,0x00,0x00,0xF0,0x00,0x1F,0x80,0x03,0x9C,0x00,0x70,0xE0,0x3F,0x9F,0xC7,0xF9,0xFE,0x3F,0x0F,0xE0, // 'x'
0x00,0x01,0x1F,0xE7,0xFB,0xFC,0xFE,0x07,0x07,0x00,0xC0,0xC0,0x0C,0x18,0x01,0x87,0x00,0x18,0xC0,0x03,0x38,0x00,0x66,0x00,0x07,0xC0,0x00,0xF0,0x00,0x1E,0x00,0x01,0x80,0x00,0x30,0x01,0x06,0x00,0x79,0xC0,0x1F,0xB0,0x01,0xFE,0x00,0x3F,0x80,0x03,0xE0,0x00,0x38,0x00,0x00, // 'y'
0x7F,0xF8,0xFF,0xE1,0x81,0xC3,0x03,0x06,0x0C,0x0C,0x30,0x00,0xC0,0x03,0x00,0x0C,0x18,0x30,0x30,0xE0,0x63,0xC0,0xE7,0xFF,0xDF,0xFF,0x88,0x3E,0x00, // 'z'
0x08,0x38,0x71,0xC3,0x0E,0x18,0x18,0x10,0x70,0xE7,0x8E,0x0F,0x0E,0x1C,0x30,0x61,0xC3,0x83,0x87,0x07,0x04, // '{'
0xDB,0x6D,0xB6,0xDB,0x6D,0xB6,0xDB,0x6D,0xB0, // '|'
0x41,0xC1,0xC1,0x83,0x83,0x0E,0x18,0x70,0xE0,0xE0,0xE1,0xC7,0x9C,0x38,0x30,0x60,0x61,0xC3,0x8E,0x1C,0x30 // '}'
};
const GFXglyph Special_Elite_Regular_30Glyphs[] = {
// bitmapOffset, width, height, xAdvance, xOffset, yOffset
{ 0, 1, 1, 10, 0, 0 }, // ' '
{ 1, 5, 21, 9, 2, -21 }, // '!'
{ 15, 9, 8, 12, 1, -21 }, // '"'
{ 24, 16, 21, 18, 1, -21 }, // '#'
{ 66, 15, 34, 17, 1, -28 }, // '$'
{ 130, 19, 32, 21, 1, -26 }, // '%'
{ 206, 19, 21, 21, 1, -21 }, // '&'
{ 256, 4, 8, 7, 1, -21 }, // '''
{ 260, 6, 25, 9, 2, -23 }, // '('
{ 279, 7, 25, 9, 1, -23 }, // ')'
{ 301, 15, 13, 17, 1, -21 }, // '*'
{ 326, 14, 13, 16, 1, -17 }, // '+'
{ 349, 9, 14, 11, 1, -8 }, // ','
{ 365, 16, 4, 20, 2, -12 }, // '-'
{ 373, 8, 7, 11, 2, -7 }, // '.'
{ 380, 16, 24, 18, 1, -23 }, // '/'
{ 428, 16, 22, 19, 2, -22 }, // '0'
{ 472, 17, 21, 18, 1, -21 }, // '1'
{ 517, 15, 21, 18, 2, -20 }, // '2'
{ 557, 15, 22, 18, 1, -21 }, // '3'
{ 599, 18, 21, 19, 0, -21 }, // '4'
{ 647, 15, 21, 17, 1, -21 }, // '5'
{ 687, 16, 21, 19, 1, -21 }, // '6'
{ 729, 17, 23, 18, 0, -22 }, // '7'
{ 778, 16, 22, 19, 2, -22 }, // '8'
{ 822, 16, 21, 19, 1, -21 }, // '9'
{ 864, 8, 16, 11, 2, -16 }, // ':'
{ 880, 9, 22, 11, 1, -16 }, // ';'
{ 905, 12, 13, 15, 1, -17 }, // '<'
{ 925, 16, 9, 20, 2, -15 }, // '='
{ 943, 12, 13, 15, 2, -17 }, // '>'
{ 963, 13, 22, 15, 1, -22 }, // '?'
{ 999, 19, 20, 21, 1, -20 }, // '@'
{ 1047, 18, 21, 18, 0, -21 }, // 'A'
{ 1095, 17, 21, 19, 1, -21 }, // 'B'
{ 1140, 16, 21, 18, 1, -21 }, // 'C'
{ 1182, 17, 21, 20, 1, -21 }, // 'D'
{ 1227, 18, 21, 20, 1, -21 }, // 'E'
{ 1275, 18, 21, 19, 1, -21 }, // 'F'
{ 1323, 18, 21, 19, 1, -21 }, // 'G'
{ 1371, 19, 22, 21, 1, -21 }, // 'H'
{ 1424, 14, 22, 16, 1, -21 }, // 'I'
{ 1463, 16, 21, 17, 1, -21 }, // 'J'
{ 1505, 18, 21, 18, 1, -21 }, // 'K'
{ 1553, 17, 22, 19, 1, -22 }, // 'L'
{ 1600, 20, 21, 22, 1, -21 }, // 'M'
{ 1653, 18, 21, 20, 1, -21 }, // 'N'
{ 1701, 17, 22, 20, 1, -21 }, // 'O'
{ 1748, 16, 21, 18, 1, -21 }, // 'P'
{ 1790, 17, 24, 19, 1, -21 }, // 'Q'
{ 1841, 20, 21, 20, 0, -21 }, // 'R'
{ 1894, 15, 21, 19, 2, -21 }, // 'S'
{ 1934, 17, 21, 19, 1, -21 }, // 'T'
{ 1979, 18, 21, 20, 1, -21 }, // 'U'
{ 2027, 19, 22, 19, 0, -22 }, // 'V'
{ 2080, 19, 21, 20, 0, -21 }, // 'W'
{ 2130, 18, 21, 18, 0, -21 }, // 'X'
{ 2178, 19, 22, 18, -1, -22 }, // 'Y'
{ 2231, 16, 21, 19, 2, -21 }, // 'Z'
{ 2273, 7, 25, 10, 3, -23 }, // '['
{ 2295, 16, 24, 18, 1, -23 }, // '\'
{ 2343, 8, 25, 10, 0, -23 }, // ']'
{ 2368, 13, 10, 13, 0, -21 }, // '^'
{ 2385, 16, 3, 21, 4, 3 }, // '_'
{ 2391, 8, 6, 8, 0, -23 }, // '`'
{ 2397, 17, 15, 18, 1, -15 }, // 'a'
{ 2429, 18, 21, 18, -1, -21 }, // 'b'
{ 2477, 15, 16, 17, 1, -15 }, // 'c'
{ 2507, 18, 22, 19, 1, -21 }, // 'd'
{ 2557, 15, 16, 17, 1, -15 }, // 'e'
{ 2587, 17, 22, 15, 1, -21 }, // 'f'
{ 2634, 17, 22, 18, 1, -15 }, // 'g'
{ 2681, 19, 21, 20, 0, -20 }, // 'h'
{ 2731, 17, 21, 18, 1, -20 }, // 'i'
{ 2776, 11, 27, 13, 0, -20 }, // 'j'
{ 2814, 19, 21, 20, 0, -20 }, // 'k'
{ 2864, 17, 21, 17, 0, -20 }, // 'l'
{ 2909, 19, 16, 21, 1, -15 }, // 'm'
{ 2947, 18, 16, 20, 1, -15 }, // 'n'
{ 2983, 16, 16, 19, 1, -15 }, // 'o'
{ 3015, 17, 21, 19, 0, -14 }, // 'p'
{ 3060, 17, 21, 18, 1, -15 }, // 'q'
{ 3105, 17, 15, 18, 1, -15 }, // 'r'
{ 3137, 14, 16, 17, 1, -15 }, // 's'
{ 3165, 16, 22, 16, 0, -21 }, // 't'
{ 3209, 20, 16, 20, 0, -15 }, // 'u'
{ 3249, 19, 15, 19, 0, -14 }, // 'v'
{ 3285, 21, 15, 21, 0, -15 }, // 'w'
{ 3325, 20, 15, 21, 0, -14 }, // 'x'
{ 3363, 19, 22, 19, 0, -15 }, // 'y'
{ 3416, 15, 15, 17, 1, -14 }, // 'z'
{ 3445, 7, 24, 9, 1, -22 }, // '{'
{ 3466, 3, 23, 9, 3, -22 }, // '|'
{ 3475, 7, 24, 9, 1, -22 } // '}'
};
const GFXfont Special_Elite_Regular_30 = {
(uint8_t *)Special_Elite_Regular_30Bitmaps,(GFXglyph *)Special_Elite_Regular_30Glyphs,0x20, 0x7E, 31};

View File

@@ -0,0 +1,199 @@
// Created by http://oleddisplay.squix.ch/ Consider a donation
// In case of problems make sure that you are using the font file with the correct version!
const uint8_t DSEG14_Classic_Mini_Regular_40Bitmaps[] = {
// Bitmap Data:
0x00, // ' '
0x00, // '!'
0xC0,0x01,0xC0,0x03,0xC0,0x07,0x81,0xEF,0x03,0xDE,0x07,0xBC,0x0F,0x78,0x1E,0xF0,0x3D,0xE0,0x7B,0xC0,0xF7,0x81,0xEF,0x01,0xDE,0x03,0x38,0x02,0x60,0x00, // '"'
0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '#'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xC0,0xE0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x03,0xC0,0x03,0xC0,0xF0,0x00,0xF0,0x3C,0x00,0x3C,0x0F,0x00,0x0F,0x03,0xC0,0x03,0xC0,0xF0,0x00,0xF0,0x3C,0x00,0x3C,0x0F,0x00,0x0F,0x03,0xC0,0x03,0xC0,0x70,0x00,0xF0,0x18,0x00,0x38,0x02,0x00,0x0C,0x7C,0x3F,0x00,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x01,0xF0,0xFC,0x60,0x00,0x80,0x38,0x00,0x60,0x1E,0x00,0x1C,0x07,0x80,0x0F,0x01,0xE0,0x03,0xC0,0x78,0x00,0xF0,0x1E,0x00,0x3C,0x07,0x80,0x0F,0x01,0xE0,0x03,0xC0,0x78,0x00,0xF0,0x1E,0x00,0x3C,0x07,0x80,0x0F,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x07,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // '$'
0xC0,0x00,0x00,0x38,0x00,0x00,0x0F,0x00,0x00,0x03,0xC8,0x00,0x80,0xF2,0x00,0x60,0x3C,0xC0,0x18,0x0F,0x30,0x0E,0x03,0xCE,0x03,0x80,0xF3,0x80,0xE0,0x3C,0xE0,0x38,0x0F,0x38,0x0C,0x03,0xC6,0x03,0x00,0xF0,0x80,0x80,0x3C,0x00,0x00,0x0E,0x00,0x00,0x03,0x1F,0x0F,0xC0,0x0F,0xE3,0xF8,0x03,0xF8,0xFE,0x00,0x7C,0x3F,0x18,0x00,0x00,0x0E,0x00,0x00,0x07,0x80,0x20,0x21,0xE0,0x18,0x0C,0x78,0x0E,0x03,0x1E,0x03,0x80,0xE7,0x80,0xE0,0x39,0xE0,0x38,0x0E,0x78,0x0C,0x03,0x9E,0x03,0x00,0x67,0x80,0x80,0x19,0xE0,0x20,0x02,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x00,0xC0, // '%'
0xFF,0xFF,0xC1,0xFF,0xFF,0xC1,0xFF,0xFF,0x01,0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x40,0x08,0x01,0x80,0x18,0x03,0x00,0x30,0x0E,0x00,0x70,0x1C,0x00,0xE0,0x38,0x01,0xC0,0x70,0x03,0x80,0xC0,0x03,0x01,0x80,0x02,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x00,0x07,0x00,0x00,0x1E,0x04,0x04,0x3C,0x18,0x0C,0x78,0x70,0x18,0xF0,0xE0,0x39,0xE1,0xC0,0x73,0xC3,0x80,0xE7,0x86,0x01,0xCF,0x0C,0x01,0x9E,0x10,0x03,0x3C,0x20,0x02,0x78,0x00,0x00,0xF0,0x00,0x01,0xE3,0xFF,0xF9,0x8F,0xFF,0xF8,0x3F,0xFF,0xF8,0x7F,0xFF,0xE0, // '&'
0xF7,0xBD,0xEF,0x7B,0xDE,0xF3,0x98,0x40, // '''
0x26,0x6E,0xEE,0xEC,0xC8,0x00,0x00,0x00,0x00,0x8C,0xCE,0xEE,0xE6,0x62, // '('
0x88,0xCC,0xEE,0xEE,0x62,0x00,0x00,0x00,0x00,0x26,0xEE,0xEE,0xCC,0x88, // ')'
0x11,0xE1,0x01,0x1E,0x30,0x19,0xE3,0x01,0x9E,0x70,0x1D,0xE7,0x01,0xDE,0x70,0x1D,0xE7,0x01,0xDE,0x60,0x0D,0xE6,0x00,0x4E,0x40,0x00,0xC0,0x00,0x04,0x00,0x3E,0x1F,0x87,0xF1,0xFC,0x7F,0x1F,0xC3,0xE1,0xF8,0x00,0x40,0x00,0x0C,0x00,0x04,0xE4,0x00,0xDE,0x60,0x1D,0xE6,0x01,0xDE,0x70,0x1D,0xE7,0x01,0xDE,0x70,0x19,0xE7,0x01,0x9E,0x30,0x11,0xE3,0x01,0x1E,0x10, // '*'
0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x0E,0x00,0x00,0xC0,0x00,0x04,0x00,0x3E,0x1F,0x87,0xF1,0xFC,0x7F,0x1F,0xC3,0xE1,0xF8,0x00,0x40,0x00,0x0C,0x00,0x00,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00, // '+'
0x26,0xEE,0xEE,0xCC,0x88, // ','
0x3E,0x1F,0x87,0xF1,0xFC,0x7F,0x1F,0xC3,0xE1,0xF8, // '-'
0x67,0xBD,0xE6,0x00, // '.'
0x00,0x08,0x00,0x60,0x01,0x80,0x0E,0x00,0x38,0x00,0xE0,0x03,0x80,0x0C,0x00,0x30,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x18,0x00,0xE0,0x03,0x80,0x0E,0x00,0x38,0x00,0xC0,0x03,0x00,0x08,0x00,0x20,0x00, // '/'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x02,0x7B,0xC0,0x01,0x9E,0xF0,0x00,0x67,0xBC,0x00,0x39,0xEF,0x00,0x0E,0x7B,0xC0,0x03,0x9E,0xF0,0x00,0xE7,0xBC,0x00,0x31,0xEF,0x00,0x0C,0x7B,0xC0,0x02,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x80,0x07,0xBC,0x60,0x01,0xEF,0x38,0x00,0x7B,0xCE,0x00,0x1E,0xF3,0x80,0x07,0xBC,0xE0,0x01,0xEF,0x30,0x00,0x7B,0xCC,0x00,0x1E,0xF2,0x00,0x07,0xBC,0x80,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // '0'
0x67,0xBD,0xEF,0x7B,0xDE,0xF7,0xBD,0xEF,0x79,0xC6,0x00,0x0C,0xEF,0x7B,0xDE,0xF7,0xBD,0xEF,0x7B,0xDE,0xF3,0x00, // '1'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x80,0x1F,0xFF,0xCC,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x00,0xE0,0x7C,0x3F,0x18,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x31,0xF0,0xFC,0x0E,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0x80,0x00,0x00,0xC7,0xFF,0xF0,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // '2'
0xFF,0xFF,0xC1,0xFF,0xFF,0xC1,0xFF,0xFF,0x01,0xFF,0xFC,0xC0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x38,0xF8,0x7E,0x33,0xF8,0xFE,0x07,0xF1,0xFC,0x07,0xC3,0xF1,0x80,0x00,0x07,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE3,0xFF,0xF9,0x8F,0xFF,0xF8,0x3F,0xFF,0xF8,0x7F,0xFF,0xE0, // '3'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEE,0x00,0x00,0x3B,0x1F,0x0F,0xC6,0x0F,0xE3,0xF8,0x03,0xF8,0xFE,0x00,0x7C,0x3F,0x18,0x00,0x00,0x0E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x00,0xC0, // '4'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xC0,0xE0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x38,0x00,0x00,0x0C,0x7C,0x3F,0x00,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x01,0xF0,0xFC,0x60,0x00,0x00,0x38,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x07,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // '5'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xC0,0xE0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x38,0x00,0x00,0x0C,0x7C,0x3F,0x00,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x31,0xF0,0xFC,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // '6'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x00,0x00,0x38,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x03,0x00, // '7'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x7C,0x3F,0x18,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x31,0xF0,0xFC,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // '8'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x7C,0x3F,0x18,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x01,0xF0,0xFC,0x60,0x00,0x00,0x38,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x07,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // '9'
0xF7,0xBD,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x67,0xBD,0xEF,0x00, // ':'
0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // ';'
0x00,0x01,0x00,0x00,0x30,0x00,0x03,0x00,0x00,0x70,0x00,0x07,0x00,0x00,0x70,0x00,0x07,0x00,0x00,0x60,0x00,0x06,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0xC0,0x00,0x1C,0x00,0x01,0xC0,0x00,0x1C,0x00,0x01,0xC0,0x00,0x18,0x00,0x01,0x80,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x87,0xFF,0xFC,0xFF,0xFF,0xEF,0xFF,0xFC, // '<'
0x3E,0x1F,0x87,0xF1,0xFC,0x7F,0x1F,0xC3,0xE1,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x87,0xFF,0xFC,0xFF,0xFF,0xEF,0xFF,0xFC, // '='
0x10,0x00,0x01,0x00,0x00,0x18,0x00,0x01,0x80,0x00,0x1C,0x00,0x01,0xC0,0x00,0x1C,0x00,0x01,0xC0,0x00,0x0C,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x60,0x00,0x06,0x00,0x00,0x70,0x00,0x07,0x00,0x00,0x70,0x00,0x07,0x00,0x00,0x30,0x00,0x03,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x87,0xFF,0xFC,0xFF,0xFF,0xEF,0xFF,0xFC, // '>'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x00,0x3F,0x18,0x00,0x0F,0xE0,0x00,0x03,0xF8,0x00,0x00,0xFC,0x00,0x00,0x80,0x00,0x00,0x60,0x00,0x00,0x1C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00, // '?'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x00,0x3F,0x18,0x00,0x0F,0xE0,0x00,0x03,0xF8,0x30,0x00,0xFC,0x6E,0x00,0x80,0x3B,0xC0,0x60,0x1E,0xF0,0x1C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // '@'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x7C,0x3F,0x18,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x31,0xF0,0xFC,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC0,0x00,0x03,0x00, // 'A'
0xFF,0xFF,0xC1,0xFF,0xFF,0xC1,0xFF,0xFF,0x01,0xFF,0xFC,0xC0,0x00,0x03,0xC0,0x00,0x07,0x80,0x78,0x0F,0x00,0xF0,0x1E,0x01,0xE0,0x3C,0x03,0xC0,0x78,0x07,0x80,0xF0,0x0F,0x01,0xE0,0x1E,0x03,0xC0,0x3C,0x07,0x80,0x78,0x0F,0x00,0x70,0x1E,0x00,0xC0,0x3C,0x00,0x80,0x38,0x00,0x7E,0x30,0x00,0xFE,0x00,0x01,0xFC,0x00,0x03,0xF1,0x80,0x10,0x07,0x00,0x60,0x1E,0x00,0xE0,0x3C,0x03,0xC0,0x78,0x07,0x80,0xF0,0x0F,0x01,0xE0,0x1E,0x03,0xC0,0x3C,0x07,0x80,0x78,0x0F,0x00,0xF0,0x1E,0x01,0xE0,0x3C,0x03,0xC0,0x78,0x00,0x00,0xF0,0x00,0x01,0xE3,0xFF,0xF9,0x8F,0xFF,0xF8,0x3F,0xFF,0xF8,0x7F,0xFF,0xE0, // 'B'
0x1F,0xFF,0xF8,0x3F,0xFF,0xF8,0x3F,0xFF,0xE6,0x3F,0xFF,0x8E,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xC0,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x38,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x00,0x00,0x0C,0x7F,0xFF,0x01,0xFF,0xFF,0x07,0xFF,0xFF,0x0F,0xFF,0xFC, // 'C'
0xFF,0xFF,0xC1,0xFF,0xFF,0xC1,0xFF,0xFF,0x01,0xFF,0xFC,0xC0,0x00,0x03,0xC0,0x00,0x07,0x80,0x78,0x0F,0x00,0xF0,0x1E,0x01,0xE0,0x3C,0x03,0xC0,0x78,0x07,0x80,0xF0,0x0F,0x01,0xE0,0x1E,0x03,0xC0,0x3C,0x07,0x80,0x78,0x0F,0x00,0x70,0x1E,0x00,0xC0,0x3C,0x00,0x80,0x38,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x10,0x07,0x00,0x60,0x1E,0x00,0xE0,0x3C,0x03,0xC0,0x78,0x07,0x80,0xF0,0x0F,0x01,0xE0,0x1E,0x03,0xC0,0x3C,0x07,0x80,0x78,0x0F,0x00,0xF0,0x1E,0x01,0xE0,0x3C,0x03,0xC0,0x78,0x00,0x00,0xF0,0x00,0x01,0xE3,0xFF,0xF9,0x8F,0xFF,0xF8,0x3F,0xFF,0xF8,0x7F,0xFF,0xE0, // 'D'
0x1F,0xFF,0xF8,0x3F,0xFF,0xF8,0x3F,0xFF,0xE6,0x3F,0xFF,0x8E,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xC0,0x00,0x03,0x1F,0x0F,0xC0,0x7F,0x1F,0xC0,0xFE,0x3F,0x98,0xF8,0x7E,0x38,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x00,0x00,0x0C,0x7F,0xFF,0x01,0xFF,0xFF,0x07,0xFF,0xFF,0x0F,0xFF,0xFC, // 'E'
0x1F,0xFF,0xF8,0x3F,0xFF,0xF8,0x3F,0xFF,0xE6,0x3F,0xFF,0x8E,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xC0,0x00,0x03,0x1F,0x0F,0xC0,0x7F,0x1F,0xC0,0xFE,0x3F,0x98,0xF8,0x7E,0x38,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x00,0x00,0x0C,0x00,0x00,0x00, // 'F'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xC0,0xE0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x38,0x00,0x00,0x0C,0x00,0x3F,0x00,0x00,0x0F,0xE0,0x00,0x03,0xF8,0x30,0x00,0xFC,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // 'G'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEE,0x00,0x00,0x3B,0x1F,0x0F,0xC6,0x0F,0xE3,0xF8,0x03,0xF8,0xFE,0x0C,0x7C,0x3F,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB0,0x00,0x00,0xC0, // 'H'
0xFF,0xFF,0xCF,0xFF,0xFE,0x7F,0xFF,0xC3,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x0E,0x00,0x00,0xC0,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x0C,0x00,0x00,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x87,0xFF,0xFC,0xFF,0xFF,0xEF,0xFF,0xFC, // 'I'
0x00,0x00,0x03,0x00,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x38,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB1,0xFF,0xFC,0xC0,0xFF,0xFF,0x80,0x7F,0xFF,0xF0,0x1F,0xFF,0xF8,0x00, // 'J'
0xC0,0x00,0x0E,0x00,0x00,0xF0,0x00,0x0F,0x00,0x02,0xF0,0x00,0x6F,0x00,0x06,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xCF,0x00,0x0C,0xF0,0x00,0x8F,0x00,0x00,0xE0,0x00,0x0C,0x7C,0x00,0x0F,0xE0,0x00,0xFE,0x00,0xC7,0xC0,0x0E,0x00,0x00,0xF0,0x00,0x0F,0x00,0x08,0xF0,0x00,0xCF,0x00,0x0C,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0x6F,0x00,0x06,0xF0,0x00,0x2F,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00, // 'K'
0xC0,0x00,0x01,0xC0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x38,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x07,0x00,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xE0,0x00,0x01,0x8F,0xFF,0xE0,0x3F,0xFF,0xE0,0xFF,0xFF,0xE1,0xFF,0xFF,0x80, // 'L'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC8,0x00,0x9E,0xF2,0x00,0x67,0xBC,0xC0,0x19,0xEF,0x30,0x0E,0x7B,0xCE,0x03,0x9E,0xF3,0x80,0xE7,0xBC,0xE0,0x39,0xEF,0x38,0x0C,0x7B,0xC6,0x03,0x1E,0xF0,0x80,0x87,0xBC,0x00,0x01,0xEE,0x00,0x00,0x3B,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x20,0x0E,0xF0,0x18,0x07,0xBC,0x07,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB0,0x00,0x00,0xC0, // 'M'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC8,0x00,0x1E,0xF2,0x00,0x07,0xBC,0xC0,0x01,0xEF,0x30,0x00,0x7B,0xCE,0x00,0x1E,0xF3,0x80,0x07,0xBC,0xE0,0x01,0xEF,0x38,0x00,0x7B,0xC6,0x00,0x1E,0xF0,0x80,0x07,0xBC,0x00,0x01,0xEE,0x00,0x00,0x3B,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x00,0x21,0xEF,0x00,0x0C,0x7B,0xC0,0x03,0x1E,0xF0,0x00,0xE7,0xBC,0x00,0x39,0xEF,0x00,0x0E,0x7B,0xC0,0x03,0x9E,0xF0,0x00,0x67,0xBC,0x00,0x19,0xEF,0x00,0x02,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB0,0x00,0x00,0xC0, // 'N'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // 'O'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x7C,0x3F,0x18,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x31,0xF0,0xFC,0x0E,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0x80,0x00,0x00,0xC0,0x00,0x00,0x00, // 'P'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x87,0xBC,0x00,0x31,0xEF,0x00,0x0C,0x7B,0xC0,0x03,0x9E,0xF0,0x00,0xE7,0xBC,0x00,0x39,0xEF,0x00,0x0E,0x7B,0xC0,0x01,0x9E,0xF0,0x00,0x67,0xBC,0x00,0x09,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // 'Q'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x7C,0x3F,0x18,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x31,0xF0,0xFC,0x0E,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x80,0x3C,0x00,0x30,0x0F,0x00,0x0C,0x03,0xC0,0x03,0x80,0xF0,0x00,0xE0,0x3C,0x00,0x38,0x0F,0x00,0x0E,0x03,0xC0,0x01,0x80,0xF0,0x00,0x60,0x3C,0x00,0x08,0x0F,0x00,0x00,0x03,0x80,0x00,0x00,0xC0,0x00,0x00,0x00, // 'R'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xC0,0xE0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x20,0x00,0x03,0xC8,0x00,0x00,0xF3,0x00,0x00,0x3C,0xC0,0x00,0x0F,0x38,0x00,0x03,0xCE,0x00,0x00,0xF3,0x80,0x00,0x3C,0xE0,0x00,0x0F,0x18,0x00,0x03,0xC2,0x00,0x00,0xF0,0x00,0x00,0x38,0x00,0x00,0x0C,0x7C,0x3F,0x00,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x01,0xF0,0xFC,0x60,0x00,0x00,0x38,0x00,0x00,0x1E,0x00,0x00,0x87,0x80,0x00,0x31,0xE0,0x00,0x0C,0x78,0x00,0x03,0x9E,0x00,0x00,0xE7,0x80,0x00,0x39,0xE0,0x00,0x0E,0x78,0x00,0x01,0x9E,0x00,0x00,0x67,0x80,0x00,0x09,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x07,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // 'S'
0xFF,0xFF,0xCF,0xFF,0xFE,0x7F,0xFF,0xC3,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x0E,0x00,0x00,0xC0,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x0C,0x00,0x00,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00, // 'T'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEE,0x00,0x00,0x3B,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB1,0xFF,0xFC,0xC0,0xFF,0xFF,0x80,0x7F,0xFF,0xF0,0x1F,0xFF,0xF8,0x00, // 'U'
0xC0,0x00,0x0E,0x00,0x00,0xF0,0x00,0x0F,0x00,0x02,0xF0,0x00,0x6F,0x00,0x06,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xCF,0x00,0x0C,0xF0,0x00,0x8F,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x0E,0x00,0x00,0xF0,0x00,0x0F,0x08,0x00,0xF1,0x80,0x0F,0x38,0x00,0xF3,0x80,0x0F,0x38,0x00,0xF3,0x80,0x0F,0x30,0x00,0xF3,0x00,0x0F,0x20,0x00,0xF2,0x00,0x0F,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00, // 'V'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x1C,0x07,0xBC,0x06,0x01,0xEE,0x00,0x80,0x3B,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x20,0x21,0xEF,0x18,0x0C,0x7B,0xCE,0x03,0x1E,0xF3,0x80,0xE7,0xBC,0xE0,0x39,0xEF,0x38,0x0E,0x7B,0xCC,0x03,0x9E,0xF3,0x00,0x67,0xBC,0x80,0x19,0xEF,0x20,0x02,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB0,0x00,0x00,0xC0, // 'W'
0x80,0x0A,0x00,0x6C,0x01,0xB0,0x0E,0xE0,0x3B,0x80,0xEE,0x03,0xB8,0x0C,0x60,0x30,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x18,0x0C,0xE0,0x33,0x80,0xEE,0x03,0xB8,0x0E,0xC0,0x3B,0x00,0x68,0x01,0xA0,0x02, // 'X'
0x80,0x0A,0x00,0x6C,0x01,0xB0,0x0E,0xE0,0x3B,0x80,0xEE,0x03,0xB8,0x0C,0x60,0x30,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x18,0x00,0x70,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xF0,0x03,0xC0, // 'Y'
0xFF,0xFF,0xCF,0xFF,0xFE,0x7F,0xFF,0xC3,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x30,0x00,0x03,0x00,0x00,0x70,0x00,0x07,0x00,0x00,0x70,0x00,0x07,0x00,0x00,0x60,0x00,0x06,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0xC0,0x00,0x1C,0x00,0x01,0xC0,0x00,0x1C,0x00,0x01,0xC0,0x00,0x18,0x00,0x01,0x80,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x87,0xFF,0xFC,0xFF,0xFF,0xEF,0xFF,0xFC, // 'Z'
0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '['
0x80,0x02,0x00,0x0C,0x00,0x30,0x00,0xE0,0x03,0x80,0x0E,0x00,0x38,0x00,0x60,0x00,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x0C,0x00,0x30,0x00,0xE0,0x03,0x80,0x0E,0x00,0x38,0x00,0x60,0x01,0x80,0x02, // '\'
0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // ']'
0xC0,0x38,0x0F,0x03,0xC8,0xF2,0x3C,0xCF,0x33,0xCE,0xF3,0xBC,0xEF,0x3B,0xC6,0xF0,0xBC,0x0E,0x03,0x00, // '^'
0x3F,0xFF,0x87,0xFF,0xFC,0xFF,0xFF,0xEF,0xFF,0xFC, // '_'
0x88,0xCC,0xEE,0xEE,0x62, // '`'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x7C,0x3F,0x18,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x31,0xF0,0xFC,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC0,0x00,0x03,0x00, // 'a'
0xFF,0xFF,0xC1,0xFF,0xFF,0xC1,0xFF,0xFF,0x01,0xFF,0xFC,0xC0,0x00,0x03,0xC0,0x00,0x07,0x80,0x78,0x0F,0x00,0xF0,0x1E,0x01,0xE0,0x3C,0x03,0xC0,0x78,0x07,0x80,0xF0,0x0F,0x01,0xE0,0x1E,0x03,0xC0,0x3C,0x07,0x80,0x78,0x0F,0x00,0x70,0x1E,0x00,0xC0,0x3C,0x00,0x80,0x38,0x00,0x7E,0x30,0x00,0xFE,0x00,0x01,0xFC,0x00,0x03,0xF1,0x80,0x10,0x07,0x00,0x60,0x1E,0x00,0xE0,0x3C,0x03,0xC0,0x78,0x07,0x80,0xF0,0x0F,0x01,0xE0,0x1E,0x03,0xC0,0x3C,0x07,0x80,0x78,0x0F,0x00,0xF0,0x1E,0x01,0xE0,0x3C,0x03,0xC0,0x78,0x00,0x00,0xF0,0x00,0x01,0xE3,0xFF,0xF9,0x8F,0xFF,0xF8,0x3F,0xFF,0xF8,0x7F,0xFF,0xE0, // 'b'
0x1F,0xFF,0xF8,0x3F,0xFF,0xF8,0x3F,0xFF,0xE6,0x3F,0xFF,0x8E,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xC0,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x38,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x00,0x00,0x0C,0x7F,0xFF,0x01,0xFF,0xFF,0x07,0xFF,0xFF,0x0F,0xFF,0xFC, // 'c'
0xFF,0xFF,0xC1,0xFF,0xFF,0xC1,0xFF,0xFF,0x01,0xFF,0xFC,0xC0,0x00,0x03,0xC0,0x00,0x07,0x80,0x78,0x0F,0x00,0xF0,0x1E,0x01,0xE0,0x3C,0x03,0xC0,0x78,0x07,0x80,0xF0,0x0F,0x01,0xE0,0x1E,0x03,0xC0,0x3C,0x07,0x80,0x78,0x0F,0x00,0x70,0x1E,0x00,0xC0,0x3C,0x00,0x80,0x38,0x00,0x00,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x80,0x10,0x07,0x00,0x60,0x1E,0x00,0xE0,0x3C,0x03,0xC0,0x78,0x07,0x80,0xF0,0x0F,0x01,0xE0,0x1E,0x03,0xC0,0x3C,0x07,0x80,0x78,0x0F,0x00,0xF0,0x1E,0x01,0xE0,0x3C,0x03,0xC0,0x78,0x00,0x00,0xF0,0x00,0x01,0xE3,0xFF,0xF9,0x8F,0xFF,0xF8,0x3F,0xFF,0xF8,0x7F,0xFF,0xE0, // 'd'
0x1F,0xFF,0xF8,0x3F,0xFF,0xF8,0x3F,0xFF,0xE6,0x3F,0xFF,0x8E,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xC0,0x00,0x03,0x1F,0x0F,0xC0,0x7F,0x1F,0xC0,0xFE,0x3F,0x98,0xF8,0x7E,0x38,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x00,0x00,0x0C,0x7F,0xFF,0x01,0xFF,0xFF,0x07,0xFF,0xFF,0x0F,0xFF,0xFC, // 'e'
0x1F,0xFF,0xF8,0x3F,0xFF,0xF8,0x3F,0xFF,0xE6,0x3F,0xFF,0x8E,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xC0,0x00,0x03,0x1F,0x0F,0xC0,0x7F,0x1F,0xC0,0xFE,0x3F,0x98,0xF8,0x7E,0x38,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x00,0x00,0x0C,0x00,0x00,0x00, // 'f'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xC0,0xE0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x38,0x00,0x00,0x0C,0x00,0x3F,0x00,0x00,0x0F,0xE0,0x00,0x03,0xF8,0x30,0x00,0xFC,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // 'g'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEE,0x00,0x00,0x3B,0x1F,0x0F,0xC6,0x0F,0xE3,0xF8,0x03,0xF8,0xFE,0x0C,0x7C,0x3F,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB0,0x00,0x00,0xC0, // 'h'
0xFF,0xFF,0xCF,0xFF,0xFE,0x7F,0xFF,0xC3,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x0E,0x00,0x00,0xC0,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x0C,0x00,0x00,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x87,0xFF,0xFC,0xFF,0xFF,0xEF,0xFF,0xFC, // 'i'
0x00,0x00,0x03,0x00,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x00,0x00,0x07,0x80,0x00,0x01,0xE0,0x00,0x00,0x38,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB1,0xFF,0xFC,0xC0,0xFF,0xFF,0x80,0x7F,0xFF,0xF0,0x1F,0xFF,0xF8,0x00, // 'j'
0xC0,0x00,0x0E,0x00,0x00,0xF0,0x00,0x0F,0x00,0x02,0xF0,0x00,0x6F,0x00,0x06,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xCF,0x00,0x0C,0xF0,0x00,0x8F,0x00,0x00,0xE0,0x00,0x0C,0x7C,0x00,0x0F,0xE0,0x00,0xFE,0x00,0xC7,0xC0,0x0E,0x00,0x00,0xF0,0x00,0x0F,0x00,0x08,0xF0,0x00,0xCF,0x00,0x0C,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0x6F,0x00,0x06,0xF0,0x00,0x2F,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00, // 'k'
0xC0,0x00,0x01,0xC0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x38,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x07,0x00,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xF0,0x00,0x01,0xE0,0x00,0x03,0xC0,0x00,0x07,0x80,0x00,0x0F,0x00,0x00,0x1E,0x00,0x00,0x3C,0x00,0x00,0x78,0x00,0x00,0xE0,0x00,0x01,0x8F,0xFF,0xE0,0x3F,0xFF,0xE0,0xFF,0xFF,0xE1,0xFF,0xFF,0x80, // 'l'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC8,0x00,0x9E,0xF2,0x00,0x67,0xBC,0xC0,0x19,0xEF,0x30,0x0E,0x7B,0xCE,0x03,0x9E,0xF3,0x80,0xE7,0xBC,0xE0,0x39,0xEF,0x38,0x0C,0x7B,0xC6,0x03,0x1E,0xF0,0x80,0x87,0xBC,0x00,0x01,0xEE,0x00,0x00,0x3B,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x20,0x0E,0xF0,0x18,0x07,0xBC,0x07,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB0,0x00,0x00,0xC0, // 'm'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC8,0x00,0x1E,0xF2,0x00,0x07,0xBC,0xC0,0x01,0xEF,0x30,0x00,0x7B,0xCE,0x00,0x1E,0xF3,0x80,0x07,0xBC,0xE0,0x01,0xEF,0x38,0x00,0x7B,0xC6,0x00,0x1E,0xF0,0x80,0x07,0xBC,0x00,0x01,0xEE,0x00,0x00,0x3B,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x00,0x21,0xEF,0x00,0x0C,0x7B,0xC0,0x03,0x1E,0xF0,0x00,0xE7,0xBC,0x00,0x39,0xEF,0x00,0x0E,0x7B,0xC0,0x03,0x9E,0xF0,0x00,0x67,0xBC,0x00,0x19,0xEF,0x00,0x02,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB0,0x00,0x00,0xC0, // 'n'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // 'o'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x7C,0x3F,0x18,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x31,0xF0,0xFC,0x0E,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x00,0x00,0x03,0x80,0x00,0x00,0xC0,0x00,0x00,0x00, // 'p'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x6E,0x00,0x00,0x3B,0xC0,0x00,0x1E,0xF0,0x00,0x87,0xBC,0x00,0x31,0xEF,0x00,0x0C,0x7B,0xC0,0x03,0x9E,0xF0,0x00,0xE7,0xBC,0x00,0x39,0xEF,0x00,0x0E,0x7B,0xC0,0x01,0x9E,0xF0,0x00,0x67,0xBC,0x00,0x09,0xEF,0x00,0x00,0x7B,0x80,0x00,0x1E,0xC7,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // 'q'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xCC,0xE0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xB8,0x00,0x00,0xEC,0x7C,0x3F,0x18,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x31,0xF0,0xFC,0x0E,0x00,0x00,0x03,0xC0,0x00,0x00,0xF0,0x00,0x80,0x3C,0x00,0x30,0x0F,0x00,0x0C,0x03,0xC0,0x03,0x80,0xF0,0x00,0xE0,0x3C,0x00,0x38,0x0F,0x00,0x0E,0x03,0xC0,0x01,0x80,0xF0,0x00,0x60,0x3C,0x00,0x08,0x0F,0x00,0x00,0x03,0x80,0x00,0x00,0xC0,0x00,0x00,0x00, // 'r'
0x1F,0xFF,0xF8,0x07,0xFF,0xFF,0x00,0xFF,0xFF,0x83,0x1F,0xFF,0xC0,0xE0,0x00,0x00,0x3C,0x00,0x00,0x0F,0x20,0x00,0x03,0xC8,0x00,0x00,0xF3,0x00,0x00,0x3C,0xC0,0x00,0x0F,0x38,0x00,0x03,0xCE,0x00,0x00,0xF3,0x80,0x00,0x3C,0xE0,0x00,0x0F,0x18,0x00,0x03,0xC2,0x00,0x00,0xF0,0x00,0x00,0x38,0x00,0x00,0x0C,0x7C,0x3F,0x00,0x3F,0x8F,0xE0,0x0F,0xE3,0xF8,0x01,0xF0,0xFC,0x60,0x00,0x00,0x38,0x00,0x00,0x1E,0x00,0x00,0x87,0x80,0x00,0x31,0xE0,0x00,0x0C,0x78,0x00,0x03,0x9E,0x00,0x00,0xE7,0x80,0x00,0x39,0xE0,0x00,0x0E,0x78,0x00,0x01,0x9E,0x00,0x00,0x67,0x80,0x00,0x09,0xE0,0x00,0x00,0x78,0x00,0x00,0x1E,0x07,0xFF,0xF3,0x03,0xFF,0xFE,0x01,0xFF,0xFF,0xC0,0x7F,0xFF,0xE0, // 's'
0xFF,0xFF,0xCF,0xFF,0xFE,0x7F,0xFF,0xC3,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x0E,0x00,0x00,0xC0,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x0C,0x00,0x00,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00,0x01,0xE0,0x00,0x1E,0x00, // 't'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEE,0x00,0x00,0x3B,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xF0,0x00,0x07,0xBC,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB1,0xFF,0xFC,0xC0,0xFF,0xFF,0x80,0x7F,0xFF,0xF0,0x1F,0xFF,0xF8,0x00, // 'u'
0xC0,0x00,0x0E,0x00,0x00,0xF0,0x00,0x0F,0x00,0x02,0xF0,0x00,0x6F,0x00,0x06,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xEF,0x00,0x0E,0xF0,0x00,0xCF,0x00,0x0C,0xF0,0x00,0x8F,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x0E,0x00,0x00,0xF0,0x00,0x0F,0x08,0x00,0xF1,0x80,0x0F,0x38,0x00,0xF3,0x80,0x0F,0x38,0x00,0xF3,0x80,0x0F,0x30,0x00,0xF3,0x00,0x0F,0x20,0x00,0xF2,0x00,0x0F,0x00,0x00,0xE0,0x00,0x0C,0x00,0x00, // 'v'
0xC0,0x00,0x03,0x38,0x00,0x01,0xEF,0x00,0x00,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x3C,0x07,0xBC,0x0F,0x01,0xEF,0x03,0xC0,0x7B,0xC0,0xF0,0x1E,0xF0,0x1C,0x07,0xBC,0x06,0x01,0xEE,0x00,0x80,0x3B,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x00,0x00,0x1B,0x80,0x00,0x0E,0xF0,0x00,0x07,0xBC,0x20,0x21,0xEF,0x18,0x0C,0x7B,0xCE,0x03,0x1E,0xF3,0x80,0xE7,0xBC,0xE0,0x39,0xEF,0x38,0x0E,0x7B,0xCC,0x03,0x9E,0xF3,0x00,0x67,0xBC,0x80,0x19,0xEF,0x20,0x02,0x7B,0xC0,0x00,0x1E,0xE0,0x00,0x07,0xB0,0x00,0x00,0xC0, // 'w'
0x80,0x0A,0x00,0x6C,0x01,0xB0,0x0E,0xE0,0x3B,0x80,0xEE,0x03,0xB8,0x0C,0x60,0x30,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x18,0x0C,0xE0,0x33,0x80,0xEE,0x03,0xB8,0x0E,0xC0,0x3B,0x00,0x68,0x01,0xA0,0x02, // 'x'
0x80,0x0A,0x00,0x6C,0x01,0xB0,0x0E,0xE0,0x3B,0x80,0xEE,0x03,0xB8,0x0C,0x60,0x30,0x80,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x18,0x00,0x70,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xF0,0x03,0xC0,0x0F,0x00,0x3C,0x00,0xF0,0x03,0xC0, // 'y'
0xFF,0xFF,0xCF,0xFF,0xFE,0x7F,0xFF,0xC3,0xFF,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x30,0x00,0x03,0x00,0x00,0x70,0x00,0x07,0x00,0x00,0x70,0x00,0x07,0x00,0x00,0x60,0x00,0x06,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0xC0,0x00,0x1C,0x00,0x01,0xC0,0x00,0x1C,0x00,0x01,0xC0,0x00,0x18,0x00,0x01,0x80,0x00,0x10,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0xFF,0x87,0xFF,0xFC,0xFF,0xFF,0xEF,0xFF,0xFC, // 'z'
0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8, // '{'
0xF7,0xBD,0xEF,0x7B,0xDE,0xF3,0x98,0x40,0x00,0x00,0x23,0x1D,0xEF,0x7B,0xDE,0xF7,0xBD,0xE0, // '|'
0xFF,0xD0,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x50,0x0A,0x01,0x40,0x28,0x05,0x00,0xA0,0x14,0x02,0x80,0x5F,0xF8 // '}'
};
const GFXglyph DSEG14_Classic_Mini_Regular_40Glyphs[] = {
// bitmapOffset, width, height, xAdvance, xOffset, yOffset
{ 0, 1, 1, 9, 0, 0 }, // ' '
{ 1, 1, 1, 34, 0, 0 }, // '!'
{ 2, 15, 16, 34, 4, -37 }, // '"'
{ 32, 11, 26, 16, 1, -26 }, // '#'
{ 68, 26, 40, 34, 4, -40 }, // '$'
{ 198, 26, 34, 34, 4, -37 }, // '%'
{ 309, 23, 40, 34, 7, -40 }, // '&'
{ 424, 5, 12, 34, 14, -34 }, // '''
{ 432, 4, 28, 34, 20, -34 }, // '('
{ 446, 4, 28, 34, 10, -34 }, // ')'
{ 460, 20, 28, 34, 7, -34 }, // '*'
{ 530, 20, 28, 34, 7, -34 }, // '+'
{ 600, 4, 10, 34, 10, -16 }, // ','
{ 605, 20, 4, 34, 7, -22 }, // '-'
{ 615, 5, 5, 1, -2, -5 }, // '.'
{ 619, 14, 28, 34, 10, -34 }, // '/'
{ 668, 26, 40, 34, 4, -40 }, // '0'
{ 798, 5, 34, 34, 25, -37 }, // '1'
{ 820, 26, 40, 34, 4, -40 }, // '2'
{ 950, 23, 40, 34, 7, -40 }, // '3'
{ 1065, 26, 34, 34, 4, -37 }, // '4'
{ 1176, 26, 40, 34, 4, -40 }, // '5'
{ 1306, 26, 40, 34, 4, -40 }, // '6'
{ 1436, 26, 37, 34, 4, -40 }, // '7'
{ 1557, 26, 40, 34, 4, -40 }, // '8'
{ 1687, 26, 40, 34, 4, -40 }, // '9'
{ 1817, 5, 21, 9, 2, -30 }, // ':'
{ 1831, 11, 26, 16, 1, -26 }, // ';'
{ 1867, 20, 34, 34, 7, -34 }, // '<'
{ 1952, 20, 22, 34, 7, -22 }, // '='
{ 2007, 20, 34, 34, 7, -34 }, // '>'
{ 2092, 26, 34, 34, 4, -40 }, // '?'
{ 2203, 26, 40, 34, 4, -40 }, // '@'
{ 2333, 26, 37, 34, 4, -40 }, // 'A'
{ 2454, 23, 40, 34, 7, -40 }, // 'B'
{ 2569, 23, 40, 34, 4, -40 }, // 'C'
{ 2684, 23, 40, 34, 7, -40 }, // 'D'
{ 2799, 23, 40, 34, 4, -40 }, // 'E'
{ 2914, 23, 37, 34, 4, -40 }, // 'F'
{ 3021, 26, 40, 34, 4, -40 }, // 'G'
{ 3151, 26, 34, 34, 4, -37 }, // 'H'
{ 3262, 20, 40, 34, 7, -40 }, // 'I'
{ 3362, 26, 37, 34, 4, -37 }, // 'J'
{ 3483, 20, 34, 34, 4, -37 }, // 'K'
{ 3568, 23, 37, 34, 4, -37 }, // 'L'
{ 3675, 26, 34, 34, 4, -37 }, // 'M'
{ 3786, 26, 34, 34, 4, -37 }, // 'N'
{ 3897, 26, 40, 34, 4, -40 }, // 'O'
{ 4027, 26, 37, 34, 4, -40 }, // 'P'
{ 4148, 26, 40, 34, 4, -40 }, // 'Q'
{ 4278, 26, 37, 34, 4, -40 }, // 'R'
{ 4399, 26, 40, 34, 4, -40 }, // 'S'
{ 4529, 20, 34, 34, 7, -40 }, // 'T'
{ 4614, 26, 37, 34, 4, -37 }, // 'U'
{ 4735, 20, 34, 34, 4, -37 }, // 'V'
{ 4820, 26, 34, 34, 4, -37 }, // 'W'
{ 4931, 14, 28, 34, 10, -34 }, // 'X'
{ 4980, 14, 28, 34, 10, -34 }, // 'Y'
{ 5029, 20, 40, 34, 7, -40 }, // 'Z'
{ 5129, 11, 26, 16, 1, -26 }, // '['
{ 5165, 14, 28, 34, 10, -34 }, // '\'
{ 5214, 11, 26, 16, 1, -26 }, // ']'
{ 5250, 10, 16, 34, 4, -37 }, // '^'
{ 5270, 20, 4, 34, 7, -4 }, // '_'
{ 5280, 4, 10, 34, 10, -34 }, // '`'
{ 5285, 26, 37, 34, 4, -40 }, // 'a'
{ 5406, 23, 40, 34, 7, -40 }, // 'b'
{ 5521, 23, 40, 34, 4, -40 }, // 'c'
{ 5636, 23, 40, 34, 7, -40 }, // 'd'
{ 5751, 23, 40, 34, 4, -40 }, // 'e'
{ 5866, 23, 37, 34, 4, -40 }, // 'f'
{ 5973, 26, 40, 34, 4, -40 }, // 'g'
{ 6103, 26, 34, 34, 4, -37 }, // 'h'
{ 6214, 20, 40, 34, 7, -40 }, // 'i'
{ 6314, 26, 37, 34, 4, -37 }, // 'j'
{ 6435, 20, 34, 34, 4, -37 }, // 'k'
{ 6520, 23, 37, 34, 4, -37 }, // 'l'
{ 6627, 26, 34, 34, 4, -37 }, // 'm'
{ 6738, 26, 34, 34, 4, -37 }, // 'n'
{ 6849, 26, 40, 34, 4, -40 }, // 'o'
{ 6979, 26, 37, 34, 4, -40 }, // 'p'
{ 7100, 26, 40, 34, 4, -40 }, // 'q'
{ 7230, 26, 37, 34, 4, -40 }, // 'r'
{ 7351, 26, 40, 34, 4, -40 }, // 's'
{ 7481, 20, 34, 34, 7, -40 }, // 't'
{ 7566, 26, 37, 34, 4, -37 }, // 'u'
{ 7687, 20, 34, 34, 4, -37 }, // 'v'
{ 7772, 26, 34, 34, 4, -37 }, // 'w'
{ 7883, 14, 28, 34, 10, -34 }, // 'x'
{ 7932, 14, 28, 34, 10, -34 }, // 'y'
{ 7981, 20, 40, 34, 7, -40 }, // 'z'
{ 8081, 11, 26, 16, 1, -26 }, // '{'
{ 8117, 5, 28, 34, 14, -34 }, // '|'
{ 8135, 11, 26, 16, 1, -26 } // '}'
};
const GFXfont DSEG14_Classic_Mini_Regular_40 = {
(uint8_t *)DSEG14_Classic_Mini_Regular_40Bitmaps,(GFXglyph *)DSEG14_Classic_Mini_Regular_40Glyphs,0x20, 0x7E, 44};

View File

@@ -0,0 +1,36 @@
#include <stdint.h>
#include "tl_common.h"
#include "main.h"
#include "i2c.h"
RAM bool i2c_sending;
void init_i2c(void)
{
i2c_gpio_set(I2C_GPIO_GROUP_C0C1);
i2c_master_init((uint8_t)(CLOCK_SYS_CLOCK_HZ / (4 * 400000)));
i2c_set_id(0x78);
}
void send_i2c(uint8_t device_id, uint8_t *buffer, int dataLen)
{
if (i2c_sending)
return;
i2c_sending = true;
i2c_set_id(device_id);
i2c_write_series(0, 0, (uint8_t *)buffer, dataLen);
i2c_sending = false;
}
uint8_t test_i2c_device(uint8_t address)
{
reg_i2c_id = address << 1;
reg_i2c_ctrl = FLD_I2C_CMD_START | FLD_I2C_CMD_ID;
while (reg_i2c_status & FLD_I2C_CMD_BUSY)
;
reg_i2c_ctrl = FLD_I2C_CMD_STOP;
while (reg_i2c_status & FLD_I2C_CMD_BUSY)
;
return (reg_i2c_status & FLD_I2C_NAK) ? 0 : 1;
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include <stdint.h>
void init_i2c(void);
void send_i2c(uint8_t device_id, uint8_t *buffer, int dataLen);
uint8_t test_i2c_device(uint8_t address);

View File

@@ -0,0 +1,52 @@
#include <stdint.h>
#include "tl_common.h"
#include "led.h"
#include "main.h"
void init_led(void)
{
gpio_setup_up_down_resistor(LED_BLUE, PM_PIN_PULLUP_1M);
gpio_write(LED_BLUE, 1);
gpio_set_func(LED_BLUE, AS_GPIO);
gpio_set_output_en(LED_BLUE, 1);
gpio_set_input_en(LED_BLUE, 0);
gpio_write(LED_RED, 1);
gpio_setup_up_down_resistor(LED_RED, PM_PIN_PULLUP_1M);
gpio_set_func(LED_RED, AS_GPIO);
gpio_set_output_en(LED_RED, 1);
gpio_set_input_en(LED_RED, 0);
gpio_setup_up_down_resistor(LED_GREEN, PM_PIN_PULLUP_1M);
gpio_write(LED_GREEN, 1);
gpio_set_func(LED_GREEN, AS_GPIO);
gpio_set_output_en(LED_GREEN, 1);
gpio_set_input_en(LED_GREEN, 0);
}
void set_led_color(uint8_t color)
{
switch (color)
{
case 1:
gpio_write(LED_BLUE, 1);
gpio_write(LED_RED, 0);
gpio_write(LED_GREEN, 1);
break;
case 2:
gpio_write(LED_BLUE, 1);
gpio_write(LED_RED, 1);
gpio_write(LED_GREEN, 0);
break;
case 3:
gpio_write(LED_BLUE, 0);
gpio_write(LED_RED, 1);
gpio_write(LED_GREEN, 1);
break;
default:
gpio_write(LED_BLUE, 1);
gpio_write(LED_RED, 1);
gpio_write(LED_GREEN, 1);
break;
}
}

View File

@@ -0,0 +1,4 @@
#pragma once
void init_led(void);
void set_led_color(uint8_t color);

View File

@@ -0,0 +1,53 @@
#pragma once
#include "screen.h"
#define LUTGROUP_NEGATIVE 0
#define LUTGROUP_FASTBLINK 1
#define LUTGROUP_SLOWBLINK 2
#define LUTGROUP_SET 3
#define LUTGROUP_IMPROVE_SHARPNESS 4
#define LUTGROUP_IMPROVE_REDS 5
#define LUTGROUP_UNUSED 6
#define LUTGROUP_UNKNOWN 7
#define LUTGROUP_UNUSED3 8
#define LUTGROUP_UNUSED4 9
struct vgroup {
uint8_t A : 2;
uint8_t B : 2;
uint8_t C : 2;
uint8_t D : 2;
};
struct lut {
struct vgroup group[7];
};
struct lut10 {
struct vgroup group[10];
} ;
struct group {
uint8_t phaselength[4];
uint8_t repeat;
} ;
struct waveform {
struct lut lut[5];
struct group group[7];
uint8_t gatelevel;
uint8_t sourcelevel[3];
uint8_t dummyline;
uint8_t gatewidth;
} ;
struct waveform10 {
struct lut10 lut[5];
struct group group[10];
uint8_t gatelevel;
uint8_t sourcelevel[3];
uint8_t dummyline;
uint8_t gatewidth;
} ;

View File

@@ -0,0 +1,259 @@
#include "tl_common.h"
#include "main.h"
#include "led.h"
#include "epd.h"
#include "uart.h"
#include "zigbee.h"
#include "nfc.h"
#include "proto.h"
#include "syncedproto.h"
#include "powermgt.h"
#include "comms.h"
#include "drawing.h"
#include "wdt.h"
#include "battery.h"
extern uint8_t our_ch;
RAM u8 ourmac[8] = {0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x02, 0x00, 0x00};
extern RAM uint8_t mSelfMac[8];
RAM char ownMacString[100] = "";
uint8_t showChannelSelect()
{ // returns 0 if no accesspoints were found
uint8_t result[sizeof(channelList)];
memset(result, 0, sizeof(result));
for (uint8_t i = 0; i < 4; i++)
{
for (uint8_t c = 0; c < sizeof(channelList); c++)
{
if (detectAP(channelList[c]))
{
if (mLastLqi > result[c])
result[c] = mLastLqi;
printf("Channel: %d - LQI: %d RSSI %d\r\n", channelList[c], mLastLqi, mLastRSSI);
}
}
}
uint8_t highestLqi = 0;
uint8_t highestSlot = 0;
for (uint8_t c = 0; c < sizeof(result); c++)
{
if (result[c] > highestLqi)
{
highestSlot = channelList[c];
highestLqi = result[c];
}
}
mLastLqi = highestLqi;
return highestSlot;
}
uint8_t channelSelect()
{ // returns 0 if no accesspoints were found
uint8_t result[16];
memset(result, 0, sizeof(result));
for (uint8_t i = 0; i < 2; i++)
{
for (uint8_t c = 0; c < sizeof(channelList); c++)
{
if (detectAP(channelList[c]))
{
if (mLastLqi > result[c])
result[c] = mLastLqi;
}
}
}
uint8_t highestLqi = 0;
uint8_t highestSlot = 0;
for (uint8_t c = 0; c < sizeof(result); c++)
{
if (result[c] > highestLqi)
{
highestSlot = channelList[c];
highestLqi = result[c];
}
}
mLastLqi = highestLqi;
return highestSlot;
}
int main(void)
{
startup_state_e state = drv_platform_init();
u8 isRetention = (state == SYSTEM_DEEP_RETENTION) ? 1 : 0;
isRetention = 0;// keep the compiler happy
drv_enable_irq();
init_led();
init_uart();
init_nfc();
printf("\r\n\r\n\r\nSTARTING\r\n\r\n\r\n\r\n");
u32 flash_mid = 0;
u8 flash_uid[16] = {0};
printf("Reading UID");
int flag = flash_read_mid_uid_with_check(&flash_mid, flash_uid);
if (flag)
{
for (int i = 0; i < 16; i++)
{
printf(" %02X", flash_uid[i]);
}
printf("\r\n");
for (int i = 0; i < 8; i++)
{
mSelfMac[i] = flash_uid[i + 8];
}
}
else
{
printf(" - Failed!\r\n");
}
sprintf(ownMacString, "%02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]);
batteryVoltage = get_battery_mv();
printf("Battery mv: %d Millis: %d\r\n", batteryVoltage, getMillis());
// epd_display("Boot", batteryVoltage, ownMacString, 1);
initializeProto();
currentChannel = showChannelSelect();
wdt10s();
if (currentChannel)
{
our_ch = currentChannel;
printf("AP Found\r\n");
epd_display("AP Found", batteryVoltage, ownMacString, 1);
initPowerSaving(INTERVAL_BASE);
doSleep(5000UL);
}
else
{
printf("No AP found\r\n");
epd_display("No AP Found", batteryVoltage, ownMacString, 1);
initPowerSaving(INTERVAL_AT_MAX_ATTEMPTS);
doSleep(120000UL);
}
while (1)
{
batteryVoltage = get_battery_mv();
uint32_t before = getMillis();
printf("Battery mv: %d Millis before: %d Uptime: %d\r\n", batteryVoltage, before, (getMillis() / 1000) / 60);
wdt10s();
if (currentChannel)
{
struct AvailDataInfo *avail;
avail = getAvailDataInfo();
// avail = getShortAvailDataInfo();
addAverageValue();
if (avail == NULL)
{
set_led_color(1);
printf("No data\r\n");
set_led_color(0);
// no data :(
nextCheckInFromAP = 0; // let the power-saving algorithm determine the next sleep period
}
else
{
nextCheckInFromAP = avail->nextCheckIn;
// got some data from the AP!
if (avail->dataType != DATATYPE_NOUPDATE)
{
set_led_color(2);
printf("Got data transfer\r\n");
set_led_color(0);
// data transfer
if (processAvailDataInfo(avail))
{
// succesful transfer, next wake time is determined by the NextCheckin;
}
else
{
// failed transfer, let the algorithm determine next sleep interval (not the AP)
nextCheckInFromAP = 0;
}
}
else
{
set_led_color(3);
printf("No data transfer\r\n");
set_led_color(0);
wakeUpReason = WAKEUP_REASON_TIMED; // Only one successfully AP communication we can have timed wakeups
// no data transfer, just sleep.
}
}
uint16_t nextCheckin = getNextSleep();
longDataReqCounter += nextCheckin;
if (nextCheckin == INTERVAL_AT_MAX_ATTEMPTS)
{
// disconnected, obviously...
currentChannel = 0;
}
doSleep(40 * 1000UL);
/*// if the AP told us to sleep for a specific period, do so.
if (nextCheckInFromAP)
{
doSleep(nextCheckInFromAP * 60000UL);
}
else
{
doSleep(getNextSleep() * 1000UL);
}*/
}
else
{
set_led_color(3);
// We sacrifice 10ms here to show a basic LED status as the scan itself takes more than a second
WaitMs(10);
set_led_color(0);
currentChannel = channelSelect();
if ((!currentChannel) || (lowBattery) || (scanAttempts == (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1)))
{
wdt60s();
if (curImgSlot != 0xFF)
{
drawImageFromEeprom(curImgSlot);
}
else if ((scanAttempts >= (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS - 1)))
{
epd_display("Sleep", batteryVoltage, ownMacString, 1);
}
else
{
epd_display("No AP", batteryVoltage, ownMacString, 1);
}
}
// did we find a working channel?
if (currentChannel)
{
// now associated!
our_ch = currentChannel;
scanAttempts = 0;
wakeUpReason = WAKEUP_REASON_NETWORK_SCAN;
initPowerSaving(INTERVAL_BASE);
doSleep(40 * 1000UL);
}
else
{
// still not associated
doSleep(15 * 60 * 1000UL);
}
}
}
return 0;
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include <stdint.h>
#define LED_BLUE GPIO_PA7
#define LED_RED GPIO_PD2
#define LED_GREEN GPIO_PD3
#define RXD GPIO_PA0
#define TXD GPIO_PB1
#define EPD_RESET GPIO_PD4
#define EPD_DC GPIO_PD7
#define EPD_BUSY GPIO_PA1
#define EPD_CS GPIO_PB4
#define EPD_CLK GPIO_PB5
#define EPD_MOSI GPIO_PB6
#define EPD_ENABLE GPIO_PC5
#define NFC_SDA GPIO_PC0
#define NFC_SCL GPIO_PC1
#define NFC_CS GPIO_PC6
#define NFC_IRQ GPIO_PC4

View File

@@ -0,0 +1,26 @@
#include <stdint.h>
#include "tl_common.h"
#include "nfc.h"
#include "main.h"
#include "i2c.h"
uint8_t nfc_reset[] = {0x03, 0xb5, 0xa0};
void init_nfc(void)
{
gpio_write(NFC_CS, 1);
gpio_set_func(NFC_CS, AS_GPIO);
gpio_set_output_en(NFC_CS, 1);
gpio_set_input_en(NFC_CS, 0);
gpio_setup_up_down_resistor(NFC_CS, PM_PIN_PULLUP_10K);
gpio_set_func(NFC_IRQ, AS_GPIO);
gpio_set_output_en(NFC_IRQ, 0);
gpio_set_input_en(NFC_IRQ, 1);
gpio_setup_up_down_resistor(NFC_IRQ, PM_PIN_PULLUP_10K);
gpio_write(NFC_CS, 0);
sleep_us(500);
send_i2c(0xae, nfc_reset, sizeof(nfc_reset));
gpio_write(NFC_CS, 1);
}

View File

@@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
#include "main.h"
void init_nfc(void);

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
//
// OneBitDisplay C wrapper
//
// prevent Arduino code from compiling
#define _LINUX_
#include "OneBitDisplay.cpp"

View File

@@ -0,0 +1,120 @@
#include "powermgt.h"
#include "main.h"
#include "drivers/drv_pm.h"
#include "tl_common.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include "zigbee.h"
#include "eeprom.h"
#include "board.h"
#include "screen.h"
#include "wdt.h"
#include "syncedproto.h"
#include "led.h"
uint16_t dataReqAttemptArr[POWER_SAVING_SMOOTHING] = {0}; // Holds the amount of attempts required per data_req/check-in
uint8_t dataReqAttemptArrayIndex = 0;
uint8_t dataReqLastAttempt = 0;
uint16_t nextCheckInFromAP = 0;
RAM uint8_t wakeUpReason = WAKEUP_REASON_FIRSTBOOT;
uint8_t scanAttempts = 0;
int8_t temperature = 0;
uint16_t batteryVoltage = 0;
bool lowBattery = false;
uint16_t longDataReqCounter = 0;
uint16_t voltageCheckCounter = 0;
uint8_t capabilities = 0;
RAM uint64_t time_ms = 0;
RAM uint32_t time_overflow = 0;
uint32_t getMillis()
{
return pm_get_32k_tick() / 32; //(float)32.768;
}
void initPowerSaving(const uint16_t initialValue)
{
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++)
{
dataReqAttemptArr[c] = initialValue;
}
}
void doSleepGpio(uint32_t t, GPIO_PinTypeDef pin)
{
set_led_color(0); // Always turn of the LED before sleep for security reasons
printf("Sleeping for: %u ms\r\n", (unsigned int)t);
// WaitMs(2000);
// return;
uint32_t r = drv_disable_irq();
pm_wakeup_pad_cfg(pin, !drv_gpio_read(pin), 1);
drv_pm_longSleep(PM_SLEEP_MODE_SUSPEND, PM_WAKEUP_SRC_TIMER | PM_WAKEUP_SRC_PAD, t);
pm_wakeup_pad_cfg(pin, !drv_gpio_read(pin), 0);
drv_restore_irq(r);
uart_ndma_clear_tx_index(); // UART will be garbled otherwise
}
void doSleep(uint32_t t)
{
uint8_t randomizer = drv_u32Rand() & 0xff;
t += randomizer;
set_led_color(0); // Always turn of the LED before sleep for security reasons
printf("Sleeping for: %u ms\r\n", (unsigned int)t);
// WaitMs(2000);
// return;
uint32_t r = drv_disable_irq();
pm_wakeup_pad_cfg(NFC_IRQ, PM_WAKEUP_LEVEL_LOW, 1);
drv_pm_longSleep(PM_SLEEP_MODE_SUSPEND, PM_WAKEUP_SRC_TIMER | PM_WAKEUP_SRC_PAD, t);
pm_wakeup_pad_cfg(NFC_IRQ, PM_WAKEUP_LEVEL_LOW, 0);
drv_restore_irq(r);
uart_ndma_clear_tx_index(); // UART will be garbled otherwise
}
uint32_t getNextScanSleep(const bool increment)
{
if (increment)
{
if (scanAttempts < 255)
scanAttempts++;
}
if (scanAttempts < INTERVAL_1_ATTEMPTS)
{
return INTERVAL_1_TIME;
}
else if (scanAttempts < (INTERVAL_1_ATTEMPTS + INTERVAL_2_ATTEMPTS))
{
return INTERVAL_2_TIME;
}
else
{
return INTERVAL_3_TIME;
}
}
void addAverageValue()
{
uint16_t curval = INTERVAL_AT_MAX_ATTEMPTS - INTERVAL_BASE;
curval *= dataReqLastAttempt;
curval /= DATA_REQ_MAX_ATTEMPTS;
curval += INTERVAL_BASE;
dataReqAttemptArr[dataReqAttemptArrayIndex % POWER_SAVING_SMOOTHING] = curval;
dataReqAttemptArrayIndex++;
}
uint16_t getNextSleep()
{
uint16_t avg = 0;
for (uint8_t c = 0; c < POWER_SAVING_SMOOTHING; c++)
{
avg += dataReqAttemptArr[c];
}
avg /= POWER_SAVING_SMOOTHING;
return avg;
}

View File

@@ -0,0 +1,74 @@
#ifndef _POWERMGT_H_
#define _POWERMGT_H_
#include <stdint.h>
#include <stdbool.h>
#include "tl_common.h"
#define WAKEUP_REASON_TIMED 0
#define WAKEUP_REASON_GPIO 2
#define WAKEUP_REASON_NFC 3
#define WAKEUP_REASON_FIRSTBOOT 0xFC
#define WAKEUP_REASON_NETWORK_SCAN 0xFD
#define WAKEUP_REASON_WDT_RESET 0xFE
#define DETECT_P1_0_NOTHING 0
#define DETECT_P1_0_BUTTON 1
#define DETECT_P1_0_JIG 2
#define INIT_EPD_VOLTREADING 0x80
#define INIT_RADIO 0x40
#define INIT_I2C 0x20
#define INIT_UART 0x10
#define INIT_EPD 0x08
#define INIT_EEPROM 0x04
#define INIT_TEMPREADING 0x02
#define INIT_BASE 0x01
// power saving algorithm
#define INTERVAL_BASE 40 // interval (in seconds) (when 1 packet is sent/received) for target current (7.2µA)
#define INTERVAL_AT_MAX_ATTEMPTS 600 // interval (in seconds) (at max attempts) for target average current
#define DATA_REQ_RX_WINDOW_SIZE 5UL // How many milliseconds we should wait for a packet during the data_request.
// If the AP holds a long list of data for tags, it may need a little more time to lookup the mac address
#define DATA_REQ_MAX_ATTEMPTS 14 // How many attempts (at most) we should do to get something back from the AP
#define POWER_SAVING_SMOOTHING 8 // How many samples we should use to smooth the data request interval
#define MINIMUM_INTERVAL 45 // IMPORTANT: Minimum interval for check-in; this determines overal battery life!
#define MAXIMUM_PING_ATTEMPTS 20 // How many attempts to discover an AP the tag should do
#define PING_REPLY_WINDOW 5UL
#define LONG_DATAREQ_INTERVAL 300 // How often (in seconds, approximately) the tag should do a long datareq (including temperature)
#define VOLTAGE_CHECK_INTERVAL 288 // How often the tag should do a battery voltage check (multiplied by LONG_DATAREQ_INTERVAL)
#define BATTERY_VOLTAGE_MINIMUM 2450 // 2600 or below is the best we can do on the EPD
// power saving when no AP's were found (scanning every X)
#define VOLTAGEREADING_DURING_SCAN_INTERVAL 2 // how often we should read voltages; this is done every scan attempt in interval bracket 3
#define INTERVAL_1_TIME 3600UL // Try every hour
#define INTERVAL_1_ATTEMPTS 24 // for 24 attempts (an entire day)
#define INTERVAL_2_TIME 7200UL // Try every 2 hours
#define INTERVAL_2_ATTEMPTS 12 // for 12 attempts (an additional day)
#define INTERVAL_3_TIME 86400UL // Finally, try every day
uint32_t getMillis();
extern void initAfterWake();
extern void doSleepGpio(uint32_t t, GPIO_PinTypeDef pin);
extern void doSleep(uint32_t t);
extern void addAverageValue();
extern uint16_t getNextSleep();
extern uint32_t getNextScanSleep(const bool increment);
extern void initPowerSaving(const uint16_t initialValue);
extern uint8_t wakeUpReason;
extern uint8_t capabilities;
extern uint16_t nextCheckInFromAP;
extern uint8_t dataReqLastAttempt;
extern int8_t temperature;
extern uint16_t batteryVoltage;
extern bool lowBattery;
extern uint8_t scanAttempts;
extern uint16_t longDataReqCounter;
extern uint16_t voltageCheckCounter;
#endif

View File

@@ -0,0 +1,227 @@
#ifndef _PROTO_H_
#define _PROTO_H_
#include <stdint.h>
#include "tag_types.h"
// power saving algorithm
#define INTERVAL_BASE 40 // interval (in seconds) (when 1 packet is sent/received) for target current (7.2µA)
#define INTERVAL_AT_MAX_ATTEMPTS 600 // interval (in seconds) (at max attempts) for target average current
#define DATA_REQ_RX_WINDOW_SIZE 5UL // How many milliseconds we should wait for a packet during the data_request.
// If the AP holds a long list of data for tags, it may need a little more time to lookup the mac address
#define DATA_REQ_MAX_ATTEMPTS 14 // How many attempts (at most) we should do to get something back from the AP
#define POWER_SAVING_SMOOTHING 8 // How many samples we should use to smooth the data request interval
#define MINIMUM_INTERVAL 45 // IMPORTANT: Minimum interval for check-in; this determines overal battery life!
#define MAXIMUM_PING_ATTEMPTS 20 // How many attempts to discover an AP the tag should do
#define LONG_DATAREQ_INTERVAL 300 // How often (in seconds, approximately) the tag should do a long datareq (including temperature)
#define VOLTAGE_CHECK_INTERVAL 288 // How often the tag should do a battery voltage check (multiplied by LONG_DATAREQ_INTERVAL)
#define BATTERY_VOLTAGE_MINIMUM 2450 // 2600 or below is the best we can do on the EPD
// power saving when no AP's were found (scanning every X)
#define VOLTAGEREADING_DURING_SCAN_INTERVAL 2 // how often we should read voltages; this is done every scan attempt in interval bracket 3
#define INTERVAL_1_TIME 3600UL // Try every hour
#define INTERVAL_1_ATTEMPTS 24 // for 24 attempts (an entire day)
#define INTERVAL_2_TIME 7200UL // Try every 2 hours
#define INTERVAL_2_ATTEMPTS 12 // for 12 attempts (an additional day)
#define INTERVAL_3_TIME 86400UL // Finally, try every day
enum TagScreenType {
TagScreenEink_BW_1bpp,
TagScreenEink_BW_2bpp,
TagScreenEink_BW_4bpp,
TagScreenEink_BWY_only, // 2bpp, but only 3 colors (BW?Y)
TagScreenEink_BWY_2bpp,
TagScreenEink_BWY_4bpp,
TagScreenEink_BWR_only, // 2bpp, but only 3 colors (BW?R)
TagScreenEink_BWR_2bpp,
TagScreenEink_BWR_4bpp,
TagScreenEink_BWY_3bpp,
TagScreenEink_BWR_3bpp,
TagScreenEink_BW_3bpp,
TagScreenPersistentLcd_1bpp,
TagScreenEink_BWY_5colors,
TagScreenEink_BWR_5colors,
TagScreenEink_BWY_6colors,
TagScreenEink_BWR_6colors,
TagScreenTypeOther = 0x7f,
};
#define PROTO_PAN_ID (0x4447) // PAN ID compression shall be used
#define RADIO_MAX_PACKET_LEN (125) // useful payload, not including the crc
#define ADDR_MODE_NONE (0)
#define ADDR_MODE_SHORT (2)
#define ADDR_MODE_LONG (3)
#define FRAME_TYPE_BEACON (0)
#define FRAME_TYPE_DATA (1)
#define FRAME_TYPE_ACK (2)
#define FRAME_TYPE_MAC_CMD (3)
#define SHORT_MAC_UNUSED (0x10000000UL) // for radioRxFilterCfg's myShortMac
struct MacFcs {
uint8_t frameType : 3;
uint8_t secure : 1;
uint8_t framePending : 1;
uint8_t ackReqd : 1;
uint8_t panIdCompressed : 1;
uint8_t rfu1 : 1;
uint8_t rfu2 : 2;
uint8_t destAddrType : 2;
uint8_t frameVer : 2;
uint8_t srcAddrType : 2;
} ;
struct MacFrameFromMaster {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint16_t from;
} ;
struct MacFrameNormal {
struct MacFcs fcs;
uint8_t seq;
uint16_t pan;
uint8_t dst[8];
uint8_t src[8];
} ;
struct MacFrameBcast {
struct MacFcs fcs;
uint8_t seq;
uint16_t dstPan;
uint16_t dstAddr;
uint16_t srcPan;
uint8_t src[8];
} ;
#define PKT_AVAIL_DATA_SHORTREQ 0xE3
#define PKT_AVAIL_DATA_REQ 0xE5
#define PKT_AVAIL_DATA_INFO 0xE6
#define PKT_BLOCK_PARTIAL_REQUEST 0xE7
#define PKT_BLOCK_REQUEST_ACK 0xE9
#define PKT_BLOCK_REQUEST 0xE4
#define PKT_BLOCK_PART 0xE8
#define PKT_XFER_COMPLETE 0xEA
#define PKT_XFER_COMPLETE_ACK 0xEB
#define PKT_CANCEL_XFER 0xEC
#define PKT_PING 0xED
#define PKT_PONG 0xEE
struct AvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
uint16_t tagSoftwareVersion;
uint8_t currentChannel;
uint8_t customMode;
uint8_t reserved[8];
} ;
struct oldAvailDataReq {
uint8_t checksum;
uint8_t lastPacketLQI;
int8_t lastPacketRSSI;
int8_t temperature;
uint16_t batteryMv;
uint8_t hwType;
uint8_t wakeupReason;
uint8_t capabilities;
} ;
struct AvailDataInfo {
uint8_t checksum;
uint64_t dataVer; // MD5 of potential traffic
uint32_t dataSize;
uint8_t dataType;
uint8_t dataTypeArgument; // extra specification or instruction for the tag (LUT to be used for drawing image)
uint16_t nextCheckIn; // when should the tag check-in again? Measured in minutes
} ;
struct pendingData {
struct AvailDataInfo availdatainfo;
uint16_t attemptsLeft;
uint8_t targetMac[8];
} ;
struct blockPart {
uint8_t checksum;
uint8_t blockId;
uint8_t blockPart;
uint8_t data[];
} ;
struct blockData {
uint16_t size;
uint16_t checksum;
uint8_t data[];
} ;
struct burstMacData {
uint16_t offset;
uint8_t targetMac[8];
} ;
#define BLOCK_PART_DATA_SIZE 99
#define BLOCK_MAX_PARTS 42
#define BLOCK_DATA_SIZE 4096UL
#define BLOCK_XFER_BUFFER_SIZE BLOCK_DATA_SIZE + sizeof(struct blockData)
#define BLOCK_REQ_PARTS_BYTES 6
struct blockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t type;
uint8_t requestedParts[BLOCK_REQ_PARTS_BYTES];
} ;
struct blockRequestAck {
uint8_t checksum;
uint16_t pleaseWaitMs;
} ;
struct espBlockRequest {
uint8_t checksum;
uint64_t ver;
uint8_t blockId;
uint8_t src[8];
} ;
struct espXferComplete {
uint8_t checksum;
uint8_t src[8];
} ;
struct espAvailDataReq {
uint8_t checksum;
uint8_t src[8];
struct AvailDataReq adr;
} ;
struct espSetChannelPower {
uint8_t checksum;
uint8_t channel;
uint8_t power;
} ;
#define MACFMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"
#define MACCVT(x) ((const uint8_t*)(x))[7], ((const uint8_t*)(x))[6], ((const uint8_t*)(x))[5], ((const uint8_t*)(x))[4], ((const uint8_t*)(x))[3], ((const uint8_t*)(x))[2], ((const uint8_t*)(x))[1], ((const uint8_t*)(x))[0]
#endif

View File

@@ -0,0 +1,24 @@
#ifndef _SCREEN_H_
#define _SCREEN_H_
#include <stdbool.h>
#include <stdint.h>
#define SCREEN_WIDTH 184
#define SCREEN_HEIGHT 384
#define SCREEN_NUM_GREYS 5
#define SCREEN_FIRST_GREY_IDX 0
#define SCREEN_EXTRA_COLOR_INDEX 5 //set to negative if nonexistent
#define SCREEN_TX_BPP 4 //in transit
#define SCREEN_WIDTH_MM 29
#define SCREEN_HEIGHT_MM 67
#define SCREEN_BYTE_FILL 0x44 //white
#define SCREEN_TYPE TagScreenEink_BWR_6colors
#define SCREEN_DATA_PASSES 2
#endif

View File

@@ -0,0 +1,941 @@
#include "main.h"
#include "zigbee.h"
#include "proto.h"
#include "syncedproto.h"
#include "comms.h"
#include "board.h"
#include "powermgt.h"
#include "eeprom.h"
#include "drawing.h"
#include "wdt.h"
#include "tl_common.h"
#include <stdint.h>
// download-stuff
RAM uint8_t blockXferBuffer[BLOCK_XFER_BUFFER_SIZE] = {0};
RAM struct blockRequest curBlock = {0}; // used by the block-requester, contains the next request that we'll send
RAM struct AvailDataInfo curDataInfo = {0}; // last 'AvailDataInfo' we received from the AP
RAM bool requestPartialBlock = false; // if we should ask the AP to get this block from the host or not
#define BLOCK_TRANSFER_ATTEMPTS 5
uint8_t prevImgSlot = 0xFF;
uint8_t curImgSlot = 0xFF;
RAM uint32_t curHighSlotId = 0;
RAM uint8_t nextImgSlot = 0;
RAM uint8_t imgSlots = 0;
uint8_t drawWithLut = 0;
// stuff we need to keep track of related to the network/AP
uint8_t APmac[8] = {0};
uint16_t APsrcPan = 0;
RAM uint8_t mSelfMac[8] = {0};
RAM uint8_t seq = 0;
RAM uint8_t currentChannel = 0;
// buffer we use to prepare/read packets
static uint8_t inBuffer[128] = {0};
static uint8_t outBuffer[128] = {0};
// tools
static uint8_t getPacketType(const void *buffer)
{
const struct MacFcs *fcs = buffer;
if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0))
{
// broadcast frame
uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameBcast)];
return type;
}
else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1))
{
// normal frame
uint8_t type = ((uint8_t *)buffer)[sizeof(struct MacFrameNormal)];
return type;
}
return 0;
}
static bool pktIsUnicast(const void *buffer)
{
const struct MacFcs *fcs = buffer;
if ((fcs->frameType == 1) && (fcs->destAddrType == 2) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 0))
{
return false;
}
else if ((fcs->frameType == 1) && (fcs->destAddrType == 3) && (fcs->srcAddrType == 3) && (fcs->panIdCompressed == 1))
{
// normal frame
return true;
}
// unknown type...
return false;
}
void dump(const uint8_t *a, const uint16_t l)
{
printf("\n ");
#define ROWS 16
for (uint8_t c = 0; c < ROWS; c++)
{
printf(" %02X", c);
}
printf("\n--------");
for (uint8_t c = 0; c < ROWS; c++)
{
printf("---");
}
for (uint16_t c = 0; c < l; c++)
{
if ((c % ROWS) == 0)
{
printf("\n0x%04X | ", c);
}
printf("%02X ", a[c]);
}
printf("\n--------");
for (uint8_t c = 0; c < ROWS; c++)
{
printf("---");
}
printf("\r\n");
}
static bool checkCRC(const void *p, const uint8_t len)
{
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++)
{
total += ((uint8_t *)p)[c];
}
// printf("CRC: rx %d, calc %d\r\n", ((uint8_t *)p)[0], total);
return ((uint8_t *)p)[0] == total;
}
static void addCRC(void *p, const uint8_t len)
{
uint8_t total = 0;
for (uint8_t c = 1; c < len; c++)
{
total += ((uint8_t *)p)[c];
}
((uint8_t *)p)[0] = total;
}
// radio stuff
static void sendPing()
{
struct MacFrameBcast *txframe = (struct MacFrameBcast *)(outBuffer + 1);
memset(outBuffer, 0, sizeof(struct MacFrameBcast) + 2 + 4);
outBuffer[0] = sizeof(struct MacFrameBcast) + 1 + 2;
outBuffer[sizeof(struct MacFrameBcast) + 1] = PKT_PING;
memcpy(txframe->src, mSelfMac, 8);
txframe->fcs.frameType = 1;
txframe->fcs.ackReqd = 1;
txframe->fcs.destAddrType = 2;
txframe->fcs.srcAddrType = 3;
txframe->seq = seq++;
txframe->dstPan = PROTO_PAN_ID;
txframe->dstAddr = 0xFFFF;
txframe->srcPan = PROTO_PAN_ID;
commsTxNoCpy(outBuffer);
}
uint8_t detectAP(const uint8_t channel)
{
radioRxEnable(false);
radioSetChannel(channel);
radioRxFlush();
radioRxEnable(true);
for (uint8_t c = 1; c <= MAXIMUM_PING_ATTEMPTS; c++)
{
sendPing();
uint32_t timeout = clock_time();
while (!clock_time_exceed(timeout, PING_REPLY_WINDOW * 1000))
{
int8_t ret = commsRxUnencrypted(inBuffer);
if (ret > 1)
{
// dump(inBuffer + sizeof(struct MacFrameNormal), 32);
if ((inBuffer[sizeof(struct MacFrameNormal) + 1] == channel) && (getPacketType(inBuffer) == PKT_PONG))
{
if (pktIsUnicast(inBuffer))
{
struct MacFrameNormal *f = (struct MacFrameNormal *)inBuffer;
memcpy(APmac, f->src, 8);
APsrcPan = f->pan;
return c;
}
}
}
WaitMs(1);
}
}
return 0;
}
// data xfer stuff
static void sendShortAvailDataReq()
{
struct MacFrameBcast *txframe = (struct MacFrameBcast *)(outBuffer + 1);
outBuffer[0] = sizeof(struct MacFrameBcast) + 1 + 2;
outBuffer[sizeof(struct MacFrameBcast) + 1] = PKT_AVAIL_DATA_SHORTREQ;
memcpy(txframe->src, mSelfMac, 8);
outBuffer[1] = 0x21;
outBuffer[2] = 0xC8; // quickly set txframe fcs structure for broadcast packet
txframe->seq = seq++;
txframe->dstPan = PROTO_PAN_ID;
txframe->dstAddr = 0xFFFF;
txframe->srcPan = PROTO_PAN_ID;
commsTxNoCpy(outBuffer);
}
static void sendAvailDataReq()
{
struct MacFrameBcast *txframe = (struct MacFrameBcast *)(outBuffer + 1);
memset(outBuffer, 0, sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 4);
struct AvailDataReq *availreq = (struct AvailDataReq *)(outBuffer + 2 + sizeof(struct MacFrameBcast));
outBuffer[0] = sizeof(struct MacFrameBcast) + sizeof(struct AvailDataReq) + 2 + 2;
outBuffer[sizeof(struct MacFrameBcast) + 1] = PKT_AVAIL_DATA_REQ;
memcpy(txframe->src, mSelfMac, 8);
txframe->fcs.frameType = 1;
txframe->fcs.ackReqd = 1;
txframe->fcs.destAddrType = 2;
txframe->fcs.srcAddrType = 3;
txframe->seq = seq++;
txframe->dstPan = PROTO_PAN_ID;
txframe->dstAddr = 0xFFFF;
txframe->srcPan = PROTO_PAN_ID;
// TODO: send some (more) meaningful data
availreq->hwType = HW_TYPE;
availreq->wakeupReason = wakeUpReason;
availreq->lastPacketRSSI = mLastRSSI;
availreq->lastPacketLQI = mLastLqi;
availreq->temperature = temperature;
availreq->batteryMv = batteryVoltage;
availreq->capabilities = capabilities;
addCRC(availreq, sizeof(struct AvailDataReq));
commsTxNoCpy(outBuffer);
}
struct AvailDataInfo *getAvailDataInfo()
{
radioRxEnable(true);
for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++)
{
sendAvailDataReq();
uint32_t timeout = clock_time();
while (!clock_time_exceed(timeout, DATA_REQ_RX_WINDOW_SIZE * 1000))
{
int8_t ret = commsRxUnencrypted(inBuffer);
if (ret > 1)
{
if (getPacketType(inBuffer) == PKT_AVAIL_DATA_INFO)
{
if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct AvailDataInfo)))
{
struct MacFrameNormal *f = (struct MacFrameNormal *)inBuffer;
memcpy(APmac, f->src, 8);
APsrcPan = f->pan;
dataReqLastAttempt = c;
return (struct AvailDataInfo *)(inBuffer + sizeof(struct MacFrameNormal) + 1);
}
}
}
}
}
dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS;
return NULL;
}
struct AvailDataInfo *getShortAvailDataInfo()
{
radioRxEnable(true);
for (uint8_t c = 0; c < DATA_REQ_MAX_ATTEMPTS; c++)
{
sendShortAvailDataReq();
uint32_t timeout = clock_time();
while (!clock_time_exceed(timeout, DATA_REQ_RX_WINDOW_SIZE * 1000))
{
int8_t ret = commsRxUnencrypted(inBuffer);
if (ret > 1)
{
if (getPacketType(inBuffer) == PKT_AVAIL_DATA_INFO)
{
if (checkCRC(inBuffer + sizeof(struct MacFrameNormal) + 1, sizeof(struct AvailDataInfo)))
{
struct MacFrameNormal *f = (struct MacFrameNormal *)inBuffer;
memcpy(APmac, f->src, 8);
APsrcPan = f->pan;
dataReqLastAttempt = c;
return (struct AvailDataInfo *)(inBuffer + sizeof(struct MacFrameNormal) + 1);
}
}
}
}
}
dataReqLastAttempt = DATA_REQ_MAX_ATTEMPTS;
return NULL;
}
static bool processBlockPart(const struct blockPart *bp)
{
uint16_t start = bp->blockPart * BLOCK_PART_DATA_SIZE;
uint16_t size = BLOCK_PART_DATA_SIZE;
// validate if it's okay to copy data
if (bp->blockId != curBlock.blockId)
{
// printf("got a packet for block %02X\r\n", bp->blockId);
return false;
}
if (start >= (sizeof(blockXferBuffer) - 1))
return false;
if (bp->blockPart > BLOCK_MAX_PARTS)
return false;
if ((start + size) > sizeof(blockXferBuffer))
{
size = sizeof(blockXferBuffer) - start;
}
if (checkCRC(bp, sizeof(struct blockPart) + BLOCK_PART_DATA_SIZE))
{
// copy block data to buffer
memcpy((void *)(blockXferBuffer + start), (const void *)bp->data, size);
// we don't need this block anymore, set bit to 0 so we don't request it again
curBlock.requestedParts[bp->blockPart / 8] &= ~(1 << (bp->blockPart % 8));
return true;
}
else
{
printf("CRC Failed \r\n");
return false;
}
}
static bool blockRxLoop(const uint32_t timeout)
{
bool success = false;
// radioRxEnable(true);
uint32_t t = clock_time();
while (!clock_time_exceed(t, 2000 * 1000))
{
int8_t ret = commsRxUnencrypted(inBuffer);
if (ret > 1)
{
printf("Len %d\r\n", ret);
if (getPacketType(inBuffer) == PKT_BLOCK_PART)
{
struct blockPart *bp = (struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1);
success = processBlockPart(bp);
}
}
}
// radioRxEnable(false);
// radioRxFlush();
return success;
}
static struct blockRequestAck *continueToRX()
{
struct blockRequestAck *ack = (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1);
ack->pleaseWaitMs = 0;
return ack;
}
static void sendBlockRequest()
{
memset(outBuffer, 0, sizeof(struct MacFrameNormal) + sizeof(struct blockRequest) + 2 + 2);
struct MacFrameNormal *f = (struct MacFrameNormal *)(outBuffer + 1);
struct blockRequest *blockreq = (struct blockRequest *)(outBuffer + 2 + sizeof(struct MacFrameNormal));
outBuffer[0] = sizeof(struct MacFrameNormal) + sizeof(struct blockRequest) + 2 + 2;
if (requestPartialBlock)
{
;
outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_PARTIAL_REQUEST;
}
else
{
outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_BLOCK_REQUEST;
}
memcpy(f->src, mSelfMac, 8);
memcpy(f->dst, APmac, 8);
f->fcs.frameType = 1;
f->fcs.secure = 0;
f->fcs.framePending = 0;
f->fcs.ackReqd = 0;
f->fcs.panIdCompressed = 1;
f->fcs.destAddrType = 3;
f->fcs.frameVer = 0;
f->fcs.srcAddrType = 3;
f->seq = seq++;
f->pan = APsrcPan;
memcpy(blockreq, &curBlock, sizeof(struct blockRequest));
// printf("req ver: %02X%02X%02X%02X%02X%02X%02X%02X\r\n", ((uint8_t*)&blockreq->ver)[0],((uint8_t*)&blockreq->ver)[1],((uint8_t*)&blockreq->ver)[2],((uint8_t*)&blockreq->ver)[3],((uint8_t*)&blockreq->ver)[4],((uint8_t*)&blockreq->ver)[5],((uint8_t*)&blockreq->ver)[6],((uint8_t*)&blockreq->ver)[7]);
addCRC(blockreq, sizeof(struct blockRequest));
commsTxNoCpy(outBuffer);
}
static struct blockRequestAck *performBlockRequest()
{
for (uint8_t c = 0; c < 30; c++)
{
sendBlockRequest();
uint32_t timeout = clock_time();
do
{
int8_t ret = commsRxUnencrypted(inBuffer);
if (ret > 1)
{
switch (getPacketType(inBuffer))
{
case PKT_BLOCK_REQUEST_ACK:
if (checkCRC((inBuffer + sizeof(struct MacFrameNormal) + 1), sizeof(struct blockRequestAck)))
return (struct blockRequestAck *)(inBuffer + sizeof(struct MacFrameNormal) + 1);
break;
case PKT_BLOCK_PART:
// block already started while we were waiting for a get block reply
// printf("!");
// processBlockPart((struct blockPart *)(inBuffer + sizeof(struct MacFrameNormal) + 1));
return continueToRX();
break;
case PKT_CANCEL_XFER:
return NULL;
default:
printf("pkt w/type %02X\r\n", getPacketType(inBuffer));
break;
}
}
} while (!clock_time_exceed(timeout, 50 * 1000));
}
return continueToRX();
// return NULL;
}
static void sendXferCompletePacket()
{
memset(outBuffer, 0, sizeof(struct MacFrameNormal) + 2 + 4);
struct MacFrameNormal *f = (struct MacFrameNormal *)(outBuffer + 1);
outBuffer[0] = sizeof(struct MacFrameNormal) + 2 + 2;
outBuffer[sizeof(struct MacFrameNormal) + 1] = PKT_XFER_COMPLETE;
memcpy(f->src, mSelfMac, 8);
memcpy(f->dst, APmac, 8);
f->fcs.frameType = 1;
f->fcs.secure = 0;
f->fcs.framePending = 0;
f->fcs.ackReqd = 0;
f->fcs.panIdCompressed = 1;
f->fcs.destAddrType = 3;
f->fcs.frameVer = 0;
f->fcs.srcAddrType = 3;
f->pan = APsrcPan;
f->seq = seq++;
commsTxNoCpy(outBuffer);
}
static void sendXferComplete()
{
radioRxEnable(true);
for (uint8_t c = 0; c < 16; c++)
{
sendXferCompletePacket();
uint32_t timeout = clock_time();
while (!clock_time_exceed(timeout, 6 * 1000))
{
int8_t ret = commsRxUnencrypted(inBuffer);
if (ret > 1)
{
if (getPacketType(inBuffer) == PKT_XFER_COMPLETE_ACK)
{
printf("XFC ACK\r\n");
return;
}
}
}
}
printf("XFC NACK!\r\n");
return;
}
static bool validateBlockData()
{
struct blockData *bd = (struct blockData *)blockXferBuffer;
printf("expected len = %04X, checksum=%04X\r\n", bd->size, bd->checksum);
if (bd->size > BLOCK_XFER_BUFFER_SIZE - sizeof(struct blockData))
{
printf("Impossible data size, we abort here\r\n");
return false;
}
uint16_t t = 0;
for (uint16_t c = 0; c < bd->size; c++)
{
t += bd->data[c];
}
printf("Checked len = %04X, checksum=%04X\r\n", bd->size, t);
return bd->checksum == t;
}
// EEprom related stuff
static uint32_t getAddressForSlot(const uint8_t s)
{
return EEPROM_IMG_START + (EEPROM_IMG_EACH * s);
}
static void getNumSlots()
{
uint32_t eeSize = eepromGetSize();
uint16_t nSlots = eeSize / (EEPROM_IMG_EACH >> 8) >> 8;
if (eeSize < EEPROM_IMG_EACH || !nSlots)
{
printf("eeprom is too small\r\n");
while (1)
;
}
else if (nSlots >> 8)
{
printf("eeprom is too big, some will be unused\r\n");
imgSlots = 254;
}
else
imgSlots = nSlots;
}
static uint8_t findSlot(const uint8_t *ver)
{
return 0xFF; // remove me! This forces the tag to re-download each and every upload without checking if it's already in the eeprom somewhere
uint32_t markerValid = EEPROM_IMG_VALID;
for (uint8_t c = 0; c < imgSlots; c++)
{
struct EepromImageHeader *eih = (struct EepromImageHeader *)blockXferBuffer;
eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader));
if (!memcmp(&eih->validMarker, &markerValid, 4))
{
if (!memcmp(&eih->version, (void *)ver, 8))
{
return c;
}
}
}
return 0xFF;
}
static void eraseUpdateBlock()
{
eepromErase(EEPROM_UPDATA_AREA_START, EEPROM_UPDATE_AREA_LEN);
}
static void eraseImageBlock(const uint8_t c)
{
eepromErase(getAddressForSlot(c), EEPROM_IMG_EACH);
}
static void saveUpdateBlockData(uint8_t blockId)
{
if (!eepromWrite(EEPROM_UPDATA_AREA_START + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), BLOCK_DATA_SIZE))
printf("EEPROM write failed\r\n");
}
static void saveImgBlockData(const uint8_t imgSlot, const uint8_t blockId)
{
uint32_t length = EEPROM_IMG_EACH - (sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE));
if (length > 4096)
length = 4096;
if (!eepromWrite(getAddressForSlot(imgSlot) + sizeof(struct EepromImageHeader) + (blockId * BLOCK_DATA_SIZE), blockXferBuffer + sizeof(struct blockData), length))
printf("EEPROM write failed\r\n");
}
void drawImageFromEeprom(const uint8_t imgSlot)
{
drawImageAtAddress(getAddressForSlot(imgSlot), drawWithLut);
drawWithLut = 0; // default back to the regular ol' stock/OTP LUT
}
static uint32_t getHighSlotId()
{
uint32_t temp = 0;
uint32_t markerValid = EEPROM_IMG_VALID;
for (uint8_t c = 0; c < imgSlots; c++)
{
struct EepromImageHeader *eih = (struct EepromImageHeader *)blockXferBuffer;
eepromRead(getAddressForSlot(c), eih, sizeof(struct EepromImageHeader));
if (!memcmp(&eih->validMarker, &markerValid, 4))
{
if (temp < eih->id)
{
temp = eih->id;
nextImgSlot = c;
}
}
}
printf("found high id=%d in slot %d\r\n", temp, nextImgSlot);
return temp;
}
static uint8_t partsThisBlock = 0;
static uint8_t blockAttempts = 0; // these CAN be local to the function, but for some reason, they won't survive sleep?
// they get overwritten with 7F 32 44 20 00 00 00 00 11, I don't know why.
static bool getDataBlock(const uint16_t blockSize)
{
blockAttempts = BLOCK_TRANSFER_ATTEMPTS;
if (blockSize == BLOCK_DATA_SIZE)
{
partsThisBlock = BLOCK_MAX_PARTS;
memset(curBlock.requestedParts, 0xFF, BLOCK_REQ_PARTS_BYTES);
}
else
{
partsThisBlock = (sizeof(struct blockData) + blockSize) / BLOCK_PART_DATA_SIZE;
if ((sizeof(struct blockData) + blockSize) % BLOCK_PART_DATA_SIZE)
partsThisBlock++;
memset(curBlock.requestedParts, 0x00, BLOCK_REQ_PARTS_BYTES);
for (uint8_t c = 0; c < partsThisBlock; c++)
{
curBlock.requestedParts[c / 8] |= (1 << (c % 8));
}
}
requestPartialBlock = false; // this forces the AP to request the block data from the host
while (blockAttempts--)
{
wdt10s();
#ifndef DEBUGBLOCKS
printf("REQ %d ", curBlock.blockId);
#else
printf("REQ %d[", curBlock.blockId);
for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++)
{
if ((c != 0) && (c % 8 == 0))
printf("][");
if (curBlock.requestedParts[c / 8] & (1 << (c % 8)))
{
printf("R");
}
else
{
printf("_");
}
}
printf("]\r\n");
#endif
struct blockRequestAck *ack = performBlockRequest();
if (ack == NULL)
{
printf("Cancelled request\r\n");
return false;
}
if (ack->pleaseWaitMs)
{ // SLEEP - until the AP is ready with the data
WaitMs(ack->pleaseWaitMs - 10);
}
else
{
// immediately start with the reception of the block data
}
blockRxLoop(270); // BLOCK RX LOOP - receive a block, until the timeout has passed
#ifdef DEBUGBLOCKS
printf("RX %d[", curBlock.blockId);
for (uint8_t c = 0; c < BLOCK_MAX_PARTS; c++)
{
if ((c != 0) && (c % 8 == 0))
printf("][");
if (curBlock.requestedParts[c / 8] & (1 << (c % 8)))
{
printf(".");
}
else
{
printf("R");
}
}
printf("]\r\n");
#endif
// check if we got all the parts we needed, e.g: has the block been completed?
bool blockComplete = true;
for (uint8_t c = 0; c < partsThisBlock; c++)
{
if (curBlock.requestedParts[c / 8] & (1 << (c % 8)))
blockComplete = false;
}
if (blockComplete)
{
#ifndef DEBUGBLOCKS
printf("- COMPLETE\r\n");
#endif
if (validateBlockData())
{
printf("- Validated\r\n");
// block download complete, validated
return true;
}
else
{
for (uint8_t c = 0; c < partsThisBlock; c++)
{
curBlock.requestedParts[c / 8] |= (1 << (c % 8));
}
requestPartialBlock = false;
printf("blk failed validation!\r\n");
}
}
else
{
#ifndef DEBUGBLOCKS
printf("- INCOMPLETE\r\n");
#endif
// block incomplete, re-request a partial block
requestPartialBlock = true;
}
}
printf("failed getting block\r\n");
return false;
}
uint16_t dataRequestSize = 0;
static bool downloadFWUpdate(const struct AvailDataInfo *avail)
{
// check if we already started the transfer of this information & haven't completed it
if (!memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8) && curDataInfo.dataSize)
{
// looks like we did. We'll carry on where we left off.
}
else
{
// start, or restart the transfer from 0. Copy data from the AvailDataInfo struct, and the struct intself. This forces a new transfer
curBlock.blockId = 0;
memcpy(&(curBlock.ver), &(avail->dataVer), 8);
curBlock.type = avail->dataType;
memcpy(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
eraseUpdateBlock();
}
while (curDataInfo.dataSize)
{
wdt10s();
if (curDataInfo.dataSize > BLOCK_DATA_SIZE)
{
// more than one block remaining
dataRequestSize = BLOCK_DATA_SIZE;
}
else
{
// only one block remains
dataRequestSize = curDataInfo.dataSize;
}
if (getDataBlock(dataRequestSize))
{
// succesfully downloaded datablock, save to eeprom
saveUpdateBlockData(curBlock.blockId);
curBlock.blockId++;
curDataInfo.dataSize -= dataRequestSize;
}
else
{
// failed to get the block we wanted, we'll stop for now, maybe resume later
return false;
}
}
// no more data, download complete
return true;
}
uint16_t imageSize = 0;
static bool downloadImageDataToEEPROM(const struct AvailDataInfo *avail)
{
// check if we already started the transfer of this information & haven't completed it
if (!memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8) && curDataInfo.dataSize)
{
// looks like we did. We'll carry on where we left off.
printf("restarting image download");
curImgSlot = nextImgSlot;
}
else
{
// go to the next image slot
nextImgSlot++;
if (nextImgSlot >= imgSlots)
nextImgSlot = 0;
curImgSlot = nextImgSlot;
printf("Saving to image slot %d\r\n", curImgSlot);
drawWithLut = avail->dataTypeArgument;
uint8_t attempt = 5;
while (attempt--)
{
if (eepromErase(getAddressForSlot(curImgSlot), EEPROM_IMG_EACH))
goto eraseSuccess;
}
// eepromFail:
doSleep(-1);
eraseSuccess:
printf("new download, writing to slot %d\r\n", curImgSlot);
// start, or restart the transfer. Copy data from the AvailDataInfo struct, and the struct intself. This forces a new transfer
curBlock.blockId = 0;
memcpy(&(curBlock.ver), &(avail->dataVer), 8);
curBlock.type = avail->dataType;
memcpy(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
imageSize = curDataInfo.dataSize;
}
while (curDataInfo.dataSize)
{
wdt10s();
if (curDataInfo.dataSize > BLOCK_DATA_SIZE)
{
// more than one block remaining
dataRequestSize = BLOCK_DATA_SIZE;
}
else
{
// only one block remains
dataRequestSize = curDataInfo.dataSize;
}
if (getDataBlock(dataRequestSize))
{
// succesfully downloaded datablock, save to eeprom
printf("Saving block %d to slot %d\r\n", curBlock.blockId, curImgSlot);
saveImgBlockData(curImgSlot, curBlock.blockId);
curBlock.blockId++;
curDataInfo.dataSize -= dataRequestSize;
}
else
{
// failed to get the block we wanted, we'll stop for now, probably resume later
return false;
}
}
// no more data, download complete
// borrow the blockXferBuffer temporarily
struct EepromImageHeader *eih = (struct EepromImageHeader *)blockXferBuffer;
memcpy(&eih->version, &curDataInfo.dataVer, 8);
eih->validMarker = EEPROM_IMG_VALID;
eih->id = ++curHighSlotId;
eih->size = imageSize;
eih->dataType = curDataInfo.dataType;
#ifdef DEBUGBLOCKS
printf("Now writing datatype 0x%02X to slot %d\r\n", curDataInfo.dataType, curImgSlot);
#endif
eepromWrite(getAddressForSlot(curImgSlot), eih, sizeof(struct EepromImageHeader));
return true;
}
bool processAvailDataInfo(struct AvailDataInfo *avail)
{
printf("dataType: %d\r\n", avail->dataType);
switch (avail->dataType)
{
case DATATYPE_IMG_BMP:
case DATATYPE_IMG_DIFF:
break;
case DATATYPE_IMG_RAW_1BPP:
case DATATYPE_IMG_RAW_2BPP:
printf("RAW_BPP\r\n");
// check if this download is currently displayed or active
if (curDataInfo.dataSize == 0 && !memcmp((const void *)&avail->dataVer, (const void *)&curDataInfo.dataVer, 8))
{
// we've downloaded this already, we're guessing it's already displayed
printf("currently shown image, send xfc\r\n");
sendXferComplete();
return true;
}
// check if we've seen this version before
curImgSlot = findSlot((uint8_t *)&(avail->dataVer));
if (curImgSlot != 0xFF)
{
// found a (complete)valid image slot for this version
sendXferComplete();
printf("already seen, drawing from eeprom slot %d\r\n", curImgSlot);
// mark as completed and draw from EEPROM
memcpy(&curDataInfo, (void *)avail, sizeof(struct AvailDataInfo));
curDataInfo.dataSize = 0; // mark as transfer not pending
drawWithLut = avail->dataTypeArgument;
wdt60s();
drawImageFromEeprom(curImgSlot);
return true;
}
else
{
// not found in cache, prepare to download
printf("downloading to imgslot\r\n");
drawWithLut = avail->dataTypeArgument;
if (downloadImageDataToEEPROM(avail))
{
printf("download complete!\r\n");
sendXferComplete();
wdt60s();
drawImageFromEeprom(curImgSlot);
return true;
}
else
{
return false;
}
}
break;
case DATATYPE_FW_UPDATE:
if (downloadFWUpdate(avail))
{
sendXferComplete();
printf("firmware download complete, doing update.\r\n");
write_ota_firmware_to_flash();
// test_firmware_writing();
}
else
{
return false;
}
break;
case DATATYPE_NFC_URL_DIRECT:
case DATATYPE_NFC_RAW_CONTENT:
break;
case DATATYPE_CUSTOM_LUT_OTA:
break;
return true;
}
return true;
}
RAM uint32_t address = 0;
RAM uint8_t ramd_to_flash_temp_buffer[PAGE_SIZE];
void test_firmware_writing()
{
irq_disable();
address = 0;
while (address < EEPROM_UPDATE_AREA_LEN)
{
// flash_erase_sector(address);
printf("Erasing sector: %X\r\n", address);
address += 0x1000;
}
address = 0;
while (address < EEPROM_UPDATE_AREA_LEN)
{
flash_read_page(EEPROM_UPDATA_AREA_START + address, PAGE_SIZE, ramd_to_flash_temp_buffer);
printf("Writing page: %X First 10 bytes: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X\r\n", address, ramd_to_flash_temp_buffer[0], ramd_to_flash_temp_buffer[1], ramd_to_flash_temp_buffer[2], ramd_to_flash_temp_buffer[3], ramd_to_flash_temp_buffer[4], ramd_to_flash_temp_buffer[5], ramd_to_flash_temp_buffer[6], ramd_to_flash_temp_buffer[7], ramd_to_flash_temp_buffer[8], ramd_to_flash_temp_buffer[9]);
// flash_write_page(address, PAGE_SIZE, ramd_to_flash_temp_buffer);
address += PAGE_SIZE;
}
analog_write(SYS_DEEP_ANA_REG, analog_read(SYS_DEEP_ANA_REG) & (~SYS_NEED_REINIT_EXT32K));
REG_ADDR8(0x6f) = 0x20;
printf("Now i will reset myself\r\n");
while (1)
{
}
}
_attribute_ram_code_ void write_ota_firmware_to_flash(void)
{
irq_disable();
address = 0;
while (address < EEPROM_UPDATE_AREA_LEN)
{
flash_mspi_write_ram(FLASH_SECT_ERASE_CMD, address, 1, NULL, 0);
address += 0x1000;
}
address = 0;
while (address < EEPROM_UPDATE_AREA_LEN)
{
flash_mspi_read_ram(FLASH_READ_CMD, EEPROM_UPDATA_AREA_START + address, 1, 0, ramd_to_flash_temp_buffer, PAGE_SIZE);
flash_mspi_write_ram(FLASH_WRITE_CMD, address, 1, ramd_to_flash_temp_buffer, PAGE_SIZE);
address += PAGE_SIZE;
}
analog_write(SYS_DEEP_ANA_REG, analog_read(SYS_DEEP_ANA_REG) & (~SYS_NEED_REINIT_EXT32K));
REG_ADDR8(0x6f) = 0x20;
while (1)
{
}
}
void initializeProto()
{
getNumSlots();
curHighSlotId = getHighSlotId();
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
extern uint8_t mSelfMac[];
extern uint8_t currentChannel;
extern uint8_t APmac[];
extern uint8_t curImgSlot;
extern void setupRadio(void);
extern void killRadio(void);
extern struct AvailDataInfo *getAvailDataInfo();
extern struct AvailDataInfo *getShortAvailDataInfo();
extern void drawImageFromEeprom(const uint8_t imgSlot);
extern bool processAvailDataInfo(struct AvailDataInfo *avail);
extern void initializeProto();
extern uint8_t detectAP(const uint8_t channel);
void write_ota_firmware_to_flash(void);

View File

@@ -0,0 +1,42 @@
#define SOLUM_154_SSD1619 0
#define SOLUM_29_SSD1619 0x01
#define SOLUM_29_SSD1619_HIGH_RES 0x03
#define SOLUM_29_UC8151 0x11
#define SOLUM_42_SSD1619 0x02
#define SOLUM_SEG_UK 0xF0
#define SOLUM_SEG_EU 0xF1
#define SOLUM_NODISPLAY 0xFF
#define CAPABILITY_SUPPORTS_COMPRESSION 0x02
#define CAPABILITY_SUPPORTS_CUSTOM_LUTS 0x04
#define CAPABILITY_ALT_LUT_SIZE 0x08
#define CAPABILITY_HAS_EXT_POWER 0x10
#define CAPABILITY_HAS_WAKE_BUTTON 0x20
#define CAPABILITY_HAS_NFC 0x40
#define CAPABILITY_NFC_WAKE 0x80
#define DATATYPE_NOUPDATE 0
#define DATATYPE_IMG_BMP 2
#define DATATYPE_FW_UPDATE 3
#define DATATYPE_IMG_DIFF 0x10 // always 1BPP
#define DATATYPE_IMG_RAW_1BPP 0x20 // 2888 bytes for 1.54" / 4736 2.9" / 15000 4.2"
#define DATATYPE_IMG_RAW_2BPP 0x21 // 5776 bytes for 1.54" / 9472 2.9" / 30000 4.2"
#define DATATYPE_IMG_RAW_1BPP_DIRECT 0x3F // only for 1.54", don't write to EEPROM, but straightaway to the EPD
#define DATATYPE_UK_SEGMENTED 0x51 // Segmented data for the UK Segmented display type (contained in availableData Reply)
#define DATATYPE_EU_SEGMENTED 0x52 // Segmented data for the EU/DE Segmented display type (contained in availableData Reply)
#define DATATYPE_NFC_RAW_CONTENT 0xA0 // raw memory content for the NT3H1101
#define DATATYPE_NFC_URL_DIRECT 0xA1 // URL format for NT3H1101
#define DATATYPE_TAG_CONFIG_DATA 0xA8 // Config data for tag
#define DATATYPE_COMMAND_DATA 0xAF // Command for the tag to execute (contained in availableData Reply)
#define DATATYPE_CUSTOM_LUT_OTA 0xB0 // Custom OTA updated LUT
#define CMD_DO_REBOOT 0
#define CMD_DO_SCAN 1
#define CMD_DO_RESET_SETTINGS 2
#define WAKEUP_REASON_TIMED 0
#define WAKEUP_REASON_GPIO 2
#define WAKEUP_REASON_NFC 3
#define WAKEUP_REASON_FIRSTBOOT 0xFC
#define WAKEUP_REASON_NETWORK_SCAN 0xFD
#define WAKEUP_REASON_WDT_RESET 0xFE

View File

@@ -0,0 +1,44 @@
#include <stdint.h>
#include "tl_common.h"
#include "uart.h"
#include "main.h"
#define RXD GPIO_PA0
#define TXD GPIO_PB1
void init_uart(void)
{
gpio_set_func(TXD, AS_GPIO);
gpio_set_output_en(TXD, 1);
gpio_write(TXD, 0);
gpio_set_func(RXD, AS_GPIO);
gpio_set_input_en(RXD, 1);
gpio_set_output_en(RXD, 0);
uart_gpio_set(UART_TX_PB1, UART_RX_PA0);
uart_reset();
uart_init(12, 15, PARITY_NONE, STOP_BIT_ONE); // baud rate: 115200
uart_dma_enable(0, 0);
dma_chn_irq_enable(0, 0);
uart_irq_enable(0, 0);
uart_ndma_irq_triglevel(0, 0);
}
void puts(const char *str)
{
while (*str != '\0')
{
putchar_custom((char)*str);
str++;
}
}
int putchar_custom(int c)
{
uart_ndma_send_byte((char)c);
while (uart_tx_is_busy())
{
sleep_us(10);
};
return 0;
}

View File

@@ -0,0 +1,4 @@
#pragma once
void init_uart(void);
int putchar_custom(int c);

View File

@@ -0,0 +1,55 @@
/********************************************************************************************************
* @file version_cfg.h
*
* @brief This is the header file for version_cfg
*
* @author Zigbee Group
* @date 2021
*
* @par Copyright (c) 2021, Telink Semiconductor (Shanghai) Co., Ltd. ("TELINK")
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*******************************************************************************************************/
#pragma once
#include "comm_cfg.h"
#if defined(MCU_CORE_826x)
#if (CHIP_8269)
#define CHIP_TYPE TLSR_8269
#else
#define CHIP_TYPE TLSR_8267
#endif
#elif defined(MCU_CORE_8258)
#define CHIP_TYPE TLSR_8258_512K//TLSR_8258_1M
#elif defined(MCU_CORE_8278)
#define CHIP_TYPE TLSR_8278
#elif defined(MCU_CORE_B91)
#define CHIP_TYPE TLSR_B91
#endif
/*********************************************************************************************
* During OTA upgrade, the upgraded device will check the rules of the following three fields.
* Refer to ZCL OTA specification for details.
*/
#define MANUFACTURER_CODE_TELINK 0x1141//Telink ID
#define IMAGE_TYPE ((CHIP_TYPE << 8) | 0)
#define FILE_VERSION (0)
/* Pre-compiled link configuration. */
#define IS_BOOT_LOADER_IMAGE 0
#define RESV_FOR_APP_RAM_CODE_SIZE 0
#define IMAGE_OFFSET APP_IMAGE_ADDR

View File

@@ -0,0 +1,11 @@
#include "wdt.h"
#include "../tl_common.h"
void watchdog_enable(int timeout)
{
wd_stop();
drv_wd_setInterval(timeout);
drv_wd_start();
drv_wd_clear();
}

View File

@@ -0,0 +1,29 @@
#pragma once
void watchdog_enable(int timeout);
#define wdt10s() \
do \
{ \
watchdog_enable(10000); \
} while (0)
#define wdt30s() \
do \
{ \
watchdog_enable(30000); \
} while (0)
#define wdt60s() \
do \
{ \
watchdog_enable(60000); \
} while (0)
#define wdt120s() \
do \
{ \
watchdog_enable(120000); \
} while (0)

View File

@@ -0,0 +1,178 @@
#include "tl_common.h"
#include "main.h"
#include "zigbee.h"
#include <stdint.h>
#include <stdbool.h>
RAM _attribute_aligned_(4) volatile uint8_t rf_tx_buf[ZB_RADIO_TX_HDR_LEN + 250];
RAM _attribute_aligned_(4) volatile uint8_t rf_rx_buf[ZB_RADIO_TX_HDR_LEN + 250];
#define LOGICCHANNEL_TO_PHYSICAL(p) (((p)-10) * 5)
void rf_setChannel(uint8_t chn)
{
u32 r = drv_disable_irq();
uint8_t phySta = ZB_RADIO_TRX_STA_GET();
ZB_RADIO_TRX_SWITCH(phySta, LOGICCHANNEL_TO_PHYSICAL(chn));
drv_restore_irq(r);
}
RAM volatile uint8_t tx_done = 0;
void zigbee_tx(uint8_t *buf, uint8_t len)
{
ZB_RADIO_DMA_HDR_BUILD(rf_tx_buf, len);
rf_tx_buf[4] = len + 2;
memcpy(rf_tx_buf + 5, buf, len);
WaitUs(ZB_TX_WAIT_US);
ZB_RADIO_RX_DONE_CLR;
tx_done = 0;
ZB_RADIO_TX_START(rf_tx_buf);
while (!tx_done)
;
}
#define ZB_MAX_BUFFER 50
RAM volatile uint8_t rxed = 0;
RAM volatile uint8_t bbb[ZB_MAX_BUFFER][250];
RAM volatile uint8_t len = 0;
RAM volatile uint8_t rssi = 0;
RAM volatile uint8_t current_buff = 0;
RAM volatile uint8_t current_buff_worked = 0;
uint8_t getRxBuffer(uint8_t *bufferout, uint8_t *rssiout)
{
if (current_buff != current_buff_worked)
{
uint8_t len_rx = bbb[current_buff_worked][0];
*rssiout = bbb[current_buff_worked][1];
memcpy(bufferout, (uint8_t *)&bbb[current_buff_worked][2], len_rx);
current_buff_worked++;
current_buff_worked %= ZB_MAX_BUFFER;
return len_rx;
}
return 0;
}
void init_zigbee(uint_fast8_t channel)
{
current_buff_worked = current_buff;
rf_set_power_level_index(RF_POWER_INDEX_P3p01dBm);
rf_drv_init(RF_MODE_ZIGBEE_250K);
rf_drv_cap(CFG_FREQUENCY_OFFSET);
drv_hwTmr_init(TIMER_IDX_3, TIMER_MODE_SCLK);
ZB_RADIO_IRQ_MASK_SET;
rf_setChannel(channel);
}
void zigbee_off()
{
rf_set_tx_rx_off();
current_buff_worked = current_buff;
}
void zigbee_rx_start()
{
rf_rx_buffer_set(rf_rx_buf, 250, 0);
rf_set_tx_rx_off();
rf_set_rxmode();
}
__attribute__((optimize("-Os"))) void rf_tx_irq_handler(void)
{
// printf("TX IRQ\r\n");
ZB_RADIO_TX_DONE_CLR;
tx_done = 1;
}
__attribute__((optimize("-Os"))) void rf_rx_irq_handler(void)
{
if (RF_DMA_BUSY())
{
return;
}
ZB_RADIO_RX_DISABLE;
if ((!ZB_RADIO_CRC_OK(rf_rx_buf)) || (!ZB_RADIO_PACKET_LENGTH_OK(rf_rx_buf)))
{
ZB_RADIO_RX_BUF_CLEAR(rf_rx_buf);
ZB_RADIO_RX_ENABLE;
return;
}
bbb[current_buff][0] = rf_rx_buf[4] - 2;
bbb[current_buff][1] = (read_reg8(0x449));
memcpy((uint8_t *)&bbb[current_buff][2], (uint8_t *)&rf_rx_buf[5], bbb[current_buff][0]);
current_buff++;
current_buff %= ZB_MAX_BUFFER;
ZB_RADIO_RX_BUF_CLEAR(rf_rx_buf);
ZB_RADIO_RX_ENABLE;
}
uint8_t channelList[6] = {11, 15, 20, 25, 26, 27};
bool next_ack = 0;
int state = 0;
#define RADIO_MAX_PACKET_LEN (250)
uint8_t seq_nr = 0;
uint8_t get_seq_nr()
{
return seq_nr++;
}
#define MAX_RX_PKTS 8
volatile uint8_t mRxBufs[MAX_RX_PKTS][RADIO_MAX_PACKET_LEN + 1 /* length */ + 1 /* LQI */ + 1 /* RSSI */];
volatile uint8_t mRxNextWrite, mRxNextRead, mRxNumFree, mRxNumGot;
bool mRxEnabled = false;
RAM uint8_t our_ch = 11;
bool radioSetChannel(uint_fast8_t channel)
{
our_ch = channel;
init_zigbee(channel);
return true;
}
bool radioRxEnable(bool on)
{
if (on)
zigbee_rx_start();
return true;
}
void radioRxFlush(void)
{
current_buff_worked = current_buff;
}
bool radioInit(void)
{
return 1;
}
int32_t radioRxDequeuePkt(uint8_t *dstBuf, uint32_t maxLen, int8_t *rssiP, uint8_t *lqiP)
{
u8 curr_rx = getRxBuffer(dstBuf, lqiP);
*rssiP = lqiP;
/*if (curr_rx)
{
printf("RX: ");
for (int i = 0; i < curr_rx; i++)
{
printf(" %02X", dstBuf[i]);
}
printf("\r\n");
}*/
return curr_rx;
}
bool radioTxLL(uint8_t *pkt)
{
init_zigbee(our_ch);
zigbee_tx((uint8_t *)&pkt[1], pkt[0] - 2);
zigbee_rx_start();
return true;
}

View File

@@ -0,0 +1,17 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
extern uint8_t channelList[6];
void init_zigbee(uint_fast8_t channel);
uint8_t getRxBuffer(uint8_t *bufferout, uint8_t *rssiout);
void zigbee_tx(uint8_t *buf, uint8_t len);
void zigbee_off();
void zigbee_rx_start();
bool radioSetChannel(uint_fast8_t channel);
bool radioRxEnable(bool on);
void radioRxFlush(void);
bool radioInit(void);
int32_t radioRxDequeuePkt(uint8_t *dstBuf, uint32_t maxLen, int8_t *rssiP, uint8_t *lqiP);
bool radioTxLL(uint8_t *pkt);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,271 @@
#!/bin/sh -
#
# bashbug - create a bug report and mail it to the bug address
#
# The bug address depends on the release status of the shell. Versions
# with status `devel', `alpha', `beta', or `rc' mail bug reports to
# chet@cwru.edu and, optionally, to bash-testers@cwru.edu.
# Other versions send mail to bug-bash@gnu.org.
#
# Copyright (C) 1996-2004 Free Software Foundation, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# configuration section:
# these variables are filled in by the make target in Makefile
#
MACHINE="i686"
OS="cygwin"
CC="gcc"
CFLAGS=" -DPROGRAM='bash.exe' -DCONF_HOSTTYPE='i686' -DCONF_OSTYPE='cygwin' -DCONF_MACHTYPE='i686-pc-cygwin' -DCONF_VENDOR='pc' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -DRECYCLES_PIDS -I. -I/usr/src/bash-4.3.42-4.i686/src/bash-4.3 -I/usr/src/bash-4.3.42-4.i686/src/bash-4.3/include -I/usr/src/bash-4.3.42-4.i686/src/bash-4.3/lib -DWORDEXP_OPTION -ggdb -O2 -pipe -Wimplicit-function-declaration -fdebug-prefix-map=/usr/src/bash-4.3.42-4.i686/build=/usr/src/debug/bash-4.3.42-4 -fdebug-prefix-map=/usr/src/bash-4.3.42-4.i686/src/bash-4.3=/usr/src/debug/bash-4.3.42-4"
RELEASE="4.3"
PATCHLEVEL="42"
RELSTATUS="release"
MACHTYPE="i686-pc-cygwin"
PATH=/bin:/usr/bin:/usr/local/bin:$PATH
export PATH
# Check if TMPDIR is set, default to /tmp
: ${TMPDIR:=/tmp}
#Securely create a temporary directory for the temporary files
TEMPDIR=$TMPDIR/bbug.$$
(umask 077 && mkdir $TEMPDIR) || {
echo "$0: could not create temporary directory" >&2
exit 1
}
TEMPFILE1=$TEMPDIR/bbug1
TEMPFILE2=$TEMPDIR/bbug2
USAGE="Usage: $0 [--help] [--version] [bug-report-email-address]"
VERSTR="GNU bashbug, version ${RELEASE}.${PATCHLEVEL}-${RELSTATUS}"
do_help= do_version=
while [ $# -gt 0 ]; do
case "$1" in
--help) shift ; do_help=y ;;
--version) shift ; do_version=y ;;
--) shift ; break ;;
-*) echo "bashbug: ${1}: invalid option" >&2
echo "$USAGE" >& 2
exit 2 ;;
*) break ;;
esac
done
if [ -n "$do_version" ]; then
echo "${VERSTR}"
exit 0
fi
if [ -n "$do_help" ]; then
echo "${VERSTR}"
echo "${USAGE}"
echo
cat << HERE_EOF
Bashbug is used to send mail to the Bash maintainers
for when Bash doesn't behave like you'd like, or expect.
Bashbug will start up your editor (as defined by the shell's
EDITOR environment variable) with a preformatted bug report
template for you to fill in. The report will be mailed to the
bug-bash mailing list by default. See the manual for details.
If you invoke bashbug by accident, just quit your editor without
saving any changes to the template, and no bug report will be sent.
HERE_EOF
exit 0
fi
# Figure out how to echo a string without a trailing newline
N=`echo 'hi there\c'`
case "$N" in
*c) n=-n c= ;;
*) n= c='\c' ;;
esac
BASHTESTERS="bash-testers@cwru.edu"
case "$RELSTATUS" in
alpha*|beta*|devel*|rc*) BUGBASH=chet@cwru.edu ;;
*) BUGBASH=bug-bash@gnu.org ;;
esac
case "$RELSTATUS" in
alpha*|beta*|devel*|rc*)
echo "$0: This is a testing release. Would you like your bug report"
echo "$0: to be sent to the bash-testers mailing list?"
echo $n "$0: Send to bash-testers? $c"
read ans
case "$ans" in
y*|Y*) BUGBASH="${BUGBASH},${BASHTESTERS}" ;;
esac ;;
esac
BUGADDR="${1-$BUGBASH}"
if [ -z "$DEFEDITOR" ] && [ -z "$EDITOR" ]; then
if [ -x /usr/bin/editor ]; then
DEFEDITOR=editor
elif [ -x /usr/local/bin/ce ]; then
DEFEDITOR=ce
elif [ -x /usr/local/bin/emacs ]; then
DEFEDITOR=emacs
elif [ -x /usr/contrib/bin/emacs ]; then
DEFEDITOR=emacs
elif [ -x /usr/bin/emacs ]; then
DEFEDITOR=emacs
elif [ -x /usr/bin/xemacs ]; then
DEFEDITOR=xemacs
elif [ -x /usr/contrib/bin/jove ]; then
DEFEDITOR=jove
elif [ -x /usr/local/bin/jove ]; then
DEFEDITOR=jove
elif [ -x /usr/bin/vi ]; then
DEFEDITOR=vi
else
echo "$0: No default editor found: attempting to use vi" >&2
DEFEDITOR=vi
fi
fi
: ${EDITOR=$DEFEDITOR}
: ${USER=${LOGNAME-`whoami`}}
trap 'rm -rf "$TEMPDIR"; exit 1' 1 2 3 13 15
trap 'rm -rf "$TEMPDIR"' 0
UN=
if (uname) >/dev/null 2>&1; then
UN=`uname -a`
fi
if [ -f /usr/lib/sendmail ] ; then
RMAIL="/usr/lib/sendmail"
SMARGS="-i -t"
elif [ -f /usr/sbin/sendmail ] ; then
RMAIL="/usr/sbin/sendmail"
SMARGS="-i -t"
else
RMAIL=rmail
SMARGS="$BUGADDR"
fi
INITIAL_SUBJECT='[50 character or so descriptive subject here (for reference)]'
cat > "$TEMPFILE1" <<EOF
From: ${USER}
To: ${BUGADDR}
Subject: ${INITIAL_SUBJECT}
Configuration Information [Automatically generated, do not change]:
Machine: $MACHINE
OS: $OS
Compiler: $CC
Compilation CFLAGS: $CFLAGS
uname output: $UN
Machine Type: $MACHTYPE
Bash Version: $RELEASE
Patch Level: $PATCHLEVEL
Release Status: $RELSTATUS
Description:
[Detailed description of the problem, suggestion, or complaint.]
Repeat-By:
[Describe the sequence of events that causes the problem
to occur.]
Fix:
[Description of how to fix the problem. If you don't know a
fix for the problem, don't include this section.]
EOF
cp "$TEMPFILE1" "$TEMPFILE2"
chmod u+w "$TEMPFILE1"
trap '' 2 # ignore interrupts while in editor
edstat=1
while [ $edstat -ne 0 ]; do
$EDITOR "$TEMPFILE1"
edstat=$?
if [ $edstat -ne 0 ]; then
echo "$0: editor \`$EDITOR' exited with nonzero status."
echo "$0: Perhaps it was interrupted."
echo "$0: Type \`y' to give up, and lose your bug report;"
echo "$0: type \`n' to re-enter the editor."
echo $n "$0: Do you want to give up? $c"
read ans
case "$ans" in
[Yy]*) exit 1 ;;
esac
continue
fi
# find the subject from the temp file and see if it's been changed
CURR_SUB=`grep '^Subject: ' "$TEMPFILE1" | sed 's|^Subject:[ ]*||' | sed 1q`
case "$CURR_SUB" in
"${INITIAL_SUBJECT}")
echo
echo "$0: You have not changed the subject from the default."
echo "$0: Please use a more descriptive subject header."
echo "$0: Type \`y' to give up, and lose your bug report;"
echo "$0: type \`n' to re-enter the editor."
echo $n "$0: Do you want to give up? $c"
read ans
case "$ans" in
[Yy]*) exit 1 ;;
esac
echo "$0: The editor will be restarted in five seconds."
sleep 5
edstat=1
;;
esac
done
trap 'rm -rf "$TEMPDIR"; exit 1' 2 # restore trap on SIGINT
if cmp -s "$TEMPFILE1" "$TEMPFILE2"
then
echo "File not changed, no bug report submitted."
exit
fi
echo $n "Send bug report to ${BUGADDR}? [y/n] $c"
read ans
case "$ans" in
[Nn]*) exit 0 ;;
esac
${RMAIL} $SMARGS < "$TEMPFILE1" || {
cat "$TEMPFILE1" >> $HOME/dead.bashbug
echo "$0: mail failed: report saved in $HOME/dead.bashbug" >&2
}
exit 0

Binary file not shown.

View File

@@ -0,0 +1,76 @@
#!/bin/sh
# sh is buggy on RS/6000 AIX 3.2. Replace above line with #!/bin/ksh
# Bzcmp/diff wrapped for bzip2,
# adapted from zdiff by Philippe Troin <phil@fifi.org> for Debian GNU/Linux.
# Bzcmp and bzdiff are used to invoke the cmp or the diff pro-
# gram on compressed files. All options specified are passed
# directly to cmp or diff. If only 1 file is specified, then
# the files compared are file1 and an uncompressed file1.gz.
# If two files are specified, then they are uncompressed (if
# necessary) and fed to cmp or diff. The exit status from cmp
# or diff is preserved.
PATH="/usr/bin:/bin:$PATH"; export PATH
prog=`echo $0 | sed 's|.*/||'`
case "$prog" in
*cmp) comp=${CMP-cmp} ;;
*) comp=${DIFF-diff} ;;
esac
OPTIONS=
FILES=
for ARG
do
case "$ARG" in
-*) OPTIONS="$OPTIONS $ARG";;
*) if test -f "$ARG"; then
FILES="$FILES $ARG"
else
echo "${prog}: $ARG not found or not a regular file"
exit 1
fi ;;
esac
done
if test -z "$FILES"; then
echo "Usage: $prog [${comp}_options] file [file]"
exit 1
fi
tmp=`mktemp ${TMPDIR:-/tmp}/bzdiff.XXXXXXXXXX` || {
echo 'cannot create a temporary file' >&2
exit 1
}
set $FILES
if test $# -eq 1; then
FILE=`echo "$1" | sed 's/.bz2$//'`
bzip2 -cd "$FILE.bz2" | $comp $OPTIONS - "$FILE"
STAT="$?"
elif test $# -eq 2; then
case "$1" in
*.bz2)
case "$2" in
*.bz2)
F=`echo "$2" | sed 's|.*/||;s|.bz2$||'`
bzip2 -cdfq "$2" > $tmp
bzip2 -cdfq "$1" | $comp $OPTIONS - $tmp
STAT="$?"
/bin/rm -f $tmp;;
*) bzip2 -cdfq "$1" | $comp $OPTIONS - "$2"
STAT="$?";;
esac;;
*) case "$2" in
*.bz2)
bzip2 -cdfq "$2" | $comp $OPTIONS "$1" -
STAT="$?";;
*) $comp $OPTIONS "$1" "$2"
STAT="$?";;
esac;;
esac
exit "$STAT"
else
echo "Usage: $prog [${comp}_options] file [file]"
exit 1
fi

Some files were not shown because too many files have changed in this diff Show More