Compare commits

..

73 Commits

Author SHA1 Message Date
pelgraine 6360a167c5 Merge branch 'dev' 2026-04-19 21:04:09 +10:00
pelgraine ca5283af4f update readme, particularly licence section 2026-04-19 21:03:31 +10:00
pelgraine b42291c5fc fix bubble display t5s3 for channel picker 2026-04-19 21:02:47 +10:00
pelgraine 8f0d961048 update readme for v1.7 updates 2026-04-19 20:54:13 +10:00
pelgraine 27e8b8422b Merge branch 'dev' 2026-04-19 20:42:45 +10:00
pelgraine b57e000496 fix: remove BLE sync marking channels as read (regression from Feb).
The markChannelReadFromBLE() calls in the CMD_SYNC_NEXT_MESSAGE handler were marking channels and DMs as read the moment the BLE companion app synced them from the offline queue. Since the app drains the entire queue automatically on connect, this had the effect of clearing all unread indicators on the device as soon as BLE connected — before the user had actually read anything in either the app or on the device.
The MeshCore BLE protocol has no "user opened this channel" command from the app side; CMD_SYNC_NEXT_MESSAGE is an automatic bulk pull, so "synced to app" ≠ "read by user." Removed the channel and DM mark-read calls so unread counts only clear when the user navigates to that channel on the device itself. The msgRead() progress counter (syncing X messages) is unaffected.
2026-04-19 20:41:06 +10:00
pelgraine f449385e8f Merge branch 'dev' :) 2026-04-19 20:30:15 +10:00
pelgraine 31ac732f08 fix bug where channels imported from older config files displayed gibberish in channel scope under settingsscreen even when region scope not set; fix bug where after device clock sync advert times last heard weren't displaying correctly (ie showed 16895h) 2026-04-19 20:23:12 +10:00
pelgraine 46413b9858 add serial command support for regions, update serial settings guide 2026-04-19 19:53:45 +10:00
pelgraine ce6acdfd34 temp cmd 54 support 2026-04-19 19:40:03 +10:00
pelgraine 81b3cd2591 try and improve key responsiveness/debounce in compose mode; fix crowding in channel screen navbar text in tiny font mode 2026-04-19 18:36:25 +10:00
pelgraine 5c275a8c23 Regions - including settings nudge to remind user if no default nor channel region set. Set region by typing custom entry 2026-04-19 18:17:25 +10:00
pelgraine b536e24f8e fix word wrapping ereader for larger custom font selection 2026-04-19 17:57:29 +10:00
pelgraine 5b38b713da fix home screen ui display when montserrat or notosans selected; fix word wrap display for other fonts in tiny mode for ereader 2026-04-19 17:27:48 +10:00
pelgraine 3e6bcfb031 updated loading splash screen for spiffs failure message first time flashers 2026-04-19 16:03:37 +10:00
pelgraine 49f1d91c15 tdpro - fixed notes screen touch recog and file open bug 2026-04-19 15:55:47 +10:00
pelgraine 8e3a09e3b1 added channel picker screen as messages home screen view; fixed battery curve reading to better reflect actual charge state (4200 to 4160); patched clock sync to throw out garbage rtc when device has been powered off for a while & now syncs on ble app connection: more font style customisation; nav bar hint text reduced when larger fonts are selected; ensured font style persists across reboots 2026-04-19 15:37:52 +10:00
pelgraine 1c4d5a0daa updated readme for clarity, esp re meck remote wifi repeaters functionality 2026-04-12 23:20:11 +10:00
pelgraine df6c977ee4 updated readme 2026-04-12 23:13:27 +10:00
pelgraine 7e9e69dd67 renamed WIP folders 2026-04-12 23:06:31 +10:00
pelgraine 6d7fd54b83 reordered emojis and improved scrolling in tdpro emojipicker; build emoji picker functionality into vkb for t5s3 2026-04-12 22:01:17 +10:00
pelgraine d2ce070a3f fix wifi companion builds sync bug & add planning for future 1000+ contacts load 2026-04-12 21:04:35 +10:00
pelgraine 44b68c40af tdpro platformio - removed unncessary helpers/esp32/SerialBLEInterface.cpp from build filters for wifi and standalone envs 2026-04-12 20:52:31 +10:00
pelgraine a4e8c31a16 fiiiiixed the contacts add and delete and toggle fav issues for real this time 2026-04-12 20:42:45 +10:00
pelgraine 8d69b69e1f fix contact limits in readme 2026-04-12 18:22:35 +10:00
pelgraine 0c032429eb Added new emoji to emoji picker; bug fixes for larger battery capacities recognition regression; updated readme for clarity on contacts add; updated firmware version; fix stupid blob storage size & buffer issue so now you can add contacts from last heard finally!!! Updated readme accordingly 2026-04-12 18:15:33 +10:00
pelgraine c578dcadc8 T5S3 - fixed touch selector fav contacts bug
TDPro - Update firmware build date

Contactsscreen.h — five changes:

- EPOCH_2026 = 1735689600UL constant added (Jan 1 2026 UTC), used in sort
  and formatAge.

- typeChar replaced by typeStr returning const char*, with "RS" for room
  servers (previously "S", easily confused with sensors). prefix buffer
  bumped to [5], all three snprintf calls updated to %s.

- Hop display: out_path_len == 0xFF branch now performs a live lookup
  against the 12 most recently heard advert paths (via
  getRecentlyHeard). Matches on first 7 bytes of pub_key, extracts hop
  count with a bph-aware sanity cap (64/bph max) to reject impossible
  values. Shows "~D" for direct flood neighbours, "~N" for N-hop flood
  path, "?" if not in the recent-heard cache. Resets to "?" on reboot
  until each contact re-advertises — intentional, ensures hop count is
  always fresh.

- Sort: _filteredTs now stores contact.lastmod (our local receive time)
  instead of contact.last_advert_timestamp (sender's claimed time).
  lastmod values below EPOCH_2026 are stored as 0 so stale repeaters
  with unsynced clocks and contacts received before our own timesync
  sink to the bottom of the list.

- formatAge rewritten: rejects timestamp == 0, timestamp < EPOCH_2026,
  and now < timestamp (all show "--" instead of wrapping or displaying
  garbage). Arithmetic changed from int to uint32_t, eliminating the
  signed overflow path that produced negative hour values. Age display
  call site switched from last_advert_timestamp to lastmod, so display
  self-corrects after a GPS or 4G timesync.
2026-04-12 12:44:10 +10:00
pelgraine ec42ac73a8 removed non-Meck v4 build 2026-04-12 09:25:38 +10:00
pelgraine aacf8c777f prelim techo card WIP files while I wait for hardware to arrive. claude putting excessive comments in platformio descriptors 2026-04-12 09:24:37 +10:00
pelgraine 570776478c merge tdeck pro max WIP variant into dev 2026-04-12 09:01:22 +10:00
pelgraine 4c654c99c6 remote wifi repeater updates - removed unnecessary envs for v4; setup v3 for remote wifi repeater role 2026-04-11 09:58:50 +10:00
pelgraine f436f5ba50 t5s3 contact limit fix 2026-04-09 12:18:29 +10:00
pelgraine 0252204d73 cpu fix for heltec v4 remote repeater build headless 2026-04-08 20:51:44 +10:00
pelgraine 9c4c4d2e03 Merge pull request #6 from pelgraine/dev
Dev
2026-04-07 20:06:51 +10:00
pelgraine 595f0073f9 TDeckBoard.cpp — both * 3 / 2 thresholds changed to > designCapacity_mAh, so FCC=3000 with DC=2500 now triggers the Qmax + stored FCC correction.
SerialBLEInterface.cpp — added esp_bt.h include and three esp_ble_tx_power_set calls at +9 dBm after BLEDevice::init(), covering default, advertising, and scan power types.

MyMesh.h — FIRMWARE_VER_CODE bumped from 10 → 11.
MyMesh.cpp — The RESP_CODE_DEVICE_INFO frame construction now:
Byte 2: sends 0xFF (sentinel) when MAX_CONTACTS > 510, otherwise the normal MAX_CONTACTS / 2. Older apps interpret 0xFF as 510 contacts — completely harmless.
Bytes 80-81 (new, appended after the version string): uint16_t little-endian with the true MAX_CONTACTS value. Apps that understand v11+ read it here. Apps < v11 ignore trailing bytes — the BLE/serial frame protocol is length-delimited, so extra bytes at the tail are safe.

platformio.ini — Both BLE builds (meck_audio_ble, meck_4g_ble) bumped from 510 → 2000.

mymesh.cpp: writeContactRespFrame return type change (return _serial->writeFrame() result)
checkSerialInterface() batch-fill loop.
2026-04-07 20:04:36 +10:00
pelgraine 8aa0f0388e meck wifi remote repeater heltec v4 2026-04-05 21:14:52 +10:00
pelgraine b070af39cc t5s3 wifi remote repeater 2026-04-05 08:57:47 +10:00
pelgraine c939aa577b fix prior env sensor manager build filter for remote repeater envs 2026-04-04 12:38:06 +11:00
pelgraine abccfe154e improve remote wifi repeater compile time 2026-04-04 12:16:52 +11:00
pelgraine 23733ca555 improve tdpro all builds compilation time but esp for remote repeater envs 2026-04-04 12:08:17 +11:00
pelgraine 9d45ac52eb fix wifi repeater and remote repeater ota process, update firmware version platiformio 2026-04-04 11:40:25 +11:00
pelgraine 424e152d4b simple remote wifi repeater v0.2 & remote repeater path hash mode improvements 2026-04-04 10:51:48 +11:00
pelgraine c687133b05 tdpro refined file export contacts selection json 2026-03-31 02:49:57 +11:00
pelgraine c7d0449181 remove sleep for remote repeater 2026-03-30 13:20:31 +11:00
pelgraine 9ddb692806 fix mqttsubscribe 2026-03-30 13:11:54 +11:00
pelgraine 0cab2ddfa7 fix tdpro remote admin display and lora init sd card mix 2026-03-30 13:02:31 +11:00
pelgraine d07ad71d5d tdpro remote 4g repeater admin via web app 2026-03-30 12:23:02 +11:00
pelgraine b4983e48f0 set custom contact paths 2026-03-29 17:06:45 +11:00
pelgraine b991eb0fe7 bumped up max contacts for BLE companions to 510 2026-03-29 16:15:55 +11:00
pelgraine c15b30079c update f send key for previously recorded voice notes 2026-03-29 14:49:31 +11:00
pelgraine 9d7cbd4866 tdpro audio only - voice notes over lora - 5 seconds stage 1 2026-03-29 14:04:54 +11:00
pelgraine b9283af7fc update serial settings guide 2026-03-28 01:41:40 +11:00
pelgraine 39cd30890b update readme for new v1.5 features 2026-03-28 01:41:16 +11:00
pelgraine 902577ed10 update build date 2026-03-28 01:11:26 +11:00
pelgraine ce93cfa033 sd file manager ota system 2026-03-27 03:36:20 +11:00
pelgraine 2be399f65a undo accidental battery size change commit 2026-03-27 02:59:51 +11:00
pelgraine 5679cda38e tdpro touch paches - dialpad touch system conflict fix and longpress changed to 750ms 2026-03-27 02:43:06 +11:00
pelgraine 1ea883783c update firmware version for incoming ota file handler updates 2026-03-27 02:29:09 +11:00
pelgraine bf8cf32bc2 speed up ble sync time; fix version in tdpro platformio 2026-03-27 01:56:17 +11:00
pelgraine 465a29bb23 fix bootindex method so ereader subdirectory files are recognised and pre-cache is completed properly 2026-03-27 00:58:02 +11:00
pelgraine 81eca29b69 implement meshcore PR 2151 changes 2026-03-27 00:43:10 +11:00
pelgraine 342cf4e745 tdpro large font pref option; various large font ui fixes; fix fcc recognition in t5s3 to match 1500 2026-03-26 15:34:09 +11:00
pelgraine c52a190ace update build date 2026-03-26 00:56:20 +11:00
pelgraine a7bc7a4733 t5s3 only lightsleep mode 2026-03-25 20:17:42 +11:00
pelgraine 47a0d2cc95 Update README.md
Made it really stupidly clear that this is vibecoded
2026-03-25 19:57:47 +11:00
pelgraine 5dda0b686e Incorporate PR 2044 and 2141; tdpro alarm screen - needs 44khz mp3 for sounds 2026-03-25 19:57:35 +11:00
pelgraine 60dcd6a89e tdpro - remove hint after boot for non-first time flash 2026-03-25 07:25:48 +11:00
pelgraine 19efb52521 udpate readme 2026-03-23 15:16:57 +11:00
pelgraine 81ef3ea3c5 update hint text for nav hint for first-time flashers; fix spiffs failure for first-time flash boot 2026-03-23 14:59:31 +11:00
pelgraine 6f07b7a372 update readme to do 2026-03-23 13:36:54 +11:00
pelgraine b0f74b101a tdpro - update firmware build date; improve keyboard responsiveness after boot 2026-03-23 13:33:23 +11:00
pelgraine 06a064538e fix lock screen bug cpupowermanager issue 2026-03-22 22:56:28 +11:00
pelgraine 166a433353 td pro - fix missing F discover prompt on home screen for standalone variants 2026-03-22 19:58:12 +11:00
120 changed files with 30131 additions and 3499 deletions
+401 -49
View File
@@ -1,6 +1,6 @@
## Meshcore + Fork = Meck
A fork created specifically to focus on enabling BLE & WiFi companion firmware for the LilyGo T-Deck Pro & LilyGo T5 E-Paper S3 Pro. Created with the assistance of Claude AI using Meshcore v1.11 code.
A fork created specifically to focus on enabling BLE & WiFi companion firmware for the LilyGo T-Deck Pro & LilyGo T5 E-Paper S3 Pro. Created wholly with Claude AI using Meshcore v1.11 code. 100% vibecoded.
[Check out the Meck discussion channel on the MeshCore Discord](https://discord.com/channels/1343693475589263471/1460136499390447670)
@@ -15,6 +15,7 @@ A fork created specifically to focus on enabling BLE & WiFi companion firmware f
- [Launcher](#launcher)
- [OTA Firmware Update](#ota-firmware-update-v13)
- [Path Hash Mode (v0.9.9+)](#path-hash-mode-v099)
- [Region Scope (v1.7+)](#region-scope-v17)
- [T-Deck Pro](#t-deck-pro)
- [Build Variants](#t-deck-pro-build-variants)
- [Keyboard Controls](#t-deck-pro-keyboard-controls)
@@ -23,17 +24,23 @@ A fork created specifically to focus on enabling BLE & WiFi companion firmware f
- [WiFi Companion](#wifi-companion)
- [Clock & Timezone](#clock--timezone)
- [Channel Message Screen](#channel-message-screen)
- [Channel Picker](#channel-picker)
- [Contacts Screen](#contacts-screen)
- [Sending a Direct Message](#sending-a-direct-message)
- [Roomservers](#roomservers)
- [Repeater Admin Screen](#repeater-admin-screen)
- [Settings Screen](#settings-screen)
- [Font Styles](#font-styles)
- [Compose Mode](#compose-mode)
- [Symbol Entry (Sym Key)](#symbol-entry-sym-key)
- [Emoji Picker](#emoji-picker)
- [SMS & Phone App (4G only)](#sms--phone-app-4g-only)
- [Web Browser & IRC](#web-browser--irc)
- [Alarm Clock (Audio only)](#alarm-clock-audio-only)
- [Voice Notes Over LoRa (Audio only)](#voice-notes-over-lora-audio-only)
- [Lock Screen (T-Deck Pro)](#lock-screen-t-deck-pro)
- [Remote Repeater (T-Deck Pro 4G)](#remote-repeater-t-deck-pro-4g)
- [WiFi Repeater](#wifi-repeater)
- [T5S3 E-Paper Pro](#t5s3-e-paper-pro)
- [Build Variants](#t5s3-build-variants)
- [Touch Navigation](#touch-navigation)
@@ -49,6 +56,8 @@ A fork created specifically to focus on enabling BLE & WiFi companion firmware f
- [Text & EPUB Reader](TXT___EPUB_Reader_Guide.md)
- [Web Browser & IRC Guide](Web_App_Guide.md)
- [SMS & Phone App Guide](SMS___Phone_App_Guide.md)
- [Audiobook Player Guide](Audiobook_Player_Guide.md)
- [Meck-Mycelium Web App](#meck-mycelium-web-app)
- [About MeshCore](#about-meshcore)
- [What is MeshCore?](#what-is-meshcore)
- [Key Features](#key-features)
@@ -66,14 +75,16 @@ A fork created specifically to focus on enabling BLE & WiFi companion firmware f
## Supported Devices
Meck currently targets two LilyGo devices:
Meck currently targets two LilyGo devices and also supports the Heltec V3 and V4 as remote repeaters:
| Device | Display | Input | LoRa | Battery | GPS | RTC |
|--------|---------|-------|------|---------|-----|-----|
| **T-Deck Pro** | 240×320 e-ink (GxEPD2) | TCA8418 keyboard + optional touch | SX1262 | BQ27220 fuel gauge, 1400 mAh | Yes | No (uses GPS time) |
| **T5S3 E-Paper Pro** (V2, H752-B) | 960×540 e-ink (FastEPD, parallel) | GT911 capacitive touch (no keyboard) | SX1262 | BQ27220 fuel gauge, 1500 mAh | No (non-GPS variant) | Yes (PCF8563 hardware RTC) |
| **Heltec V3** (remote repeater only) | 0.96" OLED (SSD1306) | — | SX1262 | — | No | No |
| **Heltec V4** (remote repeater only) | 0.96" OLED (SSD1306) | — | SX1262 | — | No | No |
Both devices use the ESP32-S3 with 16 MB flash and 8 MB PSRAM.
The T-Deck Pro and T5S3 use the ESP32-S3 with 16 MB flash and 8 MB PSRAM. The Heltec V3 and V4 use the ESP32-S3 with 8 MB flash and 8 MB PSRAM.
---
@@ -81,7 +92,7 @@ Both devices use the ESP32-S3 with 16 MB flash and 8 MB PSRAM.
**An SD card is essential for Meck to function properly.** Many features — including the e-book reader, notes, bookmarks, web reader cache, audiobook playback, firmware updates, contact import/export, and WiFi credential storage — rely on files stored on the SD card. Without an SD card inserted, the device will boot and handle mesh messaging, but most extended features will be unavailable or will fail silently.
**Recommended:** A **32 GB or larger** microSD card formatted as **FAT32**. MeshCore users have found that **SanDisk** microSD cards are the most reliable across both the T-Deck Pro and T5S3.
**Recommended:** A **32 GB or larger** microSD card formatted as **FAT32**. Meck's extensive feature set — audiobooks, e-books, voice recordings, contact exports, alarm sounds, web reader cache, notes, and firmware images — can accumulate significant storage over time, so a larger card is worthwhile. MeshCore users have found that **SanDisk** microSD cards are the most reliable across both the T-Deck Pro and T5S3.
---
@@ -138,7 +149,7 @@ If you're loading firmware from an SD card via the LilyGo Launcher firmware, use
Once Meck is installed, you can update firmware directly from your phone — no computer or serial cable required. The device creates a temporary WiFi access point and you upload the new `.bin` via your phone's browser.
1. Download the new **non-merged** `.bin` to your phone (from GitHub Releases, Discord, etc.)
2. On the device: **Settings → Firmware Update → Enter** (T-Deck Pro) or **tap** (T5S3)
2. On the device: **Settings → OTA Tools → Firmware Update → Enter** (T-Deck Pro) or **tap** (T5S3)
3. The device starts a WiFi network called `Meck-Update-XXXX` and displays connection details
4. On your phone: connect to the `Meck-Update` WiFi network, open a browser, go to `192.168.4.1`
5. Tap **Choose File**, select the `.bin`, tap **Upload**
@@ -148,6 +159,8 @@ The partition layout supports dual OTA slots — the old firmware remains on the
> **Note:** Use the **non-merged** `.bin` for OTA updates. The merged binary is only needed for first-time USB flashing.
**OTA Tools (v1.5+):** The firmware update has moved into **Settings → OTA Tools**, a submenu that also contains the new **SD File Manager**. The file manager creates the same WiFi access point and serves a browser-based interface where you can browse, upload, download, and delete files on the SD card from your phone — useful for managing audiobooks, alarm sounds, e-books, and notes without ejecting the SD card. Both OTA tools work on all variants including standalone builds.
---
## Path Hash Mode (v0.9.9+)
@@ -172,20 +185,38 @@ For a detailed explanation of what multibyte path hash means and why it matters,
---
## Region Scope (v1.7+)
Regions limit how far your flood messages propagate through the mesh. When you set a region, outgoing messages are tagged with a transport code that repeaters use to decide whether to forward them. Messages sent without a region reach all repeaters via the default wildcard, same as always.
Meck does not pre-set any region on a fresh flash. Region names are determined by your local mesh community — check with your local group for the names in use. Common patterns follow ISO 3166 country/subdivision codes (e.g. `au` for Australia, `gb-eng` for England, `us-ca` for California), but communities may also use custom names for their area. Region names must be lowercase alphanumeric characters and hyphens only, max 29 characters.
**Device-wide default region:** Set in **Settings → Default Region**. This applies to all channels and DMs unless a channel has its own override.
**Per-channel region:** In Settings → Channels, select a channel and press Enter to edit its region scope. This overrides the device default for that specific channel only.
**Settings nudge:** When exiting settings, if no region is configured anywhere (no device default and no per-channel scopes), a prompt reminds you to consider setting one. You can dismiss it to stay unscoped.
Region scope can also be configured via serial commands — see the [Serial Settings Guide](Serial_Settings_Guide.md) for `set region`, `get region`, `set channel.scope`, and `get channel.scope` commands.
---
## T-Deck Pro
### T-Deck Pro Build Variants
| Variant | Environment | BLE | WiFi | 4G Modem | Audio DAC | Web Reader | Max Contacts |
|---------|------------|-----|------|----------|-----------|------------|-------------|
| Audio + BLE | `meck_audio_ble` | Yes | Yes (via BLE stack) | — | PCM5102A | Yes | 500 |
| Audio + WiFi | `meck_audio_wifi` | — | Yes (TCP:5000) | — | PCM5102A | Yes | 1,500 |
| Audio + Standalone | `meck_audio_standalone` | — | — | — | PCM5102A | No | 1,500 |
| 4G + BLE | `meck_4g_ble` | Yes | Yes | A7682E | — | Yes | 500 |
| 4G + WiFi | `meck_4g_wifi` | — | Yes (TCP:5000) | A7682E | — | Yes | 1,500 |
| 4G + Standalone | `meck_4g_standalone` | — | Yes | A7682E | — | Yes | 1,500 |
| Audio + BLE | `meck_audio_ble` | Yes | Yes (web reader only) | — | PCM5102A | Yes | 2,000 |
| Audio + WiFi | `meck_audio_wifi` | — | Yes (TCP:5000) | — | PCM5102A | Yes | 2,000 |
| Audio + Standalone | `meck_audio_standalone` | — | — | — | PCM5102A | No | 2,000 |
| 4G + BLE | `meck_4g_ble` | Yes | Yes | A7682E | — | Yes | 2,000 |
| 4G + WiFi | `meck_4g_wifi` | — | Yes (TCP:5000) | A7682E | — | Yes | 2,000 |
| 4G + Standalone | `meck_4g_standalone` | — | Yes | A7682E | — | Yes | 2,000 |
| Remote Repeater (4G) | `meck_remote_repeater` | — | — | A7682E (MQTT) | — | No | — |
| WiFi Repeater | `meck_wifi_repeater` | — | Yes (MQTT) | — | — | No | — |
The audio DAC and 4G modem occupy the same hardware slot and are mutually exclusive.
The audio DAC and 4G modem occupy the same hardware slot and are mutually exclusive. The remote repeater and WiFi repeater variants operate as dedicated MeshCore repeaters — they forward mesh traffic and respond to guest logins as normal, but **admin management is handled remotely via MQTT** through the [Meck-Mycelium dashboard](https://pelgraine.github.io/Meck-Mycelium), not via the standard mesh admin password login. See [Remote Repeater](#remote-repeater-t-deck-pro-4g) and [WiFi Repeater](#wifi-repeater) below.
### T-Deck Pro Keyboard Controls
@@ -206,9 +237,11 @@ The T-Deck Pro firmware includes full keyboard support for standalone messaging
| B | Open web browser (BLE and 4G variants only) |
| T | Open SMS & Phone app (4G variant only) |
| P | Open audiobook player (audio variant only) |
| K | Open alarm clock (audio variant only) |
| F | Open node discovery (search for nearby repeaters/nodes) |
| H | Open last heard list (passive advert history) |
| G | Open map screen (shows contacts with GPS positions) |
| Mic | Open voice messages (audio variant only) |
| Q | Back to home screen |
| Double-click Boot | Lock / unlock screen |
@@ -233,8 +266,6 @@ Connect the MeshCore web app or meshcore.js to `<device IP>:5000`.
WiFi is also used by the web reader and IRC client on WiFi variants. The web reader shares the same connection — no extra setup needed.
> **Tip:** WiFi variants support up to 1,500 contacts (vs 500 for BLE variants) because they are not constrained by the BLE protocol ceiling.
### Clock & Timezone
The T-Deck Pro does not include a dedicated RTC chip, so after each reboot the device clock starts unset. The clock will appear in the nav bar (between node name and battery) once the time has been synced by one of these methods:
@@ -262,26 +293,99 @@ The GPS page also shows the current time, satellite count, position, altitude, a
| Key | Action |
|-----|--------|
| W / S | Scroll messages up/down |
| A / D | Switch between channels (press D past the last channel to reach the DM inbox, A to return) |
| A / D | Open channel picker — shows all channels and DM inbox with unread badges. Select a channel and press Enter to switch. |
| Enter | Compose new message |
| R | Reply to a message — enter reply select mode, scroll to a message with W/S, then press Enter to compose a reply with an @mention |
| V | View relay path of the last received message (scrollable, up to 20 hops) |
| Q | Back to channel picker |
### Channel Picker
Pressing **A** or **D** on the channel messages screen opens the channel picker. All your channels and the DM inbox are shown in a single view with unread message badges, letting you jump directly to any channel instead of cycling through them one at a time.
| Key | Action |
|-----|--------|
| W / S | Navigate up / down |
| Enter | Switch to selected channel |
| Q | Back to home screen |
On the T5S3, swiping left or right on the channel messages screen also opens the channel picker, which displays a **vertical bubble list** matching the Meck P4 aesthetic.
### Contacts Screen
Press **C** from the home screen to open the contacts list. All known mesh contacts are shown sorted by most recently seen, with their type (Chat, Repeater, Room, Sensor), hop count, and time since last advert.
Press **C** from the home screen to open the contacts list. All known mesh contacts are shown sorted by most recently heard, with their type prefix, estimated hop count, and time since last advert.
**Contact type prefixes**
| Prefix | Type |
|--------|------|
| C | Chat node |
| R | Repeater |
| RS | Room server |
| ? | Unknown / sensor |
**Hop count display**
| Display | Meaning |
|---------|---------|
| `D` | Direct path known (path exchange completed) |
| `D*` | Direct path, manually locked |
| `N` | N-hop path known (e.g. `2` = 2 hops) |
| `N*` | N-hop path, manually locked |
| `~D` | Heard direct via flood advert (no path exchange yet) |
| `~N` | Estimated N hops via flood advert |
| `?` | No path information available |
Flood-based hop estimates (`~D`, `~N`) are drawn from a cache of up to 1,000 recently heard adverts and reset to `?` on reboot until each contact re-advertises. Confirmed path values (`D`, `N`) persist until overwritten by a new path exchange.
**Normal mode controls**
| Key | Action |
|-----|--------|
| W / S | Scroll up / down through contacts |
| A / D | Cycle filter: All → Chat → Repeater → Room → Sensor → Favourites |
| Enter | Open DM compose (Chat contact) or repeater admin (Repeater contact) |
| X | Export contacts to SD card (wait 510 seconds for confirmation popup) |
| R | Import contacts from SD card (wait 510 seconds for confirmation popup) |
| A / D | Cycle filter: All → Chat → Rptr → Room → Sens → Fav |
| Enter | Enter select mode (highlights current contact, enables batch operations) |
| P | Open path editor for the highlighted contact |
| Q | Back to home screen |
**Contact limits:** Standalone and WiFi variants support up to 1,500 contacts (stored in PSRAM). BLE variants (Audio-BLE and 4G-BLE) are limited to 500 contacts due to BLE protocol constraints.
> **Note:** The **Fav** filter shows only contacts you have marked as favourites. If it appears empty, no contacts have been favourited yet — use select mode (Enter) and then **F** to mark contacts.
**Select mode** — press Enter from the contacts list to enter select mode. The highlighted contact is pre-selected. Use W/S to scroll and Enter to toggle selection on any row.
| Key | Action |
|-----|--------|
| W / S | Scroll up / down |
| Enter | Toggle selection on current contact |
| A | Select all contacts in current filter |
| D | Deselect all |
| F | Toggle favourite on all selected contacts |
| X | Export selected contacts to SD card |
| Backspace | Delete selected contacts |
| Q | Exit select mode |
**Adding contacts**
Contacts can be added three ways:
1. **Automatic** — if Settings → Contacts → Add Mode is set to *Auto All*, any node whose advert is heard is added automatically. *Custom* mode adds only nodes matching the enabled type toggles (Companion, Repeater, Room Server, Sensor) — each toggle controls whether receiving an advert of that type triggers an auto-add. *Manual Only* disables all auto-add.
2. **From the Last Heard screen** — press **H** from the home screen to open the last-heard advert list. Scroll to the node you want and press **Enter** (or tap the row) to add it to contacts. Press **Enter** again on an existing contact to remove it (favourites require a second press within 3 seconds to confirm). Entries show `[+]` if already in contacts, `[★]` if a favourite.
> **Note:** The Last Heard list holds up to 1,000 entries in PSRAM, and advert data is stored persistently on the SD card — so contacts can be added long after the original advertisement was received, even across reboots. This makes Last Heard especially useful when auto-add is set to *Manual Only*, as it provides a passive catalogue of every node heard on the network.
3. **From the Discovery screen** — press **F** from the home screen to run an active discovery scan. Nodes that respond appear in a list; press **Enter** on any entry to add it to contacts.
**Deleting contacts**
Enter select mode (Enter), select the contacts to remove (Enter to toggle, A to select all), then press **Backspace** to delete. You will be returned to the contacts list once the deletion is complete.
**Exporting and importing contacts**
In select mode, press **X** to export. If contacts are selected, only those contacts are exported; if none are selected, all contacts are exported. Contacts are saved as a JSON file to `/meshcore/` on the SD card with a timestamp in the filename. The JSON format is compatible with MeshCore companion apps — you can copy the file from the SD card and import it into the Android, iOS, or web companion app.
Press **R** on the contacts list (outside select mode) to import contacts from a JSON file on the SD card. The most recent export file in `/meshcore/` is used automatically.
**Contact limits:** All variants support up to 2,000 contacts (stored in PSRAM).
### Sending a Direct Message
@@ -289,7 +393,7 @@ Select a **Chat** contact in the contacts list and press **Enter** to start comp
Contacts with unread direct messages show a `*` marker next to their name in the contacts list.
**Reading received DMs:** On the Channel Messages screen, press **D** past the last group channel to reach the **DM inbox**. This shows all received direct messages with sender name and timestamp. Entering the DM inbox marks all DM messages as read and clears the unread indicator. Press **A** to return to group channels.
**Reading received DMs:** On the Channel Messages screen, press **A** or **D** to open the channel picker, then select the **DM Inbox** entry to view received direct messages. This shows all received direct messages with sender name and timestamp. Entering the DM inbox marks all DM messages as read and clears the unread indicator.
### Roomservers
@@ -347,15 +451,29 @@ Press **S** from the home screen to open settings. On first boot (when the devic
| Msg Rcvd LED Pulse | Toggle keyboard backlight flash on new message (Enter to toggle) |
| GPS Baud Rate | A / D to cycle (Default 38400 / 4800 / 9600 / 19200 / 38400 / 57600 / 115200), Enter to confirm. **Requires reboot to take effect.** |
| Path Hash Mode | W / S to cycle (1-byte / 2-byte / 3-byte), Enter to confirm |
| Default Region | Text entry — type a region name (e.g. `au-nsw`), Enter to confirm. Empty = unscoped. See [Region Scope](#region-scope-v17). |
| Dark Mode | Toggle inverted display — white text on black background (Enter to toggle) |
| Larger Font | Toggle larger text size on channel messages, contacts, DM inbox, and repeater admin screens (Enter to toggle) |
| Font Style | A / D to cycle styles (Classic / Noto Sans / Montserrat), Enter to apply. See [Font Styles](#font-styles). |
| Auto Lock | A / D to cycle timeout (None / 2 / 5 / 10 / 15 / 30 min), Enter to confirm |
| Contacts >> | Opens the Contacts sub-screen (see below) |
| Channels >> | Opens the Channels sub-screen (see below) |
| OTA Tools >> | Opens the OTA sub-screen — Firmware Update and SD File Manager (see [OTA Firmware Update](#ota-firmware-update-v13)) |
| Device Info | Public key and firmware version (read-only) |
**Contacts sub-screen** — press Enter on the `Contacts >>` row to open. Contains the contact auto-add mode picker (Auto All / Custom / Manual) and, when set to Custom, per-type toggles for Chat, Repeater, Room Server, Sensor, and an Overwrite Oldest option. Press Q to return to the top-level settings list.
**Contacts sub-screen** — press Enter on the `Contacts >>` row to open. Contains the contact auto-add mode picker and, when set to Custom, per-type toggles:
**Channels sub-screen** — press Enter on the `Channels >>` row to open. Lists all current channels, with an option to add hashtag channels or delete non-primary channels (X). Press Q to return to the top-level settings list.
| Toggle | Meaning when ON |
|--------|----------------|
| Companion | Auto-add a chat node when its advert is heard |
| Repeater | Auto-add repeaters heard via advert |
| Room Server | Auto-add room servers heard via advert |
| Sensor | Auto-add sensor nodes heard via advert |
| Overwrite Oldest | When the contact list is full, overwrite the oldest non-favourite entry instead of discarding the new contact |
Press Q to return to the top-level settings list.
**Channels sub-screen** — press Enter on the `Channels >>` row to open. Lists all current channels with their region scope tags (e.g. `[au-nsw]` or `[*]` for device default). Press Enter on a channel to edit its region scope. Press X to delete non-primary channels. Press Q to return to the top-level settings list.
The top-level settings screen also displays your node ID and firmware version. On the 4G variant, IMEI, carrier name, and APN details are shown here as well.
@@ -365,6 +483,14 @@ If you've changed radio parameters, pressing Q will prompt you to apply changes
> **Tip:** All device settings (plus mesh tuning parameters not available on-screen) can also be configured via USB serial. See the [Serial Settings Guide](Serial_Settings_Guide.md) for complete documentation.
### Font Styles
Meck supports three font styles across the entire UI: **Classic** (the original FreeSans look), **Noto Sans** (clean, excellent Latin Extended coverage), and **Montserrat** (geometric, distinctive).
Change the font in **Settings → Font** — use A/D to cycle with a live preview, then Enter to apply. Press Q to cancel and revert. The selected style applies to all screens including channel messages, contacts, settings, and the e-reader.
Font styles are available in both Tiny and Larger text size modes. Custom fonts at Tiny size use 7pt glyphs; at Larger size, 9pt — matching the existing FreeSans layout. The font preference is saved and persists across reboots.
### Compose Mode
| Key | Action |
@@ -401,7 +527,7 @@ Press the **Sym** key then the letter key to enter numbers and symbols:
### Emoji Picker
While in compose mode, press the **$** key to open the emoji picker. A scrollable grid of 47 emoji is displayed in a 5-column layout.
While in compose mode, press the **$** key to open the emoji picker. A scrollable grid of 76 emoji is displayed in a 5-column layout, with faces and emotions grouped first. Scrolling wraps around — pressing W on the first row goes to the last row and vice versa.
| Key | Action |
|-----|--------|
@@ -426,6 +552,87 @@ The browser is a text-centric reader best suited to text-heavy websites. It also
For full documentation including key mappings, WiFi setup, bookmarks, IRC configuration, and SD card structure, see the [Web App Guide](Web_App_Guide.md).
### Alarm Clock (Audio only)
Press **K** from the home screen to open the alarm clock. This is available on the audio variant of the T-Deck Pro (PCM5102A DAC). Set up to five daily alarms that play custom MP3 files through the headphone jack.
**Setup:**
1. Place MP3 files (44100 Hz sample rate) in `/alarms/` on the SD card
2. Press **K** to open the alarm clock
3. Select an alarm slot (15) with **W / S** and press **Enter** to edit
4. Set the hour and minute, then choose an MP3 file from the list
5. Press **Enter** to save the alarm
| Key | Action |
|-----|--------|
| W / S | Navigate alarm slots / adjust time |
| A / D | Switch between hour and minute fields |
| Enter | Edit slot / save alarm / select MP3 |
| X | Delete selected alarm |
| Q | Back to home screen |
**When an alarm fires:**
The selected MP3 plays through the headphone jack, even if you're on another screen or playing an audiobook.
| Key | Action |
|-----|--------|
| Z | Snooze for 5 minutes |
| Any other key | Dismiss alarm |
Alarm configuration is stored in `/alarms/.alarmcfg` on the SD card. Alarms persist across reboots — if the RTC has valid time (via GPS or companion app sync), alarms fire at the correct time after a restart.
> **Note:** MP3 files should be encoded at **44100 Hz** sample rate. Lower sample rates may cause distortion due to ESP32-S3 I2S hardware limitations (same requirement as the audiobook player).
**SD Card Folder Structure:**
```
SD Card
├── alarms/
│ ├── .alarmcfg (auto-created, stores alarm slot config)
│ ├── morning-chime.mp3
│ ├── rooster.mp3
│ └── gentle-bells.mp3
├── audiobooks/ (existing — audiobook player)
│ └── ...
├── books/ (existing — text reader)
│ └── ...
└── ...
```
### Voice Notes Over LoRa (Audio only)
Press the **Microphone key** (the zero key on the keyboard) to open the Voice Messages screen. This is available on the audio variant of the T-Deck Pro (PCM5102A DAC).
Record and send voice messages of up to 12 seconds over LoRa. Audio is encoded on-device using Codec2 at 1200 bps, compressing each second of speech into a single 150-byte LoRa packet. Voice notes use very little airtime relative to what they deliver — a 5-second message is just 5 packets.
Voice notes can be sent to another T-Deck Pro Audio device (plays automatically through the headphone jack) or to any MeshCore companion device connected to the [Meck-Mycelium web app](https://pelgraine.github.io/Meck-Mycelium) (plays through your phone's speaker as a tappable bubble in the DM view).
**Sending a voice note:**
1. Press the **Microphone key** to open the Voice Messages screen
2. Press and **hold** the Microphone key to record — release to stop (max 12 seconds)
3. Press **S** to open the contact picker — contacts with a direct path appear at the top
4. Scroll to your contact and press **Enter** to send
Packets are sent with staggered 3-second delays to avoid congesting the channel. On a 62.5 kHz / SF7 radio preset (e.g. Australia Narrow), a 5-second voice note arrives in roughly 20 seconds and a 12-second recording in about 42 seconds.
**Receiving voice notes:**
* **On a T-Deck Pro Audio device:** the voice message screen opens automatically and the message plays through the headphone jack. **Headphones are recommended** — the built-in speaker is very quiet.
* **Via Meck-Mycelium:** voice messages appear as "🎙️ Voice message" bubbles in the DM view. Tap to play. Codec2 decoding happens entirely in the browser via WebAssembly.
> **Note:** Voice recording and sending requires the **Audio variant** hardware (PCM5102A DAC). Receiving and playback works on all Audio variants. Non-audio Meck devices can receive and relay voice packets but cannot play them locally — use the Meck-Mycelium web app for playback on those devices.
| Key | Action |
|-----|--------|
| Mic (hold) | Record voice note |
| Mic (release) | Stop recording |
| S | Open contact picker to send |
| Enter | Send to selected contact |
| Q | Back to home screen |
### Lock Screen (T-Deck Pro)
Double-click the Boot button to lock the screen. The lock screen shows the current time, battery percentage, and unread message count. The CPU drops to 40 MHz while locked to reduce power consumption.
@@ -436,6 +643,47 @@ An auto-lock timer can be configured in **Settings → Auto Lock** (None / 2 / 5
---
## Remote Repeater (T-Deck Pro 4G)
> **TODO — This section needs full documentation.** The feature is implemented and shipping. Draft outline below.
The remote repeater variant (`meck_remote_repeater`) turns a T-Deck Pro 4G board into a dedicated MeshCore repeater with cellular MQTT remote management. The repeater functions as a normal MeshCore repeater on the mesh — it forwards packets and responds to guest logins — but **admin management (clock sync, send advert, reboot, get status, configuration) is performed remotely via MQTT** through the [Meck-Mycelium dashboard](https://pelgraine.github.io/Meck-Mycelium), not via the standard mesh admin password login. The device connects to an MQTT broker (HiveMQ Cloud recommended — free tier available) over cellular data, publishing telemetry (uptime, battery, signal strength, temperature, neighbour count) and subscribing to admin commands.
**Sections to write:**
- **Requirements** — T-Deck Pro 4G (A7682E), active SIM with data plan, SD card, MQTT broker account
- **Setting up HiveMQ Cloud** — step-by-step free account creation, cluster setup, credentials
- **SD card configuration** — `/remote/mqtt.cfg` (broker, port, username, password, device ID) and optional `/remote/apn.cfg`
- **Deploying** — flash `meck_remote_repeater`, insert SIM and SD, boot sequence, display status indicators
- **Dashboard usage** — connecting Meck-Mycelium to your MQTT broker, available commands (clock sync, send advert, reboot, get status), telemetry display
- **Troubleshooting** — common issues (SIM not registering, MQTT auth failures, APN auto-detection)
---
## WiFi Repeater
> **TODO — This section needs full documentation.** The feature is implemented. Draft outline below.
The WiFi repeater variants turn a device into a dedicated MeshCore repeater with WiFi MQTT remote management — similar to the cellular remote repeater but using WiFi instead of 4G. The repeater forwards mesh traffic and responds to guest logins as normal, but **admin management is performed remotely via MQTT** through the Meck-Mycelium dashboard, not via the standard mesh admin password login. Available for the following platforms:
| Variant | Environment | Platform |
|---------|------------|----------|
| T-Deck Pro WiFi Repeater | `meck_wifi_repeater` | LilyGo T-Deck Pro |
| T5S3 WiFi Repeater | `meck_wifi_repeater_t5s3` | LilyGo T5S3 E-Paper Pro |
| Heltec V3 WiFi Repeater | `meck_wifi_repeater_heltec_v3` | Heltec V3 |
| Heltec V4 WiFi Repeater | `meck_wifi_repeater_heltec_v4` | Heltec V4 |
| Heltec V4 WiFi Repeater (headless) | `meck_wifi_repeater_heltec_v4_headless` | Heltec V4 (no display) |
**Sections to write:**
- **Requirements** — device, WiFi network, MQTT broker account, SD card (T-Deck Pro / T5S3) or SPIFFS config (Heltec V4)
- **SD card configuration** — `/remote/wifi.cfg` (supports multiple SSIDs) and `/remote/mqtt.cfg`
- **Heltec V4 specifics** — no SD card slot, config stored in SPIFFS, headless vs display variant
- **OTA updates** — NTP time sync, HTTP firmware download over WiFi
- **Dashboard** — same Meck-Mycelium dashboard as the cellular remote repeater
---
## T5S3 E-Paper Pro
The LilyGo T5S3 E-Paper Pro (V2, H752-B) is a 4.7-inch e-ink device with capacitive touch and no physical keyboard. All navigation is done via touch gestures and the Boot button (GPIO0). The larger 960×540 display provides significantly more screen real estate than the T-Deck Pro's 240×320 panel.
@@ -444,11 +692,12 @@ The LilyGo T5S3 E-Paper Pro (V2, H752-B) is a 4.7-inch e-ink device with capacit
| Variant | Environment | BLE | WiFi | Web Reader | Max Contacts |
|---------|------------|-----|------|------------|-------------|
| Standalone | `meck_t5s3_standalone` | — | — | No | 1,500 |
| BLE Companion | `meck_t5s3_ble` | Yes | — | No | 500 |
| WiFi Companion | `meck_t5s3_wifi` | — | Yes (TCP:5000) | Yes | 1,500 |
| Standalone | `meck_t5s3_standalone` | — | — | No | 2,000 |
| BLE Companion | `meck_t5s3_ble` | Yes | — | No | 2,000 |
| WiFi Companion | `meck_t5s3_wifi` | — | Yes (TCP:5000) | Yes | 2,000 |
| WiFi Repeater | `meck_wifi_repeater_t5s3` | — | Yes (MQTT) | No | — |
The WiFi variant connects to the MeshCore web app or meshcore.js over your local network. The web reader shares the same WiFi connection — no extra setup needed.
The WiFi variant connects to the MeshCore web app or meshcore.js over your local network. The web reader shares the same WiFi connection — no extra setup needed. The WiFi Repeater variant is a dedicated remote repeater — see [WiFi Repeater](#wifi-repeater) for details on MQTT-based admin management.
### Touch Navigation
@@ -512,7 +761,9 @@ Since the T5S3 has no physical keyboard, a full-screen QWERTY virtual keyboard a
The virtual keyboard supports:
- QWERTY letter layout with a symbol/number layer (tap the **123** key to switch)
- Shift toggle for uppercase
- Backspace and Enter keys
- Backspace (UTF-8 aware — correctly deletes multi-byte emoji) and Enter keys
- **Emoji picker** — tap the **$** key to open a scrollable 8-column grid of 76 emoji sprites with page indicators. Tap an emoji to insert it inline in your message. Tap **Back** to return to the keyboard. Faces and emotions are grouped first for quick access.
- Inline emoji rendering — emoji appear as pixel sprites in the text field as you type
- Phantom keystroke prevention (a brief cooldown after the keyboard opens prevents accidental taps)
Tap keys to type. Tap **Enter** to submit, or press the **Boot button** to cancel and close the keyboard.
@@ -525,11 +776,13 @@ The CardKB is auto-detected on the I2C bus at address `0x5F`. No configuration i
### Display Settings
The T5S3 Settings screen includes one additional display option not available on the T-Deck Pro:
The T5S3 Settings screen includes display options shared with the T-Deck Pro, plus one T5S3-specific setting:
| Setting | Description |
|---------|-------------|
| **Dark Mode** | Inverts the display — white text on black background. Tap to toggle on/off. Available on both T-Deck Pro and T5S3. |
| **Larger Font** | Increases text size on channel messages, contacts, DM inbox, and repeater admin screens. Tap to toggle on/off. Available on both T-Deck Pro and T5S3. |
| **Font Style** | Choose between Classic (FreeSans), Noto Sans, or Montserrat. Swipe left/right to cycle, tap to apply. Available on both T-Deck Pro and T5S3. |
| **Portrait Mode** | Rotates the display 90° from landscape (960×540) to portrait (540×960). Touch coordinates are automatically remapped. Text reader layout recalculates on orientation change. T5S3 only. |
These settings are persisted and survive reboots.
@@ -569,20 +822,52 @@ The UTC offset is configured in the Settings screen (same as T-Deck Pro) and is
| Gesture | Action |
|---------|--------|
| Swipe up / down | Scroll messages |
| Swipe left / right | Switch between channels (swipe left past the last channel to reach the DM inbox) |
| Swipe left / right | Open channel picker — shows all channels and DM inbox in a vertical bubble list with unread badges. Tap to select. |
| Tap footer area | View relay path of last received message |
| Tap path overlay | Dismiss overlay |
| Long press (touch) | Open virtual keyboard to compose message to current channel |
#### Contacts
The contacts list shows all known nodes sorted by most recently heard, with type prefix, estimated hop count, and time since last advert. See the [T-Deck Pro Contacts Screen](#contacts-screen) section for an explanation of the type prefix and hop count display — the same conventions apply on the T5S3.
**Normal mode**
| Gesture | Action |
|---------|--------|
| Swipe up / down | Scroll through contacts |
| Swipe left / right | Cycle contact filter (All → Chat → Repeater → Room → Sensor → Favourites) |
| Tap | Select contact |
| Swipe left / right | Cycle contact filter (All → Chat → Rptr → Room → Sens → Fav) |
| Tap | Enter select mode (tapped contact is pre-selected) |
| Long press on Chat contact | View unread DMs (if any), then compose DM |
| Long press on Repeater contact | Open repeater admin login |
| Long press on Repeater/RS contact | Open repeater admin login |
> **Note:** The **Fav** filter shows only contacts you have marked as favourites. If it appears empty, no contacts have been favourited yet — use select mode (tap a contact) and then long-press to mark favourites.
**Select mode** — tap any contact row to enter select mode. The tapped contact is pre-selected (shown with `*`). Swipe or tap to navigate and toggle selections. You can also use a **two-finger tap** anywhere on the contacts screen to toggle select mode on and off.
| Gesture | Action |
|---------|--------|
| Tap | Toggle selection on tapped row |
| Swipe left | Select all contacts in current filter |
| Swipe right | Deselect all |
| Two-finger tap | Toggle select mode on/off |
| Long press | Exit select mode (confirm favourites / deletions first) |
Batch operations (favourite toggle, delete) are triggered from the overlay that appears after exiting select mode with contacts selected.
**Adding contacts**
1. **Automatic** — if Settings → Contacts → Add Mode is set to *Auto All*, nodes are added as their adverts are heard. *Custom* mode adds only nodes matching the enabled type toggles (Companion, Repeater, Room Server, Sensor). *Manual Only* disables auto-add.
2. **From the Last Heard screen** — tap the **Discover** tile (or access via the home page on non-WiFi builds) and navigate to Last Heard. Tap any entry to add it to contacts, or tap an existing contact to remove it (favourites require a second tap within 3 seconds to confirm). Entries show `[+]` if already in contacts, `[★]` if a favourite.
> **Note:** The Last Heard list holds up to 1,000 entries in PSRAM, and advert data is stored persistently on the SD card — so contacts can be added long after the original advertisement was received, even across reboots. This makes Last Heard especially useful when auto-add is set to *Manual Only*, as it provides a passive catalogue of every node heard on the network.
3. **From the Discovery screen** — tap the Discover tile and run an active scan. Tap any result to add it to contacts.
**Deleting contacts**
Tap a contact to enter select mode, select the contacts to remove, exit select mode, and choose delete from the confirmation overlay.
#### Text Reader (File List)
@@ -662,6 +947,22 @@ The UTC offset is configured in the Settings screen (same as T-Deck Pro) and is
---
## Meck-Mycelium Web App
The [Meck-Mycelium web app](https://pelgraine.github.io/Meck-Mycelium) is a browser-based companion that connects to your MeshCore device via BLE (using WebBLE in Chrome) or to your MQTT broker for remote repeater management.
**Features:**
- **Voice message playback** — voice notes sent from a Meck Audio device appear as tappable playback bubbles in the DM view. Codec2 decoding happens entirely in the browser via WebAssembly — no app install or audio hardware needed on the receiving end.
- **Remote repeater dashboard** — connect to your MQTT broker to administer remote repeater devices (cellular or WiFi). View live telemetry, send admin commands (clock sync, send advert, reboot, get status), and manage repeaters that are out of LoRa range. This replaces the standard mesh admin password login for remote repeater variants.
- **Standard companion features** — messaging, contacts, channel messages via BLE.
Open **https://pelgraine.github.io/Meck-Mycelium** in Chrome on your phone or computer.
> **Note:** WebBLE requires Chrome (or a Chromium-based browser). Safari and Firefox do not support WebBLE.
---
## About MeshCore
MeshCore is a lightweight, portable C++ library that enables multi-hop packet routing for embedded projects using LoRa and other packet radios. It is designed for developers who want to create resilient, decentralized communication networks that work without the internet.
@@ -712,6 +1013,7 @@ The companion firmware can be connected to via BLE (T-Deck Pro and T5S3 BLE vari
> **Note:** On both the T-Deck Pro and T5S3, BLE and WiFi are disabled by default at boot. On the T-Deck Pro, navigate to the Bluetooth or WiFi home page and press Enter to enable. On the T5S3, navigate to the Bluetooth home page and long-press the screen to toggle BLE on.
- Web: https://app.meshcore.nz
- Meck-Mycelium: https://pelgraine.github.io/Meck-Mycelium (voice playback, remote repeater dashboard)
- Android: https://play.google.com/store/apps/details?id=com.liamcottle.meshcore.android
- iOS: https://apps.apple.com/us/app/meshcore/id6742354151?platform=iphone
- NodeJS: https://github.com/liamcottle/meshcore.js
@@ -719,7 +1021,7 @@ The companion firmware can be connected to via BLE (T-Deck Pro and T5S3 BLE vari
## 🛠 Hardware Compatibility
MeshCore is designed for devices listed in the [MeshCore Flasher](https://flasher.meshcore.co.uk). Meck specifically targets the LilyGo T-Deck Pro and LilyGo T5S3 E-Paper Pro.
MeshCore is designed for devices listed in the [MeshCore Flasher](https://flasher.meshcore.co.uk). Meck specifically targets the LilyGo T-Deck Pro, LilyGo T5S3 E-Paper Pro, Heltec V3 (remote repeater only), and Heltec V4 (remote repeater only).
## Contributing
@@ -750,13 +1052,29 @@ There are a number of fairly major features in the pipeline, with no particular
- [X] Last heard passive advert list
- [X] Touch-to-select on contacts, discovery, settings, text reader, notes screens
- [X] Map screen with GPS tile rendering
- [ ] Fix M4B rendering to enable chaptered audiobook playback
- [ ] Better JPEG and PNG decoding
- [ ] Improve EPUB rendering and EPUB format handling
- [X] WiFi companion environment
- [X] OTA firmware update via phone
- [X] DM inbox with per-contact unread indicators
- [X] Roomserver message handling and mark-read on login
- [X] Alarm clock with custom MP3 sounds (audio variant)
- [X] Customised user option for larger-font mode
- [X] Voice notes over LoRa (Codec2, audio variant)
- [X] Contact select mode with batch favourite, export, import, and delete
- [X] Path editor for manual contact route management
- [X] Remote repeater with cellular MQTT admin management (4G variant)
- [X] WiFi remote repeater with MQTT admin management
- [X] SD File Manager via OTA Tools
- [X] 2,000 contact support (PSRAM, all variants)
- [X] Channel picker screen with unread badges
- [X] Region scope (MeshCore v1.15+ compatibility)
- [X] Selectable font styles (Classic, Noto Sans, Montserrat)
- [X] Expanded emoji picker (76 emoji, reordered, wrap scrolling)
- [X] 1,000-entry advert path cache (PSRAM)
- [ ] Fix M4B rendering to enable chaptered audiobook playback
- [ ] Better JPEG and PNG decoding
- [ ] Improve EPUB rendering and EPUB format handling
- [ ] Figure out a way to silence the ringtone
- [ ] Figure out a way to customise the ringtone
**T5S3 E-Paper Pro:**
- [X] Core port: display, touch input, LoRa, battery, RTC
@@ -777,6 +1095,26 @@ There are a number of fairly major features in the pipeline, with no particular
- [X] OTA firmware update via phone (WiFi variant)
- [X] DM inbox with per-contact unread indicators
- [X] Roomserver message handling and mark-read on login
- [X] Customised user option for larger-font mode
- [X] Contact select mode with batch favourite and delete
- [X] WiFi remote repeater with MQTT admin management
- [X] 2,000 contact support (PSRAM, all variants)
- [X] Channel picker screen with vertical bubble list layout
- [X] Region scope (MeshCore v1.15+ compatibility)
- [X] Selectable font styles (Classic, Noto Sans, Montserrat)
- [X] Virtual keyboard emoji grid with scrollable pages
- [ ] Improve EPUB rendering and EPUB format handling
**Heltec V4:**
- [X] WiFi remote repeater with MQTT admin management
- [X] Headless WiFi repeater variant (no display)
**Heltec V3:**
- [X] WiFi remote repeater with MQTT admin management
**In development (WIP):**
- [ ] T-Deck Pro MAX — ESP32-S3 with XL9555 I/O expander, combined 4G (A7682E) + audio (ES8311), working e-ink front-light, 1500 mAh battery. Variant files created; deferred until hardware ships.
- [ ] T-Echo Card — nRF52840 (BLE-native) with SX1262, SSD1315 OLED (72×40), L76K GPS, speaker, PDM mic, IMU, solar charging, NFC. Preliminary variant files created; awaiting hardware.
## 📞 Get Support
@@ -786,23 +1124,37 @@ There are a number of fairly major features in the pipeline, with no particular
The upstream [MeshCore](https://github.com/meshcore-dev/MeshCore) library is released under the **MIT License** (Copyright © 2025 Scott Powell / rippleradios.com). Meck-specific code (UI screens, display helpers, device integration) is also provided under the MIT License.
However, this firmware links against libraries with different license terms. Because two dependencies use the **GPL-3.0** copyleft license, the combined firmware binary is effectively subject to GPL-3.0 obligations when distributed. Please review the individual licenses below if you intend to redistribute or modify this firmware.
However, this firmware links against libraries with different license terms. Because some dependencies use the **GPL-3.0** copyleft license (GxEPD2, ESP32-audioI2S) and others use **LGPL-2.1** (Codec2, ESPAsyncWebServer, Arduino_LPS22HB), the combined firmware binary is effectively subject to GPL-3.0 obligations when distributed. Please review the individual licenses below if you intend to redistribute or modify this firmware.
### Third-Party Libraries
| Library | License | Author / Source |
|---------|---------|-----------------|
| [MeshCore](https://github.com/meshcore-dev/MeshCore) | MIT | Scott Powell / rippleradios.com |
| [GxEPD2](https://github.com/ZinggJM/GxEPD2) | GPL-3.0 | Jean-Marc Zingg |
| [FastEPD](https://github.com/bitbank2/FastEPD) | Apache-2.0 | Larry Bank (bitbank2) |
| [ESP32-audioI2S](https://github.com/schreibfaul1/ESP32-audioI2S) | GPL-3.0 | schreibfaul1 (Wolle) |
| [Adafruit GFX Library](https://github.com/adafruit/Adafruit-GFX-Library) | BSD | Adafruit |
| [RadioLib](https://github.com/jgromes/RadioLib) | MIT | Jan Gromeš |
| [SensorLib](https://github.com/lewisxhe/SensorLib) | MIT | Lewis He |
| [JPEGDEC](https://github.com/bitbank2/JPEGDEC) | Apache-2.0 | Larry Bank (bitbank2) |
| [PNGdec](https://github.com/bitbank2/PNGdec) | Apache-2.0 | Larry Bank (bitbank2) |
| [CRC32](https://github.com/bakercp/CRC32) | MIT | Christopher Baker |
| [base64](https://github.com/Densaugeo/base64_arduino) | MIT | densaugeo |
| [GxEPD2](https://github.com/ZinggJM/GxEPD2) | GPL-3.0 | Jean-Marc Zingg (T-Deck Pro) |
| [FastEPD](https://github.com/bitbank2/FastEPD) | Apache-2.0 | Larry Bank / bitbank2 (T5S3) |
| [Adafruit GFX Library](https://github.com/adafruit/Adafruit-GFX-Library) | BSD | Adafruit |
| [SensorLib](https://github.com/lewisxhe/SensorLib) | MIT | Lewis He (T5S3 touch/RTC) |
| [ESP32-audioI2S](https://github.com/schreibfaul1/ESP32-audioI2S) | GPL-3.0 | schreibfaul1 / Wolle |
| [Codec2](https://github.com/sh123/esp32_codec2_arduino) | LGPL-2.1 | sh123 (ESP32 port) |
| [JPEGDEC](https://github.com/bitbank2/JPEGDEC) | Apache-2.0 | Larry Bank / bitbank2 |
| [PNGdec](https://github.com/bitbank2/PNGdec) | Apache-2.0 | Larry Bank / bitbank2 |
| [ESPAsyncWebServer](https://github.com/me-no-dev/ESPAsyncWebServer) | LGPL-2.1 | Hristo Gochkov / me-no-dev (OTA) |
| [PubSubClient](https://github.com/knolleary/pubsubclient) | MIT | Nick O'Leary (MQTT) |
| [Arduino Crypto](https://github.com/rweather/arduinolibs) | MIT | Rhys Weatherley |
| [base64](https://github.com/Densaugeo/base64_arduino) | MIT | densaugeo |
| [CRC32](https://github.com/bakercp/CRC32) | MIT | Christopher Baker |
| [RTClib](https://github.com/adafruit/RTClib) | MIT | Adafruit |
| [Melopero RV3028](https://github.com/melopero/Melopero_RV-3028_Arduino_Library) | MIT | Melopero |
| [MicroNMEA](https://github.com/stevemarple/MicroNMEA) | MIT | Steve Marple (GPS) |
| [CayenneLPP](https://github.com/ElectronicCats/CayenneLPP) | MIT | Electronic Cats |
| [Adafruit ST7735/ST7789](https://github.com/adafruit/Adafruit-ST7735-Library) | MIT | Adafruit (Heltec V4 TFT) |
| [INA226](https://github.com/RobTillaart/INA226) | MIT | Rob Tillaart |
| [Arduino_LPS22HB](https://github.com/arduino-libraries/Arduino_LPS22HB) | LGPL-2.1 | Arduino |
| Adafruit sensor drivers¹ | MIT / BSD | Adafruit |
| [Sensirion I2C SHT4x](https://github.com/Sensirion/arduino-i2c-sht4x) | BSD-3-Clause | Sensirion |
¹ Includes INA219, INA260, INA3221, AHTX0, BME280, BMP280, BME680, BMP085, SHTC3, MLX90614, VL53L0X — all MIT or BSD licensed. Used via the sensor manager for optional environmental monitoring.
Full license texts for each dependency are available in their respective repositories linked above.
+142 -5
View File
@@ -64,8 +64,12 @@ All commands follow a simple pattern: `get` to read, `set` to write.
| `get af` | Airtime factor |
| `get multi.acks` | Redundant ACKs (0 or 1) |
| `get int.thresh` | Interference threshold (0=disabled) |
| `get tx.fail.threshold` | TX fail reset threshold (0=disabled, default 3) |
| `get rx.fail.threshold` | RX stuck reboot threshold (0=disabled, default 3) |
| `get gps.baud` | GPS baud rate (0=compile-time default) |
| `get channels` | List all channels with index numbers |
| `get region` | Default region scope (e.g. `au-nsw`, or `none`) |
| `get channels` | List all channels with index numbers and region scopes |
| `get channel.scope <idx>` | Show region scope for a specific channel |
| `get presets` | List all radio presets with parameters |
| `get pubkey` | Device public key (hex) |
| `get firmware` | Firmware version string |
@@ -231,6 +235,28 @@ set int.thresh 0
Values: 0 (disabled, default) or 14+ (14 is the typical setting). Values between 113 are not functional and will be rejected.
#### TX Fail Reset Threshold (tx.fail.reset)
Automatically resets the radio hardware after this many consecutive failed transmission attempts. This recovers from "zombie radio" states where the SX1262 stops responding to send commands.
```
set tx.fail.threshold 3
set tx.fail.threshold 0
```
Values: 0 (disabled) or 110 (default: 3). After the threshold is reached, the radio is reset and the failed packet is re-queued.
#### RX Stuck Reboot Threshold (rx.fail.reboot)
Automatically reboots the device after this many consecutive RX-stuck recovery failures. An RX-stuck event occurs when the radio is not in receive mode for 8 seconds despite automatic recovery attempts.
```
set rx.fail.threshold 3
set rx.fail.threshold 0
```
Values: 0 (disabled) or 110 (default: 3). A full device reboot is a last resort — this should only trigger in rare cases of persistent radio hardware malfunction.
#### GPS Baud Rate (gps.baud)
Override the GPS serial baud rate. The default (0) uses the compile-time value of 38400. **Requires a reboot to take effect** — the GPS serial port is only configured at startup.
@@ -242,6 +268,18 @@ set gps.baud 0
Valid rates: 0 (default), 4800, 9600, 19200, 38400, 57600, 115200.
#### Backlight (T5S3 E-Paper Pro Only)
Control the front-light on the T5S3 display:
```
set backlight on
set backlight off
set backlight 128
```
Values: `on`, `off`, or a brightness level from 0255.
### Channel Management
#### List Channels
@@ -253,11 +291,13 @@ get channels
Output:
```
[0] #public
[1] #meck-test
[2] #local-group
[0] #public [*]
[1] #meck-test [au-nsw]
[2] #local-group [*]
```
Each channel shows its region scope in brackets. `[*]` means the channel uses the device default region (or unscoped if no default is set). A specific name like `[au-nsw]` means that channel has its own region override.
#### Add a Hashtag Channel
```
@@ -274,6 +314,82 @@ set channel.del 2
Channels are referenced by their index number (shown in `get channels`). Channel 0 (public) cannot be deleted. Remaining channels are automatically compacted after deletion.
### Region Scope
Regions limit how far your flood messages propagate through the mesh. When you set a region, outgoing messages are tagged with a transport code that repeaters use to decide whether to forward them. Messages sent without a region reach all repeaters via the default wildcard, same as always.
Meck does not pre-set any region on a fresh flash. Region names are determined by your local mesh community — check with your local group for the names in use. Common patterns follow ISO 3166 country/subdivision codes (e.g. `au` for Australia, `gb-eng` for England, `us-ca` for California), but communities may also use custom names for their area.
Region names must be lowercase alphanumeric characters and hyphens only, max 29 characters.
#### View Default Region
```
get region
```
Output:
```
> au-nsw
```
Or if no region is set:
```
> (none — unscoped)
```
#### Set Default Region
```
set region au-nsw
```
This applies to all channels and DMs unless a channel has its own region override.
#### Clear Default Region
```
set region none
```
Returns to unscoped mode — messages reach all repeaters.
#### View Channel Region
```
get channel.scope 2
```
Output:
```
> #local-group scope: au-syd
```
Or if the channel uses the device default:
```
> #local-group scope: (device default)
```
#### Set Channel Region
```
set channel.scope 2 au-syd
```
This overrides the device default for that specific channel.
#### Clear Channel Region
```
set channel.scope 2 none
```
Returns the channel to using the device default region.
### 4G Modem (4G Variant Only)
#### Enable / Disable Modem
@@ -386,7 +502,7 @@ set channel.add local-group
get all
```
### Switching to a New Region
### Switching to a Different Radio Preset
Moving from Australia to the US? One command:
@@ -400,6 +516,27 @@ Verify with:
get radio
```
### Setting Up Regions
Check with your local mesh community for the region names in use, then set your device default:
```
set region au-nsw
```
If you want a specific channel to use a different region (e.g. a nationwide channel):
```
set channel.scope 1 au
```
Verify everything:
```
get region
get channels
```
### Custom Radio Configuration
If none of the presets match your local group or you need specific parameters, set them directly. You can do it all in one command:
+48
View File
@@ -0,0 +1,48 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": [
"-DARDUINO_NRF52840_TECHO_CARD",
"-DNRF52840_XXAA",
"-DNRF52_SERIES"
],
"f_cpu": "64000000L",
"hwids": [["0x239A", "0x8029"]],
"mcu": "nrf52840",
"variant": "lilygo_techo_card",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"usb_product": "T-Echo Card"
},
"connectivity": ["bluetooth", "lora"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"openocd_target": "nrf52840"
},
"frameworks": ["arduino"],
"name": "LilyGo T-Echo Card (nRF52840, SX1262, 4MB Flash)",
"upload": {
"flash_size": "796KB",
"maximum_ram_size": 248832,
"maximum_size": 815104,
"native_usb": true,
"protocol": "nrfutil",
"protocols": ["nrfutil", "jlink", "cmsis-dap"],
"require_upload_port": true,
"speed": 115200,
"use_1200bps_touch": true,
"wait_for_upload_port": true
},
"url": "https://github.com/Xinyuan-LilyGO/T-Echo-Card",
"vendor": "LILYGO"
}
+40
View File
@@ -0,0 +1,40 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_qspi",
"partitions": "default_16MB.csv"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "esp32s3"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "LilyGo T-Deck Pro MAX (16MB Flash 8MB QSPI PSRAM)",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"require_upload_port": true,
"speed": 921600
},
"url": "https://www.lilygo.cc/products/t-deck-pro",
"vendor": "LilyGo"
}
+5
View File
@@ -0,0 +1,5 @@
6818ce5f77dd45bb90facf753ba81d81.s1.eu.hivemq.cloud
8883
meckremote
yourpassword
heltec-wifi-1
+2
View File
@@ -0,0 +1,2 @@
SSID
Password
+108 -10
View File
@@ -268,10 +268,38 @@ void DataStore::loadPrefsInt(const char *filename, NodePrefs& _prefs, double& no
if (file.read((uint8_t *)&_prefs.auto_lock_minutes, sizeof(_prefs.auto_lock_minutes)) != sizeof(_prefs.auto_lock_minutes)) {
_prefs.auto_lock_minutes = 0; // default: disabled
}
if (file.read((uint8_t *)&_prefs.hint_shown, sizeof(_prefs.hint_shown)) != sizeof(_prefs.hint_shown)) {
_prefs.hint_shown = 0; // default: show boot hint
}
if (file.read((uint8_t *)&_prefs.large_font, sizeof(_prefs.large_font)) != sizeof(_prefs.large_font)) {
_prefs.large_font = 0; // default: tiny font
}
if (file.read((uint8_t *)&_prefs.ui_font_style, sizeof(_prefs.ui_font_style)) != sizeof(_prefs.ui_font_style)) {
_prefs.ui_font_style = 0; // default: Classic (FreeSans)
}
if (file.read((uint8_t *)&_prefs.tx_fail_reset_threshold, sizeof(_prefs.tx_fail_reset_threshold)) != sizeof(_prefs.tx_fail_reset_threshold)) {
_prefs.tx_fail_reset_threshold = 3; // default: 3
}
if (file.read((uint8_t *)&_prefs.rx_fail_reboot_threshold, sizeof(_prefs.rx_fail_reboot_threshold)) != sizeof(_prefs.rx_fail_reboot_threshold)) {
_prefs.rx_fail_reboot_threshold = 3; // default: 3
}
// v1.7+ Meck region scope fields — may not exist in older prefs files
if (file.read((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)) != sizeof(_prefs.default_scope_name)) {
memset(_prefs.default_scope_name, 0, sizeof(_prefs.default_scope_name)); // default: unscoped
}
if (file.read((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)) != sizeof(_prefs.default_scope_key)) {
memset(_prefs.default_scope_key, 0, sizeof(_prefs.default_scope_key)); // default: null key
}
// Clamp to valid ranges
if (_prefs.dark_mode > 1) _prefs.dark_mode = 0;
if (_prefs.portrait_mode > 1) _prefs.portrait_mode = 0;
if (_prefs.hint_shown > 1) _prefs.hint_shown = 0;
if (_prefs.large_font > 1) _prefs.large_font = 0;
if (_prefs.ui_font_style >= 3) _prefs.ui_font_style = 0;
if (_prefs.tx_fail_reset_threshold > 10) _prefs.tx_fail_reset_threshold = 3;
if (_prefs.rx_fail_reboot_threshold > 10) _prefs.rx_fail_reboot_threshold = 3;
// auto_lock_minutes: only accept known options (0, 2, 5, 10, 15, 30)
{
uint8_t alm = _prefs.auto_lock_minutes;
@@ -324,6 +352,13 @@ void DataStore::savePrefs(const NodePrefs& _prefs, double node_lat, double node_
file.write((uint8_t *)&_prefs.dark_mode, sizeof(_prefs.dark_mode)); // 98
file.write((uint8_t *)&_prefs.portrait_mode, sizeof(_prefs.portrait_mode)); // 99
file.write((uint8_t *)&_prefs.auto_lock_minutes, sizeof(_prefs.auto_lock_minutes)); // 100
file.write((uint8_t *)&_prefs.hint_shown, sizeof(_prefs.hint_shown)); // 101
file.write((uint8_t *)&_prefs.large_font, sizeof(_prefs.large_font)); // 102
file.write((uint8_t *)&_prefs.ui_font_style, sizeof(_prefs.ui_font_style)); // 103
file.write((uint8_t *)&_prefs.tx_fail_reset_threshold, sizeof(_prefs.tx_fail_reset_threshold)); // 104
file.write((uint8_t *)&_prefs.rx_fail_reboot_threshold, sizeof(_prefs.rx_fail_reboot_threshold)); // 105
file.write((uint8_t *)_prefs.default_scope_name, sizeof(_prefs.default_scope_name)); // 106
file.write((uint8_t *)_prefs.default_scope_key, sizeof(_prefs.default_scope_key)); // 137
file.close();
}
@@ -575,8 +610,57 @@ void DataStore::loadChannels(DataStoreHost* host) {
FILESYSTEM* fs = _getContactsChannelsFS();
// Crash recovery (same pattern as contacts)
if (!fs->exists("/channels3") && fs->exists("/channels3.tmp")) {
Serial.println("DataStore: recovering channels3 from .tmp file");
fs->rename("/channels3.tmp", "/channels3");
}
if (fs->exists("/channels3.tmp")) {
fs->remove("/channels3.tmp");
}
// Try channels3 (new format with scope_name) first
if (fs->exists("/channels3")) {
File file = openRead(fs, "/channels3");
if (file) {
bool full = false;
uint8_t channel_idx = 0;
while (!full) {
ChannelDetails ch;
memset(ch.scope_name, 0, sizeof(ch.scope_name));
uint8_t unused[4];
bool success = (file.read(unused, 4) == 4);
success = success && (file.read((uint8_t *)ch.name, 32) == 32);
success = success && (file.read((uint8_t *)ch.channel.secret, 32) == 32);
success = success && (file.read((uint8_t *)ch.scope_name, 31) == 31);
if (!success) break; // EOF
// Sanitize scope_name — reject if it contains non-region characters
// (catches garbage from uninitialised memory in early channels3 files)
ch.scope_name[30] = '\0'; // force null-terminate
for (int s = 0; ch.scope_name[s]; s++) {
char sc = ch.scope_name[s];
if (!((sc >= 'a' && sc <= 'z') || (sc >= '0' && sc <= '9') || sc == '-')) {
memset(ch.scope_name, 0, sizeof(ch.scope_name)); // invalid — clear
break;
}
}
if (host->onChannelLoaded(channel_idx, ch)) {
channel_idx++;
} else {
full = true;
}
}
file.close();
return; // channels3 loaded successfully
}
}
// Fall back to channels2 (legacy format without scope_name)
if (!fs->exists("/channels2") && fs->exists("/channels2.tmp")) {
Serial.println("DataStore: recovering channels from .tmp file");
Serial.println("DataStore: recovering channels2 from .tmp file");
fs->rename("/channels2.tmp", "/channels2");
}
if (fs->exists("/channels2.tmp")) {
@@ -589,6 +673,7 @@ void DataStore::loadChannels(DataStoreHost* host) {
uint8_t channel_idx = 0;
while (!full) {
ChannelDetails ch;
memset(ch.scope_name, 0, sizeof(ch.scope_name)); // default: no scope
uint8_t unused[4];
bool success = (file.read(unused, 4) == 4);
@@ -604,13 +689,18 @@ void DataStore::loadChannels(DataStoreHost* host) {
}
}
file.close();
// Migrate: save as channels3 and remove channels2
Serial.println("DataStore: migrating channels2 → channels3");
saveChannels(host);
fs->remove("/channels2");
}
}
void DataStore::saveChannels(DataStoreHost* host) {
FILESYSTEM* fs = _getContactsChannelsFS();
const char* finalPath = "/channels2";
const char* tmpPath = "/channels2.tmp";
const char* finalPath = "/channels3";
const char* tmpPath = "/channels3.tmp";
File file = openWrite(fs, tmpPath);
if (!file) {
@@ -628,6 +718,7 @@ void DataStore::saveChannels(DataStoreHost* host) {
bool success = (file.write(unused, 4) == 4);
success = success && (file.write((uint8_t *)ch.name, 32) == 32);
success = success && (file.write((uint8_t *)ch.channel.secret, 32) == 32);
success = success && (file.write((uint8_t *)ch.scope_name, 31) == 31);
if (!success) {
writeOk = false;
@@ -640,7 +731,7 @@ void DataStore::saveChannels(DataStoreHost* host) {
file.close();
// Reopen read-only to get true on-disk size (SPIFFS file.size() is unreliable before close)
size_t expectedBytes = channel_idx * 68; // 4 + 32 + 32 = 68 bytes per channel
size_t expectedBytes = channel_idx * 99; // 4 + 32 + 32 + 31 = 99 bytes per channel
File verify = openRead(fs, tmpPath);
size_t bytesWritten = verify ? verify.size() : 0;
if (verify) verify.close();
@@ -685,7 +776,7 @@ void DataStore::checkAdvBlobFile() {
}
void DataStore::migrateToSecondaryFS() {
// migrate old adv_blobs, contacts3 and channels2 files to secondary FS if they don't already exist
// migrate old adv_blobs, contacts3 and channels3/channels2 files to secondary FS if they don't already exist
if (!_fsExtra->exists("/adv_blobs")) {
if (_fs->exists("/adv_blobs")) {
File oldAdvBlobs = openRead(_fs, "/adv_blobs");
@@ -724,10 +815,14 @@ void DataStore::migrateToSecondaryFS() {
_fs->remove("/contacts3");
}
}
if (!_fsExtra->exists("/channels2")) {
if (_fs->exists("/channels2")) {
File oldFile = openRead(_fs, "/channels2");
File newFile = openWrite(_fsExtra, "/channels2");
if (!_fsExtra->exists("/channels3") && !_fsExtra->exists("/channels2")) {
// Migrate channels3 (preferred) or channels2 (legacy) to secondary FS
const char* srcName = _fs->exists("/channels3") ? "/channels3"
: _fs->exists("/channels2") ? "/channels2"
: nullptr;
if (srcName) {
File oldFile = openRead(_fs, srcName);
File newFile = openWrite(_fsExtra, srcName);
if (oldFile && newFile) {
uint8_t buf[64];
@@ -738,7 +833,7 @@ void DataStore::migrateToSecondaryFS() {
}
if (oldFile) oldFile.close();
if (newFile) newFile.close();
_fs->remove("/channels2");
_fs->remove(srcName);
}
}
// cleanup nodes which have been testing the extra fs, copy _main.id and new_prefs back to primary
@@ -781,6 +876,9 @@ void DataStore::migrateToSecondaryFS() {
if (_fs->exists("/contacts3")) {
_fs->remove("/contacts3");
}
if (_fs->exists("/channels3")) {
_fs->remove("/channels3");
}
if (_fs->exists("/channels2")) {
_fs->remove("/channels2");
}
+397 -56
View File
@@ -59,7 +59,7 @@
#define CMD_SEND_BINARY_REQ 50
#define CMD_FACTORY_RESET 51
#define CMD_SEND_PATH_DISCOVERY_REQ 52
#define CMD_SET_FLOOD_SCOPE 54 // v8+
#define CMD_SET_FLOOD_SCOPE_KEY 54 // v8+ (per-channel scope key from BLE app)
#define CMD_SEND_CONTROL_DATA 55 // v8+
#define CMD_GET_STATS 56 // v8+, second byte is stats type
@@ -70,6 +70,9 @@
#define CMD_SET_AUTOADD_CONFIG 58
#define CMD_GET_AUTOADD_CONFIG 59
#define CMD_SET_PATH_HASH_MODE 61
#define CMD_SEND_CHANNEL_DATA 62
#define CMD_SET_DEFAULT_FLOOD_SCOPE 63 // v1.15+ (device-wide default scope name+key)
#define CMD_GET_DEFAULT_FLOOD_SCOPE 64 // v1.15+ (query current default scope)
// Stats sub-types for CMD_GET_STATS
#define STATS_TYPE_CORE 0
@@ -102,6 +105,9 @@
#define RESP_CODE_TUNING_PARAMS 23
#define RESP_CODE_STATS 24 // v8+, second byte is stats type
#define RESP_CODE_AUTOADD_CONFIG 25
#define RESP_ALLOWED_REPEAT_FREQ 26
#define RESP_CODE_CHANNEL_DATA_RECV 27
#define RESP_CODE_DEFAULT_FLOOD_SCOPE 28 // v1.15+
#define SEND_TIMEOUT_BASE_MILLIS 500
#define FLOOD_SEND_TIMEOUT_FACTOR 16.0f
@@ -166,7 +172,7 @@ void MyMesh::writeDisabledFrame() {
_serial->writeFrame(buf, 1);
}
void MyMesh::writeContactRespFrame(uint8_t code, const ContactInfo &contact) {
size_t MyMesh::writeContactRespFrame(uint8_t code, const ContactInfo &contact) {
int i = 0;
out_frame[i++] = code;
memcpy(&out_frame[i], contact.id.pub_key, PUB_KEY_SIZE);
@@ -186,7 +192,7 @@ void MyMesh::writeContactRespFrame(uint8_t code, const ContactInfo &contact) {
i += 4;
memcpy(&out_frame[i], &contact.lastmod, 4);
i += 4;
_serial->writeFrame(out_frame, i);
return _serial->writeFrame(out_frame, i);
}
void MyMesh::updateContactFromFrame(ContactInfo &contact, uint32_t& last_mod, const uint8_t *frame, int len) {
@@ -264,6 +270,16 @@ int MyMesh::getInterferenceThreshold() const {
return _prefs.interference_threshold;
}
uint8_t MyMesh::getTxFailResetThreshold() const {
return _prefs.tx_fail_reset_threshold;
}
uint8_t MyMesh::getRxFailRebootThreshold() const {
return _prefs.rx_fail_reboot_threshold;
}
void MyMesh::onRxUnrecoverable() {
board.reboot();
}
int MyMesh::calcRxDelay(float score, uint32_t air_time) const {
if (_prefs.rx_delay_base <= 0.0f) return 0;
return (int)((pow(_prefs.rx_delay_base, 0.85f - score) - 1.0) * air_time);
@@ -305,6 +321,7 @@ bool MyMesh::isAutoAddEnabled() const {
}
bool MyMesh::shouldAutoAddContactType(uint8_t contact_type) const {
if (_forceNextImport) return true; // explicit user add from Last Heard / Discovery
if ((_prefs.manual_add_contacts & 1) == 0) {
return true;
}
@@ -350,6 +367,7 @@ void MyMesh::onContactsFull() {
}
void MyMesh::onDiscoveredContact(ContactInfo &contact, bool is_new, uint8_t path_len, const uint8_t* path) {
_forceNextImport = false; // clear force-add flag (set by forceImportContact)
if (_serial->isConnected()) {
if (is_new) {
writeContactRespFrame(PUSH_CODE_NEW_ADVERT, contact);
@@ -555,18 +573,24 @@ bool MyMesh::filterRecvFloodPacket(mesh::Packet* packet) {
return false; // never filter — let normal processing continue
}
void MyMesh::sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint32_t delay_millis) {
if (scope.isNull()) {
sendFlood(pkt, delay_millis, getPathHashSize());
} else {
uint16_t codes[2];
codes[0] = scope.calcTransportCode(pkt);
codes[1] = 0; // reserved for home region
sendFlood(pkt, codes, delay_millis, getPathHashSize());
}
}
void MyMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) {
Serial.printf("[sendFloodScoped] to '%s', delay=%lu, hash_mode=%d, bph=%d\n",
recipient.name, delay_millis, _prefs.path_hash_mode, _prefs.path_hash_mode + 1);
// TODO: dynamic send_scope, depending on recipient and current 'home' Region
if (send_scope.isNull()) {
sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
} else {
uint16_t codes[2];
codes[0] = send_scope.calcTransportCode(pkt);
codes[1] = 0; // REVISIT: set to 'home' Region, for sender/return region?
sendFlood(pkt, codes, delay_millis, _prefs.path_hash_mode + 1);
}
// DMs: use device default scope (no per-contact scope)
TransportKey default_scope;
memcpy(&default_scope.key, _prefs.default_scope_key, sizeof(default_scope.key));
sendFloodScoped(default_scope, pkt, delay_millis);
}
void MyMesh::sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis) {
// Capture payload fingerprint for repeat tracking before sending
@@ -580,20 +604,58 @@ void MyMesh::sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pk
MESH_DEBUG_PRINTLN("SentTrack: captured fingerprint for channel msg");
}
// TODO: have per-channel send_scope
if (send_scope.isNull()) {
sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
// Scope priority: BLE app send_scope → per-channel scope → device default → unscoped
TransportKey scope;
if (!send_scope.isNull()) {
// BLE app has set a scope via CMD 54 — use it (highest priority)
memcpy(scope.key, send_scope.key, sizeof(scope.key));
} else {
uint16_t codes[2];
codes[0] = send_scope.calcTransportCode(pkt);
codes[1] = 0; // REVISIT: set to 'home' Region, for sender/return region?
sendFlood(pkt, codes, delay_millis, _prefs.path_hash_mode + 1);
const char* ch_scope = getChannelScopeName(channel);
if (ch_scope && ch_scope[0]) {
deriveScopeKey(ch_scope, scope);
} else {
memcpy(scope.key, _prefs.default_scope_key, sizeof(scope.key));
}
}
sendFloodScoped(scope, pkt, delay_millis);
}
bool MyMesh::deriveScopeKey(const char* scopeName, TransportKey& keyOut) {
if (!scopeName || scopeName[0] == '\0') {
memset(keyOut.key, 0, sizeof(keyOut.key));
return false;
}
// Region names are stored without '#' prefix in user-facing code,
// but the key derivation prepends '#' (implicit auto hashtag region).
char tmp[32];
snprintf(tmp, sizeof(tmp), "#%s", scopeName);
TransportKeyStore tempStore;
tempStore.getAutoKeyFor(0, tmp, keyOut);
return true;
}
const char* MyMesh::getChannelScopeName(const mesh::GroupChannel& channel) {
ChannelDetails ch;
for (uint8_t i = 0; i < MAX_GROUP_CHANNELS; i++) {
if (getChannel(i, ch) && ch.name[0] != '\0') {
if (memcmp(ch.channel.secret, channel.secret, sizeof(channel.secret)) == 0) {
return ch.scope_name;
}
}
}
return nullptr;
}
void MyMesh::onMessageRecv(const ContactInfo &from, mesh::Packet *pkt, uint32_t sender_timestamp,
const char *text) {
markConnectionActive(from); // in case this is from a server, and we have a connection
// Detect VE3 voice envelope and notify voice handler
if (_voiceEnvHandler && text && strncmp(text, "VE3:", 4) == 0) {
MESH_DEBUG_PRINTLN("Voice: VE3 envelope from %s: %s", from.name, text);
_voiceEnvHandler(from.name, text);
}
queueMessage(from, TXT_TYPE_PLAIN, pkt, sender_timestamp, NULL, 0, text);
}
@@ -736,6 +798,31 @@ bool MyMesh::uiSendDirectMessage(uint32_t contact_idx, const char* text) {
return true;
}
bool MyMesh::uiSendRawToContact(uint32_t contact_idx, const uint8_t* data, uint8_t len) {
ContactInfo contact;
if (!getContactByIdx(contact_idx, contact)) return false;
ContactInfo* recipient = lookupContactByPubKey(contact.id.pub_key, PUB_KEY_SIZE);
if (!recipient) return false;
// Raw custom packets are direct-route only — cannot flood
if (recipient->out_path_len == OUT_PATH_UNKNOWN) {
MESH_DEBUG_PRINTLN("UI: Raw send to %s failed — no direct path", recipient->name);
return false;
}
mesh::Packet* pkt = createRawData(data, len);
if (!pkt) {
MESH_DEBUG_PRINTLN("UI: Raw send to %s failed — packet pool empty", recipient->name);
return false;
}
sendDirect(pkt, recipient->out_path, recipient->out_path_len);
MESH_DEBUG_PRINTLN("UI: Raw sent %d bytes to %s (direct, path_len=0x%02X)",
len, recipient->name, recipient->out_path_len);
return true;
}
bool MyMesh::uiLoginToRepeater(uint32_t contact_idx, const char* password, uint32_t& est_timeout_ms) {
ContactInfo contact;
if (!getContactByIdx(contact_idx, contact)) {
@@ -831,6 +918,43 @@ bool MyMesh::uiSendTelemetryRequest(uint32_t contact_idx) {
return true;
}
bool MyMesh::setCustomPath(int contactIdx, const uint8_t* path, uint8_t pathLen, bool lock) {
ContactInfo contact;
if (!getContactByIdx(contactIdx, contact)) return false;
ContactInfo* c = lookupContactByPubKey(contact.id.pub_key, PUB_KEY_SIZE);
if (!c) return false;
c->out_path_len = pathLen;
int byteLen = mesh::Packet::getPathByteLenFor(pathLen);
if (byteLen > MAX_PATH_SIZE) byteLen = MAX_PATH_SIZE;
memcpy(c->out_path, path, byteLen);
c->lastmod = getRTCClock()->getCurrentTime();
if (lock) {
c->flags |= CONTACT_FLAG_CUSTOM_PATH;
}
MESH_DEBUG_PRINTLN("setCustomPath: contact %s, pathLen=0x%02X (%d hops, %dB/hop), lock=%d",
c->name, pathLen, pathLen & 0x3F, ((pathLen >> 6) & 3) + 1, lock);
return true;
}
void MyMesh::clearCustomPath(int contactIdx) {
ContactInfo contact;
if (!getContactByIdx(contactIdx, contact)) return;
ContactInfo* c = lookupContactByPubKey(contact.id.pub_key, PUB_KEY_SIZE);
if (!c) return;
c->out_path_len = OUT_PATH_UNKNOWN;
memset(c->out_path, 0, MAX_PATH_SIZE);
c->flags &= ~CONTACT_FLAG_CUSTOM_PATH;
c->lastmod = getRTCClock()->getCurrentTime();
MESH_DEBUG_PRINTLN("clearCustomPath: contact %s — reverted to auto-discovery", c->name);
}
uint8_t MyMesh::onContactRequest(const ContactInfo &contact, uint32_t sender_timestamp, const uint8_t *data,
uint8_t len, uint8_t *reply) {
if (data[0] == REQ_TYPE_GET_TELEMETRY_DATA) {
@@ -1001,6 +1125,13 @@ bool MyMesh::onContactPathRecv(ContactInfo& contact, uint8_t* in_path, uint8_t i
}
}
// let base class handle received path and data
// BUT: if this contact has a custom (manually set) path lock, don't let
// auto-discovery overwrite it. Skip the base class call entirely — ACKs
// embedded in path responses will still be delivered via separate ACK packets.
if (contact.flags & CONTACT_FLAG_CUSTOM_PATH) {
MESH_DEBUG_PRINTLN("onContactPathRecv: skipping path update for custom-path contact %s", contact.name);
return false;
}
return BaseChatMesh::onContactPathRecv(contact, in_path, in_path_len, out_path, out_path_len, extra_type, extra, extra_len);
}
@@ -1085,6 +1216,32 @@ void MyMesh::onRawDataRecv(mesh::Packet *packet) {
MESH_DEBUG_PRINTLN("onRawDataRecv(), payload_len too long: %d", packet->payload_len);
return;
}
// Log ALL incoming raw packets for diagnosis
Serial.printf("onRawDataRecv: len=%d, magic=0x%02X, route=%s\n",
packet->payload_len,
packet->payload_len > 0 ? packet->payload[0] : 0,
packet->isRouteDirect() ? "direct" : "flood");
// Voice-over-LoRa (dz0ny VE3 protocol): intercept voice packets and fetch requests
// before forwarding to BLE companion. In standalone mode (no BLE), this is the
// only way to handle them. In BLE mode, we still intercept so on-device voice works.
if (packet->payload_len > 1 && _voiceHandler) {
uint8_t magic = packet->payload[0];
if (magic == 0x56 || magic == 0x72) { // Voice data (V) or fetch request (r)
Serial.printf("onRawDataRecv: voice %s, payload_len=%d, first6=[%02X %02X %02X %02X %02X %02X]\n",
magic == 0x56 ? "PKT" : "FETCH", packet->payload_len,
packet->payload[0],
packet->payload_len > 1 ? packet->payload[1] : 0,
packet->payload_len > 2 ? packet->payload[2] : 0,
packet->payload_len > 3 ? packet->payload[3] : 0,
packet->payload_len > 4 ? packet->payload[4] : 0,
packet->payload_len > 5 ? packet->payload[5] : 0);
_voiceHandler(magic, packet->payload, packet->payload_len);
// Don't return — still forward to BLE companion if connected
}
}
int i = 0;
out_frame[i++] = PUSH_CODE_RAW_DATA;
out_frame[i++] = (int8_t)(_radio->getLastSNR() * 4);
@@ -1153,7 +1310,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
next_ack_idx = 0;
sign_data = NULL;
dirty_contacts_expiry = 0;
memset(advert_paths, 0, sizeof(advert_paths));
advert_paths = nullptr; // PSRAM-allocated in begin()
memset(send_scope.key, 0, sizeof(send_scope.key));
memset(_sent_track, 0, sizeof(_sent_track));
_sent_track_idx = 0;
@@ -1180,6 +1337,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
}
void MyMesh::begin(bool has_display) {
advert_paths = (AdvertPath*)ps_calloc(ADVERT_PATH_TABLE_SIZE, sizeof(AdvertPath));
BaseChatMesh::begin();
if (!_store->loadMainIdentity(self_id)) {
@@ -1240,6 +1398,7 @@ void MyMesh::begin(bool has_display) {
if (_prefs.autoadd_max_hops > 64) _prefs.autoadd_max_hops = 0;
if (_prefs.dark_mode > 1) _prefs.dark_mode = 0;
if (_prefs.portrait_mode > 1) _prefs.portrait_mode = 0;
if (_prefs.hint_shown > 1) _prefs.hint_shown = 0;
#ifdef BLE_PIN_CODE // 123456 by default
if (_prefs.ble_pin == 0) {
@@ -1474,6 +1633,17 @@ void MyMesh::handleCmdFrame(size_t len) {
memcpy(&secs, &cmd_frame[1], 4);
uint32_t curr = getRTCClock()->getCurrentTime();
if (secs >= curr) {
// Adjust stored advert timestamps if clock jumps significantly
if (advert_paths && secs > curr + 60) {
uint32_t delta = secs - curr;
for (int i = 0; i < ADVERT_PATH_TABLE_SIZE; i++) {
if (advert_paths[i].recv_timestamp > 0) {
advert_paths[i].recv_timestamp += delta;
}
}
Serial.printf("[ClockSync] Adjusted %d advert timestamps by +%lu seconds\n",
ADVERT_PATH_TABLE_SIZE, (unsigned long)delta);
}
getRTCClock()->setCurrentTime(secs);
writeOKFrame();
} else {
@@ -1489,7 +1659,7 @@ void MyMesh::handleCmdFrame(size_t len) {
if (pkt) {
if (len >= 2 && cmd_frame[1] == 1) { // optional param (1 = flood, 0 = zero hop)
unsigned long delay_millis = 0;
sendFlood(pkt, delay_millis, _prefs.path_hash_mode + 1);
sendFlood(pkt, delay_millis, getPathHashSize());
} else {
sendZeroHop(pkt);
}
@@ -1602,23 +1772,12 @@ void MyMesh::handleCmdFrame(size_t len) {
#ifdef DISPLAY_CLASS
if (_ui) {
_ui->msgRead(offline_queue_len);
// Mark channel as read when BLE companion app syncs the message.
// Frame layout V3: [resp_code][snr][res1][res2][channel_idx][path_len]...
// Frame layout V1: [resp_code][channel_idx][path_len]...
bool is_v3_ch = (out_frame[0] == RESP_CODE_CHANNEL_MSG_RECV_V3);
bool is_old_ch = (out_frame[0] == RESP_CODE_CHANNEL_MSG_RECV);
if (is_v3_ch || is_old_ch) {
uint8_t ch_idx = is_v3_ch ? out_frame[4] : out_frame[1];
_ui->markChannelReadFromBLE(ch_idx);
}
// Mark DM slot read when companion app syncs a contact (DM/room) message
bool is_v3_dm = (out_frame[0] == RESP_CODE_CONTACT_MSG_RECV_V3);
bool is_old_dm = (out_frame[0] == RESP_CODE_CONTACT_MSG_RECV);
if (is_v3_dm || is_old_dm) {
_ui->markChannelReadFromBLE(0xFF);
}
// Note: we intentionally do NOT mark channels/DMs as read here.
// CMD_SYNC_NEXT_MESSAGE fires during the automatic bulk sync when
// the BLE app connects — "synced to app" ≠ "read by user in app".
// Unread counts only clear when the user navigates to that channel
// on the device itself. The MeshCore BLE protocol has no "mark as
// read" command from the app side, so this is the safest behaviour.
}
#endif
} else {
@@ -1946,6 +2105,11 @@ void MyMesh::handleCmdFrame(size_t len) {
} else if (cmd_frame[0] == CMD_SET_CHANNEL && len >= 2 + 32 + 16) {
uint8_t channel_idx = cmd_frame[1];
ChannelDetails channel;
// Preserve existing scope_name if channel already exists
ChannelDetails existing;
if (getChannel(channel_idx, existing) && existing.name[0] != '\0') {
memcpy(channel.scope_name, existing.scope_name, sizeof(channel.scope_name));
}
StrHelper::strncpy(channel.name, (char *)&cmd_frame[2], 32);
memset(channel.channel.secret, 0, sizeof(channel.channel.secret));
memcpy(channel.channel.secret, &cmd_frame[2 + 32], 16); // NOTE: only 128-bit supported
@@ -2156,13 +2320,44 @@ void MyMesh::handleCmdFrame(size_t len) {
} else {
writeErrFrame(ERR_CODE_FILE_IO_ERROR);
}
} else if (cmd_frame[0] == CMD_SET_FLOOD_SCOPE && len >= 2 && cmd_frame[1] == 0) {
} else if (cmd_frame[0] == CMD_SET_FLOOD_SCOPE_KEY && len >= 2 && cmd_frame[1] == 0) {
if (len >= 2 + 16) {
memcpy(send_scope.key, &cmd_frame[2], sizeof(send_scope.key)); // set curr scope TransportKey
Serial.printf("[CMD54] Per-channel scope key set (%d bytes)\n", len - 2);
} else {
memset(send_scope.key, 0, sizeof(send_scope.key)); // set scope to null
Serial.println("[CMD54] Per-channel scope cleared");
}
writeOKFrame();
} else if (cmd_frame[0] == CMD_SET_DEFAULT_FLOOD_SCOPE && len >= 1) {
// v1.15+ — set device-wide default flood scope (name[31] + key[16])
if (len >= 1+31+16) {
int n = strlen((char *) &cmd_frame[1]);
if (n > 0 && n < 31) {
strcpy(_prefs.default_scope_name, (char *) &cmd_frame[1]);
memcpy(_prefs.default_scope_key, &cmd_frame[1+31], 16);
savePrefs();
writeOKFrame();
} else {
writeErrFrame(ERR_CODE_ILLEGAL_ARG);
}
} else {
// Clear default scope (unscoped)
memset(_prefs.default_scope_name, 0, sizeof(_prefs.default_scope_name));
memset(_prefs.default_scope_key, 0, sizeof(_prefs.default_scope_key));
savePrefs();
writeOKFrame();
}
} else if (cmd_frame[0] == CMD_GET_DEFAULT_FLOOD_SCOPE) {
// v1.15+ — query current default flood scope
out_frame[0] = RESP_CODE_DEFAULT_FLOOD_SCOPE;
if (strlen(_prefs.default_scope_name) > 0) {
memcpy(&out_frame[1], _prefs.default_scope_name, 31);
memcpy(&out_frame[1+31], _prefs.default_scope_key, 16);
_serial->writeFrame(out_frame, 1+31+16);
} else {
_serial->writeFrame(out_frame, 1); // no name or key means null/unscoped
}
} else if (cmd_frame[0] == CMD_SEND_CONTROL_DATA && len >= 2 && (cmd_frame[1] & 0x80) != 0) {
auto resp = createControlData(&cmd_frame[1], len - 1);
if (resp) {
@@ -2254,11 +2449,35 @@ void MyMesh::checkCLIRescueCmd() {
Serial.printf(" > %d\n", _prefs.multi_acks);
} else if (strcmp(key, "int.thresh") == 0) {
Serial.printf(" > %d\n", _prefs.interference_threshold);
} else if (strcmp(key, "tx.fail.threshold") == 0) {
Serial.printf(" > %d\n", _prefs.tx_fail_reset_threshold);
} else if (strcmp(key, "rx.fail.threshold") == 0) {
Serial.printf(" > %d\n", _prefs.rx_fail_reboot_threshold);
} else if (strcmp(key, "gps.baud") == 0) {
uint32_t effective = _prefs.gps_baudrate ? _prefs.gps_baudrate : GPS_BAUDRATE;
Serial.printf(" > %lu (effective: %lu)\n",
(unsigned long)_prefs.gps_baudrate, (unsigned long)effective);
} else if (strcmp(key, "region") == 0) {
if (_prefs.default_scope_name[0]) {
Serial.printf(" > %s\n", _prefs.default_scope_name);
} else {
Serial.println(" > (none — unscoped)");
}
} else if (memcmp(key, "channel.scope ", 14) == 0) {
int idx = atoi(&key[14]);
if (idx >= 0 && idx < MAX_GROUP_CHANNELS) {
ChannelDetails ch;
if (getChannel(idx, ch) && ch.name[0] != '\0') {
Serial.printf(" > %s scope: %s\n", ch.name,
ch.scope_name[0] ? ch.scope_name : "(device default)");
} else {
Serial.printf(" Error: channel %d is empty\n", idx);
}
} else {
Serial.println(" Error: invalid channel index");
}
} else if (strcmp(key, "radio") == 0) {
Serial.printf(" > freq=%.3f bw=%.1f sf=%d cr=%d tx=%d\n",
_prefs.freq, _prefs.bw, _prefs.sf, _prefs.cr, _prefs.tx_power_dbm);
@@ -2273,7 +2492,11 @@ void MyMesh::checkCLIRescueCmd() {
for (uint8_t i = 0; i < MAX_GROUP_CHANNELS; i++) {
ChannelDetails ch;
if (getChannel(i, ch) && ch.name[0] != '\0') {
Serial.printf(" [%d] %s\n", i, ch.name);
if (ch.scope_name[0]) {
Serial.printf(" [%d] %s [%s]\n", i, ch.name, ch.scope_name);
} else {
Serial.printf(" [%d] %s [*]\n", i, ch.name);
}
found = true;
} else {
break;
@@ -2314,10 +2537,14 @@ void MyMesh::checkCLIRescueCmd() {
Serial.printf(" af: %.1f\n", _prefs.airtime_factor);
Serial.printf(" multi.acks: %d\n", _prefs.multi_acks);
Serial.printf(" int.thresh: %d\n", _prefs.interference_threshold);
Serial.printf(" tx.fail: %d\n", _prefs.tx_fail_reset_threshold);
Serial.printf(" rx.fail: %d\n", _prefs.rx_fail_reboot_threshold);
{
uint32_t eff_baud = _prefs.gps_baudrate ? _prefs.gps_baudrate : GPS_BAUDRATE;
Serial.printf(" gps.baud: %lu\n", (unsigned long)eff_baud);
}
Serial.printf(" region: %s\n",
_prefs.default_scope_name[0] ? _prefs.default_scope_name : "(none — unscoped)");
#ifdef HAS_4G_MODEM
Serial.printf(" modem: %s\n", ModemManager::loadEnabledConfig() ? "on" : "off");
Serial.printf(" apn: %s\n", modemManager.getAPN());
@@ -2352,7 +2579,11 @@ void MyMesh::checkCLIRescueCmd() {
for (uint8_t i = 0; i < MAX_GROUP_CHANNELS; i++) {
ChannelDetails ch;
if (getChannel(i, ch) && ch.name[0] != '\0') {
Serial.printf(" [%d] %s\n", i, ch.name);
if (ch.scope_name[0]) {
Serial.printf(" [%d] %s [%s]\n", i, ch.name, ch.scope_name);
} else {
Serial.printf(" [%d] %s [*]\n", i, ch.name);
}
chFound = true;
} else {
break;
@@ -2709,6 +2940,30 @@ void MyMesh::checkCLIRescueCmd() {
Serial.println(" Error: use 0 (disabled) or 14+ (typical: 14)");
}
} else if (memcmp(config, "tx.fail.threshold ", 18) == 0) {
int val = atoi(&config[18]);
if (val < 0) val = 0;
if (val > 10) val = 10;
_prefs.tx_fail_reset_threshold = (uint8_t)val;
savePrefs();
if (val == 0) {
Serial.println(" > tx fail reset disabled");
} else {
Serial.printf(" > tx fail reset after %d failures\n", val);
}
} else if (memcmp(config, "rx.fail.threshold ", 18) == 0) {
int val = atoi(&config[18]);
if (val < 0) val = 0;
if (val > 10) val = 10;
_prefs.rx_fail_reboot_threshold = (uint8_t)val;
savePrefs();
if (val == 0) {
Serial.println(" > rx fail reboot disabled");
} else {
Serial.printf(" > reboot after %d rx recovery failures\n", val);
}
} else if (memcmp(config, "gps.baud ", 9) == 0) {
uint32_t val = (uint32_t)atol(&config[9]);
if (val == 0 || val == 4800 || val == 9600 || val == 19200 ||
@@ -2722,6 +2977,54 @@ void MyMesh::checkCLIRescueCmd() {
Serial.println(" Error: use 0 (default), 4800, 9600, 19200, 38400, 57600, or 115200");
}
// Region scope commands
} else if (memcmp(config, "region ", 7) == 0) {
const char* name = &config[7];
if (strcmp(name, "none") == 0 || strcmp(name, "clear") == 0 || name[0] == '\0') {
memset(_prefs.default_scope_name, 0, sizeof(_prefs.default_scope_name));
memset(_prefs.default_scope_key, 0, sizeof(_prefs.default_scope_key));
savePrefs();
Serial.println(" > region cleared (unscoped)");
} else if (strlen(name) < 31) {
strncpy(_prefs.default_scope_name, name, sizeof(_prefs.default_scope_name));
_prefs.default_scope_name[30] = '\0';
TransportKey key;
deriveScopeKey(name, key);
memcpy(_prefs.default_scope_key, key.key, sizeof(_prefs.default_scope_key));
savePrefs();
Serial.printf(" > region = %s\n", _prefs.default_scope_name);
} else {
Serial.println(" Error: region name too long (max 29 chars)");
}
} else if (memcmp(config, "channel.scope ", 14) == 0) {
// set channel.scope <idx> <name> (or "set channel.scope <idx> none" to clear)
int idx = atoi(&config[14]);
const char* rest = strchr(&config[14], ' ');
if (idx >= 0 && idx < MAX_GROUP_CHANNELS && rest) {
rest++; // skip space
ChannelDetails ch;
if (getChannel(idx, ch) && ch.name[0] != '\0') {
if (strcmp(rest, "none") == 0 || strcmp(rest, "clear") == 0) {
memset(ch.scope_name, 0, sizeof(ch.scope_name));
} else if (strlen(rest) < 31) {
strncpy(ch.scope_name, rest, sizeof(ch.scope_name));
ch.scope_name[30] = '\0';
} else {
Serial.println(" Error: scope name too long (max 29 chars)");
cli_command[0] = 0;
return;
}
setChannel(idx, ch);
saveChannels();
Serial.printf(" > %s scope = %s\n", ch.name,
ch.scope_name[0] ? ch.scope_name : "(device default)");
} else {
Serial.printf(" Error: channel %d is empty\n", idx);
}
} else {
Serial.println(" Usage: set channel.scope <idx> <name|none>");
}
// Backlight control (T5S3 E-Paper Pro only)
} else if (memcmp(config, "backlight ", 10) == 0) {
#if defined(LilyGo_T5S3_EPaper_Pro)
@@ -2756,6 +3059,17 @@ void MyMesh::checkCLIRescueCmd() {
} else if (memcmp(cli_command, "clock sync ", 11) == 0) {
uint32_t epoch = (uint32_t)strtoul(&cli_command[11], nullptr, 10);
if (epoch > 1704067200UL && epoch < 2082758400UL) {
// Adjust stored advert timestamps if clock jumps significantly
uint32_t curr = getRTCClock()->getCurrentTime();
if (advert_paths && epoch > curr + 60) {
uint32_t delta = epoch - curr;
for (int i = 0; i < ADVERT_PATH_TABLE_SIZE; i++) {
if (advert_paths[i].recv_timestamp > 0) {
advert_paths[i].recv_timestamp += delta;
}
}
Serial.printf(" > adjusted advert timestamps by +%lu seconds\n", (unsigned long)delta);
}
getRTCClock()->setCurrentTime(epoch);
Serial.printf(" > clock synced to %lu\n", (unsigned long)epoch);
} else {
@@ -2806,6 +3120,8 @@ void MyMesh::checkCLIRescueCmd() {
Serial.println(" af <0-9> Airtime factor");
Serial.println(" multi.acks <0|1> Redundant ACKs (default: 1)");
Serial.println(" int.thresh <0|14+> Interference threshold dB (0=off, 14=typical)");
Serial.println(" tx.fail.threshold <0-10> TX fail radio reset (0=off, default 3)");
Serial.println(" rx.fail.threshold <0-10> RX stuck reboot (0=off, default 3)");
Serial.println(" gps.baud <rate> GPS baud (0=default, reboot to apply)");
Serial.println("");
Serial.println(" Clock:");
@@ -2824,6 +3140,12 @@ void MyMesh::checkCLIRescueCmd() {
Serial.println(" set preset <name|num> Apply radio preset");
Serial.println(" set channel.add <name> Add hashtag channel");
Serial.println(" set channel.del <idx> Delete channel by index");
Serial.println("");
Serial.println(" Regions:");
Serial.println(" get/set region Device default region (e.g. au-nsw)");
Serial.println(" set region none Clear default region (unscoped)");
Serial.println(" get channel.scope <i> Show scope for channel i");
Serial.println(" set channel.scope <i> <name|none>");
#ifdef HAS_4G_MODEM
Serial.println("");
Serial.println(" 4G modem:");
@@ -2997,20 +3319,29 @@ void MyMesh::checkSerialInterface() {
} else if (_iter_started // check if our ContactsIterator is 'running'
&& !_serial->isWriteBusy() // don't spam the Serial Interface too quickly!
) {
// Batch-fill: queue multiple contacts per loop iteration so the BLE
// send queue stays saturated during sync. writeFrame() returns 0
// when the queue is full, which naturally throttles us.
ContactInfo contact;
if (_iter.hasNext(this, contact)) {
if (contact.lastmod > _iter_filter_since) { // apply the 'since' filter
writeContactRespFrame(RESP_CODE_CONTACT, contact);
if (contact.lastmod > _most_recent_lastmod) {
_most_recent_lastmod = contact.lastmod; // save for the RESP_CODE_END_OF_CONTACTS frame
bool done = false;
int queued = 0;
while (!done && queued < 8) { // up to 8 per iteration to avoid starving loop()
if (_iter.hasNext(this, contact)) {
if (contact.lastmod > _iter_filter_since) { // apply the 'since' filter
if (writeContactRespFrame(RESP_CODE_CONTACT, contact) == 0) break; // queue full
queued++;
if (contact.lastmod > _most_recent_lastmod) {
_most_recent_lastmod = contact.lastmod;
}
}
} else { // EOF
out_frame[0] = RESP_CODE_END_OF_CONTACTS;
memcpy(&out_frame[1], &_most_recent_lastmod,
4); // include the most recent lastmod, so app can update their 'since'
_serial->writeFrame(out_frame, 5);
_iter_started = false;
done = true;
}
} else { // EOF
out_frame[0] = RESP_CODE_END_OF_CONTACTS;
memcpy(&out_frame[1], &_most_recent_lastmod,
4); // include the most recent lastmod, so app can update their 'since'
_serial->writeFrame(out_frame, 5);
_iter_started = false;
}
//} else if (!_serial->isWriteBusy()) {
// checkConnections(); // TODO - deprecate the 'Connections' stuff
@@ -3030,14 +3361,17 @@ void MyMesh::loop() {
// is there are pending dirty contacts write needed?
if (dirty_contacts_expiry && millisHasNowPassed(dirty_contacts_expiry)) {
if (!_store->isSaveInProgress()) {
if (_deferSaves) {
// Voice session receiving — push save forward to avoid SPI contention
dirty_contacts_expiry = futureMillis(2000);
} else if (!_store->isSaveInProgress()) {
_store->beginSaveContacts(this);
dirty_contacts_expiry = 0;
}
dirty_contacts_expiry = 0;
}
// Drive chunked contact save — write a batch each loop iteration
if (_store->isSaveInProgress()) {
if (_store->isSaveInProgress() && !_deferSaves) {
if (!_store->saveContactsChunk(20)) { // 20 contacts per chunk (~3KB, ~30ms)
_store->finishSaveContacts(); // Done or error — verify and commit
}
@@ -3101,6 +3435,13 @@ void MyMesh::stopDiscovery() {
_discoveryActive = false;
}
bool MyMesh::forceImportContact(const uint8_t* blob, uint8_t len) {
_forceNextImport = true;
bool ok = importContact(blob, len);
if (!ok) _forceNextImport = false; // clear if importContact failed (no loopback queued)
return ok;
}
bool MyMesh::addDiscoveredToContacts(int idx) {
if (idx < 0 || idx >= _discoveredCount) return false;
if (_discovered[idx].already_in_contacts) return true; // already there
@@ -3109,7 +3450,7 @@ bool MyMesh::addDiscoveredToContacts(int idx) {
uint8_t buf[256];
int plen = getBlobByKey(_discovered[idx].contact.id.pub_key, PUB_KEY_SIZE, buf);
if (plen > 0) {
bool ok = importContact(buf, (uint8_t)plen);
bool ok = forceImportContact(buf, (uint8_t)plen);
if (ok) {
_discovered[idx].already_in_contacts = true;
dirty_contacts_expiry = futureMillis(LAZY_CONTACTS_WRITE_DELAY);
+55 -7
View File
@@ -5,14 +5,14 @@
#include "AbstractUITask.h"
/*------------ Frame Protocol --------------*/
#define FIRMWARE_VER_CODE 10
#define FIRMWARE_VER_CODE 11
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "22 March 2026"
#define FIRMWARE_BUILD_DATE "19 April 2026"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "Meck v1.3"
#define FIRMWARE_VERSION "Meck v1.7"
#endif
#if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM)
@@ -70,6 +70,11 @@
#include <helpers/BaseChatMesh.h>
#include <helpers/TransportKeyStore.h>
// Custom path lock flag — bit 7 of ContactInfo.flags
// When set, onContactPathRecv skips auto-updating this contact's out_path.
// Bits 0-6 remain available (bit 0 = favourite, bits 1-3 = telemetry perms).
#define CONTACT_FLAG_CUSTOM_PATH 0x80
/* -------------------------------------------------------------------------------------- */
#define REQ_TYPE_GET_STATUS 0x01 // same as _GET_STATS
@@ -77,7 +82,7 @@
#define REQ_TYPE_GET_TELEMETRY_DATA 0x03
struct AdvertPath {
uint8_t pubkey_prefix[7];
uint8_t pubkey_prefix[8];
uint8_t path_len;
uint8_t type; // ADV_TYPE_* (Chat/Repeater/Room/Sensor)
char name[32];
@@ -126,6 +131,9 @@ public:
int getContactBlob(const uint8_t key[], int key_len, uint8_t dest_buf[]) {
return getBlobByKey(key, key_len, dest_buf);
}
// Force-add a contact from a raw advert blob, bypassing auto-add settings.
// Used by Last Heard and Discovery when the user explicitly selects a node to add.
bool forceImportContact(const uint8_t* blob, uint8_t len);
// Queue a sent channel message for BLE app sync
void queueSentChannelMessage(uint8_t channel_idx, uint32_t timestamp, const char* sender, const char* text);
@@ -133,16 +141,50 @@ public:
// Send a direct message from the UI (no BLE dependency)
bool uiSendDirectMessage(uint32_t contact_idx, const char* text);
// Send raw binary data to a contact (PAYLOAD_TYPE_RAW_CUSTOM, direct route only)
// Used for dz0ny VE3 voice protocol: voice packets (0x56) and fetch requests (0x72)
bool uiSendRawToContact(uint32_t contact_idx, const uint8_t* data, uint8_t len);
// Voice-over-LoRa: callback for incoming raw voice packets (dz0ny VE3 protocol)
// magic 0x56 = voice data packet, 0x72 = fetch request
typedef void (*VoiceRawHandler)(uint8_t magic, const uint8_t* payload, uint8_t len);
void setVoiceHandler(VoiceRawHandler h) { _voiceHandler = h; }
// Voice-over-LoRa: callback for incoming VE3 envelope in a DM
// Called with sender name and the VE3 text (e.g. "VE3:a:1:3:2")
typedef void (*VoiceEnvelopeHandler)(const char* senderName, const char* ve3Text);
void setVoiceEnvelopeHandler(VoiceEnvelopeHandler h) { _voiceEnvHandler = h; }
// Defer contact saves while voice packets are being received
// (SD writes block SPI bus shared with LoRa radio)
void setDeferSaves(bool defer) { _deferSaves = defer; }
bool isDeferSaves() const { return _deferSaves; }
// Repeater admin - UI-initiated operations
bool uiLoginToRepeater(uint32_t contact_idx, const char* password, uint32_t& est_timeout_ms);
bool uiSendCliCommand(uint32_t contact_idx, const char* command);
bool uiSendTelemetryRequest(uint32_t contact_idx);
int getAdminContactIdx() const { return _admin_contact_idx; }
// Custom path editor — set or clear a manually configured path for a contact
// When locked, automatic path discovery will not overwrite this contact's path.
bool setCustomPath(int contactIdx, const uint8_t* path, uint8_t pathLen, bool lock);
void clearCustomPath(int contactIdx);
// Region scope helpers (public — used by SettingsScreen)
// Derive a TransportKey from a region scope name (e.g. "au-nsw" → "#au-nsw" → SHA256 → key).
// Returns true if name is non-empty and key was derived; false if name is empty (unscoped).
bool deriveScopeKey(const char* scopeName, TransportKey& keyOut);
// Look up per-channel scope name by GroupChannel secret match. Returns nullptr if no scope set.
const char* getChannelScopeName(const mesh::GroupChannel& channel);
protected:
float getAirtimeBudgetFactor() const override;
int getInterferenceThreshold() const override;
uint8_t getTxFailResetThreshold() const override;
uint8_t getRxFailRebootThreshold() const override;
void onRxUnrecoverable() override;
int calcRxDelay(float score, uint32_t air_time) const override;
uint32_t getRetransmitDelay(const mesh::Packet *packet) override;
uint32_t getDirectRetransmitDelay(const mesh::Packet *packet) override;
@@ -150,8 +192,10 @@ protected:
uint8_t getAutoAddMaxHops() const override;
bool filterRecvFloodPacket(mesh::Packet* packet) override;
uint8_t getPathHashSize() const override { return _prefs.path_hash_mode + 1; }
void sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis=0) override;
void sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis=0) override;
void sendFloodScoped(const TransportKey& scope, mesh::Packet* pkt, uint32_t delay_millis=0);
void logRxRaw(float snr, float rssi, const uint8_t raw[], int len) override;
bool isAutoAddEnabled() const override;
@@ -210,7 +254,7 @@ private:
void writeOKFrame();
void writeErrFrame(uint8_t err_code);
void writeDisabledFrame();
void writeContactRespFrame(uint8_t code, const ContactInfo &contact);
size_t writeContactRespFrame(uint8_t code, const ContactInfo &contact);
void updateContactFromFrame(ContactInfo &contact, uint32_t& last_mod, const uint8_t *frame, int len);
void addToOfflineQueue(const uint8_t frame[], int len);
int getFromOfflineQueue(uint8_t frame[]);
@@ -226,6 +270,10 @@ private:
DataStore* _store;
NodePrefs _prefs;
VoiceRawHandler _voiceHandler = nullptr;
VoiceEnvelopeHandler _voiceEnvHandler = nullptr;
mutable bool _forceNextImport = false;
bool _deferSaves = false;
uint32_t pending_login;
uint32_t pending_status;
uint32_t pending_telemetry, pending_discovery; // pending _TELEMETRY_REQ
@@ -269,8 +317,8 @@ private:
AckTableEntry expected_ack_table[EXPECTED_ACK_TABLE_SIZE]; // circular table
int next_ack_idx;
#define ADVERT_PATH_TABLE_SIZE 40
AdvertPath advert_paths[ADVERT_PATH_TABLE_SIZE]; // circular table
#define ADVERT_PATH_TABLE_SIZE 1000
AdvertPath* advert_paths; // PSRAM-allocated in begin(), size = ADVERT_PATH_TABLE_SIZE
// Sent message repeat tracking
#define SENT_TRACK_SIZE 4
+53
View File
@@ -38,4 +38,57 @@ struct NodePrefs { // persisted to file
uint8_t dark_mode; // 0=off (white bg), 1=on (black bg)
uint8_t portrait_mode; // 0=landscape, 1=portrait — T5S3 only
uint8_t auto_lock_minutes; // 0=disabled, 2/5/10/15/30=auto-lock after idle
uint8_t hint_shown; // 0=show nav hint on boot, 1=already shown (dismiss permanently)
uint8_t large_font; // 0=tiny (built-in 6x8), 1=larger (FreeSans9pt) — T-Deck Pro only
uint8_t ui_font_style; // 0=Classic (FreeSans), 1=Noto Sans, 2=Montserrat
uint8_t tx_fail_reset_threshold; // 0=disabled, 1-10, default 3
uint8_t rx_fail_reboot_threshold; // 0=disabled, 1-10, default 3
// --- Region scope (MeshCore v1.15+ compatibility) ---
// Device-wide default region for flood messages.
// Empty default_scope_name = unscoped (legacy flood, reaches all repeaters).
// When set, all flood sends use ROUTE_TYPE_TRANSPORT_FLOOD with transport
// codes derived from this key. Per-channel scope (in ChannelDetails) takes
// priority when set.
char default_scope_name[31]; // e.g. "au-nsw", empty = unscoped
uint8_t default_scope_key[16]; // TransportKey derived from "#" + name
// --- Font helpers (inline, no overhead) ---
// Returns the DisplayDriver text-size index for "small/body" text.
// T-Deck Pro: 0 = built-in 6×8 (or 7pt with custom fonts), 1 = 9pt.
// T5S3: both 0 and 1 are 12pt fonts (regular vs bold) with identical line
// height, so large_font has no layout effect there.
inline uint8_t smallTextSize() const {
return large_font ? 1 : 0;
}
// Returns the virtual-coordinate line height matching smallTextSize().
// T-Deck Pro size 0 → 9 (6×8 + 1px gap), size 1 → 11 (9pt ascent+descent).
// With custom fonts (Noto 7pt, Montserrat 7pt), size 0 is slightly taller
// than built-in 6×8 but fits within the 9-unit virtual grid.
// T5S3 size 0/1 → same 12pt height → always 9 in virtual coords.
inline int smallLineH() const {
#if defined(LilyGo_T5S3_EPaper_Pro)
return 9;
#else
return large_font ? 11 : 9;
#endif
}
// Returns the Y offset for selection highlight fillRect (T-Deck Pro only).
// Size 0 (built-in font): cursor positions at top-left, +5 offset in
// setCursor places text below → fillRect at y+5 aligns with text.
// Size 0 (custom 7pt fonts): baseline fonts, same behaviour as size 1.
// Size 1 (9pt): cursor positions at baseline, ascenders render
// upward → fillRect must start above baseline to cover ascenders.
// T5S3: always 0 (both sizes use baseline fonts with highlight at y).
inline int smallHighlightOff() const {
#if defined(LilyGo_T5S3_EPaper_Pro)
return 0;
#else
// Custom 7pt fonts at textSize 0 use GFXfont (baseline rendering), not built-in
if (ui_font_style > 0 && !large_font) return -2;
return large_font ? -2 : 5;
#endif
}
};
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -43,6 +43,8 @@
// JPEG decoder for cover art — JPEGDEC by bitbank2
#include <JPEGDEC.h>
#include "../NodePrefs.h"
// Forward declarations
class UITask;
@@ -151,6 +153,7 @@ public:
private:
UITask* _task;
NodePrefs* _prefs;
Audio* _audio;
Mode _mode;
bool _sdReady;
@@ -1193,10 +1196,10 @@ private:
}
// Switch to tiny font for file list (6x8 built-in)
display.setTextSize(0);
display.setTextSize(_prefs ? _prefs->smallTextSize() : 0);
// Calculate visible items — tiny font uses ~8 virtual units per line
int itemHeight = 8;
// Calculate visible items
int itemHeight = (_prefs ? _prefs->smallLineH() : 9) - 1;
int listTop = 13;
int listBottom = display.height() - 14; // Reserve footer space
int visibleItems = (listBottom - listTop) / itemHeight;
@@ -1208,7 +1211,7 @@ private:
_scrollOffset = _selectedFile - visibleItems + 1;
}
// Approx chars that fit in tiny font (~36 on 128 virtual width)
// Approx chars for suffix/type tag sizing (still needed for type tag assembly)
const int charsPerLine = 36;
// Draw file list
@@ -1218,9 +1221,7 @@ private:
if (fileIdx == _selectedFile) {
display.setColor(DisplayDriver::LIGHT);
// setCursor adds +5 to y internally, but fillRect does not.
// Offset fillRect by +5 to align highlight bar with text.
display.fillRect(0, y + 5, display.width(), itemHeight - 1);
display.fillRect(0, y + (_prefs ? _prefs->smallHighlightOff() : 5), display.width(), itemHeight - 1);
display.setColor(DisplayDriver::DARK);
} else {
display.setColor(DisplayDriver::LIGHT);
@@ -1231,29 +1232,15 @@ private:
char fullLine[96];
if (fe.isDir) {
// Directory entry: show as "/ FolderName" or just ".."
if (fe.name == "..") {
snprintf(fullLine, sizeof(fullLine), ".. (up)");
} else {
snprintf(fullLine, sizeof(fullLine), "/%s", fe.name.c_str());
// Truncate if needed
if ((int)strlen(fullLine) > charsPerLine - 1) {
fullLine[charsPerLine - 4] = '.';
fullLine[charsPerLine - 3] = '.';
fullLine[charsPerLine - 2] = '.';
fullLine[charsPerLine - 1] = '\0';
}
}
} else {
// Audio file: "Title - Author [TYPE]"
char lineBuf[80];
// Reserve space for type tag and bookmark indicator
int suffixLen = fe.fileType.length() + 3; // " [M4B]" or " [MP3]"
int bmkLen = fe.hasBookmark ? 2 : 0; // " >"
int availChars = charsPerLine - suffixLen - bmkLen;
if (availChars < 10) availChars = 10;
if (fe.displayAuthor.length() > 0) {
snprintf(lineBuf, sizeof(lineBuf), "%s - %s",
fe.displayTitle.c_str(), fe.displayAuthor.c_str());
@@ -1261,24 +1248,13 @@ private:
snprintf(lineBuf, sizeof(lineBuf), "%s", fe.displayTitle.c_str());
}
// Truncate with ellipsis if needed
if ((int)strlen(lineBuf) > availChars) {
if (availChars > 3) {
lineBuf[availChars - 3] = '.';
lineBuf[availChars - 2] = '.';
lineBuf[availChars - 1] = '.';
lineBuf[availChars] = '\0';
} else {
lineBuf[availChars] = '\0';
}
}
// Append file type tag
snprintf(fullLine, sizeof(fullLine), "%s [%s]", lineBuf, fe.fileType.c_str());
}
display.setCursor(2, y);
display.print(fullLine);
// Pixel-aware ellipsis — reserve space for bookmark indicator
int reserveRight = (!fe.isDir && fe.hasBookmark) ? 10 : 2;
display.drawTextEllipsized(2, y, display.width() - reserveRight, fullLine);
// Bookmark indicator (right-aligned, files only)
if (!fe.isDir && fe.hasBookmark) {
@@ -1464,8 +1440,8 @@ private:
}
public:
AudiobookPlayerScreen(UITask* task, Audio* audio)
: _task(task), _audio(audio), _mode(FILE_LIST),
AudiobookPlayerScreen(UITask* task, Audio* audio, NodePrefs* prefs = nullptr)
: _task(task), _prefs(prefs), _audio(audio), _mode(FILE_LIST),
_sdReady(false), _i2sInitialized(false), _dacPowered(false),
_displayRef(nullptr),
_selectedFile(0), _scrollOffset(0),
+25 -66
View File
@@ -637,8 +637,8 @@ public:
}
// Render inbox list
display.setTextSize(0);
int lineH = 9;
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize());
int lineH = the_mesh.getNodePrefs()->smallLineH();
int headerH = 14;
int footerH = 14;
int maxY = display.height() - footerH;
@@ -672,7 +672,7 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), lineH);
#else
display.fillRect(0, y + 5, display.width(), lineH);
display.fillRect(0, y + the_mesh.getNodePrefs()->smallHighlightOff(), display.width(), lineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -745,8 +745,8 @@ public:
// --- Path detail overlay ---
if (_showPathOverlay) {
display.setTextSize(0);
int lineH = 9;
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize());
int lineH = the_mesh.getNodePrefs()->smallLineH();
int y = 14;
ChannelMessage* msg = getNewestReceivedMsg();
@@ -942,7 +942,7 @@ public:
}
if (channelMsgCount == 0) {
display.setTextSize(0); // Tiny font for body text
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize()); // Tiny font for body text
display.setCursor(0, 20);
display.setColor(DisplayDriver::LIGHT);
if (_viewChannelIdx == 0xFF) {
@@ -975,8 +975,8 @@ public:
// =================================================================
// DM Inbox: list of contacts/rooms you have DM history with
// =================================================================
display.setTextSize(0);
int lineHeight = 9;
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize());
int lineHeight = the_mesh.getNodePrefs()->smallLineH();
int headerHeight = 14;
int footerHeight = 14;
int maxY = display.height() - footerHeight;
@@ -1056,7 +1056,7 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), lineHeight);
#else
display.fillRect(0, y + 5, display.width(), lineHeight);
display.fillRect(0, y + the_mesh.getNodePrefs()->smallHighlightOff(), display.width(), lineHeight);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -1094,8 +1094,8 @@ public:
}
display.setTextSize(1);
} else {
display.setTextSize(0); // Tiny font for message body
int lineHeight = 9; // 8px font + 1px spacing
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize()); // Tiny font for message body
int lineHeight = the_mesh.getNodePrefs()->smallLineH(); // 8px font + 1px spacing
int headerHeight = 14;
int footerHeight = 14;
int scrollBarW = 4; // Width of scroll indicator on right edge
@@ -1163,7 +1163,7 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, contentW, maxFillH);
#else
display.fillRect(0, y + 5, contentW, maxFillH);
display.fillRect(0, y + the_mesh.getNodePrefs()->smallHighlightOff(), contentW, maxFillH);
#endif
}
@@ -1324,7 +1324,7 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, contentW, maxFillH - usedH);
#else
display.fillRect(0, y + 5, contentW, maxFillH - usedH);
display.fillRect(0, y + the_mesh.getNodePrefs()->smallHighlightOff(), contentW, maxFillH - usedH);
#endif
}
}
@@ -1388,7 +1388,7 @@ public:
display.setCursor(display.width() - display.getTextWidth(rtCh) - 2, footerY);
display.print(rtCh);
} else {
display.print("Swipe:Ch/Scroll");
display.print("Swipe:List/Scroll");
const char* midCh = "Tap:Path";
display.setCursor((display.width() - display.getTextWidth(midCh)) / 2, footerY);
display.print(midCh);
@@ -1413,10 +1413,14 @@ public:
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
display.print(rightText);
} else {
display.print("Q:Bck A/D:Ch R:Rply");
const char* rightText = "Ent:New";
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
display.print(rightText);
display.print("Q:Bk A/D:List R:Rply");
// "Ent:New" only fits with Classic+TINY — wider fonts cause overlap
NodePrefs* _fp = the_mesh.getNodePrefs();
if (_fp->ui_font_style == 0 && !_fp->large_font) {
const char* rightText = " Ent:New";
display.setCursor(display.width() - display.getTextWidth(rightText) - 2, footerY);
display.print(rightText);
}
}
#endif
@@ -1632,56 +1636,11 @@ public:
}
}
// A - previous channel (includes DM tab at 0xFF)
if (c == 'a' || c == 'A') {
// A/D - open channel picker (handled by main.cpp — return false to pass through)
if (c == 'a' || c == 'A' || c == 'd' || c == 'D') {
_replySelectMode = false;
_replySelectPos = -1;
if (_viewChannelIdx == 0xFF) {
// DM tab → go to last valid group channel
for (uint8_t i = MAX_GROUP_CHANNELS - 1; i > 0; i--) {
ChannelDetails ch;
if (the_mesh.getChannel(i, ch) && ch.name[0] != '\0') {
_viewChannelIdx = i;
break;
}
}
} else if (_viewChannelIdx > 0) {
_viewChannelIdx--;
} else {
// Channel 0 → wrap to DM tab
_viewChannelIdx = 0xFF;
_dmInboxMode = true;
_dmInboxScroll = 0;
_dmFilterName[0] = '\0';
}
_scrollPos = 0;
markChannelRead(_viewChannelIdx);
return true;
}
// D - next channel (includes DM tab at 0xFF)
if (c == 'd' || c == 'D') {
_replySelectMode = false;
_replySelectPos = -1;
if (_viewChannelIdx == 0xFF) {
// DM tab → wrap to channel 0
_viewChannelIdx = 0;
} else {
ChannelDetails ch;
uint8_t nextIdx = _viewChannelIdx + 1;
if (the_mesh.getChannel(nextIdx, ch) && ch.name[0] != '\0') {
_viewChannelIdx = nextIdx;
} else {
// Past last channel → go to DM tab
_viewChannelIdx = 0xFF;
_dmInboxMode = true;
_dmInboxScroll = 0;
_dmFilterName[0] = '\0';
}
}
_scrollPos = 0;
markChannelRead(_viewChannelIdx);
return true;
return false; // Let main.cpp open the channel picker
}
return false;
@@ -0,0 +1,436 @@
#pragma once
#include <helpers/ui/UIScreen.h>
#include <helpers/ui/DisplayDriver.h>
#include <helpers/ChannelDetails.h>
#include <MeshCore.h>
#include "ChannelScreen.h"
#ifndef MAX_GROUP_CHANNELS
#define MAX_GROUP_CHANNELS 20
#endif
class UITask; // Forward declaration
class MyMesh; // Forward declaration
extern MyMesh the_mesh;
// ---------------------------------------------------------------------------
// ChannelPickerScreen
// ---------------------------------------------------------------------------
// A directory-style screen that lists every group channel + the DM inbox,
// each with an unread-message badge. Selecting an entry jumps to the channel
// messages screen pre-targeted at that channel.
//
// Replaces the A/D channel-cycling model in ChannelScreen. Pressing A or D
// (or swiping left/right on T5S3) from the messages screen now opens the
// picker instead of paging one channel at a time.
//
// Rendering:
// T5S3 E-Paper Pro : vertical list of outlined "bubble" rows (full-width,
// name left-aligned, unread badge right-aligned).
// Matches the P4 channel picker aesthetic. 1-tap opens.
// T-Deck Pro / MAX : vertical list with "> " cursor, unread badge, right-
// aligned. Same highlight/tap convention as Contacts.
//
// Navigation signals use a wantsExit() flag (same pattern as PathEditor) —
// UITask is only forward-declared, so the picker cannot call UITask methods
// directly. main.cpp / UITask.cpp check the flag after injectKey().
// ---------------------------------------------------------------------------
class ChannelPickerScreen : public UIScreen {
UITask* _task;
ChannelScreen* _channelScreen;
// Ordered list of items.
// Index 0 is always the DM inbox (channel_idx == 0xFF).
// Remaining entries are populated group channels in ascending slot order.
uint8_t _items[MAX_GROUP_CHANNELS + 1];
int _itemCount;
int _cursor;
int _scrollTop; // Scroll offset (T-Deck Pro list only)
// Grid layout cache (T5S3) — set in render(), consumed by touch hit test
int _cellW;
int _cellH;
int _gridTop;
int _gridCols;
// Rebuild the items list from MyMesh. O(20), safe every render.
void rebuildItems() {
int n = 0;
uint8_t tmp[MAX_GROUP_CHANNELS + 1];
tmp[n++] = 0xFF; // DM inbox always first
for (uint8_t i = 0; i < MAX_GROUP_CHANNELS; i++) {
ChannelDetails ch;
if (the_mesh.getChannel(i, ch) && ch.name[0] != '\0') {
if (n < MAX_GROUP_CHANNELS + 1) tmp[n++] = i;
}
}
memcpy(_items, tmp, n);
_itemCount = n;
if (_cursor >= _itemCount) _cursor = _itemCount - 1;
if (_cursor < 0) _cursor = 0;
}
void getItemName(int idx, char* buf, size_t bufLen) const {
if (idx < 0 || idx >= _itemCount || bufLen == 0) { if (bufLen) buf[0] = '\0'; return; }
uint8_t c = _items[idx];
if (c == 0xFF) {
strncpy(buf, "Direct Messages", bufLen - 1);
buf[bufLen - 1] = '\0';
return;
}
ChannelDetails ch;
if (the_mesh.getChannel(c, ch) && ch.name[0] != '\0') {
strncpy(buf, ch.name, bufLen - 1);
buf[bufLen - 1] = '\0';
} else {
snprintf(buf, bufLen, "Ch %d", (int)c);
}
}
int getItemUnread(int idx) const {
if (idx < 0 || idx >= _itemCount || !_channelScreen) return 0;
return _channelScreen->getUnreadForChannel(_items[idx]);
}
public:
ChannelPickerScreen(UITask* task)
: _task(task), _channelScreen(nullptr),
_itemCount(0), _cursor(0), _scrollTop(0),
_cellW(40), _cellH(12), _gridTop(14), _gridCols(3),
_wantExit(false) {
_items[0] = 0xFF;
}
void setChannelScreen(ChannelScreen* cs) { _channelScreen = cs; }
// --- wantsExit flag — checked by main.cpp / UITask after injectKey() ---
bool _wantExit;
bool wantsExit() const { return _wantExit; }
// Called by UITask::gotoChannelPickerScreen().
void enter(uint8_t currentChannelIdx) {
rebuildItems();
_cursor = 0;
for (int i = 0; i < _itemCount; i++) {
if (_items[i] == currentChannelIdx) { _cursor = i; break; }
}
_scrollTop = 0;
_wantExit = false;
}
uint8_t getSelectedChannel() const {
if (_cursor >= 0 && _cursor < _itemCount) return _items[_cursor];
return 0xFF;
}
// -----------------------------------------------------------------------
// Render
// -----------------------------------------------------------------------
int render(DisplayDriver& display) override {
rebuildItems();
// === Header ===
display.setCursor(0, 0);
display.setTextSize(1);
display.setColor(DisplayDriver::GREEN);
display.print("Channels");
int totalUnread = 0;
for (int i = 0; i < _itemCount; i++) totalUnread += getItemUnread(i);
char tmp[24];
if (totalUnread > 0) {
snprintf(tmp, sizeof(tmp), "*%d", totalUnread);
} else {
snprintf(tmp, sizeof(tmp), "[%d]", _itemCount);
}
display.setCursor(display.width() - display.getTextWidth(tmp) - 2, 0);
display.print(tmp);
display.drawRect(0, 11, display.width(), 1);
#if defined(LilyGo_T5S3_EPaper_Pro)
// =================================================================
// T5S3: Vertical bubble list (matches P4 channel picker aesthetic)
// Full-width outlined bubbles with channel name left-aligned and
// unread badge right-aligned. 1-tap opens the channel.
// =================================================================
const int headerH = 14;
const int footerH = 14;
const int bodyH = display.height() - headerH - footerH;
const int bubbleH = 11; // Bubble height in virtual coords
const int gap = 2; // Gap between bubbles
const int padX = 3; // Horizontal padding from screen edge
const int bubbleW = display.width() - 2 * padX;
int maxVisible = bodyH / (bubbleH + gap);
if (maxVisible < 3) maxVisible = 3;
if (maxVisible > _itemCount) maxVisible = _itemCount;
// Cache layout for touch hit test
_cellW = bubbleW;
_cellH = bubbleH + gap;
_gridTop = headerH;
_gridCols = 1; // Single column — list mode
// Centre scroll window on cursor
_scrollTop = max(0, min(_cursor - maxVisible / 2, _itemCount - maxVisible));
if (_scrollTop < 0) _scrollTop = 0;
int endIdx = min(_itemCount, _scrollTop + maxVisible);
for (int i = _scrollTop; i < endIdx; i++) {
int row = i - _scrollTop;
int x = padX;
int y = headerH + row * (bubbleH + gap) + 1;
int w = bubbleW;
int h = bubbleH;
bool selected = (i == _cursor);
int unread = getItemUnread(i);
// Bubble: filled if selected, outlined otherwise
if (selected) {
display.setColor(DisplayDriver::LIGHT);
display.fillRect(x, y, w, h);
display.setColor(DisplayDriver::DARK);
} else {
display.setColor(DisplayDriver::LIGHT);
display.drawRect(x, y, w, h);
// Draw a second outline 1px inset for a bolder border
display.drawRect(x + 1, y + 1, w - 2, h - 2);
}
// Channel name — left-aligned with inner padding
char name[32];
getItemName(i, name, sizeof(name));
char filtered[32];
display.translateUTF8ToBlocks(filtered, name, sizeof(filtered));
int textY = y + (h - 9) / 2;
if (textY < y + 1) textY = y + 1;
int textX = x + 4;
// Badge width reservation
int badgeW = 0;
char badge[8];
if (unread > 0) {
if (unread > 99) snprintf(badge, sizeof(badge), "99+");
else snprintf(badge, sizeof(badge), "*%d", unread);
badgeW = display.getTextWidth(badge) + 4;
}
int nameMaxW = w - 8 - badgeW;
if (nameMaxW < 8) nameMaxW = 8;
int nameW = display.getTextWidth(filtered);
if (nameW <= nameMaxW) {
display.setCursor(textX, textY);
display.print(filtered);
} else {
display.drawTextEllipsized(textX, textY, nameMaxW, filtered);
}
// Unread badge — right-aligned inside bubble
if (unread > 0) {
int bx = x + w - badgeW;
display.setCursor(bx, textY);
display.print(badge);
}
display.setColor(DisplayDriver::LIGHT);
}
// Scroll indicator (if more items than visible)
if (_itemCount > maxVisible) {
const int sbW = 3;
int sbX = display.width() - sbW;
int sbTop = headerH;
int sbHeight = bodyH;
display.setColor(DisplayDriver::LIGHT);
display.drawRect(sbX, sbTop, sbW, sbHeight);
int thumbH = (maxVisible * sbHeight) / _itemCount;
if (thumbH < 4) thumbH = 4;
int maxScroll = _itemCount - maxVisible;
if (maxScroll < 1) maxScroll = 1;
int thumbY = sbTop + (_scrollTop * (sbHeight - thumbH)) / maxScroll;
display.fillRect(sbX + 1, thumbY + 1, sbW - 2, thumbH - 2);
}
#else
// =================================================================
// T-Deck Pro / MAX: Vertical list
// Uses NodePrefs font helpers for large_font compatibility.
// =================================================================
NodePrefs* prefs = the_mesh.getNodePrefs();
int lineH = prefs->smallLineH();
const int headerH = 14;
const int footerH = 14;
int maxY = display.height() - footerH;
int y = headerH;
int maxVisible = (maxY - headerH) / lineH;
if (maxVisible < 3) maxVisible = 3;
// Centre scroll window on cursor
_scrollTop = max(0, min(_cursor - maxVisible / 2, _itemCount - maxVisible));
if (_scrollTop < 0) _scrollTop = 0;
int endIdx = min(_itemCount, _scrollTop + maxVisible);
display.setTextSize(prefs->smallTextSize());
for (int i = _scrollTop; i < endIdx && y + lineH <= maxY; i++) {
bool selected = (i == _cursor);
int unread = getItemUnread(i);
if (selected) {
display.setColor(DisplayDriver::LIGHT);
display.fillRect(0, y + prefs->smallHighlightOff(), display.width(), lineH);
display.setColor(DisplayDriver::DARK);
} else {
display.setColor(DisplayDriver::LIGHT);
}
display.setCursor(0, y);
// Prefix: "> " for selected, " " otherwise. "*N" badge if unread.
char prefix[8];
if (unread > 0) {
snprintf(prefix, sizeof(prefix), "%s*%d ", selected ? ">" : " ", unread);
} else {
snprintf(prefix, sizeof(prefix), "%s ", selected ? ">" : " ");
}
display.print(prefix);
// Name
char name[32];
getItemName(i, name, sizeof(name));
char filtered[32];
display.translateUTF8ToBlocks(filtered, name, sizeof(filtered));
int nameX = display.getTextWidth(prefix) + 2;
int nameMaxW = display.width() - nameX - 2;
display.drawTextEllipsized(nameX, y, nameMaxW, filtered);
y += lineH;
}
// Scroll indicator
if (_itemCount > maxVisible) {
const int sbW = 3;
int sbX = display.width() - sbW;
int sbTop = headerH;
int sbHeight = maxY - headerH;
display.setColor(DisplayDriver::LIGHT);
display.drawRect(sbX, sbTop, sbW, sbHeight);
int thumbH = (maxVisible * sbHeight) / _itemCount;
if (thumbH < 4) thumbH = 4;
int maxScroll = _itemCount - maxVisible;
if (maxScroll < 1) maxScroll = 1;
int thumbY = sbTop + (_scrollTop * (sbHeight - thumbH)) / maxScroll;
display.fillRect(sbX + 1, thumbY + 1, sbW - 2, thumbH - 2);
}
#endif
// === Footer ===
display.setTextSize(1);
int footerY = display.height() - 12;
display.drawRect(0, footerY - 2, display.width(), 1);
display.setColor(DisplayDriver::YELLOW);
display.setCursor(0, footerY);
#if defined(LilyGo_T5S3_EPaper_Pro)
display.print("Tap:Open");
const char* rt = "Boot:Back";
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
display.print(rt);
#else
display.print("W/S:Nav Q:Back");
const char* rt = "Ent:Open";
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
display.print(rt);
#endif
#ifdef USE_EINK
return 5000;
#else
return 1000;
#endif
}
// -----------------------------------------------------------------------
// Input
// -----------------------------------------------------------------------
bool handleInput(char c) override {
// W / UP
if (c == 'w' || c == 'W' || c == 0xF2 || c == KEY_UP) {
if (_cursor > 0) { _cursor--; return true; }
return false;
}
// S / DOWN
if (c == 's' || c == 'S' || c == 0xF1 || c == KEY_DOWN) {
if (_cursor < _itemCount - 1) { _cursor++; return true; }
return false;
}
// A / D — consumed (no channel cycling from picker)
if (c == 'a' || c == 'A' || c == KEY_LEFT) {
return true;
}
if (c == 'd' || c == 'D' || c == KEY_RIGHT) {
return true;
}
// Enter — select the highlighted channel and signal exit
if (c == '\r' || c == 13 || c == KEY_ENTER || c == KEY_SELECT) {
if (_channelScreen && _cursor >= 0 && _cursor < _itemCount) {
_channelScreen->setViewChannelIdx(_items[_cursor]);
}
_wantExit = true;
return true; // Consumed — caller checks wantsExit() and navigates
}
// Q / backspace — cancel without changing channel, signal exit
if (c == 'q' || c == 'Q' || c == '\b' || c == KEY_CANCEL) {
_wantExit = true;
return true;
}
return false;
}
// -----------------------------------------------------------------------
// Touch hit test (virtual coordinates)
// Returns: 0=miss, 1=cursor moved, 2=activate.
// T5S3 bubbles: any tap on a bubble → 2 (direct open).
// T-Deck Pro list: 1st tap → 1 (highlight), 2nd tap same row → 2.
// -----------------------------------------------------------------------
int selectAtVxVy(int vx, int vy) {
#if defined(LilyGo_T5S3_EPaper_Pro)
// Vertical bubble list hit test
if (vy < _gridTop || _cellH == 0) return 0;
int footerY = 128 - 14;
if (vy >= footerY) return 0;
int row = (vy - _gridTop) / _cellH;
int idx = _scrollTop + row;
if (idx < 0 || idx >= _itemCount) return 0;
_cursor = idx;
return 2; // Direct open on tap
#else
// T-Deck Pro / MAX list hit test — uses NodePrefs for large_font compatibility
NodePrefs* prefs = the_mesh.getNodePrefs();
int lineH = prefs->smallLineH();
const int headerH = 14;
const int footerH = 14;
int bodyTop = headerH + prefs->smallHighlightOff();
if (vy < bodyTop || vy >= 128 - footerH) return 0;
int maxVisible = (128 - headerH - footerH) / lineH;
if (maxVisible < 3) maxVisible = 3;
int startIdx = max(0, min(_cursor - maxVisible / 2, _itemCount - maxVisible));
if (startIdx < 0) startIdx = 0;
int tappedRow = startIdx + (vy - bodyTop) / lineH;
if (tappedRow < 0 || tappedRow >= _itemCount) return 0;
if (tappedRow == _cursor) return 2;
_cursor = tappedRow;
return 1;
#endif
}
};
+190 -44
View File
@@ -4,7 +4,11 @@
#include <helpers/ui/DisplayDriver.h>
#include <MeshCore.h>
// Forward declarations
// Timestamps before this (Jan 1 2026 UTC) are treated as invalid/unsynced
#define EPOCH_2026 1735689600UL
// Forward declarations — MyMesh.h (which defines AdvertPath) is always
// included by the translation unit before this header.
class UITask;
class MyMesh;
extern MyMesh the_mesh;
@@ -33,8 +37,10 @@ private:
// We rebuild this on filter change or when entering the screen
// Arrays allocated in PSRAM when available (supports 1000+ contacts)
uint16_t* _filteredIdx; // indices into contact table
uint32_t* _filteredTs; // cached last_advert_timestamp for sorting
uint32_t* _filteredTs; // cached lastmod for sorting
int _filteredCount; // how many contacts match current filter
AdvertPath _hopBuf[40]; // recently heard advert paths for hop-count display
int _hopBufCount;
bool _cacheValid;
// How many rows fit on screen (computed during render)
@@ -43,6 +49,10 @@ private:
// Pointer to per-contact DM unread array (owned by UITask, set via setter)
const uint8_t* _dmUnread = nullptr;
// --- Select mode state ---
bool _selectMode;
uint8_t* _selectedBits; // Bitfield: 1 bit per MAX_CONTACTS raw index
// --- helpers ---
static const char* filterLabel(FilterMode f) {
@@ -57,12 +67,12 @@ private:
}
}
static char typeChar(uint8_t adv_type) {
static const char* typeStr(uint8_t adv_type) {
switch (adv_type) {
case ADV_TYPE_CHAT: return 'C';
case ADV_TYPE_REPEATER: return 'R';
case ADV_TYPE_ROOM: return 'S'; // Server
default: return '?';
case ADV_TYPE_CHAT: return "C";
case ADV_TYPE_REPEATER: return "R";
case ADV_TYPE_ROOM: return "RS";
default: return "?";
}
}
@@ -88,12 +98,13 @@ private:
if (the_mesh.getContactByIdx(i, contact)) {
if (matchesFilter(contact.type, contact.flags)) {
_filteredIdx[_filteredCount] = (uint16_t)i;
_filteredTs[_filteredCount] = contact.last_advert_timestamp;
// Use lastmod (our receive time) for sort/age; pre-2026 or zero → 0 sinks to bottom
_filteredTs[_filteredCount] = (contact.lastmod >= EPOCH_2026) ? contact.lastmod : 0;
_filteredCount++;
}
}
}
// Sort by last_advert_timestamp descending (most recently seen first)
// Sort by lastmod descending (most recently heard first; pre-2026/unsynced sink to bottom)
// Insertion sort — fine for up to ~1000 entries on ESP32
for (int i = 1; i < _filteredCount; i++) {
uint16_t tmpIdx = _filteredIdx[i];
@@ -108,41 +119,56 @@ private:
_filteredTs[j + 1] = tmpTs;
}
_cacheValid = true;
// Refresh hop-count cache from the 12 most recently heard adverts
_hopBufCount = the_mesh.getRecentlyHeard(_hopBuf, 40);
// Clamp scroll position
if (_scrollPos >= _filteredCount) {
_scrollPos = (_filteredCount > 0) ? _filteredCount - 1 : 0;
}
}
// Format seconds-ago as compact string: "3s" "5m" "2h" "4d" "??"
// Format seconds-ago as compact string: "3s" "5m" "2h" "4d" "--"
static void formatAge(char* buf, size_t bufLen, uint32_t now, uint32_t timestamp) {
if (timestamp == 0) {
if (timestamp == 0 || timestamp < EPOCH_2026 || now < timestamp) {
strncpy(buf, "--", bufLen);
return;
}
int secs = (int)(now - timestamp);
if (secs < 0) secs = 0;
uint32_t secs = now - timestamp;
if (secs < 60) {
snprintf(buf, bufLen, "%ds", secs);
snprintf(buf, bufLen, "%ds", (int)secs);
} else if (secs < 3600) {
snprintf(buf, bufLen, "%dm", secs / 60);
snprintf(buf, bufLen, "%dm", (int)(secs / 60));
} else if (secs < 86400) {
snprintf(buf, bufLen, "%dh", secs / 3600);
snprintf(buf, bufLen, "%dh", (int)(secs / 3600));
} else {
snprintf(buf, bufLen, "%dd", secs / 86400);
snprintf(buf, bufLen, "%dd", (int)(secs / 86400));
}
}
// --- Bitfield helpers ---
bool isSelectedRaw(int rawIdx) const {
if (rawIdx < 0 || rawIdx >= MAX_CONTACTS) return false;
return (_selectedBits[rawIdx / 8] & (1 << (rawIdx % 8))) != 0;
}
void setSelectedRaw(int rawIdx, bool sel) {
if (rawIdx < 0 || rawIdx >= MAX_CONTACTS) return;
if (sel) _selectedBits[rawIdx / 8] |= (1 << (rawIdx % 8));
else _selectedBits[rawIdx / 8] &= ~(1 << (rawIdx % 8));
}
public:
ContactsScreen(UITask* task, mesh::RTCClock* rtc)
: _task(task), _rtc(rtc), _scrollPos(0), _filter(FILTER_ALL),
_filteredCount(0), _cacheValid(false), _rowsPerPage(5) {
_filteredCount(0), _cacheValid(false), _rowsPerPage(5),
_selectMode(false), _hopBufCount(0) {
#if defined(ESP32) && defined(BOARD_HAS_PSRAM)
_filteredIdx = (uint16_t*)ps_calloc(MAX_CONTACTS, sizeof(uint16_t));
_filteredTs = (uint32_t*)ps_calloc(MAX_CONTACTS, sizeof(uint32_t));
_selectedBits = (uint8_t*)ps_calloc((MAX_CONTACTS + 7) / 8, 1);
#else
_filteredIdx = new uint16_t[MAX_CONTACTS]();
_filteredTs = new uint32_t[MAX_CONTACTS]();
_selectedBits = new uint8_t[(MAX_CONTACTS + 7) / 8]();
#endif
}
@@ -158,15 +184,67 @@ public:
FilterMode getFilter() const { return _filter; }
// --- Select mode API ---
bool isInSelectMode() const { return _selectMode; }
void enterSelectMode() {
_selectMode = true;
memset(_selectedBits, 0, (MAX_CONTACTS + 7) / 8);
// Pre-select the currently highlighted contact
if (_filteredCount > 0 && _scrollPos < _filteredCount) {
setSelectedRaw(_filteredIdx[_scrollPos], true);
}
}
void exitSelectMode() {
_selectMode = false;
memset(_selectedBits, 0, (MAX_CONTACTS + 7) / 8);
}
void toggleSelected() {
if (_filteredCount == 0 || _scrollPos >= _filteredCount) return;
int rawIdx = _filteredIdx[_scrollPos];
setSelectedRaw(rawIdx, !isSelectedRaw(rawIdx));
}
void selectAll() {
for (int i = 0; i < _filteredCount; i++) {
setSelectedRaw(_filteredIdx[i], true);
}
}
void deselectAll() {
memset(_selectedBits, 0, (MAX_CONTACTS + 7) / 8);
}
int getSelectedCount() const {
int count = 0;
for (int i = 0; i < _filteredCount; i++) {
if (isSelectedRaw(_filteredIdx[i])) count++;
}
return count;
}
// Fill outBuf with raw contact table indices of selected contacts
int getSelectedRawIndices(uint16_t* outBuf, int maxOut) const {
int count = 0;
for (int i = 0; i < _filteredCount && count < maxOut; i++) {
if (isSelectedRaw(_filteredIdx[i])) {
outBuf[count++] = _filteredIdx[i];
}
}
return count;
}
// Tap-to-select: given virtual Y, select contact row.
// Returns: 0=miss, 1=moved, 2=tapped current row.
int selectRowAtVY(int vy) {
if (_filteredCount == 0) return 0;
const int headerH = 14, footerH = 14, lineH = 9;
const int headerH = 14, footerH = 14, lineH = the_mesh.getNodePrefs()->smallLineH();
#if defined(LilyGo_T5S3_EPaper_Pro)
const int bodyTop = headerH;
#else
const int bodyTop = headerH + 5;
const int bodyTop = headerH + the_mesh.getNodePrefs()->smallHighlightOff();
#endif
if (vy < bodyTop || vy >= 128 - footerH) return 0;
@@ -219,7 +297,12 @@ public:
display.setTextSize(1);
display.setColor(DisplayDriver::GREEN);
display.setCursor(0, 0);
snprintf(tmp, sizeof(tmp), "Contacts [%s]", filterLabel(_filter));
if (_selectMode) {
int selCount = getSelectedCount();
snprintf(tmp, sizeof(tmp), "%d Selected [%s]", selCount, filterLabel(_filter));
} else {
snprintf(tmp, sizeof(tmp), "Contacts [%s]", filterLabel(_filter));
}
display.print(tmp);
// Count on right: All → total/max, filtered → matched/total
@@ -235,8 +318,8 @@ public:
display.drawRect(0, 11, display.width(), 1);
// === Body - contact rows ===
display.setTextSize(0); // tiny font for compact rows
int lineHeight = 9; // 8px font + 1px gap
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize()); // tiny font for compact rows
int lineHeight = the_mesh.getNodePrefs()->smallLineH(); // 8px font + 1px gap
int headerHeight = 14;
int footerHeight = 14;
int maxY = display.height() - footerHeight;
@@ -268,6 +351,7 @@ public:
if (!the_mesh.getContactByIdx(_filteredIdx[i], contact)) continue;
bool selected = (i == _scrollPos);
bool sel = _selectMode && isSelectedRaw(_filteredIdx[i]);
// Highlight: fill LIGHT rect first, then draw DARK text on top
if (selected) {
@@ -275,7 +359,7 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), lineHeight);
#else
display.fillRect(0, y + 5, display.width(), lineHeight);
display.fillRect(0, y + the_mesh.getNodePrefs()->smallHighlightOff(), display.width(), lineHeight);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -285,12 +369,16 @@ public:
// Set cursor AFTER fillRect so text draws on top of highlight
display.setCursor(0, y);
// Prefix: "> " for selected, type char + space for others
char prefix[4];
if (selected) {
snprintf(prefix, sizeof(prefix), ">%c", typeChar(contact.type));
// Prefix: select mode uses * for selected, normal uses > for cursor
char prefix[5];
if (_selectMode) {
snprintf(prefix, sizeof(prefix), "%c%s",
sel ? '*' : (selected ? '>' : ' '),
typeStr(contact.type));
} else if (selected) {
snprintf(prefix, sizeof(prefix), ">%s", typeStr(contact.type));
} else {
snprintf(prefix, sizeof(prefix), " %c", typeChar(contact.type));
snprintf(prefix, sizeof(prefix), " %s", typeStr(contact.type));
}
display.print(prefix);
@@ -300,14 +388,38 @@ public:
// Reserve space for hops + age on right side
char hopStr[6];
if (contact.out_path_len == 0xFF || contact.out_path_len == 0) {
strcpy(hopStr, "D"); // direct
if (contact.out_path_len == 0xFF) {
// No confirmed direct path — look up flood hop estimate from recent advert cache
hopStr[0] = '?'; hopStr[1] = '\0'; // default
for (int h = 0; h < _hopBufCount; h++) {
if (memcmp(contact.id.pub_key, _hopBuf[h].pubkey_prefix, 7) == 0) {
uint8_t bph = (_hopBuf[h].path_len >> 6) + 1;
uint8_t hops = _hopBuf[h].path_len & 0x3F;
uint8_t max_hops = 64 / bph; // sanity cap based on path encoding
if (hops <= max_hops) {
if (hops == 0)
strcpy(hopStr, "~D");
else
snprintf(hopStr, sizeof(hopStr), "~%d", (int)hops);
}
break;
}
}
} else if (contact.out_path_len == 0) {
bool customDirect = (contact.flags & CONTACT_FLAG_CUSTOM_PATH) != 0;
strcpy(hopStr, customDirect ? "D*" : "D");
} else {
snprintf(hopStr, sizeof(hopStr), "%d", contact.out_path_len);
int hops = contact.out_path_len & 0x3F; // lower 6 bits = hop count
bool customPath = (contact.flags & CONTACT_FLAG_CUSTOM_PATH) != 0;
if (customPath) {
snprintf(hopStr, sizeof(hopStr), "%d*", hops); // asterisk = custom/locked path
} else {
snprintf(hopStr, sizeof(hopStr), "%d", hops);
}
}
char ageStr[6];
formatAge(ageStr, sizeof(ageStr), now, contact.last_advert_timestamp);
formatAge(ageStr, sizeof(ageStr), now, contact.lastmod);
// Build right-side string: "*N hops age" if unread, else "hops age"
int dmCount = (_dmUnread && _filteredIdx[i] < MAX_CONTACTS) ? _dmUnread[_filteredIdx[i]] : 0;
@@ -343,19 +455,30 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.setCursor(0, footerY);
display.print("Swipe:Filter");
const char* right = "Hold:DM/Admin";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
if (_selectMode) {
display.print("Swipe:All/Clr");
const char* right = "Tap:Tog Hold:Exit";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
} else {
display.print("Swipe:Filter");
const char* right = "Hold:DM/Admin";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
}
#else
// Left: Q:Bk
display.setCursor(0, footerY);
display.print("Q:Bk A/D:Filter");
// Right: Tap/Ent:Select
const char* right = "Tap/Ent:Select";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
if (_selectMode) {
display.print("A:All D:Clr");
const char* right = "X:Exp F:Fav Q:Done";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
} else {
display.print("Q:Bk A/D:Filter");
const char* right = "P:Path Ent:Sel";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
}
#endif
return 5000; // e-ink: next render after 5s
@@ -378,6 +501,29 @@ public:
}
}
// --- Select mode key handling ---
if (_selectMode) {
// Enter/tap: toggle selection on current contact
if (c == 13 || c == KEY_ENTER) {
toggleSelected();
return true;
}
// A: select all in current filter
if (c == 'a' || c == 'A') {
selectAll();
return true;
}
// D: deselect all
if (c == 'd' || c == 'D') {
deselectAll();
return true;
}
// Q, X, F, Backspace — handled by main.cpp (needs mesh/SD access)
return false;
}
// --- Normal mode key handling ---
// A - previous filter
if (c == 'a' || c == 'A') {
_filter = (FilterMode)(((int)_filter + FILTER_COUNT - 1) % FILTER_COUNT);
@@ -49,11 +49,11 @@ public:
int selectRowAtVY(int vy) {
int count = the_mesh.getDiscoveredCount();
if (count == 0) return 0;
const int headerH = 14, footerH = 14, lineH = 9;
const int headerH = 14, footerH = 14, lineH = the_mesh.getNodePrefs()->smallLineH();
#if defined(LilyGo_T5S3_EPaper_Pro)
const int bodyTop = headerH;
#else
const int bodyTop = headerH + 5;
const int bodyTop = headerH + the_mesh.getNodePrefs()->smallHighlightOff();
#endif
if (vy < bodyTop || vy >= 128 - footerH) return 0;
@@ -91,8 +91,8 @@ public:
display.drawRect(0, 11, display.width(), 1);
// === Body — discovered node rows ===
display.setTextSize(0); // tiny font for compact rows
int lineHeight = 9;
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize()); // tiny font for compact rows
int lineHeight = the_mesh.getNodePrefs()->smallLineH();
int headerHeight = 14;
int footerHeight = 14;
int maxY = display.height() - footerHeight;
@@ -129,7 +129,7 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), lineHeight);
#else
display.fillRect(0, y + 5, display.width(), lineHeight);
display.fillRect(0, y + the_mesh.getNodePrefs()->smallHighlightOff(), display.width(), lineHeight);
#endif
display.setColor(DisplayDriver::DARK);
} else {
+195 -76
View File
@@ -3,7 +3,7 @@
// Emoji sprites for e-ink display - dual size
// Large (12x12) for compose/picker, Small (10x10) for channel view
// MSB-first, 2 bytes per row
// 65 total emoji: joy/thumbsup/frown first, then 43 original, then 19 new
// 76 total emoji: joy/thumbsup/frown first, then 43 original, then 19 new, then 11 newest
#include <stdint.h>
#ifdef ESP32
@@ -15,11 +15,11 @@
#define EMOJI_SM_W 10
#define EMOJI_SM_H 10
#define EMOJI_COUNT 65
#define EMOJI_COUNT 76
// Escape codes in 0x80+ range - safe from keyboard ASCII (32-126)
#define EMOJI_ESCAPE_START 0x80
#define EMOJI_ESCAPE_END 0xC0 // 0x80 + 64
#define EMOJI_ESCAPE_END 0xCB // 0x80 + 75
#define EMOJI_PAD_BYTE 0x7F // DEL, not typeable (key < 127 guard)
// ======== LARGE 12x12 SPRITES ========
@@ -36,6 +36,14 @@ static const uint8_t emoji_lg_thumbsup[] PROGMEM = {
static const uint8_t emoji_lg_frown[] PROGMEM = {
0x1F,0x80, 0x20,0x40, 0x59,0xA0, 0x59,0xA0, 0x80,0x10, 0x9F,0x90, 0xA0,0x50, 0x40,0x20, 0x20,0x40, 0x1F,0x80, 0x00,0x00, 0x00,0x00,
};
// [65] loudly_crying 😭
static const uint8_t emoji_lg_loudly_crying[] PROGMEM = {
0x1F,0x80, 0x20,0x40, 0x5B,0x40, 0x5B,0x20, 0x80,0x10, 0x9F,0x10, 0xA0,0x90, 0x60,0xC0, 0xA0,0xA0, 0x1F,0x00, 0x40,0x40, 0x00,0x00,
};
// [66] heart ♥️
static const uint8_t emoji_lg_heart[] PROGMEM = {
0x00,0x00, 0x73,0x80, 0xFF,0xC0, 0xFF,0xC0, 0xFF,0xC0, 0x7F,0x80, 0x3F,0x00, 0x1E,0x00, 0x0C,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
};
// [3] wireless
static const uint8_t emoji_lg_wireless[] PROGMEM = {
0x00,0x00, 0x3F,0xC0, 0x60,0x60, 0xC0,0x30, 0x0F,0x00, 0x19,0x80, 0x30,0xC0, 0x00,0x00, 0x06,0x00, 0x0F,0x00, 0x06,0x00, 0x00,0x00,
@@ -284,23 +292,68 @@ static const uint8_t emoji_lg_tipping[] PROGMEM = {
static const uint8_t emoji_lg_hedgehog[] PROGMEM = {
0x00,0x00, 0x0A,0x80, 0x15,0x40, 0x2A,0xA0, 0x55,0x60, 0x7E,0xF0, 0xDB,0x90, 0xFF,0xD0, 0x7F,0xE0, 0x3F,0xC0, 0x24,0x80, 0x00,0x00,
};
// [67] diamond_suit ♦️
static const uint8_t emoji_lg_diamond_suit[] PROGMEM = {
0x00,0x00, 0x04,0x00, 0x0E,0x00, 0x1F,0x00, 0x3F,0x80, 0x7F,0xC0, 0x3F,0x80, 0x1F,0x00, 0x0E,0x00, 0x04,0x00, 0x00,0x00, 0x00,0x00,
};
// [68] spade_suit ♠️
static const uint8_t emoji_lg_spade_suit[] PROGMEM = {
0x04,0x00, 0x0E,0x00, 0x1F,0x00, 0x3F,0x80, 0x7F,0xC0, 0xFF,0xE0, 0xFF,0xE0, 0x7F,0xC0, 0x15,0x00, 0x04,0x00, 0x0E,0x00, 0x00,0x00,
};
// [69] pizza 🍕
static const uint8_t emoji_lg_pizza[] PROGMEM = {
0x02,0x00, 0x06,0x00, 0x0F,0x00, 0x0B,0x00, 0x1F,0x80, 0x1D,0x80, 0x3F,0xC0, 0x2F,0x40, 0x7F,0xE0, 0x7F,0xE0, 0xFF,0xF0, 0x00,0x00,
};
// [70] four_leaf_clover 🍀
static const uint8_t emoji_lg_four_leaf_clover[] PROGMEM = {
0x0C,0x00, 0x1E,0x00, 0x1E,0x00, 0x6D,0x80, 0xF3,0xC0, 0xF3,0xC0, 0x6D,0x80, 0x1E,0x00, 0x1E,0x00, 0x0C,0x00, 0x06,0x00, 0x00,0x00,
};
// [71] cloud ☁️
static const uint8_t emoji_lg_cloud[] PROGMEM = {
0x00,0x00, 0x1C,0x00, 0x3E,0x00, 0x7F,0x80, 0xFF,0xC0, 0xFF,0xE0, 0xFF,0xE0, 0x7F,0xC0, 0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
};
// [72] rocket 🚀
static const uint8_t emoji_lg_rocket[] PROGMEM = {
0x04,0x00, 0x0E,0x00, 0x1F,0x00, 0x1B,0x00, 0x1B,0x00, 0x3F,0x80, 0x7F,0xC0, 0x5F,0x40, 0x9F,0x20, 0x0E,0x00, 0x15,0x00, 0x00,0x00,
};
// [73] passport_control 🛂
static const uint8_t emoji_lg_passport_control[] PROGMEM = {
0x3F,0xC0, 0x40,0x20, 0x46,0x20, 0x4F,0x20, 0x46,0x20, 0x40,0x20, 0x44,0x20, 0x4E,0x20, 0x5F,0x20, 0x40,0x20, 0x3F,0xC0, 0x00,0x00,
};
// [74] eight_spoked_asterisk ✳️
static const uint8_t emoji_lg_eight_spoked_asterisk[] PROGMEM = {
0x7F,0xE0, 0x84,0x10, 0xA4,0x90, 0x95,0x10, 0x8E,0x10, 0xFF,0xD0, 0x8E,0x10, 0x95,0x10, 0xA4,0x90, 0x84,0x10, 0x7F,0xE0, 0x00,0x00,
};
// [75] signal_strength 📶
static const uint8_t emoji_lg_signal_strength[] PROGMEM = {
0x00,0x20, 0x00,0x20, 0x00,0xA0, 0x00,0xA0, 0x02,0xA0, 0x02,0xA0, 0x0A,0xA0, 0x0A,0xA0, 0x2A,0xA0, 0x2A,0xA0, 0xAA,0xA0, 0xAA,0xA0,
};
static const uint8_t* const EMOJI_SPRITES_LG[] PROGMEM = {
emoji_lg_joy, emoji_lg_thumbsup, emoji_lg_frown,
// Faces/emotion first
emoji_lg_joy, emoji_lg_frown, emoji_lg_loudly_crying,
emoji_lg_grimace, emoji_lg_zany_face, emoji_lg_cowboy,
// Thumbsup + heart
emoji_lg_thumbsup, emoji_lg_heart,
// Everything else in original relative order
emoji_lg_wireless, emoji_lg_infinity, emoji_lg_trex, emoji_lg_skull, emoji_lg_cross,
emoji_lg_lightning, emoji_lg_tophat, emoji_lg_motorcycle, emoji_lg_seedling, emoji_lg_flag_au,
emoji_lg_umbrella, emoji_lg_nazar, emoji_lg_globe, emoji_lg_radioactive, emoji_lg_cow,
emoji_lg_alien, emoji_lg_invader, emoji_lg_dagger, emoji_lg_grimace,
emoji_lg_alien, emoji_lg_invader, emoji_lg_dagger,
emoji_lg_mountain, emoji_lg_end_arrow, emoji_lg_hollow_circle, emoji_lg_dragon, emoji_lg_globe_meridians,
emoji_lg_eggplant, emoji_lg_shield, emoji_lg_goggles, emoji_lg_lizard, emoji_lg_zany_face,
emoji_lg_eggplant, emoji_lg_shield, emoji_lg_goggles, emoji_lg_lizard,
emoji_lg_kangaroo, emoji_lg_feather, emoji_lg_bright, emoji_lg_part_alt, emoji_lg_motorboat,
emoji_lg_domino, emoji_lg_satellite, emoji_lg_customs, emoji_lg_cowboy, emoji_lg_wheel,
emoji_lg_domino, emoji_lg_satellite, emoji_lg_customs, emoji_lg_wheel,
emoji_lg_koala, emoji_lg_control_knobs, emoji_lg_peach, emoji_lg_racing_car,
emoji_lg_mouse, emoji_lg_mushroom, emoji_lg_biohazard, emoji_lg_panda,
emoji_lg_anger, emoji_lg_dragon_face, emoji_lg_pager, emoji_lg_bee,
emoji_lg_bulb, emoji_lg_cat, emoji_lg_fleur, emoji_lg_moon,
emoji_lg_coffee, emoji_lg_tooth, emoji_lg_pretzel, emoji_lg_abacus,
emoji_lg_moai, emoji_lg_tipping, emoji_lg_hedgehog,
emoji_lg_diamond_suit, emoji_lg_spade_suit, emoji_lg_pizza, emoji_lg_four_leaf_clover,
emoji_lg_cloud, emoji_lg_rocket, emoji_lg_passport_control,
emoji_lg_eight_spoked_asterisk, emoji_lg_signal_strength,
};
// ======== SMALL 10x10 SPRITES ========
@@ -519,94 +572,160 @@ static const uint8_t emoji_sm_tipping[] PROGMEM = {
static const uint8_t emoji_sm_hedgehog[] PROGMEM = {
0x15,0x00, 0x2A,0x80, 0x55,0x40, 0xFF,0xC0, 0xDB,0x40, 0xFF,0x80, 0x7F,0x80, 0x3F,0x00, 0x24,0x00, 0x00,0x00,
};
// [65] loudly_crying 😭
static const uint8_t emoji_sm_loudly_crying[] PROGMEM = {
0x3E,0x00, 0x41,0x00, 0xB6,0x80, 0x80,0x40, 0xBE,0x40, 0x81,0x40, 0x63,0x00, 0x9C,0x80, 0x00,0x00, 0x00,0x00,
};
// [66] heart ♥️
static const uint8_t emoji_sm_heart[] PROGMEM = {
0x00,0x00, 0x6C,0x00, 0xFE,0x00, 0xFE,0x00, 0x7C,0x00, 0x38,0x00, 0x10,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
};
// [67] diamond_suit ♦️
static const uint8_t emoji_sm_diamond_suit[] PROGMEM = {
0x00,0x00, 0x08,0x00, 0x1C,0x00, 0x3E,0x00, 0x7F,0x00, 0x3E,0x00, 0x1C,0x00, 0x08,0x00, 0x00,0x00, 0x00,0x00,
};
// [68] spade_suit ♠️
static const uint8_t emoji_sm_spade_suit[] PROGMEM = {
0x08,0x00, 0x1C,0x00, 0x3E,0x00, 0x7F,0x00, 0xFF,0x80, 0xFF,0x80, 0x2A,0x00, 0x08,0x00, 0x1C,0x00, 0x00,0x00,
};
// [69] pizza 🍕
static const uint8_t emoji_sm_pizza[] PROGMEM = {
0x08,0x00, 0x1C,0x00, 0x14,0x00, 0x3E,0x00, 0x36,0x00, 0x6D,0x00, 0x7F,0x00, 0xFF,0x80, 0xFF,0x80, 0x00,0x00,
};
// [70] four_leaf_clover 🍀
static const uint8_t emoji_sm_four_leaf_clover[] PROGMEM = {
0x18,0x00, 0x3C,0x00, 0xDB,0x00, 0xE7,0x00, 0xE7,0x00, 0xDB,0x00, 0x3C,0x00, 0x18,0x00, 0x0C,0x00, 0x00,0x00,
};
// [71] cloud ☁️
static const uint8_t emoji_sm_cloud[] PROGMEM = {
0x00,0x00, 0x38,0x00, 0x7E,0x00, 0xFF,0x00, 0xFF,0x80, 0xFF,0x80, 0x7F,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,
};
// [72] rocket 🚀
static const uint8_t emoji_sm_rocket[] PROGMEM = {
0x08,0x00, 0x1C,0x00, 0x36,0x00, 0x36,0x00, 0x7F,0x00, 0xBE,0x80, 0x3E,0x00, 0x1C,0x00, 0x2A,0x00, 0x00,0x00,
};
// [73] passport_control 🛂
static const uint8_t emoji_sm_passport_control[] PROGMEM = {
0x7F,0x80, 0x80,0x40, 0x8C,0x40, 0x9E,0x40, 0x8C,0x40, 0x80,0x40, 0x9C,0x40, 0xBE,0x40, 0x80,0x40, 0x7F,0x80,
};
// [74] eight_spoked_asterisk ✳️
static const uint8_t emoji_sm_eight_spoked_asterisk[] PROGMEM = {
0x7F,0x80, 0x84,0x40, 0xA5,0x40, 0x9E,0x40, 0xFF,0xC0, 0x9E,0x40, 0xA5,0x40, 0x84,0x40, 0x7F,0x80, 0x00,0x00,
};
// [75] signal_strength 📶
static const uint8_t emoji_sm_signal_strength[] PROGMEM = {
0x00,0x80, 0x00,0x80, 0x02,0x80, 0x02,0x80, 0x0A,0x80, 0x0A,0x80, 0x2A,0x80, 0x2A,0x80, 0xAA,0x80, 0xAA,0x80,
};
static const uint8_t* const EMOJI_SPRITES_SM[] PROGMEM = {
emoji_sm_joy, emoji_sm_thumbsup, emoji_sm_frown,
// Faces/emotion first
emoji_sm_joy, emoji_sm_frown, emoji_sm_loudly_crying,
emoji_sm_grimace, emoji_sm_zany_face, emoji_sm_cowboy,
// Thumbsup + heart
emoji_sm_thumbsup, emoji_sm_heart,
// Everything else in original relative order
emoji_sm_wireless, emoji_sm_infinity, emoji_sm_trex, emoji_sm_skull, emoji_sm_cross,
emoji_sm_lightning, emoji_sm_tophat, emoji_sm_motorcycle, emoji_sm_seedling, emoji_sm_flag_au,
emoji_sm_umbrella, emoji_sm_nazar, emoji_sm_globe, emoji_sm_radioactive, emoji_sm_cow,
emoji_sm_alien, emoji_sm_invader, emoji_sm_dagger, emoji_sm_grimace,
emoji_sm_alien, emoji_sm_invader, emoji_sm_dagger,
emoji_sm_mountain, emoji_sm_end_arrow, emoji_sm_hollow_circle, emoji_sm_dragon, emoji_sm_globe_meridians,
emoji_sm_eggplant, emoji_sm_shield, emoji_sm_goggles, emoji_sm_lizard, emoji_sm_zany_face,
emoji_sm_eggplant, emoji_sm_shield, emoji_sm_goggles, emoji_sm_lizard,
emoji_sm_kangaroo, emoji_sm_feather, emoji_sm_bright, emoji_sm_part_alt, emoji_sm_motorboat,
emoji_sm_domino, emoji_sm_satellite, emoji_sm_customs, emoji_sm_cowboy, emoji_sm_wheel,
emoji_sm_domino, emoji_sm_satellite, emoji_sm_customs, emoji_sm_wheel,
emoji_sm_koala, emoji_sm_control_knobs, emoji_sm_peach, emoji_sm_racing_car,
emoji_sm_mouse, emoji_sm_mushroom, emoji_sm_biohazard, emoji_sm_panda,
emoji_sm_anger, emoji_sm_dragon_face, emoji_sm_pager, emoji_sm_bee,
emoji_sm_bulb, emoji_sm_cat, emoji_sm_fleur, emoji_sm_moon,
emoji_sm_coffee, emoji_sm_tooth, emoji_sm_pretzel, emoji_sm_abacus,
emoji_sm_moai, emoji_sm_tipping, emoji_sm_hedgehog,
emoji_sm_diamond_suit, emoji_sm_spade_suit, emoji_sm_pizza, emoji_sm_four_leaf_clover,
emoji_sm_cloud, emoji_sm_rocket, emoji_sm_passport_control,
emoji_sm_eight_spoked_asterisk, emoji_sm_signal_strength,
};
// ---- Codepoint lookup for UTF-8 conversion ----
struct EmojiCodepoint { uint32_t cp; uint32_t cp2; uint8_t escape; };
static const EmojiCodepoint EMOJI_CODEPOINTS[EMOJI_COUNT] = {
// Faces/emotion first
{ 0x1F602, 0x0000, 0x80 }, // joy
{ 0x1F44D, 0x0000, 0x81 }, // thumbsup
{ 0x2639, 0x0000, 0x82 }, // frown
{ 0x1F6DC, 0x0000, 0x83 }, // wireless
{ 0x267E, 0x0000, 0x84 }, // infinity
{ 0x1F996, 0x0000, 0x85 }, // trex
{ 0x2620, 0x0000, 0x86 }, // skull
{ 0x271D, 0x0000, 0x87 }, // cross
{ 0x26A1, 0x0000, 0x88 }, // lightning
{ 0x1F3A9, 0x0000, 0x89 }, // tophat
{ 0x1F3CD, 0x0000, 0x8A }, // motorcycle
{ 0x1F331, 0x0000, 0x8B }, // seedling
{ 0x1F1E6, 0x1F1FA, 0x8C }, // flag_au
{ 0x2602, 0x0000, 0x8D }, // umbrella
{ 0x1F9FF, 0x0000, 0x8E }, // nazar
{ 0x1F30F, 0x0000, 0x8F }, // globe
{ 0x2622, 0x0000, 0x90 }, // radioactive
{ 0x1F404, 0x0000, 0x91 }, // cow
{ 0x1F47D, 0x0000, 0x92 }, // alien
{ 0x1F47E, 0x0000, 0x93 }, // invader
{ 0x1F5E1, 0x0000, 0x94 }, // dagger
{ 0x1F62C, 0x0000, 0x95 }, // grimace
{ 0x26F0, 0x0000, 0x96 }, // mountain
{ 0x1F51A, 0x0000, 0x97 }, // end_arrow
{ 0x2B55, 0x0000, 0x98 }, // hollow_circle
{ 0x1F409, 0x0000, 0x99 }, // dragon
{ 0x1F310, 0x0000, 0x9A }, // globe_meridians
{ 0x1F346, 0x0000, 0x9B }, // eggplant
{ 0x1F6E1, 0x0000, 0x9C }, // shield
{ 0x1F97D, 0x0000, 0x9D }, // goggles
{ 0x1F98E, 0x0000, 0x9E }, // lizard
{ 0x1F92A, 0x0000, 0x9F }, // zany_face
{ 0x1F998, 0x0000, 0xA0 }, // kangaroo
{ 0x1FAB6, 0x0000, 0xA1 }, // feather
{ 0x1F506, 0x0000, 0xA2 }, // bright
{ 0x303D, 0x0000, 0xA3 }, // part_alt
{ 0x1F6E5, 0x0000, 0xA4 }, // motorboat
{ 0x1F030, 0x0000, 0xA5 }, // domino
{ 0x1F4E1, 0x0000, 0xA6 }, // satellite
{ 0x1F6C3, 0x0000, 0xA7 }, // customs
{ 0x1F920, 0x0000, 0xA8 }, // cowboy
{ 0x1F6DE, 0x0000, 0xA9 }, // wheel
{ 0x1F428, 0x0000, 0xAA }, // koala
{ 0x1F39B, 0x0000, 0xAB }, // control_knobs
{ 0x1F351, 0x0000, 0xAC }, // peach
{ 0x1F3CE, 0x0000, 0xAD }, // racing_car
{ 0x1F42D, 0x0000, 0xAE }, // mouse
{ 0x1F344, 0x0000, 0xAF }, // mushroom
{ 0x2623, 0x0000, 0xB0 }, // biohazard
{ 0x1F43C, 0x0000, 0xB1 }, // panda
{ 0x1F4A2, 0x0000, 0xB2 }, // anger
{ 0x1F432, 0x0000, 0xB3 }, // dragon_face
{ 0x1F4DF, 0x0000, 0xB4 }, // pager
{ 0x1F41D, 0x0000, 0xB5 }, // bee
{ 0x1F4A1, 0x0000, 0xB6 }, // bulb
{ 0x1F431, 0x0000, 0xB7 }, // cat
{ 0x269C, 0x0000, 0xB8 }, // fleur
{ 0x1F314, 0x0000, 0xB9 }, // moon
{ 0x2615, 0x0000, 0xBA }, // coffee
{ 0x1F9B7, 0x0000, 0xBB }, // tooth
{ 0x1F968, 0x0000, 0xBC }, // pretzel
{ 0x1F9EE, 0x0000, 0xBD }, // abacus
{ 0x1F5FF, 0x0000, 0xBE }, // moai
{ 0x1F481, 0x0000, 0xBF }, // tipping
{ 0x1F994, 0x0000, 0xC0 }, // hedgehog
{ 0x2639, 0x0000, 0x81 }, // frown
{ 0x1F62D, 0x0000, 0x82 }, // loudly_crying
{ 0x1F62C, 0x0000, 0x83 }, // grimace
{ 0x1F92A, 0x0000, 0x84 }, // zany_face
{ 0x1F920, 0x0000, 0x85 }, // cowboy
// Thumbsup + heart
{ 0x1F44D, 0x0000, 0x86 }, // thumbsup
{ 0x2665, 0x0000, 0x87 }, // heart
// Everything else in original relative order
{ 0x1F6DC, 0x0000, 0x88 }, // wireless
{ 0x267E, 0x0000, 0x89 }, // infinity
{ 0x1F996, 0x0000, 0x8A }, // trex
{ 0x2620, 0x0000, 0x8B }, // skull
{ 0x271D, 0x0000, 0x8C }, // cross
{ 0x26A1, 0x0000, 0x8D }, // lightning
{ 0x1F3A9, 0x0000, 0x8E }, // tophat
{ 0x1F3CD, 0x0000, 0x8F }, // motorcycle
{ 0x1F331, 0x0000, 0x90 }, // seedling
{ 0x1F1E6, 0x1F1FA, 0x91 }, // flag_au
{ 0x2602, 0x0000, 0x92 }, // umbrella
{ 0x1F9FF, 0x0000, 0x93 }, // nazar
{ 0x1F30F, 0x0000, 0x94 }, // globe
{ 0x2622, 0x0000, 0x95 }, // radioactive
{ 0x1F404, 0x0000, 0x96 }, // cow
{ 0x1F47D, 0x0000, 0x97 }, // alien
{ 0x1F47E, 0x0000, 0x98 }, // invader
{ 0x1F5E1, 0x0000, 0x99 }, // dagger
{ 0x26F0, 0x0000, 0x9A }, // mountain
{ 0x1F51A, 0x0000, 0x9B }, // end_arrow
{ 0x2B55, 0x0000, 0x9C }, // hollow_circle
{ 0x1F409, 0x0000, 0x9D }, // dragon
{ 0x1F310, 0x0000, 0x9E }, // globe_meridians
{ 0x1F346, 0x0000, 0x9F }, // eggplant
{ 0x1F6E1, 0x0000, 0xA0 }, // shield
{ 0x1F97D, 0x0000, 0xA1 }, // goggles
{ 0x1F98E, 0x0000, 0xA2 }, // lizard
{ 0x1F998, 0x0000, 0xA3 }, // kangaroo
{ 0x1FAB6, 0x0000, 0xA4 }, // feather
{ 0x1F506, 0x0000, 0xA5 }, // bright
{ 0x303D, 0x0000, 0xA6 }, // part_alt
{ 0x1F6E5, 0x0000, 0xA7 }, // motorboat
{ 0x1F030, 0x0000, 0xA8 }, // domino
{ 0x1F4E1, 0x0000, 0xA9 }, // satellite
{ 0x1F6C3, 0x0000, 0xAA }, // customs
{ 0x1F6DE, 0x0000, 0xAB }, // wheel
{ 0x1F428, 0x0000, 0xAC }, // koala
{ 0x1F39B, 0x0000, 0xAD }, // control_knobs
{ 0x1F351, 0x0000, 0xAE }, // peach
{ 0x1F3CE, 0x0000, 0xAF }, // racing_car
{ 0x1F42D, 0x0000, 0xB0 }, // mouse
{ 0x1F344, 0x0000, 0xB1 }, // mushroom
{ 0x2623, 0x0000, 0xB2 }, // biohazard
{ 0x1F43C, 0x0000, 0xB3 }, // panda
{ 0x1F4A2, 0x0000, 0xB4 }, // anger
{ 0x1F432, 0x0000, 0xB5 }, // dragon_face
{ 0x1F4DF, 0x0000, 0xB6 }, // pager
{ 0x1F41D, 0x0000, 0xB7 }, // bee
{ 0x1F4A1, 0x0000, 0xB8 }, // bulb
{ 0x1F431, 0x0000, 0xB9 }, // cat
{ 0x269C, 0x0000, 0xBA }, // fleur
{ 0x1F314, 0x0000, 0xBB }, // moon
{ 0x2615, 0x0000, 0xBC }, // coffee
{ 0x1F9B7, 0x0000, 0xBD }, // tooth
{ 0x1F968, 0x0000, 0xBE }, // pretzel
{ 0x1F9EE, 0x0000, 0xBF }, // abacus
{ 0x1F5FF, 0x0000, 0xC0 }, // moai
{ 0x1F481, 0x0000, 0xC1 }, // tipping
{ 0x1F994, 0x0000, 0xC2 }, // hedgehog
{ 0x2666, 0x0000, 0xC3 }, // diamond_suit
{ 0x2660, 0x0000, 0xC4 }, // spade_suit
{ 0x1F355, 0x0000, 0xC5 }, // pizza
{ 0x1F340, 0x0000, 0xC6 }, // four_leaf_clover
{ 0x2601, 0x0000, 0xC7 }, // cloud
{ 0x1F680, 0x0000, 0xC8 }, // rocket
{ 0x1F6C2, 0x0000, 0xC9 }, // passport_control
{ 0x2733, 0x0000, 0xCA }, // eight_spoked_asterisk
{ 0x1F4F6, 0x0000, 0xCB }, // signal_strength
};
// ---- Helper functions ----
@@ -616,7 +735,7 @@ static const EmojiCodepoint EMOJI_CODEPOINTS[EMOJI_COUNT] = {
struct EmojiAlias { uint32_t cp; uint8_t escape; };
#define EMOJI_ALIAS_COUNT 1
static const EmojiAlias EMOJI_ALIASES[EMOJI_ALIAS_COUNT] = {
{ 0x1F08E, 0xA5 }, // domino tile (MWD node signifier) -> domino sprite
{ 0x1F08E, 0xA8 }, // domino tile (MWD node signifier) -> domino sprite
};
static uint32_t emojiDecodeUtf8(const uint8_t* s, int remaining, int* bytes_consumed) {
@@ -0,0 +1,214 @@
#pragma once
#include <helpers/ui/UIScreen.h>
#include <helpers/ui/DisplayDriver.h>
#include <MeshCore.h>
#include "../NodePrefs.h"
#include "MeckFonts.h"
// Forward declarations
class UITask;
class MyMesh;
extern MyMesh the_mesh;
// ---------------------------------------------------------------------------
// FontPreviewScreen
// ---------------------------------------------------------------------------
// Subscreen opened from Settings → Font Style. Shows a live preview of each
// font style (Classic, Noto Sans, Montserrat) with sample body and title text.
// The user cycles through styles with W/S (or swipe on T5S3), previews the
// actual rendering on-screen, and applies with Enter or cancels with Q.
//
// The preview works by temporarily calling display.setFontStyle() for each
// sample block during render(), then restoring the original style.
// ---------------------------------------------------------------------------
class FontPreviewScreen : public UIScreen {
UITask* _task;
NodePrefs* _prefs;
uint8_t _cursor; // Currently highlighted style (0, 1, 2)
uint8_t _originalStyle; // Style when screen was opened (for cancel)
bool _wantExit;
bool _applied; // True if user pressed Enter (vs Q cancel)
public:
FontPreviewScreen(UITask* task, NodePrefs* prefs)
: _task(task), _prefs(prefs),
_cursor(0), _originalStyle(0),
_wantExit(false), _applied(false) {}
// Called when entering the screen from Settings
void enter() {
_originalStyle = _prefs->ui_font_style;
_cursor = _originalStyle;
_wantExit = false;
_applied = false;
}
bool wantsExit() const { return _wantExit; }
bool wasApplied() const { return _applied; }
// -----------------------------------------------------------------------
// Render
// -----------------------------------------------------------------------
int render(DisplayDriver& display) override {
// === Header ===
display.setTextSize(1);
display.setColor(DisplayDriver::GREEN);
display.setCursor(0, 0);
display.print("Font Style Preview");
display.drawRect(0, 11, display.width(), 1);
// === Size mode indicator ===
{
const char* sizeLabel = _prefs->large_font ? "[LARGER]" : "[TINY]";
display.setCursor(display.width() - display.getTextWidth(sizeLabel) - 2, 0);
display.print(sizeLabel);
}
// === Style preview rows ===
// Each style gets a block showing: style name + sample text rendered in
// that style. The selected style is highlighted.
const int headerH = 14;
const int footerH = 14;
const int bodyH = display.height() - headerH - footerH;
const int rowH = bodyH / MECK_FONT_STYLE_COUNT;
uint8_t savedStyle = display.getFontStyle();
for (int i = 0; i < MECK_FONT_STYLE_COUNT; i++) {
int y = headerH + i * rowH;
bool selected = (i == _cursor);
// Highlight selected row
if (selected) {
display.setColor(DisplayDriver::LIGHT);
display.fillRect(0, y, display.width(), rowH);
display.setColor(DisplayDriver::DARK);
} else {
display.setColor(DisplayDriver::LIGHT);
}
// Style name — rendered in default font (size 1)
display.setFontStyle(MECK_FONT_CLASSIC); // Name label always in Classic
display.setTextSize(1);
display.setCursor(2, y + 1);
const char* name = meckFontStyleName(i);
// Prefix with selection indicator
char label[32];
if (selected) {
snprintf(label, sizeof(label), "> %s", name);
} else {
snprintf(label, sizeof(label), " %s", name);
}
display.print(label);
// Sample text — rendered in the preview style
display.setFontStyle(i);
// Body text sample (textSize = smallTextSize based on current size pref)
display.setTextSize(_prefs->smallTextSize());
int sampleY = y + (rowH / 2) - 2;
display.setCursor(4, sampleY);
display.print("The quick brown fox 0123");
// Title sample (textSize 3) — only if row is tall enough
if (rowH > 22) {
display.setTextSize(3);
int titleY = y + rowH - 6;
display.setCursor(4, titleY);
display.print("Meck");
}
}
// Restore original font style
display.setFontStyle(savedStyle);
// === Footer ===
display.setTextSize(1);
display.setColor(DisplayDriver::YELLOW);
int footerY = display.height() - 12;
display.drawRect(0, footerY - 2, display.width(), 1);
display.setCursor(0, footerY);
#if defined(LilyGo_T5S3_EPaper_Pro)
display.print("Swipe:Pick");
const char* rt = "Boot:Back Tap:Apply";
#else
display.print("W/S:Pick Q:Back");
const char* rt = "Enter:Apply";
#endif
display.setCursor(display.width() - display.getTextWidth(rt) - 2, footerY);
display.print(rt);
#ifdef USE_EINK
return 5000;
#else
return 1000;
#endif
}
// -----------------------------------------------------------------------
// Input
// -----------------------------------------------------------------------
bool handleInput(char c) override {
// W / UP — previous style
if (c == 'w' || c == 'W' || c == 0xF2 || c == KEY_UP) {
if (_cursor > 0) {
_cursor--;
return true;
}
return false;
}
// S / DOWN — next style
if (c == 's' || c == 'S' || c == 0xF1 || c == KEY_DOWN) {
if (_cursor < MECK_FONT_STYLE_COUNT - 1) {
_cursor++;
return true;
}
return false;
}
// Enter — apply selected style and exit
if (c == '\r' || c == 13 || c == KEY_ENTER || c == KEY_SELECT) {
_prefs->ui_font_style = _cursor;
the_mesh.savePrefs();
_applied = true;
_wantExit = true;
Serial.printf("FontPreview: Applied style = %s (%d)\n",
meckFontStyleName(_cursor), _cursor);
return true;
}
// Q / backspace — cancel, restore original style
if (c == 'q' || c == 'Q' || c == '\b' || c == KEY_CANCEL) {
_prefs->ui_font_style = _originalStyle;
_wantExit = true;
return true;
}
return false;
}
// -----------------------------------------------------------------------
// Touch hit test (virtual coordinates)
// Returns: 0=miss, 1=cursor moved, 2=activate (apply).
// -----------------------------------------------------------------------
int selectAtVxVy(int vx, int vy) {
const int headerH = 14;
const int footerH = 14;
const int bodyH = 128 - headerH - footerH; // virtual 128×128
const int rowH = bodyH / MECK_FONT_STYLE_COUNT;
if (vy < headerH || vy >= 128 - footerH) return 0;
int tapped = (vy - headerH) / rowH;
if (tapped < 0 || tapped >= MECK_FONT_STYLE_COUNT) return 0;
if (tapped == _cursor) return 2; // Tap same row = apply
_cursor = tapped;
return 1; // Moved cursor
}
};
@@ -13,12 +13,15 @@ extern MyMesh the_mesh;
// recency. Unlike Discovery (active zero-hop scan), this is purely passive
// — it shows nodes whose adverts have been received over time.
// ==========================================================================
// Display cap — we never need to show all 200 storage entries at once
#define LAST_HEARD_DISPLAY_SIZE 100
class LastHeardScreen : public UIScreen {
mesh::RTCClock* _rtc;
int _scrollPos;
// Local sorted copy of advert paths (refreshed each render)
AdvertPath _entries[ADVERT_PATH_TABLE_SIZE];
// Local sorted copy of advert paths (PSRAM-allocated, refreshed each render)
AdvertPath* _entries;
int _count;
static char typeChar(uint8_t adv_type) {
@@ -46,7 +49,9 @@ class LastHeardScreen : public UIScreen {
public:
LastHeardScreen(mesh::RTCClock* rtc)
: _rtc(rtc), _scrollPos(0), _count(0) {}
: _rtc(rtc), _scrollPos(0), _count(0) {
_entries = (AdvertPath*)ps_calloc(LAST_HEARD_DISPLAY_SIZE, sizeof(AdvertPath));
}
void resetScroll() { _scrollPos = 0; }
@@ -68,11 +73,11 @@ public:
// Returns: 0=miss, 1=moved, 2=tapped current row.
int selectRowAtVY(int vy) {
if (_count == 0) return 0;
const int headerH = 14, footerH = 14, lineH = 9;
const int headerH = 14, footerH = 14, lineH = the_mesh.getNodePrefs()->smallLineH();
#if defined(LilyGo_T5S3_EPaper_Pro)
const int bodyTop = headerH;
#else
const int bodyTop = headerH + 5;
const int bodyTop = headerH + the_mesh.getNodePrefs()->smallHighlightOff();
#endif
if (vy < bodyTop || vy >= 128 - footerH) return 0;
@@ -91,7 +96,7 @@ public:
int render(DisplayDriver& display) override {
// Refresh sorted list from mesh
_count = the_mesh.getRecentlyHeard(_entries, ADVERT_PATH_TABLE_SIZE);
_count = the_mesh.getRecentlyHeard(_entries, LAST_HEARD_DISPLAY_SIZE);
// Filter out empty entries (recv_timestamp == 0)
int validCount = 0;
@@ -117,8 +122,8 @@ public:
display.drawRect(0, 11, display.width(), 1);
// === Body — node rows ===
display.setTextSize(0);
int lineHeight = 9;
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize());
int lineHeight = the_mesh.getNodePrefs()->smallLineH();
int headerHeight = 14;
int footerHeight = 14;
int maxY = display.height() - footerHeight;
@@ -147,7 +152,7 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), lineHeight);
#else
display.fillRect(0, y + 5, display.width(), lineHeight);
display.fillRect(0, y + the_mesh.getNodePrefs()->smallHighlightOff(), display.width(), lineHeight);
#endif
display.setColor(DisplayDriver::DARK);
} else {
+168
View File
@@ -0,0 +1,168 @@
#pragma once
// ---------------------------------------------------------------------------
// MeckFonts.h — Font style system for Meck
// ---------------------------------------------------------------------------
// Defines font styles (Classic, Noto Sans, Montserrat) and provides lookup
// tables for each display driver's setTextSize() method.
//
// Place this file in: examples/companion_radio/ui-new/
// Place font .h files in: examples/companion_radio/ui-new/fonts/
//
// Both GxEPDDisplay.h and FastEPDDisplay.h include this file.
// The -I examples/companion_radio/ui-new flag (already in platformio.ini)
// makes everything resolve.
// ---------------------------------------------------------------------------
#include <Adafruit_GFX.h> // GFXfont type
// ---------------------------------------------------------------------------
// Font style IDs — stored in NodePrefs.ui_font_style
// ---------------------------------------------------------------------------
#define MECK_FONT_CLASSIC 0 // FreeSans (original Meck look)
#define MECK_FONT_NOTO 1 // Noto Sans — clean, excellent Latin Extended
#define MECK_FONT_MONTSERRAT 2 // Montserrat — geometric, distinctive
#define MECK_FONT_STYLE_COUNT 3
static inline const char* meckFontStyleName(uint8_t style) {
switch (style) {
case MECK_FONT_CLASSIC: return "Classic";
case MECK_FONT_NOTO: return "Noto Sans";
case MECK_FONT_MONTSERRAT: return "Montserrat";
default: return "Classic";
}
}
// ---------------------------------------------------------------------------
// Font includes — Noto Sans family
// ---------------------------------------------------------------------------
#include "fonts/NotoSans7pt7b.h"
#include "fonts/NotoSans9pt7b.h"
#include "fonts/NotoSans12pt7b.h"
#include "fonts/NotoSansBold7pt7b.h"
#include "fonts/NotoSansBold9pt7b.h"
#include "fonts/NotoSansBold12pt7b.h"
#include "fonts/NotoSansBold18pt7b.h"
#include "fonts/NotoSansBold24pt7b.h"
// ---------------------------------------------------------------------------
// Font includes — Montserrat family
// ---------------------------------------------------------------------------
#include "fonts/Montserrat7pt7b.h"
#include "fonts/Montserrat9pt7b.h"
#include "fonts/Montserrat12pt7b.h"
#include "fonts/MontserratBold7pt7b.h"
#include "fonts/MontserratBold9pt7b.h"
#include "fonts/MontserratBold12pt7b.h"
#include "fonts/MontserratBold18pt7b.h"
#include "fonts/MontserratBold24pt7b.h"
// ---------------------------------------------------------------------------
// T-Deck Pro font lookup (240×320, GxEPD2)
// ---------------------------------------------------------------------------
// Maps (fontStyle, textSize) → GFXfont*.
// Returns NULL for textSize 0 with Classic (built-in 6×8 font).
//
// textSize values used by Meck screens:
// 0 = tiny body (built-in 6×8 or 7pt with custom fonts)
// 1 = body (9pt)
// 2 = medium (9pt, same as body in current layout)
// 3 = title (12pt bold)
// 5 = clock face (12pt bold ×2 scaling — caller handles setTextSize(2))
//
// yAdvance reference (physical pixels):
// Classic 9pt=22, Noto 9pt=24, Montserrat 9pt=21 — close enough
// Classic 12ptB=29, Noto 12ptB=32, Montserrat 12ptB=29 — close
// ---------------------------------------------------------------------------
#if !defined(LilyGo_T5S3_EPaper_Pro)
static inline const GFXfont* meckGetFont_TDeckPro(uint8_t style, int textSize) {
// Classic — return NULL to let display driver use its defaults
if (style == MECK_FONT_CLASSIC) return nullptr;
if (style == MECK_FONT_NOTO) {
switch (textSize) {
case 0: return &NotoSans_Regular7pt7b;
case 1: return &NotoSans_Regular9pt7b;
case 2: return &NotoSans_Regular9pt7b;
case 3: return &NotoSans_Bold12pt7b;
case 5: return &NotoSans_Bold12pt7b; // caller applies ×2 scale
default: return &NotoSans_Regular9pt7b;
}
}
// MECK_FONT_MONTSERRAT
switch (textSize) {
case 0: return &Montserrat_Regular7pt7b;
case 1: return &Montserrat_Regular9pt7b;
case 2: return &Montserrat_Regular9pt7b;
case 3: return &Montserrat_Bold12pt7b;
case 5: return &Montserrat_Bold12pt7b; // caller applies ×2 scale
default: return &Montserrat_Regular9pt7b;
}
}
#endif // !LilyGo_T5S3_EPaper_Pro
// ---------------------------------------------------------------------------
// T5S3 font lookup (960×540, FastEPD)
// ---------------------------------------------------------------------------
// Metric-matched to existing FreeSans sizes so virtual-coordinate layouts
// stay intact. The larger Noto/Montserrat sizes (18-26pt) are available in
// the fonts/ directory for a future T5S3 layout rework.
//
// textSize values used by Meck screens:
// 0 = body (12pt regular)
// 1 = heading (12pt bold)
// 2 = large bold (18pt bold)
// 3 = extra large (24pt bold)
// 5 = clock face (24pt bold ×5 scaling)
//
// yAdvance reference (physical pixels):
// FreeSans12pt=29, Noto12pt=32, Montserrat12pt=29
// FreeSansBold18pt=42, NotoBold18pt=48, MontBold18pt=43
// FreeSansBold24pt=56, NotoBold24pt=64, MontBold24pt=57
// ---------------------------------------------------------------------------
#if defined(LilyGo_T5S3_EPaper_Pro)
static inline const GFXfont* meckGetFont_T5S3(uint8_t style, int textSize) {
if (style == MECK_FONT_CLASSIC) return nullptr;
if (style == MECK_FONT_NOTO) {
switch (textSize) {
case 0: return &NotoSans_Regular12pt7b;
case 1: return &NotoSans_Bold12pt7b;
case 2: return &NotoSans_Bold18pt7b;
case 3: return &NotoSans_Bold24pt7b;
case 5: return &NotoSans_Bold24pt7b; // caller applies ×5 scale
default: return &NotoSans_Regular12pt7b;
}
}
// MECK_FONT_MONTSERRAT
switch (textSize) {
case 0: return &Montserrat_Regular12pt7b;
case 1: return &Montserrat_Bold12pt7b;
case 2: return &Montserrat_Bold18pt7b;
case 3: return &Montserrat_Bold24pt7b;
case 5: return &Montserrat_Bold24pt7b; // caller applies ×5 scale
default: return &Montserrat_Regular12pt7b;
}
}
#endif // LilyGo_T5S3_EPaper_Pro
// ---------------------------------------------------------------------------
// Unified lookup — called from display driver setTextSize()
// ---------------------------------------------------------------------------
// Returns the GFXfont* for the given style and textSize.
// If nullptr is returned, the display driver should use its built-in default
// (FreeSans for Classic style, or built-in 6×8 for textSize 0).
// ---------------------------------------------------------------------------
static inline const GFXfont* meckGetFont(uint8_t style, int textSize) {
#if defined(LilyGo_T5S3_EPaper_Pro)
return meckGetFont_T5S3(style, textSize);
#else
return meckGetFont_TDeckPro(style, textSize);
#endif
}
+70 -24
View File
@@ -5,6 +5,7 @@
#include <SD.h>
#include <vector>
#include "Utf8CP437.h"
#include "../NodePrefs.h"
// Forward declarations
class UITask;
@@ -52,9 +53,11 @@ public:
private:
UITask* _task;
NodePrefs* _prefs;
Mode _mode;
bool _sdReady;
bool _initialized;
uint8_t _lastFontPref;
DisplayDriver* _display;
// Display layout (calculated once from display metrics)
@@ -518,8 +521,8 @@ private:
display.drawRect(0, 11, display.width(), 1);
// File list with "+ New Note" at index 0
display.setTextSize(0);
int listLineH = 9; // Match contacts/discovery for consistent selection highlight
display.setTextSize(_prefs->smallTextSize());
int listLineH = _prefs->smallLineH();
int startY = 14;
int totalItems = 1 + (int)_fileList.size();
int maxVisible = (display.height() - startY - _footerHeight) / listLineH;
@@ -539,27 +542,21 @@ private:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), listLineH);
#else
display.fillRect(0, y + 5, display.width(), listLineH);
display.fillRect(0, y + _prefs->smallHighlightOff(), display.width(), listLineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
display.setColor(DisplayDriver::LIGHT);
}
display.setCursor(0, y);
if (i == 0) {
display.setColor(selected ? DisplayDriver::DARK : DisplayDriver::GREEN);
display.print(selected ? "> + New Note" : " + New Note");
display.drawTextEllipsized(0, y, display.width() - 4,
selected ? "> + New Note" : " + New Note");
} else {
String line = selected ? "> " : " ";
String name = _fileList[i - 1];
int maxLen = _charsPerLine - 4;
if ((int)name.length() > maxLen) {
name = name.substring(0, maxLen - 3) + "...";
}
line += name;
display.print(line.c_str());
line += _fileList[i - 1];
display.drawTextEllipsized(0, y, display.width() - 4, line.c_str());
}
y += listLineH;
}
@@ -605,7 +602,7 @@ private:
}
// Render current page using tiny font
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
int pageStart = _pageOffsets[_currentPage];
@@ -722,7 +719,7 @@ private:
int textAreaTop = 14;
int textAreaBottom = display.height() - 16;
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
// Find cursor line
int cursorLine = lineForPos(_cursorPos);
@@ -771,7 +768,7 @@ private:
// If buffer is empty, show cursor at top
if (_bufLen == 0) {
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::GREEN);
display.setCursor(0, textAreaTop);
display.print("|");
@@ -829,7 +826,7 @@ private:
display.setCursor(0, 20);
display.setColor(DisplayDriver::LIGHT);
display.print("From: ");
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
String origDisplay = _renameOriginal;
if (origDisplay.length() > 30) origDisplay = origDisplay.substring(0, 27) + "...";
display.print(origDisplay.c_str());
@@ -840,7 +837,7 @@ private:
display.setColor(DisplayDriver::LIGHT);
display.print("To: ");
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::GREEN);
char displayName[NOTES_RENAME_MAX + 2];
snprintf(displayName, sizeof(displayName), "%s|", _renameBuf);
@@ -880,7 +877,7 @@ private:
display.setCursor(0, 25);
display.print("File:");
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setCursor(0, 38);
String nameDisplay = _deleteTarget;
if (nameDisplay.length() > 35) nameDisplay = nameDisplay.substring(0, 32) + "...";
@@ -1096,9 +1093,9 @@ private:
}
public:
NotesScreen(UITask* task)
: _task(task), _mode(FILE_LIST),
_sdReady(false), _initialized(false), _display(nullptr),
NotesScreen(UITask* task, NodePrefs* prefs = nullptr)
: _task(task), _prefs(prefs), _mode(FILE_LIST),
_sdReady(false), _initialized(false), _lastFontPref(0), _display(nullptr),
_charsPerLine(38), _linesPerPage(22), _lineHeight(5), _footerHeight(14),
_editCharsPerLine(20), _editLineHeight(12), _editMaxLines(8),
_selectedFile(0), _buf(nullptr), _bufLen(0), _cursorPos(0),
@@ -1133,15 +1130,31 @@ public:
// ---- Layout Init ----
void initLayout(DisplayDriver& display) {
// Re-init if font preference changed since last layout
uint8_t curFont = _prefs ? _prefs->large_font : 0;
if (_initialized && curFont != _lastFontPref) {
_initialized = false;
Serial.println("Notes: font changed, recalculating layout");
}
if (_initialized) return;
_lastFontPref = curFont;
_display = &display;
// Tiny font metrics (for read mode)
display.setTextSize(0);
// Font metrics (for read mode)
display.setTextSize(_prefs->smallTextSize());
uint16_t tenCharsW = display.getTextWidth("MMMMMMMMMM");
if (tenCharsW > 0) {
_charsPerLine = (display.width() * 10) / tenCharsW;
}
// Proportional font: use average-width measurement instead of M-width
if (_prefs && _prefs->large_font) {
const char* sample = "the quick brown fox jumps over lazy dog";
uint16_t sampleW = display.getTextWidth(sample);
int sampleLen = strlen(sample);
if (sampleW > 0 && sampleLen > 0) {
_charsPerLine = (display.width() * sampleLen * 70) / ((int)sampleW * 100);
}
}
if (_charsPerLine < 15) _charsPerLine = 15;
if (_charsPerLine > 60) _charsPerLine = 60;
@@ -1151,6 +1164,10 @@ public:
} else {
_lineHeight = 5;
}
// Large font: formula above assumes built-in 6x8 ratio — too small for 9pt
if (_prefs && _prefs->large_font) {
_lineHeight = _prefs->smallLineH();
}
_footerHeight = 14;
int textAreaHeight = display.height() - _footerHeight;
@@ -1203,6 +1220,35 @@ public:
bool isConfirmingDelete() const { return _mode == CONFIRM_DELETE; }
bool isEmpty() const { return _bufLen == 0; }
// Touch: select file list row by virtual Y coordinate
// Returns: 0 = outside list, 1 = moved selection, 2 = tapped same row (open)
int selectRowAtVY(int vy) {
if (_mode != FILE_LIST) return 0;
const int startY = 14, footerH = 14;
const int listLineH = _prefs ? _prefs->smallLineH() : 9;
#if defined(LilyGo_T5S3_EPaper_Pro)
const int bodyTop = startY;
#else
const int bodyTop = startY + (_prefs ? _prefs->smallHighlightOff() : 5);
#endif
if (vy < bodyTop || vy >= 128 - footerH) return 0;
int totalItems = 1 + (int)_fileList.size();
if (totalItems == 0) return 0;
int maxVisible = (128 - startY - footerH) / listLineH;
if (maxVisible < 3) maxVisible = 3;
if (maxVisible > 15) maxVisible = 15;
int startIdx = max(0, min(_selectedFile - maxVisible / 2,
totalItems - maxVisible));
int tappedRow = startIdx + (vy - bodyTop) / listLineH;
if (tappedRow < 0 || tappedRow >= totalItems) return 0;
if (tappedRow == _selectedFile) return 2;
_selectedFile = tappedRow;
return 1;
}
// ---- Cursor Navigation (called from main.cpp) ----
void moveCursorLeft() {
@@ -0,0 +1,805 @@
#pragma once
#include <helpers/ui/UIScreen.h>
#include <helpers/ui/DisplayDriver.h>
#include <MeshCore.h>
#include <Packet.h>
// Forward declarations
class UITask;
class MyMesh;
extern MyMesh the_mesh;
class PathEditorScreen : public UIScreen {
public:
enum EditorState {
STATE_MAIN,
STATE_PICK_HOP
};
// Main-state menu items (dynamic, built each render)
enum MenuItem {
MENU_MODE = 0, // "Mode: 1B/hop" or "Mode: 2B/hop"
// After mode: hop lines (MENU_HOP_BASE + i)
// Then: action items
MENU_HOP_BASE = 1,
// Dynamic items after hops:
MENU_ADD_HOP = 100,
MENU_SET_DIRECT,
MENU_REMOVE_LAST,
MENU_CLEAR_PATH,
MENU_SAVE_EXIT
};
private:
UITask* _task;
mesh::RTCClock* _rtc;
int _contactIdx; // Index into contact table
char _contactName[32]; // Contact name for header
EditorState _state;
int _menuSel; // Selected menu item index (0-based in visible list)
int _menuCount; // Total visible menu items
// Path being edited (working copy)
uint8_t _pathBuf[MAX_PATH_SIZE];
uint8_t _pathLen; // Encoded: bits[7:6]=mode, bits[5:0]=hops
int _hopCount; // Decoded hop count
int _bytesPerHop; // 1 or 2
// Repeater picker state
static const int MAX_REPEATERS = 200;
uint16_t* _repIdx; // Indices into contact table (PSRAM)
int _repCount; // Number of repeaters found
int _repSel; // Selected repeater in picker
int _repScroll; // Scroll offset in picker
bool _dirty; // Path has been modified
bool _wantExit; // Set by Save & Exit — caller should navigate back
bool _directLocked; // True = path is explicitly set to direct (0 hops, locked)
// --- helpers ---
void decodePath() {
_hopCount = _pathLen & 0x3F;
uint8_t mode = (_pathLen >> 6) & 0x03;
_bytesPerHop = mode + 1;
}
uint8_t encodePath() const {
uint8_t mode = (_bytesPerHop - 1) & 0x03;
return (mode << 6) | (_hopCount & 0x3F);
}
void buildRepeaterList() {
_repCount = 0;
uint32_t numContacts = the_mesh.getNumContacts();
ContactInfo c;
for (uint32_t i = 0; i < numContacts && _repCount < MAX_REPEATERS; i++) {
if (the_mesh.getContactByIdx(i, c)) {
if (c.type == ADV_TYPE_REPEATER) {
_repIdx[_repCount++] = (uint16_t)i;
}
}
}
}
// Look up a contact name by matching pub_key prefix bytes
bool findNameForHop(int hopIndex, char* name, size_t nameLen) const {
if (hopIndex < 0 || hopIndex >= _hopCount) return false;
int offset = hopIndex * _bytesPerHop;
uint32_t numContacts = the_mesh.getNumContacts();
ContactInfo c;
for (uint32_t i = 0; i < numContacts; i++) {
if (the_mesh.getContactByIdx(i, c)) {
bool match = true;
for (int b = 0; b < _bytesPerHop; b++) {
if (c.id.pub_key[b] != _pathBuf[offset + b]) {
match = false;
break;
}
}
if (match) {
strncpy(name, c.name, nameLen);
name[nameLen - 1] = '\0';
return true;
}
}
}
return false;
}
// Build the visible menu items list and return count
// Menu layout:
// 0: Mode selector
// 1..hopCount: each hop
// hopCount+1: Add hop
// hopCount+2: Remove last (only if hops > 0)
// hopCount+2 or +3: Clear path (only if custom path flag set or hops > 0)
// last: Save & Exit
int buildMenuCount() const {
int count = 1; // Mode selector
count += _hopCount; // One per hop
if (_hopCount < 8) count++; // Add hop (max 8 hops)
count++; // Set Direct (always visible)
if (_hopCount > 0) count++; // Remove last
if (_hopCount > 0 || _directLocked || isCustomPathSet()) count++; // Clear path
count++; // Save & Exit
return count;
}
// Map a menu index to a MenuItem enum
MenuItem menuItemAt(int idx) const {
if (idx == 0) return MENU_MODE;
int pos = 1;
// Hop lines
for (int h = 0; h < _hopCount; h++) {
if (idx == pos) return (MenuItem)(MENU_HOP_BASE + h);
pos++;
}
// Add hop
if (_hopCount < 8) {
if (idx == pos) return MENU_ADD_HOP;
pos++;
}
// Set Direct
if (idx == pos) return MENU_SET_DIRECT;
pos++;
// Remove last
if (_hopCount > 0) {
if (idx == pos) return MENU_REMOVE_LAST;
pos++;
}
// Clear path
if (_hopCount > 0 || _directLocked || isCustomPathSet()) {
if (idx == pos) return MENU_CLEAR_PATH;
pos++;
}
// Save & Exit
return MENU_SAVE_EXIT;
}
bool isCustomPathSet() const {
ContactInfo c;
if (!the_mesh.getContactByIdx(_contactIdx, c)) return false;
return (c.flags & CONTACT_FLAG_CUSTOM_PATH) != 0;
}
public:
PathEditorScreen(UITask* task, mesh::RTCClock* rtc)
: _task(task), _rtc(rtc), _contactIdx(-1), _state(STATE_MAIN),
_menuSel(0), _menuCount(1), _pathLen(0), _hopCount(0),
_bytesPerHop(1), _repCount(0), _repSel(0), _repScroll(0),
_dirty(false), _wantExit(false), _directLocked(false) {
memset(_contactName, 0, sizeof(_contactName));
memset(_pathBuf, 0, sizeof(_pathBuf));
#if defined(ESP32) && defined(BOARD_HAS_PSRAM)
_repIdx = (uint16_t*)ps_calloc(MAX_REPEATERS, sizeof(uint16_t));
#else
_repIdx = new uint16_t[MAX_REPEATERS]();
#endif
}
void openForContact(int contactIdx) {
_contactIdx = contactIdx;
_state = STATE_MAIN;
_menuSel = 0;
_repSel = 0;
_repScroll = 0;
_dirty = false;
_wantExit = false;
_directLocked = false;
// Load contact info
ContactInfo c;
if (the_mesh.getContactByIdx(contactIdx, c)) {
strncpy(_contactName, c.name, sizeof(_contactName) - 1);
_contactName[sizeof(_contactName) - 1] = '\0';
// Copy current path
if (c.out_path_len != OUT_PATH_UNKNOWN) {
_pathLen = c.out_path_len;
decodePath();
int byteLen = _hopCount * _bytesPerHop;
if (byteLen > MAX_PATH_SIZE) byteLen = MAX_PATH_SIZE;
memcpy(_pathBuf, c.out_path, byteLen);
// Detect existing direct-locked path
if (_hopCount == 0 && (c.flags & CONTACT_FLAG_CUSTOM_PATH)) {
_directLocked = true;
}
} else {
_pathLen = 0;
_hopCount = 0;
_bytesPerHop = 1;
memset(_pathBuf, 0, sizeof(_pathBuf));
}
} else {
strcpy(_contactName, "Unknown");
_pathLen = 0;
_hopCount = 0;
_bytesPerHop = 1;
}
_menuCount = buildMenuCount();
}
int render(DisplayDriver& display) override {
if (_state == STATE_PICK_HOP) {
return renderPicker(display);
}
return renderMain(display);
}
int renderMain(DisplayDriver& display) {
char tmp[64];
// === Header ===
display.setTextSize(1);
display.setColor(DisplayDriver::GREEN);
display.setCursor(0, 0);
snprintf(tmp, sizeof(tmp), "Path: %s", _contactName);
// Truncate if too long
if (display.getTextWidth(tmp) > display.width() - 4) {
snprintf(tmp, sizeof(tmp), "Path: %.12s..", _contactName);
}
display.print(tmp);
// Show lock icon or dirty indicator on right
if (_dirty) {
const char* mod = "[*]";
display.setCursor(display.width() - display.getTextWidth(mod) - 2, 0);
display.print(mod);
} else if (isCustomPathSet()) {
const char* lock = "[L]";
display.setCursor(display.width() - display.getTextWidth(lock) - 2, 0);
display.print(lock);
}
display.drawRect(0, 11, display.width(), 1);
// === Body ===
display.setTextSize(0);
int lineH = 9;
int headerH = 14;
int footerH = 14;
int maxY = display.height() - footerH;
int y = headerH;
_menuCount = buildMenuCount();
// Center visible window around selected item
int maxVisible = (maxY - headerH) / lineH;
if (maxVisible < 3) maxVisible = 3;
int startIdx = max(0, min(_menuSel - maxVisible / 2, _menuCount - maxVisible));
if (startIdx < 0) startIdx = 0;
int endIdx = min(_menuCount, startIdx + maxVisible);
for (int i = startIdx; i < endIdx && y + lineH <= maxY; i++) {
bool selected = (i == _menuSel);
MenuItem item = menuItemAt(i);
if (selected) {
display.setColor(DisplayDriver::LIGHT);
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), lineH);
#else
display.fillRect(0, y + 5, display.width(), lineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
display.setColor(DisplayDriver::LIGHT);
}
display.setCursor(2, y);
char prefix = selected ? '>' : ' ';
switch (item) {
case MENU_MODE:
if (_directLocked) {
snprintf(tmp, sizeof(tmp), "%c Mode: DIRECT", prefix);
} else {
snprintf(tmp, sizeof(tmp), "%c Mode: %dB/hop", prefix, _bytesPerHop);
}
display.print(tmp);
// Show hint on right
if (!_directLocked) {
const char* hint = "(A/D)";
display.setCursor(display.width() - display.getTextWidth(hint) - 4, y);
display.print(hint);
}
break;
case MENU_ADD_HOP:
snprintf(tmp, sizeof(tmp), "%c + Add hop...", prefix);
display.print(tmp);
break;
case MENU_SET_DIRECT:
if (_directLocked) {
snprintf(tmp, sizeof(tmp), "%c * Direct (set)", prefix);
} else {
snprintf(tmp, sizeof(tmp), "%c * Set Direct", prefix);
}
display.print(tmp);
break;
case MENU_REMOVE_LAST:
snprintf(tmp, sizeof(tmp), "%c - Remove last hop", prefix);
display.print(tmp);
break;
case MENU_CLEAR_PATH:
snprintf(tmp, sizeof(tmp), "%c Clear custom path", prefix);
display.print(tmp);
break;
case MENU_SAVE_EXIT:
snprintf(tmp, sizeof(tmp), "%c Save & Exit", prefix);
display.print(tmp);
break;
default:
// Hop line: MENU_HOP_BASE + hopIndex
if (item >= MENU_HOP_BASE && item < MENU_HOP_BASE + 64) {
int hopIdx = item - MENU_HOP_BASE;
char hopName[24];
int offset = hopIdx * _bytesPerHop;
if (findNameForHop(hopIdx, hopName, sizeof(hopName))) {
if (_bytesPerHop == 1) {
snprintf(tmp, sizeof(tmp), "%c %d: %s (%02X)", prefix, hopIdx + 1,
hopName, _pathBuf[offset]);
} else {
snprintf(tmp, sizeof(tmp), "%c %d: %s (%02X%02X)", prefix, hopIdx + 1,
hopName, _pathBuf[offset], _pathBuf[offset + 1]);
}
} else {
if (_bytesPerHop == 1) {
snprintf(tmp, sizeof(tmp), "%c %d: ??? (%02X)", prefix, hopIdx + 1,
_pathBuf[offset]);
} else {
snprintf(tmp, sizeof(tmp), "%c %d: ??? (%02X%02X)", prefix, hopIdx + 1,
_pathBuf[offset], _pathBuf[offset + 1]);
}
}
display.drawTextEllipsized(2, y, display.width() - 4, tmp);
}
break;
}
y += lineH;
}
// === Footer ===
display.setTextSize(1);
int footerY = display.height() - 12;
display.drawRect(0, footerY - 2, display.width(), 1);
display.setColor(DisplayDriver::YELLOW);
#if defined(LilyGo_T5S3_EPaper_Pro)
display.setCursor(0, footerY);
display.print("Swipe:Nav");
const char* right = "Hold:Select";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
#else
display.setCursor(0, footerY);
display.print("Q:Bk W/S:Nav");
const char* right = "Enter:Sel";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
#endif
return 5000;
}
int renderPicker(DisplayDriver& display) {
char tmp[64];
// === Header ===
display.setTextSize(1);
display.setColor(DisplayDriver::GREEN);
display.setCursor(0, 0);
snprintf(tmp, sizeof(tmp), "Select Repeater (%d)", _repCount);
display.print(tmp);
display.drawRect(0, 11, display.width(), 1);
// === Body ===
display.setTextSize(0);
int lineH = 9;
int headerH = 14;
int footerH = 14;
int maxY = display.height() - footerH;
int y = headerH;
if (_repCount == 0) {
display.setColor(DisplayDriver::LIGHT);
display.setCursor(0, y);
display.print("No repeaters in contacts");
display.setCursor(0, y + lineH);
display.print("Add repeaters first");
} else {
int maxVisible = (maxY - headerH) / lineH;
if (maxVisible < 3) maxVisible = 3;
int startIdx = max(0, min(_repSel - maxVisible / 2, _repCount - maxVisible));
if (startIdx < 0) startIdx = 0;
int endIdx = min(_repCount, startIdx + maxVisible);
for (int i = startIdx; i < endIdx && y + lineH <= maxY; i++) {
ContactInfo c;
if (!the_mesh.getContactByIdx(_repIdx[i], c)) continue;
bool selected = (i == _repSel);
if (selected) {
display.setColor(DisplayDriver::LIGHT);
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), lineH);
#else
display.fillRect(0, y + 5, display.width(), lineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
display.setColor(DisplayDriver::LIGHT);
}
display.setCursor(2, y);
char prefix = selected ? '>' : ' ';
if (_bytesPerHop == 1) {
snprintf(tmp, sizeof(tmp), "%c %s (%02X)", prefix, c.name, c.id.pub_key[0]);
} else {
snprintf(tmp, sizeof(tmp), "%c %s (%02X%02X)", prefix, c.name,
c.id.pub_key[0], c.id.pub_key[1]);
}
display.drawTextEllipsized(2, y, display.width() - 4, tmp);
y += lineH;
}
}
// === Footer ===
display.setTextSize(1);
int footerY = display.height() - 12;
display.drawRect(0, footerY - 2, display.width(), 1);
display.setColor(DisplayDriver::YELLOW);
#if defined(LilyGo_T5S3_EPaper_Pro)
display.setCursor(0, footerY);
display.print("Swipe:Scroll");
const char* right = "Hold:Add Back:Cancel";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
#else
display.setCursor(0, footerY);
display.print("Q:Cancel W/S:Scroll");
const char* right = "Enter:Add";
display.setCursor(display.width() - display.getTextWidth(right) - 2, footerY);
display.print(right);
#endif
return 5000;
}
bool handleInput(char c) override {
if (_state == STATE_PICK_HOP) {
return handlePickerInput(c);
}
return handleMainInput(c);
}
bool handleMainInput(char c) {
// W - scroll up
if (c == 'w' || c == 'W' || c == 0xF2) {
if (_menuSel > 0) {
_menuSel--;
return true;
}
return false;
}
// S - scroll down
if (c == 's' || c == 'S' || c == 0xF1) {
if (_menuSel < _menuCount - 1) {
_menuSel++;
return true;
}
return false;
}
// A/D — toggle mode (only when Mode item is selected and not direct-locked)
if (c == 'a' || c == 'A' || c == 'd' || c == 'D') {
MenuItem item = menuItemAt(_menuSel);
if (item == MENU_MODE && !_directLocked) {
// Toggle between 1-byte and 2-byte
if (_bytesPerHop == 1) {
switchMode(2);
} else {
switchMode(1);
}
_dirty = true;
_menuCount = buildMenuCount();
return true;
}
return false;
}
// Enter - select
if (c == 13 || c == KEY_ENTER || c == '\r') {
MenuItem item = menuItemAt(_menuSel);
switch (item) {
case MENU_MODE:
// Toggle mode on Enter too (no-op if direct locked)
if (!_directLocked) {
if (_bytesPerHop == 1) {
switchMode(2);
} else {
switchMode(1);
}
_dirty = true;
_menuCount = buildMenuCount();
}
return true;
case MENU_ADD_HOP:
// Enter picker mode — adding a hop clears direct lock
_directLocked = false;
buildRepeaterList();
_repSel = 0;
_repScroll = 0;
_state = STATE_PICK_HOP;
return true;
case MENU_SET_DIRECT:
// Set path to direct (0 hops, locked)
_hopCount = 0;
_pathLen = 0;
memset(_pathBuf, 0, sizeof(_pathBuf));
_directLocked = true;
_dirty = true;
_menuCount = buildMenuCount();
return true;
case MENU_REMOVE_LAST:
if (_hopCount > 0) {
_hopCount--;
_pathLen = encodePath();
_dirty = true;
_menuCount = buildMenuCount();
// Clamp selection
if (_menuSel >= _menuCount) _menuSel = _menuCount - 1;
}
return true;
case MENU_CLEAR_PATH:
_hopCount = 0;
_pathLen = 0;
_directLocked = false;
memset(_pathBuf, 0, sizeof(_pathBuf));
_dirty = true;
_menuCount = buildMenuCount();
_menuSel = 0;
return true;
case MENU_SAVE_EXIT:
savePath();
_wantExit = true; // Signal to main.cpp to navigate back to contacts
return true;
default:
// Hop line — no action (could add remove-specific-hop later)
break;
}
return true;
}
// Q - back (discard changes or prompt?)
// For simplicity, just go back without saving
if (c == 'q' || c == 'Q') {
// Return to contacts screen without saving
// The UITask will handle this via the key falling through
return false; // Let UITask handle Q as back
}
return false;
}
bool handlePickerInput(char c) {
// W - scroll up
if (c == 'w' || c == 'W' || c == 0xF2) {
if (_repSel > 0) {
_repSel--;
return true;
}
return false;
}
// S - scroll down
if (c == 's' || c == 'S' || c == 0xF1) {
if (_repSel < _repCount - 1) {
_repSel++;
return true;
}
return false;
}
// Enter - add selected repeater as hop
if (c == 13 || c == KEY_ENTER || c == '\r') {
if (_repCount > 0 && _repSel >= 0 && _repSel < _repCount) {
addHopFromContact(_repIdx[_repSel]);
}
_state = STATE_MAIN;
_menuCount = buildMenuCount();
return true;
}
// Q - cancel picker, return to main
if (c == 'q' || c == 'Q') {
_state = STATE_MAIN;
return true;
}
return false;
}
// Tap-to-select for T5S3 touch
int selectRowAtVY(int vy) {
if (_state == STATE_PICK_HOP) {
return selectPickerRowAtVY(vy);
}
return selectMainRowAtVY(vy);
}
int selectMainRowAtVY(int vy) {
if (_menuCount == 0) return 0;
const int headerH = 14, footerH = 14, lineH = 9;
#if defined(LilyGo_T5S3_EPaper_Pro)
const int bodyTop = headerH;
#else
const int bodyTop = headerH + 5;
#endif
if (vy < bodyTop || vy >= 128 - footerH) return 0;
int maxVisible = (128 - headerH - footerH) / lineH;
if (maxVisible < 3) maxVisible = 3;
int startIdx = max(0, min(_menuSel - maxVisible / 2, _menuCount - maxVisible));
if (startIdx < 0) startIdx = 0;
int tappedRow = startIdx + (vy - bodyTop) / lineH;
if (tappedRow < 0 || tappedRow >= _menuCount) return 0;
if (tappedRow == _menuSel) return 2;
_menuSel = tappedRow;
return 1;
}
int selectPickerRowAtVY(int vy) {
if (_repCount == 0) return 0;
const int headerH = 14, footerH = 14, lineH = 9;
#if defined(LilyGo_T5S3_EPaper_Pro)
const int bodyTop = headerH;
#else
const int bodyTop = headerH + 5;
#endif
if (vy < bodyTop || vy >= 128 - footerH) return 0;
int maxVisible = (128 - headerH - footerH) / lineH;
if (maxVisible < 3) maxVisible = 3;
int startIdx = max(0, min(_repSel - maxVisible / 2, _repCount - maxVisible));
if (startIdx < 0) startIdx = 0;
int tappedRow = startIdx + (vy - bodyTop) / lineH;
if (tappedRow < 0 || tappedRow >= _repCount) return 0;
if (tappedRow == _repSel) return 2;
_repSel = tappedRow;
return 1;
}
EditorState getState() const { return _state; }
bool isDirty() const { return _dirty; }
bool wantsExit() const { return _wantExit; }
private:
void switchMode(int newBytesPerHop) {
if (newBytesPerHop == _bytesPerHop) return;
if (_hopCount > 0) {
// Rebuild path buffer for new mode
// We need the full pub_keys to re-extract the right prefix bytes
uint8_t newBuf[MAX_PATH_SIZE];
memset(newBuf, 0, sizeof(newBuf));
int newHopCount = 0;
for (int h = 0; h < _hopCount && newHopCount < 8; h++) {
int oldOffset = h * _bytesPerHop;
// Try to find the contact that matches this hop
uint32_t numContacts = the_mesh.getNumContacts();
ContactInfo c;
bool found = false;
for (uint32_t i = 0; i < numContacts; i++) {
if (the_mesh.getContactByIdx(i, c)) {
bool match = true;
for (int b = 0; b < _bytesPerHop; b++) {
if (c.id.pub_key[b] != _pathBuf[oldOffset + b]) {
match = false;
break;
}
}
if (match) {
// Found the contact — copy new prefix size
int newOffset = newHopCount * newBytesPerHop;
for (int b = 0; b < newBytesPerHop; b++) {
newBuf[newOffset + b] = c.id.pub_key[b];
}
newHopCount++;
found = true;
break;
}
}
}
if (!found) {
// Contact not found — copy what we can
int newOffset = newHopCount * newBytesPerHop;
int oldOff = h * _bytesPerHop;
for (int b = 0; b < newBytesPerHop; b++) {
if (b < _bytesPerHop) {
newBuf[newOffset + b] = _pathBuf[oldOff + b];
} else {
newBuf[newOffset + b] = 0x00; // pad with zero
}
}
newHopCount++;
}
}
_hopCount = newHopCount;
memcpy(_pathBuf, newBuf, sizeof(newBuf));
}
_bytesPerHop = newBytesPerHop;
_pathLen = encodePath();
}
void addHopFromContact(uint16_t contactTableIdx) {
if (_hopCount >= 8) return;
ContactInfo c;
if (!the_mesh.getContactByIdx(contactTableIdx, c)) return;
int offset = _hopCount * _bytesPerHop;
if (offset + _bytesPerHop > MAX_PATH_SIZE) return;
for (int b = 0; b < _bytesPerHop; b++) {
_pathBuf[offset + b] = c.id.pub_key[b];
}
_hopCount++;
_pathLen = encodePath();
_dirty = true;
}
void savePath() {
if (_contactIdx < 0) return;
if (_directLocked) {
// Set as direct (0 hops) with lock — prevents flood routing
the_mesh.setCustomPath(_contactIdx, _pathBuf, 0, true);
Serial.printf("PathEditor: set DIRECT path for contact %d (%s)\n",
_contactIdx, _contactName);
} else if (_hopCount > 0) {
// Set custom path with lock
the_mesh.setCustomPath(_contactIdx, _pathBuf, encodePath(), true);
Serial.printf("PathEditor: saved %d-hop %dB/hop path for contact %d (%s)\n",
_hopCount, _bytesPerHop, _contactIdx, _contactName);
} else {
// Clear custom path — revert to auto-discovery
the_mesh.clearCustomPath(_contactIdx);
Serial.printf("PathEditor: cleared custom path for contact %d (%s)\n",
_contactIdx, _contactName);
}
// Trigger contact save to SD
the_mesh.saveContacts();
_dirty = false;
}
};
@@ -777,8 +777,8 @@ private:
// =====================================================================
void renderCategoryMenu(DisplayDriver& display, int y, int bodyHeight) {
display.setTextSize(0);
int lineHeight = 9;
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize());
int lineHeight = the_mesh.getNodePrefs()->smallLineH();
// Clock drift info line
if (_serverTime > 0) {
@@ -862,8 +862,8 @@ private:
// =====================================================================
void renderCommandMenu(DisplayDriver& display, int y, int bodyHeight) {
display.setTextSize(0);
int lineHeight = 9;
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize());
int lineHeight = the_mesh.getNodePrefs()->smallLineH();
const AdminCategoryDef& cat = CATEGORIES[_catSel];
// Category title
@@ -1025,7 +1025,7 @@ private:
if (_pendingCmd) display.print(_pendingCmd->label);
y += 14;
display.setTextSize(0);
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize());
display.setCursor(0, y);
// Show the param value if one was collected
@@ -1033,7 +1033,7 @@ private:
char preview[80];
snprintf(preview, sizeof(preview), "Value: %s", _paramBuf);
display.print(preview);
y += 10;
y += the_mesh.getNodePrefs()->smallLineH() + 1;
display.setCursor(0, y);
}
@@ -1071,8 +1071,8 @@ private:
// =====================================================================
void renderResponse(DisplayDriver& display, int y, int bodyHeight) {
display.setTextSize(0);
int lineHeight = 9;
display.setTextSize(the_mesh.getNodePrefs()->smallTextSize());
int lineHeight = the_mesh.getNodePrefs()->smallLineH();
display.setColor((_state == STATE_ERROR) ? DisplayDriver::YELLOW : DisplayDriver::LIGHT);
@@ -1166,7 +1166,7 @@ private:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), lineHeight);
#else
display.fillRect(0, y + 5, display.width(), lineHeight);
display.fillRect(0, y + the_mesh.getNodePrefs()->smallHighlightOff(), display.width(), lineHeight);
#endif
display.setColor(DisplayDriver::DARK);
} else if (warn) {
+24 -21
View File
@@ -36,6 +36,7 @@
#include "ModemManager.h"
#include "SMSStore.h"
#include "SMSContacts.h"
#include "../NodePrefs.h"
// Limits
#define SMS_INBOX_PAGE_SIZE 4
@@ -51,6 +52,7 @@ public:
private:
UITask* _task;
NodePrefs* _prefs;
SubView _view;
// App menu state
@@ -117,8 +119,8 @@ private:
}
public:
SMSScreen(UITask* task)
: _task(task), _view(APP_MENU)
SMSScreen(UITask* task, NodePrefs* prefs = nullptr)
: _task(task), _prefs(prefs), _view(APP_MENU)
, _menuCursor(0)
, _convCount(0), _inboxCursor(0), _inboxScrollTop(0)
, _msgCount(0), _msgScrollPos(0)
@@ -276,7 +278,7 @@ public:
// Show modem state text if not ready
if (ms != ModemState::READY && ms != ModemState::SENDING_SMS) {
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::YELLOW);
const char* label = ModemManager::stateToString(ms);
uint16_t labelW = display.getTextWidth(label);
@@ -356,7 +358,7 @@ public:
// Modem status indicator
ModemState ms = modemManager.getState();
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setCursor(4, y + lineHeight + 8);
if (ms == ModemState::OFF || ms == ModemState::POWERING_ON ||
ms == ModemState::INITIALIZING) {
@@ -483,7 +485,7 @@ public:
bool isAction = (row == 4); // Bottom row has action buttons
if (isAction) {
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
if (col == 2 && _phoneInputPos > 0) {
display.setColor(DisplayDriver::GREEN); // CALL
} else if (col == 1) {
@@ -544,7 +546,7 @@ public:
display.drawRect(0, 11, display.width(), 1);
if (_convCount == 0) {
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(0, 20);
display.print("No conversations");
@@ -560,8 +562,8 @@ public:
}
display.setTextSize(1);
} else {
display.setTextSize(0);
int lineHeight = 10;
display.setTextSize(_prefs->smallTextSize());
int lineHeight = _prefs->smallLineH() + 1;
int y = 14;
int visibleCount = (display.height() - 14 - 14) / (lineHeight * 2 + 2);
@@ -643,14 +645,14 @@ public:
display.drawRect(0, 11, display.width(), 1);
if (_msgCount == 0) {
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(0, 25);
display.print("No messages");
display.setTextSize(1);
} else {
display.setTextSize(0);
int lineHeight = 10;
display.setTextSize(_prefs->smallTextSize());
int lineHeight = _prefs->smallLineH() + 1;
int headerHeight = 14;
int footerHeight = 14;
@@ -764,12 +766,13 @@ public:
// Message body
display.setCursor(0, 14);
display.setColor(DisplayDriver::LIGHT);
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
uint16_t testWidth = display.getTextWidth("MMMMMMMMMM");
int charsPerLine = (testWidth > 0) ? (display.width() * 10) / testWidth : 20;
if (charsPerLine < 12) charsPerLine = 12;
int composeLH = _prefs->smallLineH() + 1;
int y = 14;
int x = 0;
char cs[2] = {0, 0};
@@ -780,7 +783,7 @@ public:
x++;
if (x >= charsPerLine) {
x = 0;
y += 10;
y += composeLH;
}
}
@@ -827,7 +830,7 @@ public:
int cnt = smsContacts.count();
if (cnt == 0) {
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(0, 25);
display.print("No contacts saved");
@@ -837,8 +840,8 @@ public:
display.print("and press A to add");
display.setTextSize(1);
} else {
display.setTextSize(0);
int lineHeight = 10;
display.setTextSize(_prefs->smallTextSize());
int lineHeight = _prefs->smallLineH() + 1;
int y = 14;
int visibleCount = (display.height() - 14 - 14) / (lineHeight * 2 + 2);
@@ -900,7 +903,7 @@ public:
display.drawRect(0, 11, display.width(), 1);
// Phone number (read-only)
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(0, 16);
display.print("Phone: ");
@@ -956,7 +959,7 @@ public:
display.print(dispName);
// Phone number below name (smaller, dimmer)
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(4, 36);
display.print(_callPhone);
@@ -1011,7 +1014,7 @@ public:
display.print(dispName);
// Phone number below name (smaller, dimmer)
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(4, 36);
display.print(_callPhone);
@@ -1070,7 +1073,7 @@ public:
display.print(dispName);
// Phone number below name (smaller, dimmer)
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(4, 36);
display.print(_callPhone);
@@ -1090,7 +1093,7 @@ public:
display.print(timeBuf);
// Volume (left-aligned)
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
char volLabel[12];
snprintf(volLabel, sizeof(volLabel), "Vol: %d/5", _callVolume);
File diff suppressed because it is too large Load Diff
@@ -6,6 +6,7 @@
#include <vector>
#include "Utf8CP437.h"
#include "EpubProcessor.h"
#include "../NodePrefs.h"
// Forward declarations
class UITask;
@@ -15,7 +16,7 @@ class UITask;
// ============================================================================
#define BOOKS_FOLDER "/books"
#define INDEX_FOLDER "/.indexes"
#define INDEX_VERSION 12 // v12: indexer breaks page BEFORE overflowing line (matches renderer pre-check)
#define INDEX_VERSION 13 // v13: font key in header — auto-invalidate on font/style change
#define PREINDEX_PAGES 100
#define READER_MAX_FILES 50
#define READER_BUF_SIZE 4096
@@ -105,8 +106,6 @@ inline WrapResult findLineBreak(const char* buffer, int bufLen, int lineStart, i
// width variation in proportional fonts like FreeSans12pt.
// maxChars is a safety upper bound to prevent runaway on spaceless lines.
// ============================================================================
#if defined(LilyGo_T5S3_EPaper_Pro)
#include <helpers/ui/DisplayDriver.h>
inline WrapResult findLineBreakPixel(const char* buffer, int bufLen, int lineStart,
DisplayDriver* display, int maxChars) {
@@ -234,7 +233,6 @@ inline WrapResult findLineBreakPixel(const char* buffer, int bufLen, int lineSta
result.nextStart = bufLen;
return result;
}
#endif // LilyGo_T5S3_EPaper_Pro
// ============================================================================
// Page Indexer (word-wrap aware, matches display rendering)
@@ -246,7 +244,8 @@ inline int indexPagesWordWrap(File& file, long startPos,
std::vector<long>& pagePositions,
int linesPerPage, int charsPerLine,
int maxPages,
int textAreaHeight = 0, int lineHeight = 0) {
int textAreaHeight = 0, int lineHeight = 0,
DisplayDriver* pixelDisplay = nullptr) {
const int BUF_SIZE = READER_BUF_SIZE; // Match page buffer to avoid chunk boundary wrap mismatches
char buffer[BUF_SIZE];
@@ -268,7 +267,10 @@ inline int indexPagesWordWrap(File& file, long startPos,
int pos = 0;
while (pos < bufLen) {
int lineStart = pos;
WrapResult wrap = findLineBreak(buffer, bufLen, pos, charsPerLine);
// Pixel-based wrapping for proportional fonts; char-count for monospaced
WrapResult wrap = pixelDisplay
? findLineBreakPixel(buffer, bufLen, pos, pixelDisplay, charsPerLine)
: findLineBreak(buffer, bufLen, pos, charsPerLine);
if (wrap.nextStart <= pos && wrap.lineEnd >= bufLen) break;
// Blank line = newline at line start (no printable content before it)
@@ -321,18 +323,18 @@ inline int indexPagesWordWrap(File& file, long startPos,
}
// ============================================================================
// Pixel-based Page Indexer for T5S3 (proportional font word wrap)
// Pixel-based Page Indexer (proportional font word wrap)
// ============================================================================
#if defined(LilyGo_T5S3_EPaper_Pro)
inline int indexPagesWordWrapPixel(File& file, long startPos,
std::vector<long>& pagePositions,
int linesPerPage, int maxChars,
DisplayDriver* display, int maxPages) {
DisplayDriver* display, int maxPages,
NodePrefs* prefs = nullptr) {
const int BUF_SIZE = READER_BUF_SIZE; // Match page buffer to avoid chunk boundary wrap mismatches
char buffer[BUF_SIZE];
// Ensure body font is active for pixel measurement
display->setTextSize(0);
display->setTextSize(prefs ? prefs->smallTextSize() : 0);
file.seek(startPos);
int pagesAdded = 0;
@@ -375,7 +377,6 @@ inline int indexPagesWordWrapPixel(File& file, long startPos,
display->setTextSize(1); // Restore
return pagesAdded;
}
#endif // LilyGo_T5S3_EPaper_Pro
// ============================================================================
// TextReaderScreen
@@ -396,9 +397,12 @@ public:
private:
UITask* _task;
NodePrefs* _prefs;
Mode _mode;
bool _sdReady;
bool _initialized; // Layout metrics calculated
uint8_t _lastFontPref; // Font preference at last layout init (large_font | fontStyle<<4)
uint8_t _fontKey; // Current font key stored in .idx files for cache invalidation
bool _bootIndexed; // Boot-time pre-indexing done
DisplayDriver* _display; // Stored reference for splash screens
@@ -623,6 +627,15 @@ private:
return false;
}
// Font key: page boundaries depend on font metrics — discard if font changed
uint8_t savedFontKey = 0;
idxFile.read(&savedFontKey, 1);
if (savedFontKey != _fontKey) {
idxFile.close();
SD.remove(idxPath.c_str());
return false;
}
idxFile.read((uint8_t*)&savedSize, 4);
idxFile.read((uint8_t*)&pageCount, 4);
idxFile.read(&fullyFlag, 1);
@@ -677,6 +690,7 @@ private:
uint8_t fullyFlag = fullyIndexed ? 1 : 0;
idxFile.write(&version, 1);
idxFile.write(&_fontKey, 1); // Font key for cache invalidation
idxFile.write((uint8_t*)&fileSize, 4);
idxFile.write((uint8_t*)&pageCount, 4);
idxFile.write(&fullyFlag, 1);
@@ -710,8 +724,8 @@ private:
return false;
}
// Seek to lastReadPage field: version(1) + fileSize(4) + pageCount(4) + fullyIndexed(1)
idxFile.seek(1 + 4 + 4 + 1);
// Seek to lastReadPage field: version(1) + fontKey(1) + fileSize(4) + pageCount(4) + fullyIndexed(1)
idxFile.seek(1 + 1 + 4 + 4 + 1);
idxFile.write((uint8_t*)&page, 4);
idxFile.close();
return true;
@@ -931,17 +945,19 @@ private:
}
drawSplash("Indexing...", "Please wait", shortName);
DisplayDriver* pxd = (_prefs->large_font || _prefs->ui_font_style > 0) ? _display : nullptr;
if (pxd) pxd->setTextSize(_prefs->smallTextSize());
if (_pagePositions.empty()) {
// Cache had no pages (e.g. dummy entry) — full index from scratch
_pagePositions.push_back(0);
indexPagesWordWrap(_file, 0, _pagePositions,
_linesPerPage, _charsPerLine, 0,
_textAreaHeight, _lineHeight);
_textAreaHeight, _lineHeight, pxd);
} else {
long lastPos = cache->pagePositions.back();
indexPagesWordWrap(_file, lastPos, _pagePositions,
_linesPerPage, _charsPerLine, 0,
_textAreaHeight, _lineHeight);
_textAreaHeight, _lineHeight, pxd);
}
} else {
// No cache — full index from scratch
@@ -959,9 +975,11 @@ private:
drawSplash("Indexing...", "Please wait", shortName);
_pagePositions.push_back(0);
DisplayDriver* pxd = (_prefs->large_font || _prefs->ui_font_style > 0) ? _display : nullptr;
if (pxd) pxd->setTextSize(_prefs->smallTextSize());
indexPagesWordWrap(_file, 0, _pagePositions,
_linesPerPage, _charsPerLine, 0,
_textAreaHeight, _lineHeight);
_textAreaHeight, _lineHeight, pxd);
}
// Save complete index
@@ -1084,8 +1102,8 @@ private:
display.setCursor(0, 42);
display.print("/books/ on SD card");
} else {
display.setTextSize(0); // Tiny font for file list
int listLineH = 8; // Approximate tiny font line height in virtual coords
display.setTextSize(_prefs->smallTextSize()); // Tiny font for file list
int listLineH = _prefs->smallLineH();
int startY = 14;
int maxVisible = (display.height() - startY - _footerHeight) / listLineH;
if (maxVisible < 3) maxVisible = 3;
@@ -1105,8 +1123,10 @@ private:
display.fillRect(0, y, display.width(), listLineH);
#else
// setCursor adds +5 to y internally, but fillRect does not.
// Offset fillRect by +5 to align highlight bar with text.
display.fillRect(0, y + 5, display.width(), listLineH);
// Built-in font: offset by +5 to align with top-left positioned text.
// GFX fonts (large_font or custom style): offset by -2 to cover ascenders above baseline.
int hlOff = (!_prefs->large_font && display.getFontStyle() > 0) ? -2 : _prefs->smallHighlightOff();
display.fillRect(0, y + hlOff, display.width(), listLineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -1114,8 +1134,6 @@ private:
}
// Set cursor AFTER fillRect so text draws on top of highlight
display.setCursor(0, y);
int type = itemTypeAt(i);
String line = selected ? "> " : " ";
@@ -1125,10 +1143,6 @@ private:
} else if (type == 1) {
// Subdirectory
line += "/" + dirNameAt(i);
// Truncate if needed
if ((int)line.length() > _charsPerLine) {
line = line.substring(0, _charsPerLine - 3) + "...";
}
} else {
// File
int fi = fileIndexAt(i);
@@ -1141,16 +1155,11 @@ private:
suffix = " *";
}
}
// Truncate if needed
int maxLen = _charsPerLine - 4 - suffix.length();
if ((int)name.length() > maxLen) {
name = name.substring(0, maxLen - 3) + "...";
}
line += name + suffix;
}
display.print(line.c_str());
// Pixel-aware ellipsis — small margin prevents GxEPD edge wrapping
display.drawTextEllipsized(0, y, display.width() - 4, line.c_str());
y += listLineH;
}
display.setTextSize(1); // Restore
@@ -1163,7 +1172,7 @@ private:
display.setColor(DisplayDriver::YELLOW);
#if defined(LilyGo_T5S3_EPaper_Pro)
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.drawTextCentered(display.width() / 2, footerY, "Swipe: Scroll Tap: Open Boot: home");
#else
display.setCursor(0, footerY);
@@ -1177,24 +1186,35 @@ private:
void renderPage(DisplayDriver& display) {
// Use tiny font for maximum text density
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
int y = 0;
int lineCount = 0;
int pos = 0;
int maxY = display.height() - _footerHeight - _lineHeight;
int textArea = display.height() - _footerHeight; // total usable height (matches indexer's textAreaHeight)
// Render all lines in the page buffer using word wrap.
// The buffer contains exactly the bytes for this page (from indexed positions),
// so we render everything in it.
while (pos < _pageBufLen && y <= maxY) {
// Proportional fonts use pixel-based wrapping to match the indexer exactly.
bool usePixelWrap = (_prefs->large_font || display.getFontStyle() > 0);
while (pos < _pageBufLen) {
int oldPos = pos;
WrapResult wrap = findLineBreak(_pageBuf, _pageBufLen, pos, _charsPerLine);
WrapResult wrap = usePixelWrap
? findLineBreakPixel(_pageBuf, _pageBufLen, pos, &display, _charsPerLine)
: findLineBreak(_pageBuf, _pageBufLen, pos, _charsPerLine);
// Safety: stop if findLineBreak made no progress (stuck at end of buffer)
// Safety: stop if wrap made no progress (stuck at end of buffer)
if (wrap.nextStart <= oldPos && wrap.lineEnd >= _pageBufLen) break;
// Height-aware stop check — must match the indexer exactly.
// Blank lines (lineEnd == lineStart) get reduced height.
// Check BEFORE rendering: does this line fit on the current page?
bool isBlankLine = (wrap.lineEnd == pos);
int thisH = isBlankLine ? max(2, _lineHeight * 2 / 5) : _lineHeight;
if (y > 0 && y + thisH > textArea) break;
display.setCursor(0, y);
// Print line with UTF-8 decoding: multi-byte sequences are decoded
// to Unicode codepoints, then mapped to CP437 for the built-in font.
@@ -1270,7 +1290,7 @@ private:
}
#if defined(LilyGo_T5S3_EPaper_Pro)
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setCursor(0, footerY);
display.print(status);
const char* right = "Swipe:Page Tap:GoTo Hold:Close";
@@ -1287,8 +1307,8 @@ private:
}
public:
TextReaderScreen(UITask* task)
: _task(task), _mode(FILE_LIST), _sdReady(false), _initialized(false),
TextReaderScreen(UITask* task, NodePrefs* prefs = nullptr)
: _task(task), _prefs(prefs), _mode(FILE_LIST), _sdReady(false), _initialized(false), _lastFontPref(0), _fontKey(0),
_bootIndexed(false), _display(nullptr),
_charsPerLine(38), _linesPerPage(22), _lineHeight(5),
_textAreaHeight(100), _headerHeight(14), _footerHeight(14),
@@ -1313,16 +1333,26 @@ public:
// Call once after display is available to calculate layout metrics
void initLayout(DisplayDriver& display) {
// Re-init if font preference OR font style changed since last layout
uint8_t curFont = _prefs ? (_prefs->large_font | (display.getFontStyle() << 4)) : 0;
if (_initialized && curFont != _lastFontPref) {
_initialized = false;
_fileCache.clear(); // Page positions are font-dependent — force re-index
Serial.println("TextReader: font changed, recalculating layout");
}
if (_initialized) return;
_lastFontPref = curFont;
_fontKey = curFont; // Stored in .idx files for SD cache invalidation
// Store display reference for splash screens during openBook
_display = &display;
// Measure tiny font metrics using the display driver
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
// Measure character width: use 10 M's for monospace (T-Deck Pro).
// T5S3 overrides this below with average-width measurement.
// Measure character width: use 10 M's for monospace (T-Deck Pro tiny font).
// Proportional fonts (T5S3 and T-Deck Pro large_font) override below with
// average-width measurement since M is the widest glyph (~40% wider than average).
uint16_t tenCharsW = display.getTextWidth("MMMMMMMMMM");
if (tenCharsW > 0) {
_charsPerLine = (display.width() * 10) / tenCharsW;
@@ -1343,6 +1373,18 @@ public:
if (_charsPerLine < 15) _charsPerLine = 15;
if (_charsPerLine > 80) _charsPerLine = 80;
#else
// T-Deck Pro: proportional font — measure average character width from
// a sample sentence (M is widest glyph, ~40% wider than average).
// Large font (9pt) uses 70% safety margin; custom tiny (7pt) uses 85%.
if (_prefs && (_prefs->large_font || display.getFontStyle() > 0)) {
const char* sample = "the quick brown fox jumps over lazy dog";
uint16_t sampleW = display.getTextWidth(sample);
int sampleLen = strlen(sample);
if (sampleW > 0 && sampleLen > 0) {
int pct = _prefs->large_font ? 70 : 85;
_charsPerLine = (display.width() * sampleLen * pct) / ((int)sampleW * 100);
}
}
if (_charsPerLine < 15) _charsPerLine = 15;
if (_charsPerLine > 60) _charsPerLine = 60;
#endif
@@ -1362,13 +1404,20 @@ public:
#if defined(LilyGo_T5S3_EPaper_Pro)
// T5S3 uses FreeSans12pt/FreeSerif12pt for size 0 (yAdvance=29px).
// Line height in virtual coords depends on orientation:
// Landscape: 29px / scale_y(4.22) ≈ 7 + 1 spacing = 8
// Portrait: 29px / scale_y(7.50) ≈ 4 + 1 spacing = 5
{
extern DISPLAY_CLASS display;
_lineHeight = display.isPortraitMode() ? 5 : 8;
}
#else
// T-Deck Pro large_font uses FreeSans9pt (yAdvance=22px at scale 1.5625×).
// Custom proportional fonts (Noto Sans, Montserrat) at size 0 also need
// a tuned line height — the 6x8 formula above uses a width:height ratio
// that doesn't apply to GFX fonts, causing overlap or excessive spacing.
if (_prefs && _prefs->large_font) {
_lineHeight = _prefs->smallLineH(); // 11 — tested for FreeSans9pt
} else if (display.getFontStyle() > 0) {
_lineHeight = 7; // Custom 7pt fonts: 7 * 2.5 = 17.5px — fits ~16 lines/page
}
#endif
_headerHeight = 0; // No header in reading mode (maximize text area)
@@ -1389,6 +1438,109 @@ public:
// Called from setup() after SD card init. Scans files, pre-indexes first
// 100 pages of each, and shows progress on the e-ink display.
// Pre-index files inside one level of subdirectories so navigating
// into them later is instant (idx files already on SD).
void bootIndexSubfolders() {
// Work from the root-level _dirList that scanFiles() already populated.
// Copy it -- scanFiles() will overwrite _dirList when we scan each subfolder.
std::vector<String> subDirs = _dirList;
if (subDirs.empty()) return;
Serial.printf("TextReader: Pre-indexing %d subfolders\n", (int)subDirs.size());
int totalSubFiles = 0;
int cachedSubFiles = 0;
int indexedSubFiles = 0;
for (int d = 0; d < (int)subDirs.size(); d++) {
String subPath = String(BOOKS_FOLDER) + "/" + subDirs[d];
_currentPath = subPath;
scanFiles(); // populates _fileList for this subfolder
// Also pick up previously converted EPUB cache files for this subfolder
String epubCachePath = subPath + "/.epub_cache";
if (SD.exists(epubCachePath.c_str())) {
File cacheDir = SD.open(epubCachePath.c_str());
if (cacheDir && cacheDir.isDirectory()) {
File cf = cacheDir.openNextFile();
while (cf && _fileList.size() < READER_MAX_FILES) {
if (!cf.isDirectory()) {
String cname = String(cf.name());
int cslash = cname.lastIndexOf('/');
if (cslash >= 0) cname = cname.substring(cslash + 1);
if (cname.endsWith(".txt") || cname.endsWith(".TXT")) {
bool dup = false;
for (int k = 0; k < (int)_fileList.size(); k++) {
if (_fileList[k] == cname) { dup = true; break; }
}
if (!dup) _fileList.push_back(cname);
}
}
cf = cacheDir.openNextFile();
}
cacheDir.close();
}
}
for (int i = 0; i < (int)_fileList.size(); i++) {
totalSubFiles++;
// Try loading existing .idx cache -- if hit, skip
FileCache tempCache;
if (loadIndex(_fileList[i], tempCache)) {
cachedSubFiles++;
continue;
}
// Skip .epub files (converted on first open)
if (_fileList[i].endsWith(".epub") || _fileList[i].endsWith(".EPUB")) continue;
// Index this .txt file
String fullPath = _currentPath + "/" + _fileList[i];
File file = SD.open(fullPath.c_str(), FILE_READ);
if (!file) {
// Try epub cache fallback
String cacheFallback = epubCachePath + "/" + _fileList[i];
file = SD.open(cacheFallback.c_str(), FILE_READ);
}
if (!file) continue;
indexedSubFiles++;
String displayName = subDirs[d] + "/" + _fileList[i];
drawBootSplash(indexedSubFiles, 0, displayName);
FileCache cache;
cache.filename = _fileList[i];
cache.fileSize = file.size();
cache.fullyIndexed = false;
cache.lastReadPage = 0;
cache.pagePositions.clear();
cache.pagePositions.push_back(0);
DisplayDriver* pxd = (_prefs->large_font || _prefs->ui_font_style > 0) ? _display : nullptr;
if (pxd) pxd->setTextSize(_prefs->smallTextSize());
indexPagesWordWrap(file, 0, cache.pagePositions,
_linesPerPage, _charsPerLine,
PREINDEX_PAGES - 1,
_textAreaHeight, _lineHeight, pxd);
cache.fullyIndexed = !file.available();
file.close();
saveIndex(cache.filename, cache.pagePositions, cache.fileSize,
cache.fullyIndexed, 0);
Serial.printf("TextReader: %s/%s - indexed %d pages%s\n",
subDirs[d].c_str(), _fileList[i].c_str(),
(int)cache.pagePositions.size(),
cache.fullyIndexed ? " (complete)" : "");
yield(); // Feed WDT between files
}
}
Serial.printf("TextReader: Subfolder pre-index: %d files (%d cached, %d newly indexed)\n",
totalSubFiles, cachedSubFiles, indexedSubFiles);
}
void bootIndex(DisplayDriver& display) {
if (!_sdReady) return;
@@ -1430,20 +1582,24 @@ public:
}
}
if (_fileList.size() == 0) {
Serial.println("TextReader: No files to index");
if (_fileList.size() == 0 && _dirList.size() == 0) {
Serial.println("TextReader: No files or folders to index");
_bootIndexed = true;
return;
}
int cachedCount = 0;
int needsIndexCount = 0;
// --- Pass 1 & 2: Index root-level files ---
if (_fileList.size() > 0) {
// --- Pass 1: Fast cache load (no per-file splash screens) ---
// Try to load existing .idx files from SD for every file.
// This is just SD reads — no indexing, no e-ink refreshes.
_fileCache.clear();
_fileCache.resize(_fileList.size()); // Pre-allocate slots to maintain alignment with _fileList
int cachedCount = 0;
int needsIndexCount = 0;
for (int i = 0; i < (int)_fileList.size(); i++) {
if (loadIndex(_fileList[i], _fileCache[i])) {
@@ -1493,10 +1649,12 @@ public:
cache.pagePositions.clear();
cache.pagePositions.push_back(0);
DisplayDriver* pxd = (_prefs->large_font || _prefs->ui_font_style > 0) ? _display : nullptr;
if (pxd) pxd->setTextSize(_prefs->smallTextSize());
int added = indexPagesWordWrap(file, 0, cache.pagePositions,
_linesPerPage, _charsPerLine,
PREINDEX_PAGES - 1,
_textAreaHeight, _lineHeight);
_textAreaHeight, _lineHeight, pxd);
cache.fullyIndexed = !file.available();
file.close();
@@ -1509,6 +1667,26 @@ public:
}
}
} // end if (_fileList.size() > 0)
// --- Pass 3: Pre-index files inside subfolders (one level deep) ---
// Save root state -- bootIndexSubfolders() will overwrite _fileList/_dirList
// via scanFiles() as it iterates each subdirectory.
if (_dirList.size() > 0) {
std::vector<String> savedFileList = _fileList;
std::vector<String> savedDirList = _dirList;
std::vector<FileCache> savedFileCache = _fileCache;
bootIndexSubfolders();
// Restore root state
_currentPath = String(BOOKS_FOLDER);
_fileList = savedFileList;
_dirList = savedDirList;
_fileCache = savedFileCache;
}
// Deselect SD to free SPI bus
digitalWrite(SDCARD_CS, HIGH);
@@ -1539,9 +1717,11 @@ public:
// Layout was invalidated (orientation change) — reindex the open book
Serial.println("TextReader: Reindexing after layout change");
_pagePositions.push_back(0);
DisplayDriver* pxd = (_prefs->large_font || _prefs->ui_font_style > 0) ? _display : nullptr;
if (pxd) pxd->setTextSize(_prefs->smallTextSize());
indexPagesWordWrap(_file, 0, _pagePositions,
_linesPerPage, _charsPerLine, 0,
_textAreaHeight, _lineHeight);
_textAreaHeight, _lineHeight, pxd);
_totalPages = _pagePositions.size();
if (_currentPage >= _totalPages) _currentPage = 0;
_mode = READING;
@@ -1574,11 +1754,12 @@ public:
// Returns: 0=miss, 1=moved, 2=tapped current row.
int selectRowAtVY(int vy) {
if (_mode != FILE_LIST) return 0;
const int startY = 14, footerH = 14, listLineH = 8;
const int startY = 14, footerH = 14;
const int listLineH = _prefs ? _prefs->smallLineH() : 9;
#if defined(LilyGo_T5S3_EPaper_Pro)
const int bodyTop = startY;
#else
const int bodyTop = startY + 5; // GxEPD baseline offset
const int bodyTop = startY + ((_prefs && !_prefs->large_font && _prefs->ui_font_style > 0) ? -2 : (_prefs ? _prefs->smallHighlightOff() : 5));
#endif
if (vy < bodyTop || vy >= 128 - footerH) return 0;
@@ -1709,10 +1890,12 @@ public:
cache.lastReadPage = 0;
cache.pagePositions.clear();
cache.pagePositions.push_back(0);
DisplayDriver* pxd = (_prefs->large_font || _prefs->ui_font_style > 0) ? _display : nullptr;
if (pxd) pxd->setTextSize(_prefs->smallTextSize());
indexPagesWordWrap(file, 0, cache.pagePositions,
_linesPerPage, _charsPerLine,
PREINDEX_PAGES - 1,
_textAreaHeight, _lineHeight);
_textAreaHeight, _lineHeight, pxd);
cache.fullyIndexed = !file.available();
file.close();
saveIndex(cache.filename, cache.pagePositions, cache.fileSize,
+441 -82
View File
@@ -3,6 +3,7 @@
#include "../MyMesh.h"
#include "NotesScreen.h"
#include "RepeaterAdminScreen.h"
#include "PathEditorScreen.h"
#include "DiscoveryScreen.h"
#include "LastHeardScreen.h"
#ifdef MECK_WEB_READER
@@ -12,12 +13,15 @@
#include "MapScreen.h"
#endif
#include "target.h"
#if defined(LilyGo_T5S3_EPaper_Pro)
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(MECK_AUDIO_VARIANT)
#include "HomeIcons.h"
#endif
#if defined(WIFI_SSID) || defined(MECK_WIFI_COMPANION)
#include <WiFi.h>
#endif
#if defined(LilyGo_T5S3_EPaper_Pro) && !defined(BLE_PIN_CODE) && !defined(MECK_WIFI_COMPANION)
#include "esp_sleep.h"
#endif
#ifndef AUTO_OFF_MILLIS
#define AUTO_OFF_MILLIS 15000 // 15 seconds
@@ -50,11 +54,13 @@
#include "icons.h"
#include "ChannelScreen.h"
#include "ChannelPickerScreen.h"
#include "ContactsScreen.h"
#include "TextReaderScreen.h"
#include "SettingsScreen.h"
#ifdef MECK_AUDIO_VARIANT
#include "AudiobookPlayerScreen.h"
#include "VoiceMessageScreen.h"
#endif
#ifdef HAS_4G_MODEM
#include "SMSScreen.h"
@@ -156,7 +162,7 @@ void renderBatteryIndicator(DisplayDriver& display, uint16_t batteryMilliVolts,
}
display.setColor(DisplayDriver::GREEN);
display.setTextSize(0);
display.setTextSize(_node_prefs->smallTextSize());
#if defined(LilyGo_T5S3_EPaper_Pro)
// T5S3: text-only battery indicator — "Batt 99% 4.1v"
@@ -170,7 +176,7 @@ void renderBatteryIndicator(DisplayDriver& display, uint16_t batteryMilliVolts,
display.print(battStr);
display.setTextSize(1); // restore default text size
#else
// T-Deck Pro: icon + percentage text
// T-Deck Pro: icon + percentage text (icon hidden in large font)
int iconWidth = 16;
int iconHeight = 6;
int iconY = 0;
@@ -181,26 +187,35 @@ void renderBatteryIndicator(DisplayDriver& display, uint16_t batteryMilliVolts,
sprintf(pctStr, "%d%%", batteryPercentage);
uint16_t textWidth = display.getTextWidth(pctStr);
// layout: [icon][cap 2px][gap 2px][text][margin 2px]
int totalWidth = iconWidth + 2 + 2 + textWidth + 2;
int iconX = display.width() - totalWidth;
if (_node_prefs->large_font || display.getFontStyle() > 0) {
// Large font or custom proportional font: text only — icon doesn't align
int textX = display.width() - textWidth - 2;
if (outIconX) *outIconX = textX;
display.setCursor(textX, textY);
display.print(pctStr);
} else {
// Classic tiny font (monospaced): icon + text
// layout: [icon][cap 2px][gap 2px][text][margin 2px]
int totalWidth = iconWidth + 2 + 2 + textWidth + 2;
int iconX = display.width() - totalWidth;
if (outIconX) *outIconX = iconX;
if (outIconX) *outIconX = iconX;
// battery outline
display.drawRect(iconX, iconY, iconWidth, iconHeight);
// battery outline
display.drawRect(iconX, iconY, iconWidth, iconHeight);
// battery "cap"
display.fillRect(iconX + iconWidth, iconY + (iconHeight / 4), 2, iconHeight / 2);
// battery "cap"
display.fillRect(iconX + iconWidth, iconY + (iconHeight / 4), 2, iconHeight / 2);
// fill the battery based on the percentage
int fillWidth = (batteryPercentage * (iconWidth - 4)) / 100;
display.fillRect(iconX + 2, iconY + 2, fillWidth, iconHeight - 4);
// fill the battery based on the percentage
int fillWidth = (batteryPercentage * (iconWidth - 4)) / 100;
display.fillRect(iconX + 2, iconY + 2, fillWidth, iconHeight - 4);
// draw percentage text after the battery cap
int textX = iconX + iconWidth + 2 + 2; // after cap + gap
display.setCursor(textX, textY);
display.print(pctStr);
// draw percentage text after the battery cap
int textX = iconX + iconWidth + 2 + 2; // after cap + gap
display.setCursor(textX, textY);
display.print(pctStr);
}
display.setTextSize(1); // restore default text size
#endif
}
@@ -215,12 +230,31 @@ void renderBatteryIndicator(DisplayDriver& display, uint16_t batteryMilliVolts,
if (!_task->isAudioPlayingInBackground()) return;
display.setColor(DisplayDriver::GREEN);
display.setTextSize(0); // tiny font (same as clock & battery %)
display.setTextSize(_node_prefs->smallTextSize()); // tiny font (same as clock & battery %)
int x = batteryLeftX - display.getTextWidth(">>") - 2;
display.setCursor(x, -3); // align vertically with battery text
display.print(">>");
display.setTextSize(1); // restore
}
// ---- Alarm enabled indicator ----
// Shows a small bell icon to the left of the audio indicator
// (or battery icon if no audio playing) when any alarm is enabled.
void renderAlarmIndicator(DisplayDriver& display, int batteryLeftX) {
AlarmScreen* alarmScr = (AlarmScreen*)_task->getAlarmScreen();
if (!alarmScr || alarmScr->enabledCount() == 0) return;
// Calculate X: shift left past audio indicator if it's showing
int rightEdge = batteryLeftX;
if (_task->isAudioPlayingInBackground()) {
display.setTextSize(_node_prefs->smallTextSize());
rightEdge = rightEdge - display.getTextWidth(">>") - 2;
}
display.setColor(DisplayDriver::GREEN);
int x = rightEdge - BELL_ICON_W - 2;
display.drawXbm(x, 1, icon_bell_small, BELL_ICON_W, BELL_ICON_H);
}
#endif
CayenneLPP sensors_lpp;
@@ -276,7 +310,7 @@ public:
_task->setHomeShowingTiles(false); // Reset — only set true on FIRST page
#endif
// node name (tinyfont to avoid overlapping clock)
display.setTextSize(0);
display.setTextSize(_node_prefs->smallTextSize());
display.setColor(DisplayDriver::GREEN);
char filtered_name[sizeof(_node_prefs->node_name)];
display.translateUTF8ToBlocks(filtered_name, _node_prefs->node_name, sizeof(filtered_name));
@@ -290,18 +324,21 @@ public:
display.setCursor(0, HOME_HDR_Y);
display.print(filtered_name);
// battery voltage
// battery voltage + status icons
#ifdef MECK_AUDIO_VARIANT
int battLeftX = display.width(); // default if battery doesn't render
renderBatteryIndicator(display, _task->getBattMilliVolts(), &battLeftX);
// audio background playback indicator (>> icon next to battery)
renderAudioIndicator(display, battLeftX);
// alarm enabled indicator (AL icon, left of audio or battery)
renderAlarmIndicator(display, battLeftX);
#else
renderBatteryIndicator(display, _task->getBattMilliVolts());
#endif
// centered clock (tinyfont) - only show when time is valid
// centered clock only show when time is valid
{
uint32_t now = _rtc->getCurrentTime();
if (now > 1700000000) { // valid timestamp (after ~Nov 2023)
@@ -315,11 +352,14 @@ public:
char timeBuf[6];
sprintf(timeBuf, "%02d:%02d", hrs, mins);
display.setTextSize(0); // tinyfont
display.setTextSize(_node_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
uint16_t tw = display.getTextWidth(timeBuf);
int clockX = (display.width() - tw) / 2;
display.setCursor(clockX, HOME_HDR_Y); // align with node name Y
// Ensure clock doesn't overlap the node name
int nameRight = display.getTextWidth(filtered_name) + 4;
if (clockX < nameRight) clockX = nameRight;
display.setCursor(clockX, HOME_HDR_Y);
display.print(timeBuf);
display.setTextSize(1); // restore
}
@@ -362,17 +402,17 @@ public:
IPAddress ip = WiFi.localIP();
if (ip != IPAddress(0,0,0,0)) {
snprintf(tmp, sizeof(tmp), "IP: %d.%d.%d.%d:%d", ip[0], ip[1], ip[2], ip[3], TCP_PORT);
display.setTextSize(0); // Tiny font for IP
display.setTextSize(_node_prefs->smallTextSize()); // Tiny font for IP
display.drawTextCentered(display.width() / 2, y, tmp);
y += 8;
y += _node_prefs->smallLineH() - 1;
}
#endif
#if defined(BLE_PIN_CODE) || defined(WIFI_SSID) || defined(MECK_WIFI_COMPANION)
if (_task->hasConnection()) {
display.setColor(DisplayDriver::GREEN);
display.setTextSize(0); // Tiny font for Connected
display.setTextSize(_node_prefs->smallTextSize()); // Tiny font for Connected
display.drawTextCentered(display.width() / 2, y, "< Connected >");
y += 8; // Reduced from 12
y += _node_prefs->smallLineH() - 1;
#ifdef BLE_PIN_CODE
} else if (_task->isSerialEnabled() && the_mesh.getBLEPin() != 0) {
display.setColor(DisplayDriver::RED);
@@ -423,7 +463,7 @@ public:
display.drawXbm(iconX, iconY, tiles[row][col].icon, HOME_ICON_W, HOME_ICON_H);
// Label centered below icon
display.setTextSize(0);
display.setTextSize(_node_prefs->smallTextSize());
display.drawTextCentered(tx + tileW / 2, ty + 18, tiles[row][col].label);
}
}
@@ -431,47 +471,108 @@ public:
// Nav hint below grid
y = gridY + 2 * tileH + gapY + 2;
display.setColor(DisplayDriver::GREEN);
display.setTextSize(0);
display.setTextSize(_node_prefs->smallTextSize());
display.drawTextCentered(display.width() / 2, y, "Tap tile to open");
}
display.setTextSize(1);
#else
// ----- T-Deck Pro: Keyboard shortcut text menu -----
// Menu shortcuts - tinyfont monospaced grid
y += 6;
display.setColor(DisplayDriver::LIGHT);
display.setTextSize(0); // tinyfont 6x8 monospaced
display.drawTextCentered(display.width() / 2, y, "Press:");
y += 12;
display.drawTextCentered(display.width() / 2, y, "[M] Messages [C] Contacts ");
y += 10;
display.drawTextCentered(display.width() / 2, y, "[N] Notes [S] Settings ");
y += 10;
#if HAS_GPS
display.drawTextCentered(display.width() / 2, y, "[E] Reader [G] Maps ");
#else
display.drawTextCentered(display.width() / 2, y, "[E] Reader ");
#endif
y += 10;
#if defined(HAS_4G_MODEM) && defined(MECK_WEB_READER)
display.drawTextCentered(display.width() / 2, y, "[T] Phone [B] Browser ");
#elif defined(HAS_4G_MODEM)
display.drawTextCentered(display.width() / 2, y, "[T] Phone ");
#elif defined(MECK_AUDIO_VARIANT) && defined(MECK_WEB_READER)
display.drawTextCentered(display.width() / 2, y, "[P] Audiobooks [B] Browser ");
#elif defined(MECK_AUDIO_VARIANT)
display.drawTextCentered(display.width() / 2, y, "[P] Audiobooks ");
#elif defined(MECK_WEB_READER)
display.drawTextCentered(display.width() / 2, y, "[B] Browser ");
#else
y -= 10; // reclaim the row for standalone
#endif
y += 14;
display.setTextSize(_node_prefs->smallTextSize());
int menuLH = _node_prefs->smallLineH();
// Nav hint
display.setColor(DisplayDriver::GREEN);
display.drawTextCentered(display.width() / 2, y, "Press A/D to cycle home views");
if (_node_prefs->large_font || display.getFontStyle() > 0) {
// Proportional font: two-column layout with fixed X positions
y += 2;
int col1, col2;
if (_node_prefs->large_font) {
// 9pt font: measure widest left entry and place col2 just past it
col1 = 2;
int leftW = display.getTextWidth("[M] Messages");
col2 = col1 + leftW + 3;
} else {
// Custom tiny (7pt): centered layout
col1 = display.width() / 10;
col2 = display.width() * 11 / 20;
}
display.setCursor(col1, y); display.print("[M] Messages");
display.setCursor(col2, y); display.print("[C] Contacts");
y += menuLH;
display.setCursor(col1, y); display.print("[N] Notes");
display.setCursor(col2, y); display.print("[S] Settings");
y += menuLH;
#if HAS_GPS
display.setCursor(col1, y); display.print("[E] Reader");
display.setCursor(col2, y); display.print("[G] Maps");
#else
display.setCursor(col1, y); display.print("[E] Reader");
#endif
y += menuLH;
#if defined(HAS_4G_MODEM) && defined(MECK_WEB_READER)
display.setCursor(col1, y); display.print("[T] Phone");
display.setCursor(col2, y); display.print("[B] Browser");
#elif defined(HAS_4G_MODEM)
display.setCursor(col1, y); display.print("[T] Phone");
display.setCursor(col2, y); display.print("[F] Discover");
#elif defined(MECK_AUDIO_VARIANT)
display.setCursor(col1, y); display.print("[P] Audio");
display.setCursor(col2, y); display.print("[K] Alarm");
y += menuLH;
#ifdef MECK_WEB_READER
display.setCursor(col1, y); display.print("[B] Browser");
display.setCursor(col2, y); display.print("[F] Discover");
#else
display.setCursor(col1, y); display.print("[F] Discover");
#endif
#elif defined(MECK_WEB_READER)
display.setCursor(col1, y); display.print("[B] Browser");
#else
display.setCursor(col1, y); display.print("[F] Discover");
#endif
y += menuLH + 2;
} else {
// Monospaced built-in font (Classic): centered space-padded strings
y += 6;
display.drawTextCentered(display.width() / 2, y, "Press:");
y += 12;
display.drawTextCentered(display.width() / 2, y, "[M] Messages [C] Contacts ");
y += 10;
display.drawTextCentered(display.width() / 2, y, "[N] Notes [S] Settings ");
y += 10;
#if HAS_GPS
display.drawTextCentered(display.width() / 2, y, "[E] Reader [G] Maps ");
#else
display.drawTextCentered(display.width() / 2, y, "[E] Reader ");
#endif
y += 10;
#if defined(HAS_4G_MODEM) && defined(MECK_WEB_READER)
display.drawTextCentered(display.width() / 2, y, "[T] Phone [B] Browser ");
#elif defined(HAS_4G_MODEM)
display.drawTextCentered(display.width() / 2, y, "[T] Phone [F] Discover ");
#elif defined(MECK_AUDIO_VARIANT)
display.drawTextCentered(display.width() / 2, y, "[P] Audiobooks [K] Alarm ");
y += 10;
#ifdef MECK_WEB_READER
display.drawTextCentered(display.width() / 2, y, "[B] Browser [F] Discover ");
#else
display.drawTextCentered(display.width() / 2, y, "[F] Discover ");
#endif
#elif defined(MECK_WEB_READER)
display.drawTextCentered(display.width() / 2, y, "[B] Browser ");
#else
display.drawTextCentered(display.width() / 2, y, "[F] Discover ");
#endif
y += 14;
}
// Nav hint (only if room)
if (y < display.height() - 14) {
display.setColor(DisplayDriver::GREEN);
display.drawTextCentered(display.width() / 2, y,
(_node_prefs->large_font || display.getFontStyle() > 0) ? "A/D: cycle views" : "Press A/D to cycle home views");
}
display.setTextSize(1); // restore
#endif
} else if (_page == HomePage::RECENT) {
@@ -501,7 +602,7 @@ public:
}
// Hint for full Last Heard screen
display.setColor(DisplayDriver::LIGHT);
display.setTextSize(0);
display.setTextSize(_node_prefs->smallTextSize());
#if defined(LilyGo_T5S3_EPaper_Pro)
display.drawTextCentered(display.width() / 2, display.height() - 24,
"Tap here for full Last Heard list");
@@ -571,19 +672,20 @@ public:
display.drawTextCentered(display.width() / 2, 18, "WiFi Companion");
int wy = 36;
display.setTextSize(0);
display.setTextSize(_node_prefs->smallTextSize());
int wLH = _node_prefs->smallLineH() + 1;
if (WiFi.status() == WL_CONNECTED) {
display.setColor(DisplayDriver::GREEN);
snprintf(tmp, sizeof(tmp), "SSID: %s", WiFi.SSID().c_str());
display.drawTextCentered(display.width() / 2, wy, tmp);
wy += 10;
wy += wLH;
IPAddress ip = WiFi.localIP();
snprintf(tmp, sizeof(tmp), "IP: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
display.drawTextCentered(display.width() / 2, wy, tmp);
wy += 10;
wy += wLH;
snprintf(tmp, sizeof(tmp), "Port: %d", TCP_PORT);
display.drawTextCentered(display.width() / 2, wy, tmp);
wy += 12;
wy += wLH + 2;
if (_task->hasConnection()) {
display.setColor(DisplayDriver::GREEN);
display.setTextSize(1);
@@ -596,7 +698,7 @@ public:
} else {
display.setColor(DisplayDriver::RED);
display.drawTextCentered(display.width() / 2, wy, "Not connected");
wy += 12;
wy += wLH + 2;
display.setColor(DisplayDriver::LIGHT);
display.drawTextCentered(display.width() / 2, wy, "Configure in Settings");
}
@@ -697,7 +799,7 @@ public:
display.drawTextCentered(display.width() / 2, by + 4, buf);
// Show controls hint
display.setTextSize(0);
display.setTextSize(_node_prefs->smallTextSize());
display.drawTextCentered(display.width() / 2, by + bh - 10, "W/S:adj Enter:ok Q:cancel");
display.setTextSize(1);
}
@@ -1107,12 +1209,10 @@ public:
}
// ---- Unlock hint ----
display.setTextSize(0);
display.setColor(DisplayDriver::LIGHT);
#if defined(LilyGo_T5S3_EPaper_Pro)
display.setTextSize(_node_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.drawTextCentered(display.width() / 2, 120, "Hold button to unlock");
#else
display.drawTextCentered(display.width() / 2, 120, "Dbl-press to unlock");
#endif
return 30000;
@@ -1196,20 +1296,27 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
msg_preview = new MsgPreviewScreen(this, &rtc_clock);
channel_screen = new ChannelScreen(this, &rtc_clock);
((ChannelScreen*)channel_screen)->setDMUnreadPtr(_dmUnread);
channel_picker_screen = new ChannelPickerScreen(this);
((ChannelPickerScreen*)channel_picker_screen)->setChannelScreen((ChannelScreen*)channel_screen);
contacts_screen = new ContactsScreen(this, &rtc_clock);
((ContactsScreen*)contacts_screen)->setDMUnreadPtr(_dmUnread);
text_reader = new TextReaderScreen(this);
notes_screen = new NotesScreen(this);
text_reader = new TextReaderScreen(this, node_prefs);
notes_screen = new NotesScreen(this, node_prefs);
settings_screen = new SettingsScreen(this, &rtc_clock, node_prefs);
repeater_admin = nullptr; // Lazy-initialized on first use to preserve heap for audio
path_editor = nullptr; // Lazy-initialized on first use from contacts screen
discovery_screen = new DiscoveryScreen(this, &rtc_clock);
last_heard_screen = new LastHeardScreen(&rtc_clock);
#if defined(LilyGo_T5S3_EPaper_Pro) || defined(LilyGo_TDeck_Pro)
lock_screen = new LockScreen(this, &rtc_clock, node_prefs);
#endif
audiobook_screen = nullptr; // Created and assigned from main.cpp if audio hardware present
#ifdef MECK_AUDIO_VARIANT
alarm_screen = nullptr; // Created and assigned from main.cpp if audio hardware present
voice_screen = nullptr; // Created and assigned from main.cpp on first mic key press
#endif
#ifdef HAS_4G_MODEM
sms_screen = new SMSScreen(this);
sms_screen = new SMSScreen(this, node_prefs);
#endif
#if HAS_GPS
map_screen = new MapScreen(this);
@@ -1229,6 +1336,11 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no
::display.setDarkMode(true);
}
// Apply saved font style preference (Classic / Noto Sans / Montserrat)
if (_node_prefs->ui_font_style > 0) {
::display.setFontStyle(_node_prefs->ui_font_style);
}
setCurrScreen(splash);
}
@@ -1238,6 +1350,34 @@ void UITask::showAlert(const char* text, int duration_millis) {
_next_refresh = millis() + 100; // trigger re-render to show updated text
}
void UITask::showBootHint(bool immediate) {
if (immediate) {
// Activate now — used when hint should overlay the current screen (e.g. onboarding)
_hintActive = true;
_hintExpiry = millis() + 8000; // 8 seconds auto-dismiss
_pendingBootHint = false;
_next_refresh = millis() + 100;
Serial.println("[UI] Boot hint activated (immediate)");
} else {
// Defer until after splash screen — actual activation happens in gotoHomeScreen()
_pendingBootHint = true;
Serial.println("[UI] Boot hint pending (will show after splash)");
}
}
void UITask::dismissBootHint() {
if (!_hintActive) return;
_hintActive = false;
_hintExpiry = 0;
// Persist so hint never shows again
if (_node_prefs) {
_node_prefs->hint_shown = 1;
the_mesh.savePrefs();
}
_next_refresh = millis() + 100;
Serial.println("[UI] Boot hint dismissed");
}
void UITask::notify(UIEventType t) {
#if defined(PIN_BUZZER)
switch(t){
@@ -1371,6 +1511,10 @@ void UITask::newMsg(uint8_t path_len, const char* from_name, const char* text, i
snprintf(alertBuf, sizeof(alertBuf), "New: %s", from_name);
showAlert(alertBuf, 2000);
}
// Ensure picker badges update after toaster clears
if (isOnChannelPickerScreen()) {
forceRefresh();
}
#else
// Other devices: Show full preview screen (legacy behavior, skip room sync)
if (!isRoomMsg) setCurrScreen(msg_preview);
@@ -1426,6 +1570,7 @@ void UITask::setCurrScreen(UIScreen* c) {
curr = c;
_alert_expiry = 0; // Dismiss any active toast — prevents stale overlay from
// triggering extra 644ms e-ink refreshes on the new screen
if (_hintActive) dismissBootHint(); // Dismiss hint when navigating away
_next_refresh = 100;
}
@@ -1550,6 +1695,12 @@ void UITask::loop() {
gotoHomeScreen();
}
c = 0;
} else if (isOnChannelPickerScreen()) {
gotoHomeScreen(); // picker → home
c = 0;
} else if (isOnChannelScreen()) {
gotoChannelPickerScreen(); // channel messages → picker
c = 0;
} else {
gotoHomeScreen();
c = 0; // consumed
@@ -1600,6 +1751,14 @@ void UITask::loop() {
}
#endif
if (c != 0 && curr) {
// Dismiss boot hint on any button input (boot button on T5S3)
if (_hintActive) {
dismissBootHint();
c = 0; // Consume the press
}
}
if (c != 0 && curr) {
curr->handleInput(c);
_auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer
@@ -1690,6 +1849,10 @@ if (curr) curr->poll();
}
}
#endif
// Sync font style with prefs (settings toggle takes effect here)
if (_node_prefs && display.getFontStyle() != _node_prefs->ui_font_style) {
display.setFontStyle(_node_prefs->ui_font_style);
}
_display->startFrame();
#if defined(LilyGo_T5S3_EPaper_Pro)
if (_vkbActive) {
@@ -1721,7 +1884,56 @@ if (curr) curr->poll();
}
#endif
if (millis() < _alert_expiry) {
// Check if settings screen needs VKB for text editing (channel name, freq, APN)
if (isOnSettingsScreen() && !_vkbActive) {
SettingsScreen* ss = (SettingsScreen*)settings_screen;
if (ss->needsTextVKB()) {
ss->clearTextNeedsVKB();
// Pick a context-appropriate label
const char* label = "Edit";
SettingsRowType rt = ss->getCurrentRowType();
if (rt == ROW_NAME) label = "Node Name";
else if (rt == ROW_ADD_CHANNEL) label = "Channel Name";
else if (rt == ROW_FREQ) label = "Frequency";
showVirtualKeyboard(VKB_SETTINGS_TEXT, label, ss->getEditBuf(), 31);
}
}
if (_hintActive && millis() < _hintExpiry) {
// Boot navigation hint overlay — multi-line, larger box
_display->setTextSize(1);
int w = _display->width();
int h = _display->height();
int boxX = w / 8;
int boxY = h / 5;
int boxW = w - boxX * 2;
int boxH = h * 3 / 5;
_display->setColor(DisplayDriver::DARK);
_display->fillRect(boxX, boxY, boxW, boxH);
_display->setColor(DisplayDriver::LIGHT);
_display->drawRect(boxX, boxY, boxW, boxH);
int cx = w / 2;
int lineH = 11;
int startY = boxY + 6;
#if defined(LilyGo_T5S3_EPaper_Pro)
_display->drawTextCentered(cx, startY, "Swipe: Navigate");
_display->drawTextCentered(cx, startY + lineH, "Tap: Select");
_display->drawTextCentered(cx, startY + lineH * 2, "Long Press: Action");
_display->drawTextCentered(cx, startY + lineH * 3, "Boot Btn: Home");
_display->drawTextCentered(cx, startY + lineH * 4 + 4, "[Tap to dismiss hint]");
#else
_display->drawTextCentered(cx, startY, "M:Msgs C:Contacts");
_display->drawTextCentered(cx, startY + lineH, "S:Settings E:Reader");
_display->drawTextCentered(cx, startY + lineH * 2, "N:Notes W/S:Scroll");
_display->drawTextCentered(cx, startY + lineH * 3, "A/D:Cycle Left/Right");
_display->drawTextCentered(cx, startY + lineH * 4 + 4, "[X to dismiss hint]");
#endif
_next_refresh = _hintExpiry;
} else if (_hintActive) {
// Hint expired — auto-dismiss
dismissBootHint();
_next_refresh = millis() + 200;
} else if (millis() < _alert_expiry) {
_display->setTextSize(1);
int y = _display->height() / 3;
int p = _display->height() / 32;
@@ -1737,7 +1949,33 @@ if (curr) curr->poll();
}
#else
int delay_millis = curr->render(*_display);
if (millis() < _alert_expiry) { // render alert popup
if (_hintActive && millis() < _hintExpiry) {
// Boot navigation hint overlay — multi-line, larger box
_display->setTextSize(1);
int w = _display->width();
int h = _display->height();
int boxX = w / 8;
int boxY = h / 5;
int boxW = w - boxX * 2;
int boxH = h * 3 / 5;
_display->setColor(DisplayDriver::DARK);
_display->fillRect(boxX, boxY, boxW, boxH);
_display->setColor(DisplayDriver::LIGHT);
_display->drawRect(boxX, boxY, boxW, boxH);
int cx = w / 2;
int lineH = 11;
int startY = boxY + 6;
_display->drawTextCentered(cx, startY, "M:Msgs C:Contacts");
_display->drawTextCentered(cx, startY + lineH, "S:Settings E:Reader");
_display->drawTextCentered(cx, startY + lineH * 2, "N:Notes W/S:Scroll");
_display->drawTextCentered(cx, startY + lineH * 3, "A/D:Cycle Left/Right");
_display->drawTextCentered(cx, startY + lineH * 4 + 4, "[X to dismiss]");
_next_refresh = _hintExpiry;
} else if (_hintActive) {
// Hint expired — auto-dismiss
dismissBootHint();
_next_refresh = millis() + 200;
} else if (millis() < _alert_expiry) { // render alert popup
_display->setTextSize(1);
int y = _display->height() / 3;
int p = _display->height() / 32;
@@ -1796,6 +2034,42 @@ if (curr) curr->poll();
}
#endif
// ── T5S3 standalone powersaving ──────────────────────────────────────────
// When locked with display off, enter ESP32 light sleep (~8 mA total).
// Radio stays in continuous RX — DIO1 going HIGH wakes the CPU instantly.
// Boot button (GPIO0 LOW) and a 30-min safety timer also wake.
// First sleep starts 60s after lock; subsequent cycles wake for 5s to let
// the mesh stack process/relay any received packet, then sleep again.
#if defined(LilyGo_T5S3_EPaper_Pro) && !defined(BLE_PIN_CODE) && !defined(MECK_WIFI_COMPANION)
if (_locked && _display != NULL && !_display->isOn()) {
unsigned long now = millis();
if (now - _psLastActive >= _psNextSleepSecs * 1000UL) {
Serial.println("[POWERSAVE] Entering light sleep (locked+idle)");
board.sleep(1800); // Light sleep up to 30 min
// ── CPU resumes here on wake ──
unsigned long wakeAt = millis();
_psLastActive = wakeAt;
_psNextSleepSecs = 5; // Stay awake 5s for mesh processing
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
if (cause == ESP_SLEEP_WAKEUP_GPIO) {
// Boot button pressed — unlock and return to normal use
Serial.println("[POWERSAVE] Woke by button — unlocking");
unlockScreen();
_psNextSleepSecs = 60; // Reset to long delay after user interaction
} else if (cause == ESP_SLEEP_WAKEUP_EXT1) {
Serial.println("[POWERSAVE] Woke by LoRa packet");
} else if (cause == ESP_SLEEP_WAKEUP_TIMER) {
Serial.println("[POWERSAVE] Woke by timer");
}
}
} else if (!_locked) {
// Not locked — keep powersaving timer reset so first sleep is 60s after lock
_psLastActive = millis();
_psNextSleepSecs = 60;
}
#endif
#ifdef PIN_VIBRATION
vibration.loop();
#endif
@@ -1922,6 +2196,10 @@ void UITask::lockScreen() {
_next_refresh = 0; // Draw lock screen immediately
_auto_off = millis() + 60000; // 60s before display off while locked
_lastLockRefresh = millis(); // Start 15-min clock refresh cycle
#if defined(LilyGo_T5S3_EPaper_Pro) && !defined(BLE_PIN_CODE) && !defined(MECK_WIFI_COMPANION)
_psLastActive = millis(); // Start powersaving countdown (60s to first sleep)
_psNextSleepSecs = 60;
#endif
Serial.println("[UI] Screen locked — entering low-power mode");
}
@@ -2044,6 +2322,19 @@ void UITask::onVKBSubmit() {
if (_screenBeforeVKB) setCurrScreen(_screenBeforeVKB);
break;
}
case VKB_SETTINGS_TEXT: {
// Generic settings text edit — copy text back to settings edit buffer
// and confirm via the normal Enter path (handles name/freq/channel/APN)
SettingsScreen* ss = (SettingsScreen*)settings_screen;
if (strlen(text) > 0) {
ss->submitEditText(text);
} else {
// Empty submission — cancel the edit
ss->handleInput('q');
}
if (_screenBeforeVKB) setCurrScreen(_screenBeforeVKB);
break;
}
case VKB_NOTES: {
NotesScreen* notes = (NotesScreen*)getNotesScreen();
if (notes && strlen(text) > 0) {
@@ -2248,6 +2539,15 @@ void UITask::gotoHomeScreen() {
}
_auto_off = millis() + AUTO_OFF_MILLIS;
_next_refresh = 100;
// Activate deferred boot hint now that home screen is visible
if (_pendingBootHint) {
_pendingBootHint = false;
_hintActive = true;
_hintExpiry = millis() + 8000; // 8 seconds auto-dismiss
_next_refresh = millis() + 100;
Serial.println("[UI] Boot hint activated");
}
}
bool UITask::isEditingHomeScreen() const {
@@ -2258,10 +2558,10 @@ bool UITask::isHomeOnRecentPage() const {
return curr == home && ((HomeScreen *) home)->isOnRecentPage();
}
void UITask::gotoChannelScreen() {
void UITask::gotoChannelScreen(bool resetDmView) {
ChannelScreen* cs = (ChannelScreen*)channel_screen;
// If currently showing DM view, reset to channel 0
if (cs->getViewChannelIdx() == 0xFF) {
// If currently showing DM view, reset to channel 0 (unless caller opts out)
if (resetDmView && cs->getViewChannelIdx() == 0xFF) {
cs->setViewChannelIdx(0);
}
cs->resetScroll();
@@ -2275,6 +2575,18 @@ void UITask::gotoChannelScreen() {
_next_refresh = 100;
}
void UITask::gotoChannelPickerScreen() {
ChannelScreen* cs = (ChannelScreen*)channel_screen;
ChannelPickerScreen* pick = (ChannelPickerScreen*)channel_picker_screen;
pick->enter(cs->getViewChannelIdx());
setCurrScreen(channel_picker_screen);
if (_display != NULL && !_display->isOn()) {
_display->turnOn();
}
_auto_off = millis() + AUTO_OFF_MILLIS;
_next_refresh = 100;
}
void UITask::gotoDMTab() {
((ChannelScreen *) channel_screen)->setViewChannelIdx(0xFF); // switches + marks read
((ChannelScreen *) channel_screen)->resetScroll();
@@ -2375,6 +2687,36 @@ void UITask::gotoAudiobookPlayer() {
#endif
}
#ifdef MECK_AUDIO_VARIANT
void UITask::gotoAlarmScreen() {
if (alarm_screen == nullptr) return;
AlarmScreen* alarmScr = (AlarmScreen*)alarm_screen;
if (_display != NULL) {
alarmScr->enter(*_display);
}
setCurrScreen(alarm_screen);
if (_display != NULL && !_display->isOn()) {
_display->turnOn();
}
_auto_off = millis() + AUTO_OFF_MILLIS;
_next_refresh = 100;
}
void UITask::gotoVoiceScreen() {
if (voice_screen == nullptr) return;
VoiceMessageScreen* voiceScr = (VoiceMessageScreen*)voice_screen;
if (_display != NULL) {
voiceScr->enter(*_display);
}
setCurrScreen(voice_screen);
if (_display != NULL && !_display->isOn()) {
_display->turnOn();
}
_auto_off = millis() + AUTO_OFF_MILLIS;
_next_refresh = 100;
}
#endif
#ifdef HAS_4G_MODEM
void UITask::gotoSMSScreen() {
SMSScreen* smsScr = (SMSScreen*)sms_screen;
@@ -2479,6 +2821,23 @@ void UITask::gotoRepeaterAdminDirect(int contactIdx) {
}
}
void UITask::gotoPathEditor(int contactIdx) {
// Lazy-initialize on first use
if (path_editor == nullptr) {
path_editor = new PathEditorScreen(this, &rtc_clock);
}
PathEditorScreen* editor = (PathEditorScreen*)path_editor;
editor->openForContact(contactIdx);
setCurrScreen(path_editor);
if (_display != NULL && !_display->isOn()) {
_display->turnOn();
}
_auto_off = millis() + AUTO_OFF_MILLIS;
_next_refresh = 100;
}
void UITask::gotoDiscoveryScreen() {
((DiscoveryScreen*)discovery_screen)->resetScroll();
setCurrScreen(discovery_screen);
@@ -2505,7 +2864,7 @@ void UITask::gotoWebReader() {
if (web_reader == nullptr) {
Serial.printf("WebReader: lazy init - free heap: %d, largest block: %d\n",
ESP.getFreeHeap(), ESP.getMaxAllocHeap());
web_reader = new WebReaderScreen(this);
web_reader = new WebReaderScreen(this, _node_prefs);
Serial.printf("WebReader: init complete - free heap: %d\n", ESP.getFreeHeap());
}
WebReaderScreen* wr = (WebReaderScreen*)web_reader;
+45 -1
View File
@@ -30,6 +30,10 @@
#include "WebReaderScreen.h"
#endif
#ifdef MECK_AUDIO_VARIANT
#include "AlarmScreen.h"
#endif
#if defined(LilyGo_T5S3_EPaper_Pro)
#include "VirtualKeyboard.h"
#endif
@@ -56,6 +60,9 @@ class UITask : public AbstractUITask {
NodePrefs* _node_prefs;
char _alert[80];
unsigned long _alert_expiry;
bool _hintActive = false; // Boot navigation hint overlay
unsigned long _hintExpiry = 0; // Auto-dismiss time for hint
bool _pendingBootHint = false; // Deferred hint — show after splash screen
int _msgcount;
unsigned long ui_started_at, next_batt_chck;
uint8_t _low_batt_count = 0; // Consecutive low-voltage readings for debounce
@@ -74,15 +81,21 @@ class UITask : public AbstractUITask {
UIScreen* home;
UIScreen* msg_preview;
UIScreen* channel_screen; // Channel message history screen
UIScreen* channel_picker_screen; // Channel picker (bubble/list view)
UIScreen* contacts_screen; // Contacts list screen
UIScreen* text_reader; // *** NEW: Text reader screen ***
UIScreen* notes_screen; // Notes editor screen
UIScreen* settings_screen; // Settings/onboarding screen
UIScreen* audiobook_screen; // Audiobook player screen (null if not available)
#ifdef MECK_AUDIO_VARIANT
UIScreen* alarm_screen; // Alarm clock screen (audio variant only)
UIScreen* voice_screen; // Voice message screen (audio variant only)
#endif
#ifdef HAS_4G_MODEM
UIScreen* sms_screen; // SMS messaging screen (4G variant only)
#endif
UIScreen* repeater_admin; // Repeater admin screen
UIScreen* path_editor; // Custom path editor screen (lazy-init)
UIScreen* discovery_screen; // Node discovery scan screen
UIScreen* last_heard_screen; // Last heard passive advert list
#ifdef MECK_WEB_READER
@@ -103,6 +116,13 @@ class UITask : public AbstractUITask {
bool _vkbActive = false;
UIScreen* _screenBeforeVKB = nullptr;
unsigned long _vkbOpenedAt = 0;
// Powersaving: light sleep when locked + idle (standalone only — no BLE/WiFi)
// Wakes on LoRa packet (DIO1), boot button (GPIO0), or 30-min timer
#if !defined(BLE_PIN_CODE) && !defined(MECK_WIFI_COMPANION)
unsigned long _psLastActive = 0; // millis() at last wake or lock entry
unsigned long _psNextSleepSecs = 60; // Seconds before first sleep (60s), then 5s cycles
#endif
#ifdef MECK_CARDKB
bool _cardkbDetected = false;
#endif
@@ -160,7 +180,8 @@ public:
void begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* node_prefs);
void gotoHomeScreen();
void gotoChannelScreen(); // Navigate to channel message screen
void gotoChannelScreen(bool resetDmView = true); // Navigate to channel message screen
void gotoChannelPickerScreen(); // Navigate to channel picker (bubble/list)
void gotoDMTab(); // Navigate directly to DM tab on channel screen
void gotoDMConversation(const char* contactName, int contactIdx = -1, uint8_t perms = 0);
void gotoContactsScreen(); // Navigate to contacts list
@@ -169,8 +190,13 @@ public:
void gotoSettingsScreen(); // Navigate to settings
void gotoOnboarding(); // Navigate to settings in onboarding mode
void gotoAudiobookPlayer(); // Navigate to audiobook player
#ifdef MECK_AUDIO_VARIANT
void gotoAlarmScreen(); // Navigate to alarm clock
void gotoVoiceScreen(); // Navigate to voice message recorder
#endif
void gotoRepeaterAdmin(int contactIdx); // Navigate to repeater admin
void gotoRepeaterAdminDirect(int contactIdx); // Auto-login admin (L key from conversation)
void gotoPathEditor(int contactIdx); // Navigate to custom path editor
void gotoDiscoveryScreen(); // Navigate to node discovery scan
void gotoLastHeardScreen(); // Navigate to last heard passive list
#if HAS_GPS
@@ -186,6 +212,9 @@ public:
#endif
void showAlert(const char* text, int duration_millis) override;
void forceRefresh() override { _next_refresh = 100; }
void showBootHint(bool immediate = false); // Show navigation hint overlay on first boot
void dismissBootHint(); // Dismiss hint and save preference
bool isHintActive() const { return _hintActive; }
// Wake display and extend auto-off timer. Call this when handling keys
// outside of injectKey() to prevent display auto-off during direct input.
void keepAlive() {
@@ -205,6 +234,7 @@ public:
bool hasDisplay() const { return _display != NULL; }
bool isButtonPressed() const;
bool isOnChannelScreen() const { return curr == channel_screen; }
bool isOnChannelPickerScreen() const { return curr == channel_picker_screen; }
bool isOnContactsScreen() const { return curr == contacts_screen; }
bool isOnTextReader() const { return curr == text_reader; } // *** NEW ***
bool isOnHomeScreen() const { return curr == home; }
@@ -215,7 +245,12 @@ public:
bool isOnNotesScreen() const { return curr == notes_screen; }
bool isOnSettingsScreen() const { return curr == settings_screen; }
bool isOnAudiobookPlayer() const { return curr == audiobook_screen; }
#ifdef MECK_AUDIO_VARIANT
bool isOnAlarmScreen() const { return curr == alarm_screen; }
bool isOnVoiceScreen() const { return curr == voice_screen; }
#endif
bool isOnRepeaterAdmin() const { return curr == repeater_admin; }
bool isOnPathEditor() const { return curr == path_editor; }
bool isOnDiscoveryScreen() const { return curr == discovery_screen; }
bool isOnLastHeardScreen() const { return curr == last_heard_screen; }
bool isOnMapScreen() const { return curr == map_screen; }
@@ -279,10 +314,19 @@ public:
UIScreen* getNotesScreen() const { return notes_screen; }
UIScreen* getContactsScreen() const { return contacts_screen; }
UIScreen* getChannelScreen() const { return channel_screen; }
UIScreen* getChannelPickerScreen() const { return channel_picker_screen; }
UIScreen* getSettingsScreen() const { return settings_screen; }
NodePrefs* getNodePrefs() const { return _node_prefs; }
UIScreen* getAudiobookScreen() const { return audiobook_screen; }
void setAudiobookScreen(UIScreen* s) { audiobook_screen = s; }
#ifdef MECK_AUDIO_VARIANT
UIScreen* getAlarmScreen() const { return alarm_screen; }
void setAlarmScreen(UIScreen* s) { alarm_screen = s; }
UIScreen* getVoiceScreen() const { return voice_screen; }
void setVoiceScreen(UIScreen* s) { voice_screen = s; }
#endif
UIScreen* getRepeaterAdminScreen() const { return repeater_admin; }
UIScreen* getPathEditorScreen() const { return path_editor; }
UIScreen* getDiscoveryScreen() const { return discovery_screen; }
UIScreen* getLastHeardScreen() const { return last_heard_screen; }
UIScreen* getMapScreen() const { return map_screen; }
File diff suppressed because it is too large Load Diff
@@ -39,6 +39,7 @@
#include "ModemManager.h"
#endif
#include "Utf8CP437.h"
#include "../NodePrefs.h"
// Forward declarations
class UITask;
@@ -1030,8 +1031,10 @@ public:
private:
UITask* _task;
NodePrefs* _prefs;
Mode _mode;
bool _initialized;
uint8_t _lastFontPref;
DisplayDriver* _display;
// Display layout (calculated once)
@@ -1424,7 +1427,7 @@ private:
_display->print("WiFi Setup");
_display->drawRect(0, 11, _display->width(), 1);
_display->setColor(DisplayDriver::LIGHT);
_display->setTextSize(0);
_display->setTextSize(_prefs->smallTextSize());
_display->setCursor(0, 18);
_display->print("Scanning for networks...");
_display->endFrame();
@@ -1524,7 +1527,7 @@ private:
_display->print("Web Reader");
_display->drawRect(0, 11, _display->width(), 1);
_display->setTextSize(0);
_display->setTextSize(_prefs->smallTextSize());
_display->setCursor(0, 18);
_display->print("Connected!");
_display->setCursor(0, 30);
@@ -2306,7 +2309,7 @@ private:
_display->print("Web Reader");
_display->drawRect(0, 11, _display->width(), 1);
_display->setColor(DisplayDriver::YELLOW);
_display->setTextSize(0);
_display->setTextSize(_prefs->smallTextSize());
_display->setCursor(0, 18);
_display->print("Fetch failed:");
_display->setColor(DisplayDriver::LIGHT);
@@ -2442,7 +2445,7 @@ private:
_display->setTextSize(2);
_display->setCursor(10, 20);
_display->print("Logging in...");
_display->setTextSize(0);
_display->setTextSize(_prefs->smallTextSize());
_display->setColor(DisplayDriver::LIGHT);
_display->setCursor(10, 45);
_display->print("Refreshing session...");
@@ -2656,14 +2659,14 @@ private:
display.drawRect(0, 11, display.width(), 1);
display.setColor(DisplayDriver::LIGHT);
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
if (_wifiState == WIFI_SCANNING) {
display.setCursor(0, 18);
display.print("Scanning for networks...");
} else if (_wifiState == WIFI_SCAN_DONE) {
int y = 14;
int listLineH = 8;
int listLineH = _prefs ? _prefs->smallLineH() : 9;
for (int i = 0; i < _ssidCount && y < display.height() - 24; i++) {
bool selected = (i == _selectedSSID);
if (selected) {
@@ -2671,7 +2674,7 @@ private:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width(), listLineH);
#else
display.fillRect(0, y + 5, display.width(), listLineH);
display.fillRect(0, y + _prefs->smallHighlightOff(), display.width(), listLineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -2695,7 +2698,7 @@ private:
y += 12;
display.setCursor(0, y);
display.print("Password:");
y += 10;
y += _prefs->smallLineH() + 1;
display.setCursor(0, y);
// Show masked password with brief reveal of last char
char passBuf[WEB_WIFI_PASS_LEN + 2];
@@ -2771,7 +2774,7 @@ private:
if (isNetworkAvailable()) {
display.print("Web Reader");
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::GREEN);
if (isWiFiConnected()) {
IPAddress ip = WiFi.localIP();
@@ -2797,7 +2800,7 @@ private:
const int footerY = display.height() - 12;
const int viewportH = display.height() - headerY - footerH;
const int scrollbarW = 4;
const int listLineH = 8;
const int listLineH = _prefs ? _prefs->smallLineH() : 9;
const int sepH = 8; // Separator between IRC and web sections
const int sectionH = listLineH; // Section header height
int maxChars = _charsPerLine - 2; // Account for "> " prefix
@@ -2875,7 +2878,7 @@ private:
if (totalContentH <= viewportH) _homeScrollY = 0;
// ---- Render pass (with scroll offset) ----
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
int y = headerY - _homeScrollY; // Start Y in screen coords
itemIdx = 0;
bool needsScroll = (totalContentH > viewportH);
@@ -2895,7 +2898,7 @@ private:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width() - (needsScroll ? scrollbarW + 1 : 0), listLineH);
#else
display.fillRect(0, y + 5, display.width() - (needsScroll ? scrollbarW + 1 : 0), listLineH);
display.fillRect(0, y + _prefs->smallHighlightOff(), display.width() - (needsScroll ? scrollbarW + 1 : 0), listLineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -2934,7 +2937,7 @@ private:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width() - (needsScroll ? scrollbarW + 1 : 0), listLineH);
#else
display.fillRect(0, y + 5, display.width() - (needsScroll ? scrollbarW + 1 : 0), listLineH);
display.fillRect(0, y + _prefs->smallHighlightOff(), display.width() - (needsScroll ? scrollbarW + 1 : 0), listLineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -2971,7 +2974,7 @@ private:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, display.width() - (needsScroll ? scrollbarW + 1 : 0), listLineH);
#else
display.fillRect(0, y + 5, display.width() - (needsScroll ? scrollbarW + 1 : 0), listLineH);
display.fillRect(0, y + _prefs->smallHighlightOff(), display.width() - (needsScroll ? scrollbarW + 1 : 0), listLineH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -3024,7 +3027,7 @@ private:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, contentW, itemH);
#else
display.fillRect(0, y + 5, contentW, itemH);
display.fillRect(0, y + _prefs->smallHighlightOff(), contentW, itemH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -3076,7 +3079,7 @@ private:
#if defined(LilyGo_T5S3_EPaper_Pro)
display.fillRect(0, y, contentW, itemH);
#else
display.fillRect(0, y + 5, contentW, itemH);
display.fillRect(0, y + _prefs->smallHighlightOff(), contentW, itemH);
#endif
display.setColor(DisplayDriver::DARK);
} else {
@@ -3198,7 +3201,7 @@ private:
display.setCursor(10, 20);
display.print("Loading...");
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
// Word-wrap the URL across multiple lines
@@ -3243,7 +3246,7 @@ private:
display.print("Download Complete");
display.drawRect(0, 11, display.width(), 1);
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(0, 16);
display.print("Saved to /books/:");
@@ -3277,7 +3280,7 @@ private:
display.print("Download Failed");
display.drawRect(0, 11, display.width(), 1);
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(0, 18);
display.print(_fetchError.c_str());
@@ -3314,7 +3317,7 @@ private:
return;
}
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
// Determine page bounds
@@ -3476,9 +3479,16 @@ private:
// ---- Layout Initialization ----
void initLayout(DisplayDriver& display) {
// Re-init if font preference changed since last layout
uint8_t curFont = _prefs ? _prefs->large_font : 0;
if (_initialized && curFont != _lastFontPref) {
_initialized = false;
Serial.println("WebReader: font changed, recalculating layout");
}
if (_initialized) return;
_lastFontPref = curFont;
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
uint16_t mWidth = display.getTextWidth("M");
if (mWidth > 0) {
_charsPerLine = display.width() / mWidth;
@@ -3487,6 +3497,19 @@ private:
_charsPerLine = 40;
_lineHeight = 5;
}
// Proportional font: use average-width measurement instead of M-width
if (_prefs && _prefs->large_font && mWidth > 0) {
const char* sample = "the quick brown fox jumps over lazy dog";
uint16_t sampleW = display.getTextWidth(sample);
int sampleLen = strlen(sample);
if (sampleW > 0 && sampleLen > 0) {
_charsPerLine = (display.width() * sampleLen * 70) / ((int)sampleW * 100);
}
}
// Large font: formula above assumes built-in 6x8 ratio — too small for 9pt
if (_prefs && _prefs->large_font) {
_lineHeight = _prefs->smallLineH();
}
_footerHeight = 14;
int textAreaHeight = display.height() - _footerHeight;
@@ -3931,7 +3954,7 @@ private:
if (_activeForm < 0 || _activeForm >= _formCount) return;
WebForm& form = _forms[_activeForm];
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
// Header
display.setColor(DisplayDriver::GREEN);
@@ -3954,7 +3977,7 @@ private:
display.drawRect(0, 9, display.width(), 1);
int y = 12;
int lineH = 10; // Taller lines for form fields
int lineH = _prefs->smallLineH() + 1; // Taller lines for form fields
int visCount = getVisibleFieldCount(form);
// Render each visible field
@@ -4662,9 +4685,9 @@ private:
display.print("IRC Setup");
display.drawRect(0, 11, display.width(), 1);
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
int y = 16;
int lineH = 10;
int lineH = _prefs->smallLineH() + 1;
const char* labels[] = {"Server:", "Port:", "Nick:", "Channel:", "[ Connect ]"};
const char* chanDisp = (_ircChannel[0] != '\0') ? _ircChannel : "(none)";
@@ -4822,7 +4845,7 @@ private:
display.print(header);
// Connection indicator on right
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
if (!_ircConnected) {
display.setColor(DisplayDriver::YELLOW);
display.setCursor(display.width() - 42, -3);
@@ -4848,7 +4871,7 @@ private:
if (_ircComposing) {
// Compose text just above separator (tiny font to match messages)
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
display.setColor(DisplayDriver::LIGHT);
display.setCursor(0, footerY - 12);
char compDisp[IRC_COMPOSE_MAX + 4];
@@ -4878,10 +4901,10 @@ private:
}
// Message area
display.setTextSize(0);
display.setTextSize(_prefs->smallTextSize());
int msgAreaTop = 14;
int msgAreaBottom = _ircComposing ? footerY - 16 : footerY - 4;
int lineH = 8;
int lineH = _prefs->smallLineH() - 1;
int scrollBarW = 4;
int lineW = _charsPerLine - 1; // Reserve space for scroll bar
_ircLinesPerPage = (msgAreaBottom - msgAreaTop) / lineH;
@@ -5065,8 +5088,8 @@ private:
}
public:
WebReaderScreen(UITask* task)
: _task(task), _mode(HOME), _initialized(false), _display(nullptr),
WebReaderScreen(UITask* task, NodePrefs* prefs = nullptr)
: _task(task), _prefs(prefs), _mode(HOME), _initialized(false), _lastFontPref(0), _display(nullptr),
_charsPerLine(40), _linesPerPage(15), _lineHeight(5), _footerHeight(14),
_wifiState(WIFI_IDLE), _ssidCount(0), _selectedSSID(0), _wifiPassLen(0),
_urlLen(0), _urlCursor(0),
@@ -5150,7 +5173,7 @@ public:
_display->print("Web Reader");
_display->drawRect(0, 11, _display->width(), 1);
_display->setColor(DisplayDriver::LIGHT);
_display->setTextSize(0);
_display->setTextSize(_prefs->smallTextSize());
_display->setCursor(0, 18);
_display->print("Connecting to WiFi...");
_display->endFrame();
+92 -68
View File
@@ -1,7 +1,7 @@
#pragma once
// Emoji Picker with scrolling grid and scroll bar
// 5 columns, 4 visible rows, scrollable through all 65 emoji
// 5 columns, 4 visible rows, scrollable through all 76 emoji
// WASD navigation, Enter to select, $/Q/Backspace to cancel
#include <helpers/ui/DisplayDriver.h>
@@ -12,71 +12,85 @@
#define EMOJI_PICKER_TOTAL_ROWS ((EMOJI_COUNT + EMOJI_PICKER_COLS - 1) / EMOJI_PICKER_COLS)
static const char* EMOJI_LABELS[EMOJI_COUNT] = {
// Faces/emotion
"Lol", // 0 joy
"Like", // 1 thumbsup
"Sad", // 2 frown
"WiFi", // 3 wireless
"Inf", // 4 infinity
"Rex", // 5 trex
"Skul", // 6 skull
"Cros", // 7 cross
"Bolt", // 8 lightning
"Hat", // 9 tophat
"Moto", // 10 motorcycle
"Leaf", // 11 seedling
"AU", // 12 flag_au
"Umbr", // 13 umbrella
"Eye", // 14 nazar
"Glob", // 15 globe
"Rad", // 16 radioactive
"Cow", // 17 cow
"ET", // 18 alien
"Inv", // 19 invader
"Dagr", // 20 dagger
"Grim", // 21 grimace
"Mtn", // 22 mountain
"End", // 23 end_arrow
"Ring", // 24 hollow_circle
"Drag", // 25 dragon
"Web", // 26 globe_meridians
"Eggp", // 27 eggplant
"Shld", // 28 shield
"Gogl", // 29 goggles
"Lzrd", // 30 lizard
"Zany", // 31 zany_face
"Roo", // 32 kangaroo
"Fthr", // 33 feather
"Sun", // 34 bright
"Wave", // 35 part_alt
"Boat", // 36 motorboat
"Domi", // 37 domino
"Dish", // 38 satellite
"Pass", // 39 customs
"Cowb", // 40 cowboy
"Whl", // 41 wheel
"Koal", // 42 koala
"Knob", // 43 control_knobs
"Pch", // 44 peach
"Race", // 45 racing_car
"Mous", // 46 mouse
"Shrm", // 47 mushroom
"Bio", // 48 biohazard
"Pnda", // 49 panda
"Bang", // 50 anger
"DrgF", // 51 dragon_face
"Pagr", // 52 pager
"Bee", // 53 bee
"Bulb", // 54 bulb
"Cat", // 55 cat
"Flur", // 56 fleur
"Moon", // 57 moon
"Cafe", // 58 coffee
"Toth", // 59 tooth
"Prtz", // 60 pretzel
"Abac", // 61 abacus
"Moai", // 62 moai
"Hiii", // 63 tipping
"Hedg", // 64 hedgehog
"Sad", // 1 frown
"Cry", // 2 loudly_crying
"Grim", // 3 grimace
"Zany", // 4 zany_face
"Cowb", // 5 cowboy
// Thumbsup + heart
"Like", // 6 thumbsup
"Love", // 7 heart
// Everything else
"WiFi", // 8 wireless
"Inf", // 9 infinity
"Rex", // 10 trex
"Skul", // 11 skull
"Cros", // 12 cross
"Bolt", // 13 lightning
"Hat", // 14 tophat
"Moto", // 15 motorcycle
"Leaf", // 16 seedling
"AU", // 17 flag_au
"Umbr", // 18 umbrella
"Eye", // 19 nazar
"Glob", // 20 globe
"Rad", // 21 radioactive
"Cow", // 22 cow
"ET", // 23 alien
"Inv", // 24 invader
"Dagr", // 25 dagger
"Mtn", // 26 mountain
"End", // 27 end_arrow
"Ring", // 28 hollow_circle
"Drag", // 29 dragon
"Web", // 30 globe_meridians
"Eggp", // 31 eggplant
"Shld", // 32 shield
"Gogl", // 33 goggles
"Lzrd", // 34 lizard
"Roo", // 35 kangaroo
"Fthr", // 36 feather
"Sun", // 37 bright
"Wave", // 38 part_alt
"Boat", // 39 motorboat
"Domi", // 40 domino
"Dish", // 41 satellite
"Pass", // 42 customs
"Whl", // 43 wheel
"Koal", // 44 koala
"Knob", // 45 control_knobs
"Pch", // 46 peach
"Race", // 47 racing_car
"Mous", // 48 mouse
"Shrm", // 49 mushroom
"Bio", // 50 biohazard
"Pnda", // 51 panda
"Bang", // 52 anger
"DrgF", // 53 dragon_face
"Pagr", // 54 pager
"Bee", // 55 bee
"Bulb", // 56 bulb
"Cat", // 57 cat
"Flur", // 58 fleur
"Moon", // 59 moon
"Cafe", // 60 coffee
"Toth", // 61 tooth
"Prtz", // 62 pretzel
"Abac", // 63 abacus
"Moai", // 64 moai
"Hiii", // 65 tipping
"Hedg", // 66 hedgehog
"Diam", // 67 diamond_suit
"Spde", // 68 spade_suit
"Piza", // 69 pizza
"Luck", // 70 four_leaf_clover
"Cld", // 71 cloud
"Rckt", // 72 rocket
"HFC", // 73 passport_control
"Star", // 74 eight_spoked_asterisk
"Sig", // 75 signal_strength
};
struct EmojiPicker {
@@ -105,13 +119,23 @@ struct EmojiPicker {
switch (key) {
case 'w': case 'W': case 0xF2:
if (row > 0) cursor -= EMOJI_PICKER_COLS;
if (row > 0) {
cursor -= EMOJI_PICKER_COLS;
} else {
// Wrap to last row, same column
int target = (EMOJI_PICKER_TOTAL_ROWS - 1) * EMOJI_PICKER_COLS + col;
cursor = (target >= EMOJI_COUNT) ? EMOJI_COUNT - 1 : target;
}
break;
case 's': case 'S': case 0xF1:
if (cursor + EMOJI_PICKER_COLS < EMOJI_COUNT)
if (cursor + EMOJI_PICKER_COLS < EMOJI_COUNT) {
cursor += EMOJI_PICKER_COLS;
else if (row < EMOJI_PICKER_TOTAL_ROWS - 1)
} else if (row < EMOJI_PICKER_TOTAL_ROWS - 1) {
cursor = EMOJI_COUNT - 1;
} else {
// Wrap to first row, same column
cursor = col;
}
break;
case 'a': case 'A':
if (cursor > 0) cursor--;
@@ -0,0 +1,288 @@
#ifndef MONTSERRAT12PT7B_H
#define MONTSERRAT12PT7B_H
const uint8_t Montserrat_Regular12pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x8C, 0x63, 0x18, 0xC6, 0x20, 0x04,
0x10, 0x18, 0x20, 0x30, 0x40, 0x61, 0x80, 0x83, 0x1F, 0xFF, 0xC2, 0x08,
0x04, 0x10, 0x08, 0x20, 0x30, 0x40, 0x60, 0x87, 0xFF, 0xE1, 0x06, 0x02,
0x0C, 0x04, 0x10, 0x08, 0x20, 0x10, 0x40, 0x02, 0x00, 0x10, 0x00, 0x80,
0x1F, 0x83, 0xFF, 0x31, 0x09, 0x88, 0x08, 0x40, 0x42, 0x03, 0x10, 0x0E,
0x80, 0x3F, 0x00, 0x3E, 0x01, 0x18, 0x08, 0x60, 0x43, 0x02, 0x1E, 0x11,
0x9E, 0xF8, 0x3F, 0x80, 0x20, 0x01, 0x00, 0x08, 0x00, 0x3C, 0x02, 0x19,
0x81, 0x8C, 0x20, 0xC2, 0x08, 0x20, 0x83, 0x10, 0x20, 0xCC, 0x08, 0x22,
0x01, 0x19, 0x00, 0x3C, 0xCF, 0x00, 0x26, 0x60, 0x11, 0x0C, 0x0C, 0xC1,
0x02, 0x30, 0x41, 0x0C, 0x10, 0xC1, 0x0C, 0x20, 0x62, 0x10, 0x0F, 0x00,
0x0F, 0x80, 0x3B, 0x80, 0xC1, 0x01, 0x82, 0x03, 0x04, 0x03, 0x18, 0x06,
0xE0, 0x07, 0x00, 0x1E, 0x00, 0x66, 0x11, 0x86, 0x36, 0x06, 0x4C, 0x07,
0x98, 0x06, 0x18, 0x0E, 0x3C, 0x76, 0x1F, 0x84, 0xFE, 0x18, 0x8C, 0x46,
0x31, 0x88, 0x42, 0x31, 0x84, 0x21, 0x08, 0x63, 0x18, 0x43, 0x08, 0x60,
0xC4, 0x66, 0x23, 0x33, 0x11, 0x11, 0x11, 0x13, 0x33, 0x26, 0x64, 0xC0,
0x10, 0x10, 0x93, 0x7E, 0x38, 0x7C, 0x93, 0x10, 0x10, 0x0C, 0x03, 0x00,
0xC0, 0x30, 0xFF, 0xC3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0x1D, 0xA4,
0xB0, 0xFE, 0x1F, 0x80, 0x00, 0xC0, 0x20, 0x18, 0x06, 0x01, 0x00, 0xC0,
0x30, 0x08, 0x06, 0x01, 0x00, 0x40, 0x30, 0x08, 0x02, 0x01, 0x80, 0x40,
0x30, 0x0C, 0x02, 0x01, 0x80, 0x60, 0x10, 0x00, 0x07, 0x80, 0x7F, 0x83,
0x03, 0x18, 0x06, 0x60, 0x19, 0x00, 0x6C, 0x00, 0xF0, 0x03, 0xC0, 0x0F,
0x00, 0x3C, 0x00, 0xD0, 0x02, 0x60, 0x19, 0x80, 0x63, 0x03, 0x07, 0xF8,
0x0F, 0xC0, 0xFF, 0xF0, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
0x30, 0xC3, 0x0C, 0x1F, 0x83, 0xFF, 0x38, 0x18, 0x00, 0x60, 0x03, 0x00,
0x18, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xC0,
0x0C, 0x00, 0xC0, 0x0F, 0xFF, 0x7F, 0xF8, 0x7F, 0xF7, 0xFF, 0x00, 0x60,
0x0C, 0x01, 0x80, 0x30, 0x03, 0x00, 0x60, 0x07, 0xE0, 0x07, 0x00, 0x30,
0x01, 0x00, 0x10, 0x03, 0x40, 0x37, 0xDE, 0x1F, 0xC0, 0x00, 0x60, 0x01,
0x80, 0x06, 0x00, 0x18, 0x00, 0x60, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x30,
0x30, 0x60, 0xC0, 0xC1, 0x81, 0x87, 0xFF, 0xFF, 0xFF, 0xE0, 0x0C, 0x00,
0x18, 0x00, 0x30, 0x00, 0x60, 0x3F, 0xE7, 0xFE, 0x60, 0x06, 0x00, 0x60,
0x06, 0x00, 0x60, 0x07, 0xF0, 0x7F, 0xC0, 0x06, 0x00, 0x60, 0x03, 0x00,
0x30, 0x02, 0xC0, 0x6F, 0xBC, 0x3F, 0x80, 0x07, 0xE0, 0xFF, 0x8E, 0x00,
0xC0, 0x06, 0x00, 0x20, 0x03, 0x00, 0x19, 0xF8, 0xDE, 0xE7, 0x81, 0xB8,
0x07, 0xC0, 0x36, 0x01, 0xB0, 0x0C, 0xC0, 0xC3, 0x9E, 0x0F, 0xC0, 0xFF,
0xFF, 0xFF, 0x80, 0x38, 0x06, 0x80, 0x60, 0x0C, 0x00, 0xC0, 0x18, 0x01,
0x80, 0x10, 0x03, 0x00, 0x30, 0x06, 0x00, 0x60, 0x0C, 0x00, 0xC0, 0x18,
0x00, 0x0F, 0x81, 0xFF, 0x18, 0x0C, 0xC0, 0x26, 0x01, 0xB0, 0x09, 0x80,
0xC7, 0xBC, 0x1F, 0xE3, 0x83, 0x98, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0D,
0x80, 0xEF, 0x1E, 0x1F, 0xC0, 0x1F, 0x07, 0xFC, 0xE0, 0x6C, 0x02, 0xC0,
0x38, 0x03, 0xC0, 0x3C, 0x07, 0x71, 0xD3, 0xF9, 0x00, 0x30, 0x03, 0x00,
0x30, 0x06, 0x00, 0xE6, 0x7C, 0x7F, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x7E,
0x1F, 0x80, 0x00, 0x00, 0x76, 0x92, 0xC0, 0x00, 0xC1, 0xE1, 0xE3, 0xC0,
0xC0, 0x3C, 0x03, 0xC0, 0x1E, 0x01, 0xC0, 0x00, 0xFF, 0xFF, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x0F, 0xFC, 0xC0, 0x1C, 0x01, 0xE0, 0x0E, 0x00, 0xC0,
0xF0, 0xE1, 0xE0, 0xC0, 0x00, 0x00, 0x1F, 0x87, 0xFE, 0xE0, 0x60, 0x03,
0x00, 0x30, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x03, 0x00, 0x20,
0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x07, 0x00, 0x00, 0xFE, 0x00, 0x07,
0x07, 0x00, 0x30, 0x01, 0x80, 0xC0, 0x01, 0x83, 0x00, 0x01, 0x84, 0x1F,
0x91, 0x10, 0x61, 0xA3, 0x21, 0x80, 0xC2, 0xC2, 0x01, 0x85, 0x8C, 0x01,
0x0B, 0x18, 0x02, 0x1E, 0x30, 0x04, 0x3C, 0x60, 0x08, 0x58, 0x40, 0x30,
0x90, 0xC0, 0xE1, 0x30, 0xE3, 0x64, 0x20, 0xFC, 0x78, 0x60, 0x00, 0x00,
0x60, 0x00, 0x00, 0x70, 0x00, 0x00, 0x3C, 0xF0, 0x00, 0x1F, 0x80, 0x00,
0x00, 0xC0, 0x00, 0xE0, 0x00, 0x58, 0x00, 0x6C, 0x00, 0x22, 0x00, 0x31,
0x80, 0x18, 0x40, 0x18, 0x30, 0x0C, 0x18, 0x0C, 0x06, 0x06, 0x03, 0x03,
0xFF, 0xC3, 0xFF, 0xE1, 0x00, 0x19, 0x80, 0x0C, 0xC0, 0x02, 0xC0, 0x01,
0x80, 0xFF, 0xC3, 0xFF, 0xCC, 0x03, 0x30, 0x06, 0xC0, 0x1B, 0x00, 0x6C,
0x01, 0x30, 0x1C, 0xFF, 0xE3, 0x00, 0xEC, 0x01, 0xB0, 0x03, 0xC0, 0x0F,
0x00, 0x3C, 0x01, 0xB0, 0x3E, 0xFF, 0xE0, 0x03, 0xF0, 0x1F, 0xF8, 0x70,
0x19, 0x80, 0x06, 0x00, 0x0C, 0x00, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x01,
0x80, 0x03, 0x00, 0x03, 0x00, 0x06, 0x00, 0x06, 0x00, 0x06, 0x01, 0x87,
0xBE, 0x07, 0xF8, 0xFF, 0x80, 0xFF, 0xF0, 0xC0, 0x38, 0xC0, 0x0C, 0xC0,
0x06, 0xC0, 0x06, 0xC0, 0x02, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
0x02, 0xC0, 0x06, 0xC0, 0x06, 0xC0, 0x0C, 0xC0, 0x38, 0xFF, 0xF0, 0xFF,
0xC0, 0xFF, 0xEF, 0xFE, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C,
0x00, 0xFF, 0xCC, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0F,
0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30,
0x06, 0x00, 0xFF, 0xDF, 0xFB, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06,
0x00, 0xC0, 0x00, 0x03, 0xF0, 0x1F, 0xF8, 0x70, 0x19, 0x80, 0x06, 0x00,
0x0C, 0x00, 0x30, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0x07, 0x00, 0x0B,
0x00, 0x16, 0x00, 0x26, 0x00, 0x46, 0x01, 0x87, 0xDF, 0x03, 0xF8, 0xC0,
0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0,
0x03, 0xFF, 0xFF, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C,
0x00, 0xF0, 0x03, 0xC0, 0x0C, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0x9F,
0xC0, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10,
0x08, 0x0F, 0x07, 0xEE, 0x3E, 0x00, 0xC0, 0x1B, 0x00, 0xCC, 0x06, 0x30,
0x30, 0xC1, 0x83, 0x0C, 0x0C, 0x60, 0x33, 0x00, 0xDE, 0x03, 0xFC, 0x0F,
0x30, 0x38, 0x60, 0xC0, 0xC3, 0x01, 0x8C, 0x03, 0x30, 0x0E, 0xC0, 0x1C,
0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0,
0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x07, 0xFF, 0xFF, 0xE0,
0x80, 0x00, 0xE0, 0x00, 0xF8, 0x00, 0xFC, 0x00, 0x7B, 0x00, 0x7C, 0x80,
0x2E, 0x60, 0x37, 0x10, 0x33, 0x8C, 0x19, 0xC3, 0x18, 0xE1, 0x88, 0x70,
0x6C, 0x38, 0x14, 0x1C, 0x0E, 0x0E, 0x02, 0x07, 0x00, 0x03, 0x80, 0x01,
0x80, 0x80, 0x0F, 0x00, 0x3E, 0x00, 0xFC, 0x03, 0xF8, 0x0F, 0x60, 0x3C,
0xC0, 0xF1, 0x83, 0xC3, 0x0F, 0x0E, 0x3C, 0x18, 0xF0, 0x33, 0xC0, 0x6F,
0x00, 0xFC, 0x03, 0xF0, 0x07, 0xC0, 0x0C, 0x03, 0xF0, 0x03, 0xFF, 0x01,
0xC0, 0x60, 0xC0, 0x0C, 0x60, 0x01, 0x98, 0x00, 0x6C, 0x00, 0x0F, 0x00,
0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0D, 0x80, 0x02, 0x60, 0x01,
0x8C, 0x00, 0xC1, 0x80, 0x70, 0x3C, 0xF0, 0x03, 0xF8, 0x00, 0xFF, 0x87,
0xFF, 0x30, 0x1D, 0x80, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0,
0x36, 0x03, 0xBF, 0xF9, 0xFE, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x18, 0x00,
0xC0, 0x00, 0x03, 0xF0, 0x01, 0xFF, 0x80, 0x70, 0x18, 0x18, 0x01, 0x86,
0x00, 0x18, 0xC0, 0x03, 0x30, 0x00, 0x36, 0x00, 0x06, 0xC0, 0x00, 0xD8,
0x00, 0x1B, 0x00, 0x03, 0x30, 0x00, 0xC6, 0x00, 0x18, 0x60, 0x06, 0x06,
0x01, 0xC0, 0x79, 0xE0, 0x07, 0xF8, 0x00, 0x0E, 0x00, 0x00, 0xE3, 0x80,
0x07, 0xE0, 0xFF, 0x87, 0xFF, 0x30, 0x1D, 0x80, 0x6C, 0x01, 0xE0, 0x0F,
0x00, 0x78, 0x03, 0xC0, 0x36, 0x03, 0xBF, 0xF9, 0xFF, 0x0C, 0x0C, 0x60,
0x33, 0x01, 0x98, 0x06, 0xC0, 0x18, 0x0F, 0xC1, 0xFF, 0x98, 0x04, 0xC0,
0x04, 0x00, 0x20, 0x01, 0x80, 0x07, 0x00, 0x1F, 0x80, 0x0F, 0x00, 0x0C,
0x00, 0x30, 0x01, 0x80, 0x0F, 0x00, 0xCF, 0x3C, 0x1F, 0xC0, 0xFF, 0xFF,
0xFF, 0xF0, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0,
0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00, 0x30,
0x00, 0xC0, 0x03, 0x00, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x18, 0x00,
0xC0, 0x06, 0x00, 0x30, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x3C,
0x01, 0xE0, 0x0D, 0x80, 0xC7, 0xBC, 0x1F, 0xC0, 0xC0, 0x01, 0xB0, 0x01,
0x98, 0x00, 0xC4, 0x00, 0xC3, 0x00, 0x61, 0x80, 0x20, 0x60, 0x30, 0x30,
0x10, 0x0C, 0x18, 0x06, 0x0C, 0x01, 0x8C, 0x00, 0xC6, 0x00, 0x26, 0x00,
0x1B, 0x00, 0x0D, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xC0, 0x18, 0x01,
0xE0, 0x0E, 0x00, 0x90, 0x07, 0x00, 0xCC, 0x06, 0x80, 0x66, 0x03, 0x60,
0x21, 0x01, 0x30, 0x30, 0xC1, 0x88, 0x18, 0x60, 0xC6, 0x08, 0x18, 0x43,
0x0C, 0x0C, 0x60, 0x86, 0x06, 0x30, 0x62, 0x01, 0x10, 0x33, 0x00, 0xD8,
0x09, 0x80, 0x6C, 0x06, 0x80, 0x1C, 0x03, 0xC0, 0x0E, 0x00, 0xE0, 0x07,
0x00, 0x60, 0x00, 0x60, 0x06, 0x60, 0x18, 0xE0, 0x60, 0xC0, 0x80, 0xC3,
0x00, 0xCC, 0x01, 0xF0, 0x01, 0xE0, 0x01, 0x80, 0x07, 0x80, 0x1B, 0x80,
0x63, 0x00, 0xC3, 0x03, 0x03, 0x0C, 0x07, 0x18, 0x06, 0x60, 0x06, 0xC0,
0x06, 0xC0, 0x09, 0x80, 0x31, 0x80, 0xC1, 0x81, 0x83, 0x06, 0x03, 0x08,
0x06, 0x30, 0x06, 0xC0, 0x07, 0x80, 0x0E, 0x00, 0x0C, 0x00, 0x18, 0x00,
0x30, 0x00, 0x60, 0x00, 0xC0, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xF0, 0x01,
0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0x1C, 0x00, 0x60, 0x03, 0x00, 0x18,
0x00, 0xC0, 0x07, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x3F, 0xFF, 0xFF,
0xFC, 0xFF, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x8F,
0xF0, 0xC0, 0x10, 0x06, 0x01, 0x80, 0x20, 0x0C, 0x01, 0x00, 0x40, 0x18,
0x02, 0x00, 0x80, 0x30, 0x04, 0x01, 0x80, 0x60, 0x08, 0x03, 0x00, 0xC0,
0x10, 0x06, 0x01, 0x80, 0x20, 0xFF, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6,
0x31, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0xFF, 0xE0, 0x0C, 0x07, 0x01, 0x60,
0x48, 0x33, 0x08, 0x46, 0x19, 0x02, 0xC0, 0xA0, 0x30, 0xFF, 0xF0, 0xE0,
0xC1, 0x80, 0x0E, 0x0F, 0xF9, 0x83, 0x00, 0x30, 0x06, 0x00, 0xCF, 0xFB,
0x03, 0xC0, 0x78, 0x0F, 0x03, 0xB8, 0xF3, 0xF6, 0xC0, 0x06, 0x00, 0x30,
0x01, 0x80, 0x0C, 0x00, 0x63, 0xC3, 0x7F, 0x9E, 0x0E, 0xE0, 0x36, 0x00,
0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x80, 0x7E, 0x06, 0xDC, 0xE6,
0x7E, 0x00, 0x07, 0x01, 0xFC, 0x30, 0x66, 0x00, 0xC0, 0x0C, 0x00, 0xC0,
0x0C, 0x00, 0xC0, 0x06, 0x00, 0x60, 0x23, 0xDE, 0x0F, 0x80, 0x00, 0x18,
0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x83, 0x8C, 0x7F, 0x6E, 0x0F, 0x60,
0x3E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0D, 0x80, 0xEC, 0x07,
0x3D, 0xD8, 0xFC, 0xC0, 0x07, 0x01, 0xFC, 0x70, 0x66, 0x03, 0xC0, 0x3C,
0x01, 0xFF, 0xFC, 0x00, 0xC0, 0x06, 0x00, 0x60, 0x23, 0xDE, 0x0F, 0xC0,
0x0F, 0x0F, 0xC6, 0x02, 0x01, 0x07, 0xFB, 0xFC, 0x20, 0x10, 0x08, 0x04,
0x02, 0x01, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x07, 0x19, 0xFE,
0xDC, 0x1E, 0xC0, 0x7C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B,
0x01, 0xCC, 0x1E, 0x3F, 0xB0, 0x21, 0x80, 0x0C, 0x00, 0x6C, 0x06, 0x3F,
0xE0, 0x7C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x78,
0xDF, 0xCF, 0x06, 0xE0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03,
0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xF0, 0x3F, 0xFF, 0xFF, 0xF0, 0x0C,
0x30, 0x00, 0x00, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
0x30, 0xC3, 0x0F, 0xE7, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0,
0x0C, 0x07, 0xC0, 0xEC, 0x1C, 0xC3, 0x0C, 0x60, 0xCC, 0x0D, 0xE0, 0xF3,
0x0E, 0x18, 0xC1, 0x8C, 0x0C, 0xC0, 0x6C, 0x03, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xC7, 0x01, 0xC6, 0xFE, 0x7F, 0xBC, 0x1E, 0x0D, 0xC0, 0xE0, 0x3C,
0x03, 0x01, 0xE0, 0x18, 0x0F, 0x00, 0xC0, 0x78, 0x06, 0x03, 0xC0, 0x30,
0x1E, 0x01, 0x80, 0xF0, 0x0C, 0x07, 0x80, 0x60, 0x3C, 0x03, 0x01, 0x80,
0xC7, 0x8D, 0xFC, 0xF0, 0x6E, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03,
0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x30, 0x07, 0x00, 0xFE, 0x0C,
0x1C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01,
0x98, 0x0C, 0x7B, 0xC0, 0xF8, 0x00, 0xC7, 0x86, 0xFF, 0x3C, 0x1D, 0xC0,
0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1F, 0x00, 0xFC, 0x0D,
0xB9, 0xCC, 0xFC, 0x60, 0x03, 0x00, 0x18, 0x00, 0xC0, 0x06, 0x00, 0x00,
0x07, 0x18, 0xFE, 0xDC, 0x1E, 0xC0, 0x7C, 0x01, 0xE0, 0x0F, 0x00, 0x78,
0x03, 0xC0, 0x1B, 0x01, 0xD8, 0x0E, 0x7B, 0xB1, 0xF9, 0x80, 0x0C, 0x00,
0x60, 0x03, 0x00, 0x18, 0x00, 0xC0, 0xC7, 0xBF, 0xC7, 0x0C, 0x18, 0x30,
0x60, 0xC1, 0x83, 0x06, 0x0C, 0x00, 0x0E, 0x1F, 0xFC, 0x0B, 0x00, 0xC0,
0x38, 0x07, 0xE0, 0x1E, 0x00, 0xC0, 0x38, 0x0F, 0xCE, 0x7F, 0x00, 0x10,
0x08, 0x3F, 0xDF, 0xE1, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02,
0x01, 0x80, 0xE4, 0x3E, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C,
0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x07, 0x60, 0x77, 0x9F, 0x1F, 0x30,
0xC0, 0x1A, 0x00, 0xD8, 0x0C, 0xC0, 0x63, 0x06, 0x18, 0x30, 0x41, 0x03,
0x18, 0x08, 0x80, 0x6C, 0x03, 0x40, 0x0E, 0x00, 0x70, 0x00, 0xC0, 0x20,
0x1A, 0x03, 0x80, 0xD8, 0x1C, 0x04, 0xC0, 0xA0, 0x62, 0x0D, 0x82, 0x18,
0x44, 0x30, 0xC2, 0x31, 0x82, 0x31, 0x88, 0x19, 0x04, 0xC0, 0x58, 0x34,
0x03, 0xC0, 0xA0, 0x1C, 0x07, 0x00, 0x60, 0x30, 0x00, 0x60, 0x32, 0x06,
0x30, 0x41, 0x8C, 0x0D, 0x80, 0x70, 0x06, 0x00, 0x70, 0x0D, 0x81, 0x8C,
0x30, 0x43, 0x06, 0x60, 0x30, 0x60, 0x0C, 0x80, 0x33, 0x01, 0x8C, 0x06,
0x18, 0x30, 0x60, 0xC0, 0xC2, 0x03, 0x18, 0x04, 0x40, 0x1B, 0x00, 0x28,
0x00, 0xE0, 0x03, 0x80, 0x0C, 0x00, 0x30, 0x01, 0x80, 0xFC, 0x00, 0xE0,
0x00, 0xFF, 0xFF, 0xF0, 0x18, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x18,
0x0C, 0x06, 0x03, 0x00, 0xFF, 0xC0, 0x0E, 0x3C, 0xC1, 0x83, 0x06, 0x0C,
0x18, 0x30, 0x60, 0xC7, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83,
0x03, 0xC3, 0x80, 0xFF, 0xFF, 0xFE, 0xE1, 0xE0, 0x60, 0xC1, 0x83, 0x06,
0x0C, 0x18, 0x30, 0x60, 0x71, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1,
0x9E, 0x38, 0x00, 0x7C, 0x28, 0xC5, 0x0F, 0x00 };
const GFXglyph Montserrat_Regular12pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 6, 0, 0 }, // 0x20 ' '
{ 1, 2, 17, 6, 2, -16 }, // 0x21 '!'
{ 6, 5, 7, 9, 2, -16 }, // 0x22 '"'
{ 11, 15, 17, 17, 1, -16 }, // 0x23 '#'
{ 43, 13, 23, 15, 1, -19 }, // 0x24 '$'
{ 81, 18, 17, 20, 1, -16 }, // 0x25 '%'
{ 120, 15, 17, 16, 1, -16 }, // 0x26 '&'
{ 152, 1, 7, 5, 2, -16 }, // 0x27 '''
{ 153, 5, 23, 8, 2, -17 }, // 0x28 '('
{ 168, 4, 23, 8, 1, -17 }, // 0x29 ')'
{ 180, 8, 9, 9, 1, -17 }, // 0x2A '*'
{ 189, 10, 10, 14, 2, -12 }, // 0x2B '+'
{ 202, 3, 7, 5, 1, -2 }, // 0x2C ','
{ 205, 7, 1, 9, 1, -6 }, // 0x2D '-'
{ 206, 3, 3, 5, 1, -2 }, // 0x2E '.'
{ 208, 10, 22, 8, -1, -19 }, // 0x2F '/'
{ 236, 14, 17, 16, 1, -16 }, // 0x30 '0'
{ 266, 6, 17, 9, 0, -16 }, // 0x31 '1'
{ 279, 13, 17, 14, 0, -16 }, // 0x32 '2'
{ 307, 12, 17, 14, 0, -16 }, // 0x33 '3'
{ 333, 15, 17, 16, 1, -16 }, // 0x34 '4'
{ 365, 12, 17, 14, 1, -16 }, // 0x35 '5'
{ 391, 13, 17, 15, 1, -16 }, // 0x36 '6'
{ 419, 12, 17, 14, 1, -16 }, // 0x37 '7'
{ 445, 13, 17, 15, 1, -16 }, // 0x38 '8'
{ 473, 12, 17, 15, 1, -16 }, // 0x39 '9'
{ 499, 3, 13, 5, 1, -12 }, // 0x3A ':'
{ 504, 3, 17, 5, 1, -12 }, // 0x3B ';'
{ 511, 10, 10, 14, 2, -12 }, // 0x3C '<'
{ 524, 10, 7, 14, 2, -11 }, // 0x3D '='
{ 533, 10, 10, 14, 2, -12 }, // 0x3E '>'
{ 546, 12, 17, 14, 0, -16 }, // 0x3F '?'
{ 572, 23, 22, 25, 1, -16 }, // 0x40 '@'
{ 636, 17, 17, 17, 0, -16 }, // 0x41 'A'
{ 673, 14, 17, 18, 3, -16 }, // 0x42 'B'
{ 703, 15, 17, 17, 1, -16 }, // 0x43 'C'
{ 735, 16, 17, 20, 3, -16 }, // 0x44 'D'
{ 769, 12, 17, 16, 3, -16 }, // 0x45 'E'
{ 795, 11, 17, 15, 3, -16 }, // 0x46 'F'
{ 819, 15, 17, 19, 1, -16 }, // 0x47 'G'
{ 851, 14, 17, 20, 3, -16 }, // 0x48 'H'
{ 881, 2, 17, 7, 3, -16 }, // 0x49 'I'
{ 886, 9, 17, 12, 0, -16 }, // 0x4A 'J'
{ 906, 14, 17, 17, 3, -16 }, // 0x4B 'K'
{ 936, 11, 17, 14, 3, -16 }, // 0x4C 'L'
{ 960, 17, 17, 23, 3, -16 }, // 0x4D 'M'
{ 997, 14, 17, 20, 3, -16 }, // 0x4E 'N'
{ 1027, 18, 17, 20, 1, -16 }, // 0x4F 'O'
{ 1066, 13, 17, 17, 3, -16 }, // 0x50 'P'
{ 1094, 19, 20, 20, 1, -16 }, // 0x51 'Q'
{ 1142, 13, 17, 17, 3, -16 }, // 0x52 'R'
{ 1170, 13, 17, 15, 1, -16 }, // 0x53 'S'
{ 1198, 14, 17, 14, 0, -16 }, // 0x54 'T'
{ 1228, 13, 17, 19, 3, -16 }, // 0x55 'U'
{ 1256, 17, 17, 17, 0, -16 }, // 0x56 'V'
{ 1293, 25, 17, 27, 1, -16 }, // 0x57 'W'
{ 1347, 15, 17, 16, 0, -16 }, // 0x58 'X'
{ 1379, 15, 17, 15, 0, -16 }, // 0x59 'Y'
{ 1411, 14, 17, 16, 1, -16 }, // 0x5A 'Z'
{ 1441, 4, 23, 8, 3, -17 }, // 0x5B '['
{ 1453, 10, 22, 8, -1, -19 }, // 0x5C '\'
{ 1481, 5, 23, 8, 0, -17 }, // 0x5D ']'
{ 1496, 10, 10, 14, 2, -12 }, // 0x5E '^'
{ 1509, 12, 1, 12, 0, 1 }, // 0x5F '_'
{ 1511, 6, 3, 14, 3, -17 }, // 0x60 '`'
{ 1514, 11, 13, 14, 1, -12 }, // 0x61 'a'
{ 1532, 13, 18, 16, 2, -17 }, // 0x62 'b'
{ 1562, 12, 13, 14, 1, -12 }, // 0x63 'c'
{ 1582, 13, 18, 16, 1, -17 }, // 0x64 'd'
{ 1612, 12, 13, 15, 1, -12 }, // 0x65 'e'
{ 1632, 9, 18, 8, 0, -17 }, // 0x66 'f'
{ 1653, 13, 18, 16, 1, -12 }, // 0x67 'g'
{ 1683, 12, 18, 16, 2, -17 }, // 0x68 'h'
{ 1710, 2, 18, 6, 2, -17 }, // 0x69 'i'
{ 1715, 6, 23, 7, -2, -17 }, // 0x6A 'j'
{ 1733, 12, 18, 14, 2, -17 }, // 0x6B 'k'
{ 1760, 2, 18, 6, 2, -17 }, // 0x6C 'l'
{ 1765, 21, 13, 25, 2, -12 }, // 0x6D 'm'
{ 1800, 12, 13, 16, 2, -12 }, // 0x6E 'n'
{ 1820, 13, 13, 15, 1, -12 }, // 0x6F 'o'
{ 1842, 13, 18, 16, 2, -12 }, // 0x70 'p'
{ 1872, 13, 18, 16, 1, -12 }, // 0x71 'q'
{ 1902, 7, 13, 10, 2, -12 }, // 0x72 'r'
{ 1914, 10, 13, 12, 1, -12 }, // 0x73 's'
{ 1931, 9, 15, 10, 0, -14 }, // 0x74 't'
{ 1948, 12, 13, 16, 2, -12 }, // 0x75 'u'
{ 1968, 13, 13, 13, 0, -12 }, // 0x76 'v'
{ 1990, 21, 13, 21, 0, -12 }, // 0x77 'w'
{ 2025, 12, 13, 13, 0, -12 }, // 0x78 'x'
{ 2045, 14, 18, 13, -1, -12 }, // 0x79 'y'
{ 2077, 10, 13, 12, 1, -12 }, // 0x7A 'z'
{ 2094, 7, 23, 8, 1, -17 }, // 0x7B '{'
{ 2115, 1, 23, 7, 3, -17 }, // 0x7C '|'
{ 2118, 7, 23, 8, 0, -17 }, // 0x7D '}'
{ 2139, 11, 3, 14, 1, -9 } }; // 0x7E '~'
const GFXfont Montserrat_Regular12pt7b PROGMEM = {
(uint8_t *)Montserrat_Regular12pt7bBitmaps,
(GFXglyph *)Montserrat_Regular12pt7bGlyphs,
0x20, 0x7E, 29 };
// Approx. 2816 bytes
#endif // MONTSERRAT12PT7B_H
@@ -0,0 +1,481 @@
#ifndef MONTSERRAT18PT7B_H
#define MONTSERRAT18PT7B_H
const uint8_t Montserrat_Regular18pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0x6C, 0x00, 0x3F, 0xE0, 0xE3,
0xF1, 0xF8, 0xFC, 0x76, 0x1B, 0x0D, 0x86, 0x82, 0x41, 0x20, 0x80, 0x01,
0x80, 0xC0, 0x06, 0x03, 0x00, 0x18, 0x0C, 0x00, 0x60, 0x30, 0x01, 0x80,
0xC0, 0x06, 0x03, 0x00, 0x30, 0x08, 0x1F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFC,
0x0C, 0x06, 0x00, 0x30, 0x18, 0x00, 0xC0, 0x60, 0x03, 0x01, 0x80, 0x0C,
0x06, 0x00, 0x60, 0x10, 0x01, 0x80, 0xC0, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF,
0xE0, 0x60, 0x30, 0x01, 0x80, 0xC0, 0x06, 0x03, 0x00, 0x18, 0x0C, 0x00,
0xC0, 0x20, 0x03, 0x01, 0x80, 0x0C, 0x06, 0x00, 0x00, 0xC0, 0x00, 0x30,
0x00, 0x0C, 0x00, 0x03, 0x00, 0x01, 0xF0, 0x03, 0xFF, 0x83, 0xFF, 0xF9,
0xE3, 0x0C, 0x70, 0xC0, 0x38, 0x30, 0x0E, 0x0C, 0x03, 0x83, 0x00, 0xE0,
0xC0, 0x1C, 0x30, 0x07, 0x8C, 0x00, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x7F,
0x80, 0x0D, 0xF0, 0x03, 0x1E, 0x00, 0xC1, 0xC0, 0x30, 0x70, 0x0C, 0x1C,
0x03, 0x07, 0x80, 0xC1, 0xF8, 0x30, 0xEF, 0x8C, 0xF0, 0xFF, 0xF8, 0x0F,
0xF8, 0x00, 0x30, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0xC0, 0x00, 0x06,
0x00, 0x06, 0x03, 0xF0, 0x01, 0x80, 0xC3, 0x00, 0x70, 0x30, 0x30, 0x0C,
0x06, 0x06, 0x03, 0x00, 0x80, 0x40, 0xE0, 0x30, 0x0C, 0x18, 0x06, 0x01,
0x86, 0x00, 0x40, 0x21, 0x80, 0x0C, 0x0C, 0x30, 0x01, 0x81, 0x8C, 0x00,
0x18, 0x63, 0x00, 0x01, 0xF8, 0x63, 0xF0, 0x0C, 0x18, 0xFF, 0x00, 0x06,
0x38, 0x70, 0x00, 0xC6, 0x06, 0x00, 0x30, 0x80, 0x40, 0x0C, 0x10, 0x08,
0x01, 0x86, 0x01, 0x80, 0x60, 0x40, 0x30, 0x18, 0x08, 0x04, 0x07, 0x01,
0x81, 0x80, 0xC0, 0x30, 0x30, 0x30, 0x03, 0xFC, 0x0E, 0x00, 0x3F, 0x00,
0x01, 0xE0, 0x00, 0x3F, 0xC0, 0x03, 0x87, 0x00, 0x38, 0x18, 0x01, 0x80,
0xE0, 0x0C, 0x03, 0x00, 0x60, 0x38, 0x03, 0x81, 0x80, 0x0C, 0x18, 0x00,
0x73, 0x80, 0x01, 0xF8, 0x00, 0x07, 0x80, 0x00, 0xFC, 0x00, 0x0E, 0x70,
0x00, 0xE1, 0xC1, 0xCE, 0x07, 0x0C, 0xE0, 0x1C, 0x66, 0x00, 0x77, 0x30,
0x01, 0xF1, 0x80, 0x07, 0x8E, 0x00, 0x1C, 0x70, 0x03, 0xF1, 0xE0, 0x39,
0xC7, 0xFF, 0x87, 0x0F, 0xF0, 0x10, 0xFF, 0xF6, 0xDA, 0x48, 0x1C, 0x63,
0x8C, 0x31, 0xC6, 0x18, 0xE3, 0x8E, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
0x30, 0xC3, 0x0E, 0x38, 0xE1, 0x86, 0x1C, 0x30, 0xC3, 0x86, 0x0C, 0x60,
0xE0, 0xC1, 0xC3, 0x83, 0x07, 0x0E, 0x0C, 0x18, 0x30, 0x70, 0xE1, 0xC3,
0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x06, 0x0C, 0x38, 0x70, 0xC3,
0x86, 0x0C, 0x38, 0x60, 0x06, 0x00, 0x60, 0x06, 0x0C, 0x67, 0x77, 0xE1,
0xF8, 0x0F, 0x03, 0xF8, 0xF6, 0xEC, 0x62, 0x06, 0x00, 0x60, 0x06, 0x00,
0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x4E, 0xFE, 0x66, 0x4C, 0xC0, 0xFF,
0xFF, 0xFF, 0xE0, 0x4E, 0xFE, 0x00, 0x1C, 0x00, 0x60, 0x01, 0x80, 0x0E,
0x00, 0x30, 0x00, 0xC0, 0x07, 0x00, 0x18, 0x00, 0x60, 0x03, 0x00, 0x0C,
0x00, 0x70, 0x01, 0x80, 0x06, 0x00, 0x38, 0x00, 0xC0, 0x03, 0x00, 0x1C,
0x00, 0x60, 0x01, 0x80, 0x0E, 0x00, 0x30, 0x00, 0xC0, 0x07, 0x00, 0x18,
0x00, 0x60, 0x03, 0x80, 0x0C, 0x00, 0x30, 0x01, 0x80, 0x06, 0x00, 0x38,
0x00, 0xC0, 0x00, 0x00, 0xE0, 0x00, 0xFF, 0x80, 0x3F, 0xFC, 0x0E, 0x03,
0xC3, 0x80, 0x38, 0xE0, 0x03, 0x9C, 0x00, 0x33, 0x00, 0x07, 0xE0, 0x00,
0xFC, 0x00, 0x0F, 0x00, 0x01, 0xE0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x00,
0xF0, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0xFC, 0x00, 0x1D, 0x80, 0x03,
0x38, 0x00, 0xE3, 0x80, 0x1C, 0x78, 0x07, 0x07, 0x83, 0xC0, 0x7F, 0xF0,
0x03, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07,
0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0,
0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x80, 0x03, 0xE0, 0x07, 0xFE,
0x07, 0xFF, 0xE3, 0xC0, 0x3C, 0xC0, 0x07, 0x00, 0x00, 0xC0, 0x00, 0x30,
0x00, 0x0C, 0x00, 0x03, 0x00, 0x01, 0xC0, 0x00, 0x70, 0x00, 0x38, 0x00,
0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0,
0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03,
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0x9F, 0xFF, 0xE7, 0xFF, 0xF8,
0x00, 0x1C, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00,
0x70, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x07, 0xE0, 0x01, 0xFE, 0x00, 0x03,
0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x01, 0xC0, 0x00, 0x70, 0x00, 0x1C,
0x00, 0x07, 0x40, 0x01, 0xD8, 0x00, 0xE7, 0xC0, 0xF0, 0xFF, 0xF8, 0x0F,
0xF8, 0x00, 0x00, 0x07, 0x00, 0x00, 0x18, 0x00, 0x00, 0xE0, 0x00, 0x07,
0x00, 0x00, 0x38, 0x00, 0x01, 0xC0, 0x00, 0x06, 0x00, 0x00, 0x38, 0x00,
0x01, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x70, 0x00, 0x01, 0x80, 0xE0, 0x0E,
0x03, 0x80, 0x70, 0x0E, 0x03, 0x80, 0x38, 0x1C, 0x00, 0xE0, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xE0, 0x00, 0x03, 0x80,
0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0xE0, 0x00, 0x03, 0x80, 0x1F,
0xFF, 0x0F, 0xFF, 0x87, 0xFF, 0xC7, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00,
0xE0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0C, 0x00, 0x07, 0xFF,
0x03, 0xFF, 0xE0, 0x00, 0x78, 0x00, 0x1E, 0x00, 0x07, 0x00, 0x01, 0x80,
0x00, 0xC0, 0x00, 0x60, 0x00, 0x30, 0x00, 0x3F, 0x00, 0x3B, 0xE0, 0x7C,
0x7F, 0xFC, 0x0F, 0xF8, 0x00, 0x00, 0x7C, 0x00, 0xFF, 0xE0, 0xFF, 0xF0,
0x78, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x07, 0x00, 0x01, 0x80, 0x00, 0xE0,
0x00, 0x38, 0x00, 0x0C, 0x0F, 0x03, 0x1F, 0xF8, 0xCF, 0xBF, 0x37, 0x00,
0xEF, 0x80, 0x1F, 0xC0, 0x07, 0xE0, 0x00, 0xF8, 0x00, 0x36, 0x00, 0x0D,
0xC0, 0x07, 0x70, 0x01, 0xCE, 0x00, 0xE1, 0xE0, 0x78, 0x3F, 0xF8, 0x03,
0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x07, 0xE0,
0x03, 0xB8, 0x00, 0xEE, 0x00, 0x70, 0x00, 0x1C, 0x00, 0x06, 0x00, 0x03,
0x80, 0x00, 0xC0, 0x00, 0x70, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x03, 0x80,
0x01, 0xC0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x01,
0xC0, 0x00, 0x60, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x00, 0x01,
0xF0, 0x01, 0xFF, 0xC0, 0xFC, 0xFC, 0x3C, 0x03, 0xC7, 0x00, 0x38, 0xC0,
0x03, 0x98, 0x00, 0x73, 0x00, 0x0E, 0x60, 0x01, 0xCE, 0x00, 0x70, 0xE0,
0x1C, 0x0F, 0xFF, 0x00, 0xFF, 0xE0, 0x7C, 0x3E, 0x1C, 0x00, 0xE7, 0x00,
0x0E, 0xE0, 0x00, 0xD8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7E, 0x00,
0x1C, 0xE0, 0x03, 0x9F, 0x01, 0xE1, 0xFF, 0xF8, 0x0F, 0xFC, 0x00, 0x03,
0xC0, 0x01, 0xFF, 0x80, 0xFD, 0xF8, 0x3C, 0x03, 0x87, 0x00, 0x39, 0xC0,
0x07, 0x38, 0x00, 0x77, 0x00, 0x0E, 0xE0, 0x01, 0xDC, 0x00, 0x39, 0x80,
0x0F, 0x38, 0x03, 0xE3, 0xC0, 0xEC, 0x3F, 0xF9, 0x81, 0xFC, 0x30, 0x00,
0x06, 0x00, 0x00, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x01, 0xC0, 0x00,
0x30, 0x00, 0x1E, 0x0C, 0x0F, 0x81, 0xFF, 0xE0, 0x1F, 0xF0, 0x00, 0x4E,
0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xEF, 0xE0, 0x4E, 0xFE, 0x00,
0x00, 0x00, 0x00, 0x00, 0x04, 0xEF, 0xE6, 0x64, 0xCC, 0x00, 0x00, 0x00,
0x07, 0x00, 0x1F, 0x00, 0xFC, 0x03, 0xE0, 0x1F, 0x80, 0x7C, 0x00, 0xE0,
0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0xC0, 0x01, 0xF0, 0x00, 0x7E, 0x00,
0x0F, 0x00, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0xE0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00,
0x3E, 0x00, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x03, 0xF0, 0x0F, 0x80, 0x7E,
0x00, 0xF0, 0x00, 0xC0, 0x00, 0x01, 0xF0, 0x07, 0xFE, 0x0F, 0xFF, 0xCF,
0x00, 0xE6, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x06, 0x00, 0x03, 0x00, 0x03,
0x80, 0x01, 0x80, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xC0, 0x01,
0xC0, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x00,
0x03, 0xE0, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x01, 0xF0, 0x0F, 0x80, 0x03,
0x80, 0x01, 0xE0, 0x07, 0x00, 0x00, 0x70, 0x0C, 0x00, 0x00, 0x38, 0x18,
0x00, 0x00, 0x1C, 0x30, 0x07, 0xC1, 0x8C, 0x30, 0x1F, 0xF1, 0x86, 0x60,
0x3C, 0x3D, 0x86, 0x60, 0x70, 0x0D, 0x83, 0xC0, 0xE0, 0x07, 0x83, 0xC0,
0xC0, 0x03, 0x83, 0xC1, 0xC0, 0x03, 0x83, 0xC1, 0x80, 0x03, 0x83, 0xC1,
0x80, 0x03, 0x81, 0xC1, 0x80, 0x01, 0x81, 0xC1, 0x80, 0x03, 0x83, 0xC1,
0xC0, 0x03, 0x83, 0xC1, 0xC0, 0x03, 0x83, 0xC0, 0xE0, 0x07, 0x83, 0x60,
0xE0, 0x0F, 0x86, 0x60, 0x78, 0x1D, 0x86, 0x70, 0x3F, 0xF9, 0xFC, 0x30,
0x0F, 0xE0, 0xF8, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0E,
0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x01, 0xE0, 0x06, 0x00, 0x00,
0x7F, 0xFE, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x0E,
0x00, 0x00, 0x0F, 0x80, 0x00, 0x06, 0xC0, 0x00, 0x07, 0x70, 0x00, 0x03,
0x98, 0x00, 0x01, 0x8E, 0x00, 0x01, 0xC7, 0x00, 0x00, 0xC1, 0x80, 0x00,
0xE0, 0xE0, 0x00, 0x60, 0x30, 0x00, 0x70, 0x1C, 0x00, 0x30, 0x06, 0x00,
0x38, 0x03, 0x80, 0x18, 0x00, 0xC0, 0x1C, 0x00, 0x70, 0x0F, 0xFF, 0xF8,
0x0F, 0xFF, 0xFE, 0x07, 0x00, 0x07, 0x03, 0x00, 0x01, 0xC3, 0x80, 0x00,
0xE1, 0x80, 0x00, 0x31, 0xC0, 0x00, 0x1C, 0xC0, 0x00, 0x06, 0xE0, 0x00,
0x03, 0x80, 0xFF, 0xE0, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0x8E, 0x00, 0x3C,
0xE0, 0x00, 0xEE, 0x00, 0x0E, 0xE0, 0x00, 0x6E, 0x00, 0x06, 0xE0, 0x00,
0xEE, 0x00, 0x0E, 0xE0, 0x01, 0xCE, 0x01, 0xF8, 0xFF, 0xFF, 0x0F, 0xFF,
0xFC, 0xE0, 0x00, 0xEE, 0x00, 0x07, 0xE0, 0x00, 0x3E, 0x00, 0x03, 0xE0,
0x00, 0x3E, 0x00, 0x03, 0xE0, 0x00, 0x7E, 0x00, 0x07, 0xE0, 0x03, 0xEF,
0xFF, 0xFC, 0xFF, 0xFF, 0x00, 0x00, 0x3E, 0x00, 0x07, 0xFF, 0x00, 0x7F,
0xFF, 0x03, 0xC0, 0x1E, 0x1E, 0x00, 0x18, 0xE0, 0x00, 0x07, 0x00, 0x00,
0x1C, 0x00, 0x00, 0xE0, 0x00, 0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x30,
0x00, 0x00, 0xC0, 0x00, 0x03, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x38, 0x00,
0x00, 0xE0, 0x00, 0x01, 0x80, 0x00, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00,
0x3C, 0x00, 0x18, 0x78, 0x00, 0xF0, 0xFC, 0x0F, 0x80, 0xFF, 0xF8, 0x00,
0xFF, 0x80, 0xFF, 0xC0, 0x01, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0x07, 0x00,
0x1F, 0x0E, 0x00, 0x0F, 0x1C, 0x00, 0x07, 0x38, 0x00, 0x0F, 0x70, 0x00,
0x0E, 0xE0, 0x00, 0x0D, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00, 0x00,
0x7E, 0x00, 0x00, 0xFC, 0x00, 0x01, 0xF8, 0x00, 0x03, 0xF0, 0x00, 0x07,
0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x3B, 0x80, 0x00, 0x77, 0x00, 0x01, 0xCE,
0x00, 0x07, 0x1C, 0x00, 0x3E, 0x38, 0x03, 0xF0, 0x7F, 0xFF, 0xC0, 0xFF,
0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x0E, 0x00,
0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38,
0x00, 0x1F, 0xFF, 0xCF, 0xFF, 0xE7, 0xFF, 0xF3, 0x80, 0x01, 0xC0, 0x00,
0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00,
0x03, 0x80, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFC, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0,
0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0F, 0xFF, 0xE7,
0xFF, 0xF3, 0xFF, 0xF9, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00,
0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0,
0x00, 0x00, 0x00, 0x3E, 0x00, 0x07, 0xFF, 0x80, 0x7F, 0xFF, 0x03, 0xC0,
0x1F, 0x1E, 0x00, 0x18, 0xE0, 0x00, 0x07, 0x00, 0x00, 0x1C, 0x00, 0x00,
0xE0, 0x00, 0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x30, 0x00, 0x00, 0xC0,
0x00, 0x03, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xF8, 0x00, 0x07, 0xE0, 0x00,
0x1D, 0x80, 0x00, 0x77, 0x00, 0x01, 0xCE, 0x00, 0x07, 0x3C, 0x00, 0x1C,
0x78, 0x00, 0xF0, 0xFC, 0x0F, 0x80, 0xFF, 0xFC, 0x00, 0xFF, 0x80, 0xE0,
0x00, 0x3E, 0x00, 0x03, 0xE0, 0x00, 0x3E, 0x00, 0x03, 0xE0, 0x00, 0x3E,
0x00, 0x03, 0xE0, 0x00, 0x3E, 0x00, 0x03, 0xE0, 0x00, 0x3E, 0x00, 0x03,
0xE0, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00,
0x3E, 0x00, 0x03, 0xE0, 0x00, 0x3E, 0x00, 0x03, 0xE0, 0x00, 0x3E, 0x00,
0x03, 0xE0, 0x00, 0x3E, 0x00, 0x03, 0xE0, 0x00, 0x3E, 0x00, 0x03, 0xE0,
0x00, 0x30, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
0x3F, 0xFC, 0xFF, 0xF3, 0xFF, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01,
0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00,
0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x40,
0x1B, 0x80, 0xEF, 0x07, 0x9F, 0xFC, 0x1F, 0xC0, 0xE0, 0x00, 0x77, 0x00,
0x07, 0x38, 0x00, 0x71, 0xC0, 0x07, 0x0E, 0x00, 0x70, 0x70, 0x07, 0x03,
0x80, 0x70, 0x1C, 0x07, 0x00, 0xE0, 0x70, 0x07, 0x07, 0x00, 0x38, 0x70,
0x01, 0xC7, 0x00, 0x0E, 0x7C, 0x00, 0x77, 0xF0, 0x03, 0xFB, 0xC0, 0x1F,
0x8F, 0x00, 0xF8, 0x3C, 0x07, 0x80, 0xE0, 0x38, 0x03, 0x81, 0xC0, 0x0E,
0x0E, 0x00, 0x38, 0x70, 0x00, 0xE3, 0x80, 0x07, 0x9C, 0x00, 0x1C, 0xE0,
0x00, 0x70, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0xF8, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0x70,
0x00, 0x37, 0x98, 0x00, 0x3B, 0xCE, 0x00, 0x19, 0xE3, 0x00, 0x1C, 0xF1,
0xC0, 0x1C, 0x78, 0x70, 0x0C, 0x3C, 0x18, 0x0E, 0x1E, 0x0E, 0x06, 0x0F,
0x03, 0x07, 0x07, 0x81, 0xC3, 0x03, 0xC0, 0x73, 0x01, 0xE0, 0x1B, 0x80,
0xF0, 0x0F, 0x80, 0x78, 0x03, 0xC0, 0x3C, 0x01, 0xC0, 0x1E, 0x00, 0x60,
0x0F, 0x00, 0x00, 0x07, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0x80, 0xC0,
0x00, 0x3E, 0x00, 0x03, 0xF0, 0x00, 0x3F, 0x80, 0x03, 0xF8, 0x00, 0x3F,
0xC0, 0x03, 0xEE, 0x00, 0x3E, 0xF0, 0x03, 0xE7, 0x00, 0x3E, 0x38, 0x03,
0xE1, 0xC0, 0x3E, 0x0E, 0x03, 0xE0, 0xF0, 0x3E, 0x07, 0x03, 0xE0, 0x38,
0x3E, 0x01, 0xC3, 0xE0, 0x0E, 0x3E, 0x00, 0xF3, 0xE0, 0x07, 0x3E, 0x00,
0x3B, 0xE0, 0x01, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x07, 0xE0,
0x00, 0x30, 0x00, 0x3E, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x7F, 0xFF, 0x00,
0x3C, 0x01, 0xF0, 0x1C, 0x00, 0x1E, 0x0E, 0x00, 0x03, 0x87, 0x00, 0x00,
0x71, 0xC0, 0x00, 0x0C, 0xE0, 0x00, 0x03, 0xB8, 0x00, 0x00, 0xEE, 0x00,
0x00, 0x1B, 0x00, 0x00, 0x06, 0xC0, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x7E,
0x00, 0x00, 0x1B, 0x80, 0x00, 0x06, 0xE0, 0x00, 0x03, 0x98, 0x00, 0x00,
0xE7, 0x00, 0x00, 0x70, 0xE0, 0x00, 0x3C, 0x3C, 0x00, 0x1E, 0x07, 0x80,
0x0F, 0x00, 0xFC, 0x0F, 0x80, 0x0F, 0xFF, 0xC0, 0x00, 0xFF, 0x80, 0x00,
0xFF, 0xC0, 0x1F, 0xFF, 0xC3, 0xFF, 0xFC, 0x70, 0x03, 0xCE, 0x00, 0x1D,
0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0x7C, 0x00, 0x0F,
0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0D, 0xC0, 0x03, 0xB8, 0x01, 0xE7,
0xFF, 0xF8, 0xFF, 0xFC, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0E,
0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x00,
0x00, 0x3E, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0x80,
0x3E, 0x01, 0xC0, 0x01, 0xE0, 0x70, 0x00, 0x1C, 0x1C, 0x00, 0x01, 0xC3,
0x80, 0x00, 0x18, 0xE0, 0x00, 0x03, 0x9C, 0x00, 0x00, 0x73, 0x80, 0x00,
0x06, 0x60, 0x00, 0x00, 0xCC, 0x00, 0x00, 0x1D, 0x80, 0x00, 0x03, 0xB8,
0x00, 0x00, 0x67, 0x00, 0x00, 0x0C, 0xE0, 0x00, 0x03, 0x8E, 0x00, 0x00,
0x71, 0xC0, 0x00, 0x1C, 0x1C, 0x00, 0x07, 0x83, 0xC0, 0x01, 0xE0, 0x3C,
0x00, 0x78, 0x03, 0xF0, 0x3E, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0xFF, 0x80,
0x00, 0x00, 0xE0, 0x00, 0x00, 0x0E, 0x03, 0x00, 0x00, 0xF0, 0xE0, 0x00,
0x0F, 0xF8, 0x00, 0x00, 0x7C, 0x00, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0xFF,
0xFF, 0x0E, 0x00, 0x78, 0xE0, 0x01, 0xCE, 0x00, 0x0E, 0xE0, 0x00, 0xEE,
0x00, 0x0E, 0xE0, 0x00, 0x6E, 0x00, 0x06, 0xE0, 0x00, 0xEE, 0x00, 0x0E,
0xE0, 0x00, 0xCE, 0x00, 0x1C, 0xE0, 0x07, 0x8F, 0xFF, 0xF0, 0xFF, 0xFC,
0x0E, 0x01, 0xC0, 0xE0, 0x0E, 0x0E, 0x00, 0x70, 0xE0, 0x03, 0x0E, 0x00,
0x38, 0xE0, 0x01, 0xCE, 0x00, 0x0E, 0xE0, 0x00, 0xE0, 0x01, 0xF0, 0x03,
0xFF, 0x83, 0xFF, 0xF9, 0xE0, 0x0C, 0x70, 0x00, 0x38, 0x00, 0x0E, 0x00,
0x03, 0x80, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x07, 0x80, 0x00, 0xFE, 0x00,
0x0F, 0xF8, 0x00, 0x7F, 0x80, 0x01, 0xF0, 0x00, 0x1E, 0x00, 0x01, 0xC0,
0x00, 0x70, 0x00, 0x1C, 0x00, 0x07, 0x80, 0x01, 0xF8, 0x00, 0xEF, 0x80,
0xF0, 0xFF, 0xF8, 0x0F, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0x06, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00,
0x06, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00,
0x00, 0x60, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x00, 0x60,
0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x06,
0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0xC0, 0x00, 0x7C,
0x00, 0x07, 0xC0, 0x00, 0x7C, 0x00, 0x07, 0xC0, 0x00, 0x7C, 0x00, 0x07,
0xC0, 0x00, 0x7C, 0x00, 0x07, 0xC0, 0x00, 0x7C, 0x00, 0x07, 0xC0, 0x00,
0x7C, 0x00, 0x07, 0xC0, 0x00, 0x7C, 0x00, 0x07, 0xC0, 0x00, 0x7C, 0x00,
0x07, 0xC0, 0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00, 0x66, 0x00, 0x0E, 0x70,
0x00, 0xE3, 0x80, 0x1C, 0x3E, 0x07, 0x80, 0xFF, 0xF0, 0x03, 0xFC, 0x00,
0xE0, 0x00, 0x03, 0x60, 0x00, 0x07, 0x70, 0x00, 0x06, 0x70, 0x00, 0x0E,
0x38, 0x00, 0x0E, 0x38, 0x00, 0x0C, 0x1C, 0x00, 0x1C, 0x1C, 0x00, 0x18,
0x0C, 0x00, 0x38, 0x0E, 0x00, 0x30, 0x06, 0x00, 0x70, 0x07, 0x00, 0x70,
0x07, 0x00, 0xE0, 0x03, 0x80, 0xE0, 0x03, 0x80, 0xC0, 0x01, 0xC1, 0xC0,
0x01, 0xC1, 0x80, 0x00, 0xC3, 0x80, 0x00, 0xE3, 0x00, 0x00, 0x67, 0x00,
0x00, 0x77, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3C, 0x00,
0x00, 0x1C, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x3B, 0x00, 0x03, 0x80, 0x01,
0x9C, 0x00, 0x1C, 0x00, 0x1C, 0xE0, 0x01, 0xF0, 0x00, 0xE3, 0x00, 0x0D,
0x80, 0x06, 0x1C, 0x00, 0x6C, 0x00, 0x70, 0xE0, 0x07, 0x70, 0x03, 0x83,
0x00, 0x31, 0x80, 0x18, 0x1C, 0x01, 0x8C, 0x01, 0xC0, 0xE0, 0x1C, 0x70,
0x0E, 0x03, 0x00, 0xC1, 0x80, 0x60, 0x1C, 0x06, 0x0C, 0x07, 0x00, 0xE0,
0x70, 0x70, 0x38, 0x03, 0x03, 0x01, 0x81, 0x80, 0x1C, 0x38, 0x0C, 0x1C,
0x00, 0xE1, 0xC0, 0x70, 0xE0, 0x03, 0x0C, 0x01, 0x86, 0x00, 0x1C, 0xE0,
0x0E, 0x70, 0x00, 0xE7, 0x00, 0x73, 0x80, 0x03, 0x30, 0x01, 0x98, 0x00,
0x1F, 0x80, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x7E, 0x00, 0x03, 0xC0, 0x01,
0xE0, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x00, 0xE0, 0x00, 0x78, 0x00, 0xE0,
0x00, 0x3B, 0x80, 0x03, 0x8E, 0x00, 0x38, 0x70, 0x01, 0xC1, 0xC0, 0x1C,
0x07, 0x01, 0xC0, 0x1C, 0x1C, 0x00, 0xE0, 0xE0, 0x03, 0x8E, 0x00, 0x0E,
0xE0, 0x00, 0x3E, 0x00, 0x01, 0xF0, 0x00, 0x07, 0x00, 0x00, 0x7C, 0x00,
0x07, 0x70, 0x00, 0x3B, 0x80, 0x03, 0x8E, 0x00, 0x38, 0x38, 0x03, 0x80,
0xE0, 0x1C, 0x07, 0x01, 0xC0, 0x1C, 0x1C, 0x00, 0x71, 0xC0, 0x01, 0xCE,
0x00, 0x0E, 0xE0, 0x00, 0x38, 0xE0, 0x00, 0x0D, 0x80, 0x00, 0x77, 0x00,
0x03, 0x8E, 0x00, 0x0C, 0x38, 0x00, 0x70, 0x70, 0x01, 0x80, 0xC0, 0x0E,
0x03, 0x80, 0x70, 0x07, 0x01, 0x80, 0x0C, 0x0E, 0x00, 0x38, 0x70, 0x00,
0x71, 0x80, 0x01, 0xCE, 0x00, 0x03, 0xB0, 0x00, 0x07, 0xC0, 0x00, 0x1E,
0x00, 0x00, 0x30, 0x00, 0x00, 0xC0, 0x00, 0x03, 0x00, 0x00, 0x0C, 0x00,
0x00, 0x30, 0x00, 0x00, 0xC0, 0x00, 0x03, 0x00, 0x00, 0x0C, 0x00, 0x00,
0x30, 0x00, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xE0, 0x00, 0x1C,
0x00, 0x03, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C,
0x00, 0x03, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C,
0x00, 0x03, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C,
0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x0F,
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFC, 0x30, 0xC3, 0x0C, 0x30, 0xC3,
0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3,
0x0C, 0x30, 0xC3, 0x0C, 0x3F, 0xFC, 0xC0, 0x03, 0x80, 0x06, 0x00, 0x18,
0x00, 0x30, 0x00, 0xC0, 0x03, 0x00, 0x06, 0x00, 0x18, 0x00, 0x70, 0x00,
0xC0, 0x03, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x60, 0x01, 0xC0, 0x03, 0x00,
0x0C, 0x00, 0x38, 0x00, 0x60, 0x01, 0x80, 0x07, 0x00, 0x0C, 0x00, 0x30,
0x00, 0x60, 0x01, 0x80, 0x06, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xE0, 0x01,
0x80, 0x06, 0x00, 0x1C, 0xFF, 0xF0, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30,
0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30,
0xC3, 0x0C, 0x30, 0xFF, 0xFC, 0x03, 0x00, 0x0E, 0x00, 0x78, 0x01, 0xE0,
0x0C, 0xC0, 0x33, 0x01, 0xC6, 0x06, 0x18, 0x18, 0x30, 0xC0, 0xC3, 0x03,
0x18, 0x06, 0x60, 0x19, 0x80, 0x3C, 0x00, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xE0, 0x70, 0x38, 0x0C, 0x07, 0x01, 0x00, 0x3F, 0xE1, 0xFF, 0xF3,
0x80, 0xE4, 0x00, 0xE0, 0x00, 0xC0, 0x01, 0x80, 0x03, 0x00, 0x06, 0x3F,
0xFD, 0xF8, 0x1F, 0x00, 0x3E, 0x00, 0x78, 0x00, 0xF0, 0x03, 0xF0, 0x07,
0x70, 0x3E, 0xFF, 0xEC, 0x7F, 0x18, 0xE0, 0x00, 0x1C, 0x00, 0x03, 0x80,
0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00,
0x00, 0xE3, 0xFC, 0x1D, 0xFF, 0xE3, 0xF0, 0x1E, 0x7C, 0x00, 0xEF, 0x00,
0x1D, 0xE0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0x7C, 0x00,
0x0F, 0x80, 0x03, 0xF0, 0x00, 0x7F, 0x00, 0x0D, 0xE0, 0x03, 0xBE, 0x00,
0xE7, 0x70, 0x7C, 0xE7, 0xFE, 0x1C, 0x7F, 0x80, 0x00, 0x40, 0x0F, 0xFC,
0x1F, 0xFE, 0x3C, 0x0F, 0x70, 0x03, 0x60, 0x00, 0xE0, 0x00, 0xC0, 0x00,
0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0x70, 0x02, 0x78, 0x07, 0x3C, 0x0F, 0x1F, 0xFE, 0x07, 0xF8, 0x00, 0x00,
0xC0, 0x00, 0x30, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x00, 0xC0, 0x00, 0x30,
0x00, 0x0C, 0x02, 0x03, 0x0F, 0xF8, 0xC7, 0xFF, 0x33, 0xC0, 0xED, 0xC0,
0x0F, 0xE0, 0x01, 0xF8, 0x00, 0x7C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00,
0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x80, 0x07, 0xE0, 0x01, 0xDC, 0x00, 0xF7,
0x80, 0x7C, 0xF0, 0x3B, 0x1F, 0xFC, 0xC1, 0xFC, 0x30, 0x00, 0xC0, 0x03,
0xFE, 0x01, 0xFF, 0xC0, 0xE0, 0x38, 0x70, 0x07, 0x38, 0x00, 0xEE, 0x00,
0x1B, 0x00, 0x06, 0xC0, 0x01, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x01, 0xE0, 0x0C, 0x3E, 0x0F, 0x07,
0xFF, 0x80, 0x7F, 0x80, 0x07, 0xE0, 0xFF, 0x1E, 0x01, 0xC0, 0x18, 0x01,
0x80, 0x18, 0x01, 0x80, 0xFF, 0xEF, 0xFE, 0x18, 0x01, 0x80, 0x18, 0x01,
0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01,
0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x00, 0x80, 0x01, 0xFF, 0x1C,
0x7F, 0xFB, 0x9C, 0x03, 0xF7, 0x00, 0x3F, 0xC0, 0x03, 0xF8, 0x00, 0x3E,
0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7E,
0x00, 0x1E, 0xC0, 0x03, 0xDC, 0x00, 0xF9, 0xE0, 0x77, 0x1F, 0xFC, 0xE0,
0xFF, 0x1C, 0x00, 0x03, 0x00, 0x00, 0x60, 0x00, 0x1C, 0x00, 0x03, 0x9C,
0x00, 0xE3, 0xF0, 0xF8, 0x1F, 0xFE, 0x00, 0xFF, 0x00, 0xE0, 0x00, 0x70,
0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01,
0xC0, 0x80, 0xE7, 0xFC, 0x77, 0xFF, 0x3F, 0x01, 0xDF, 0x00, 0x7F, 0x00,
0x3F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xE0, 0x01, 0xF0, 0x00, 0xF8,
0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03,
0xE0, 0x01, 0xF0, 0x00, 0xC0, 0xFF, 0xA0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFC, 0x03, 0x81, 0xC0, 0xE0, 0x20, 0x00, 0x00, 0x00, 0x00,
0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0,
0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18,
0x1F, 0x1D, 0xFE, 0x7C, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03,
0x80, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x00, 0xE0,
0x07, 0x38, 0x03, 0x8E, 0x01, 0xC3, 0x80, 0xE0, 0xE0, 0x70, 0x38, 0x78,
0x0E, 0x3C, 0x03, 0x9E, 0x00, 0xEF, 0xC0, 0x3F, 0x38, 0x0F, 0x87, 0x03,
0xC1, 0xE0, 0xE0, 0x38, 0x38, 0x07, 0x0E, 0x00, 0xE3, 0x80, 0x1C, 0xE0,
0x07, 0xB8, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFC, 0x00, 0x60, 0x01, 0x01, 0xCF, 0xF8, 0x3F, 0xE3, 0xBF, 0xF8,
0xFF, 0xE7, 0xE0, 0x7B, 0x81, 0xEF, 0x80, 0x7E, 0x01, 0xDE, 0x00, 0x78,
0x01, 0xF8, 0x00, 0xE0, 0x03, 0xF0, 0x01, 0xC0, 0x07, 0xE0, 0x03, 0x80,
0x0F, 0xC0, 0x07, 0x00, 0x1F, 0x80, 0x0E, 0x00, 0x3F, 0x00, 0x1C, 0x00,
0x7E, 0x00, 0x38, 0x00, 0xFC, 0x00, 0x70, 0x01, 0xF8, 0x00, 0xE0, 0x03,
0xF0, 0x01, 0xC0, 0x07, 0xE0, 0x03, 0x80, 0x0F, 0xC0, 0x07, 0x00, 0x1F,
0x80, 0x0E, 0x00, 0x38, 0x00, 0x40, 0x73, 0xFE, 0x3B, 0xFF, 0x9F, 0x80,
0xEF, 0x80, 0x3F, 0x80, 0x1F, 0x80, 0x07, 0xC0, 0x03, 0xE0, 0x01, 0xF0,
0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07,
0xC0, 0x03, 0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x60, 0x00, 0x00, 0x03,
0xFF, 0x01, 0xFF, 0xE0, 0xF0, 0x3C, 0x70, 0x03, 0x98, 0x00, 0x6E, 0x00,
0x1F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03,
0xE0, 0x01, 0xF8, 0x00, 0x77, 0x00, 0x39, 0xE0, 0x1E, 0x3C, 0x0F, 0x07,
0xFF, 0x80, 0x7F, 0x80, 0x00, 0x00, 0x1C, 0x7F, 0x83, 0xBF, 0xFC, 0x7E,
0x03, 0xCF, 0x80, 0x1D, 0xE0, 0x03, 0xBC, 0x00, 0x3F, 0x00, 0x07, 0xE0,
0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xE0,
0x01, 0xBC, 0x00, 0x77, 0xC0, 0x1C, 0xEE, 0x0F, 0x9C, 0xFF, 0xC3, 0x8F,
0xF0, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00,
0x00, 0xE0, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x80, 0x03, 0xFE, 0x31, 0xFF,
0xCC, 0xF0, 0x3B, 0x70, 0x03, 0xF8, 0x00, 0x7E, 0x00, 0x1F, 0x00, 0x07,
0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xE0, 0x01, 0xF8,
0x00, 0x77, 0x00, 0x3D, 0xE0, 0x1F, 0x3C, 0x0E, 0xC7, 0xFF, 0x30, 0x7F,
0x0C, 0x00, 0x03, 0x00, 0x00, 0xC0, 0x00, 0x30, 0x00, 0x0C, 0x00, 0x03,
0x00, 0x00, 0xC0, 0x00, 0x30, 0x00, 0x79, 0xFE, 0xFF, 0xF0, 0xF8, 0x3C,
0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03,
0x80, 0xE0, 0x38, 0x0E, 0x00, 0x01, 0x00, 0x3F, 0xF0, 0xFF, 0xF3, 0x80,
0x66, 0x00, 0x0C, 0x00, 0x18, 0x00, 0x38, 0x00, 0x7E, 0x00, 0x3F, 0xC0,
0x1F, 0xE0, 0x01, 0xE0, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0xA0, 0x07, 0xF0,
0x1C, 0xFF, 0xF0, 0x7F, 0xC0, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0xFF,
0xEF, 0xFE, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18,
0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0x80, 0x1C, 0x01, 0xE0, 0x0F,
0xF0, 0x7E, 0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00,
0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xE0, 0x01, 0xF0, 0x00, 0xF8,
0x00, 0xFC, 0x00, 0x7E, 0x00, 0x3B, 0x80, 0x3D, 0xC0, 0x1E, 0x78, 0x3B,
0x1F, 0xF9, 0x87, 0xF8, 0xC0, 0xE0, 0x00, 0xEC, 0x00, 0x19, 0xC0, 0x07,
0x18, 0x00, 0xC3, 0x80, 0x38, 0x30, 0x06, 0x07, 0x01, 0xC0, 0x60, 0x30,
0x0E, 0x06, 0x01, 0xC1, 0xC0, 0x18, 0x30, 0x03, 0x8E, 0x00, 0x31, 0x80,
0x07, 0x70, 0x00, 0x6C, 0x00, 0x0F, 0x80, 0x00, 0xE0, 0x00, 0x1C, 0x00,
0x60, 0x03, 0x80, 0x0D, 0x80, 0x0E, 0x00, 0x77, 0x00, 0x7C, 0x01, 0x8C,
0x01, 0xB0, 0x06, 0x30, 0x0E, 0xC0, 0x38, 0xE0, 0x33, 0x80, 0xC1, 0x80,
0xC6, 0x03, 0x07, 0x07, 0x18, 0x1C, 0x0C, 0x18, 0x30, 0x60, 0x30, 0x60,
0xC3, 0x80, 0xE3, 0x03, 0x8C, 0x01, 0x8C, 0x06, 0x30, 0x06, 0x70, 0x19,
0xC0, 0x1D, 0x80, 0x76, 0x00, 0x36, 0x00, 0xD8, 0x00, 0xF8, 0x03, 0xC0,
0x01, 0xC0, 0x07, 0x00, 0x07, 0x00, 0x1C, 0x00, 0x60, 0x07, 0x38, 0x07,
0x0E, 0x03, 0x03, 0x83, 0x80, 0xE3, 0x80, 0x33, 0x80, 0x1D, 0x80, 0x07,
0xC0, 0x01, 0xC0, 0x01, 0xE0, 0x01, 0xF8, 0x00, 0xCE, 0x00, 0xE3, 0x80,
0xE0, 0xE0, 0xE0, 0x30, 0x60, 0x1C, 0x70, 0x07, 0x70, 0x01, 0xC0, 0x70,
0x00, 0x73, 0x00, 0x06, 0x38, 0x00, 0xE1, 0x80, 0x0C, 0x1C, 0x01, 0xC0,
0xC0, 0x18, 0x0E, 0x03, 0x80, 0x60, 0x30, 0x07, 0x03, 0x00, 0x70, 0x70,
0x03, 0x06, 0x00, 0x38, 0xE0, 0x01, 0x8C, 0x00, 0x1D, 0xC0, 0x00, 0xD8,
0x00, 0x0F, 0x80, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x06,
0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x63, 0x80, 0x0F, 0xF8, 0x00, 0x3E,
0x00, 0x00, 0x7F, 0xFE, 0xFF, 0xFC, 0x00, 0x70, 0x00, 0xC0, 0x03, 0x80,
0x0E, 0x00, 0x38, 0x00, 0xE0, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70,
0x01, 0xC0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xFF, 0xFF, 0xFF, 0xFC,
0x07, 0x87, 0xC7, 0x03, 0x81, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06,
0x03, 0x01, 0x80, 0xC0, 0x61, 0xF0, 0xF0, 0x3C, 0x06, 0x03, 0x01, 0x80,
0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xE0, 0x78, 0x1F,
0x07, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xF0,
0x7C, 0x0E, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03,
0x81, 0xC0, 0xE0, 0x70, 0x1F, 0x07, 0x87, 0x07, 0x03, 0x81, 0xC0, 0xE0,
0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0xE1, 0xF0, 0xE0,
0x00, 0x3E, 0x03, 0x7F, 0x03, 0x63, 0x83, 0xC1, 0xEE, 0xC0, 0x7C };
const GFXglyph Montserrat_Regular18pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 9, 0, 0 }, // 0x20 ' '
{ 1, 3, 25, 9, 3, -24 }, // 0x21 '!'
{ 11, 9, 10, 13, 2, -24 }, // 0x22 '"'
{ 23, 22, 25, 24, 1, -24 }, // 0x23 '#'
{ 92, 18, 33, 22, 2, -28 }, // 0x24 '$'
{ 167, 27, 25, 29, 1, -24 }, // 0x25 '%'
{ 252, 21, 25, 23, 2, -24 }, // 0x26 '&'
{ 318, 3, 10, 7, 2, -24 }, // 0x27 '''
{ 322, 6, 33, 12, 4, -25 }, // 0x28 '('
{ 347, 7, 33, 12, 1, -25 }, // 0x29 ')'
{ 376, 12, 13, 14, 1, -25 }, // 0x2A '*'
{ 396, 16, 15, 20, 2, -19 }, // 0x2B '+'
{ 426, 4, 9, 7, 2, -3 }, // 0x2C ','
{ 431, 9, 3, 13, 2, -10 }, // 0x2D '-'
{ 435, 4, 4, 7, 2, -3 }, // 0x2E '.'
{ 437, 14, 33, 12, -1, -28 }, // 0x2F '/'
{ 495, 19, 25, 23, 2, -24 }, // 0x30 '0'
{ 555, 9, 25, 13, 0, -24 }, // 0x31 '1'
{ 584, 18, 25, 20, 1, -24 }, // 0x32 '2'
{ 641, 18, 25, 20, 0, -24 }, // 0x33 '3'
{ 698, 22, 25, 23, 1, -24 }, // 0x34 '4'
{ 767, 17, 25, 20, 1, -24 }, // 0x35 '5'
{ 821, 18, 25, 21, 2, -24 }, // 0x36 '6'
{ 878, 18, 25, 21, 1, -24 }, // 0x37 '7'
{ 935, 19, 25, 22, 2, -24 }, // 0x38 '8'
{ 995, 19, 25, 21, 1, -24 }, // 0x39 '9'
{ 1055, 4, 19, 7, 2, -18 }, // 0x3A ':'
{ 1065, 4, 24, 7, 2, -18 }, // 0x3B ';'
{ 1077, 16, 15, 20, 2, -19 }, // 0x3C '<'
{ 1107, 16, 10, 20, 2, -16 }, // 0x3D '='
{ 1127, 16, 15, 20, 2, -19 }, // 0x3E '>'
{ 1157, 17, 25, 20, 0, -24 }, // 0x3F '?'
{ 1211, 32, 32, 36, 2, -24 }, // 0x40 '@'
{ 1339, 25, 25, 25, 0, -24 }, // 0x41 'A'
{ 1418, 20, 25, 26, 4, -24 }, // 0x42 'B'
{ 1481, 22, 25, 25, 2, -24 }, // 0x43 'C'
{ 1550, 23, 25, 29, 4, -24 }, // 0x44 'D'
{ 1622, 17, 25, 23, 4, -24 }, // 0x45 'E'
{ 1676, 17, 25, 22, 4, -24 }, // 0x46 'F'
{ 1730, 22, 25, 27, 2, -24 }, // 0x47 'G'
{ 1799, 20, 25, 28, 4, -24 }, // 0x48 'H'
{ 1862, 3, 25, 11, 4, -24 }, // 0x49 'I'
{ 1872, 14, 25, 18, 0, -24 }, // 0x4A 'J'
{ 1916, 21, 25, 25, 4, -24 }, // 0x4B 'K'
{ 1982, 16, 25, 21, 4, -24 }, // 0x4C 'L'
{ 2032, 25, 25, 33, 4, -24 }, // 0x4D 'M'
{ 2111, 20, 25, 28, 4, -24 }, // 0x4E 'N'
{ 2174, 26, 25, 29, 2, -24 }, // 0x4F 'O'
{ 2256, 19, 25, 25, 4, -24 }, // 0x50 'P'
{ 2316, 27, 30, 29, 2, -24 }, // 0x51 'Q'
{ 2418, 20, 25, 25, 4, -24 }, // 0x52 'R'
{ 2481, 18, 25, 22, 2, -24 }, // 0x53 'S'
{ 2538, 20, 25, 20, 0, -24 }, // 0x54 'T'
{ 2601, 20, 25, 28, 4, -24 }, // 0x55 'U'
{ 2664, 24, 25, 24, 0, -24 }, // 0x56 'V'
{ 2739, 37, 25, 39, 1, -24 }, // 0x57 'W'
{ 2855, 21, 25, 23, 1, -24 }, // 0x58 'X'
{ 2921, 22, 25, 22, 0, -24 }, // 0x59 'Y'
{ 2990, 20, 25, 23, 2, -24 }, // 0x5A 'Z'
{ 3053, 6, 33, 11, 4, -25 }, // 0x5B '['
{ 3078, 14, 33, 12, -1, -28 }, // 0x5C '\'
{ 3136, 6, 33, 11, 1, -25 }, // 0x5D ']'
{ 3161, 14, 15, 20, 3, -19 }, // 0x5E '^'
{ 3188, 18, 2, 18, 0, 1 }, // 0x5F '_'
{ 3193, 8, 5, 21, 5, -25 }, // 0x60 '`'
{ 3198, 15, 19, 21, 2, -18 }, // 0x61 'a'
{ 3234, 19, 26, 24, 3, -25 }, // 0x62 'b'
{ 3296, 16, 19, 20, 2, -18 }, // 0x63 'c'
{ 3334, 18, 26, 24, 2, -25 }, // 0x64 'd'
{ 3393, 18, 19, 21, 2, -18 }, // 0x65 'e'
{ 3436, 12, 26, 12, 1, -25 }, // 0x66 'f'
{ 3475, 19, 26, 24, 2, -18 }, // 0x67 'g'
{ 3537, 17, 26, 24, 3, -25 }, // 0x68 'h'
{ 3593, 3, 26, 9, 3, -25 }, // 0x69 'i'
{ 3603, 9, 33, 10, -3, -25 }, // 0x6A 'j'
{ 3641, 18, 26, 21, 3, -25 }, // 0x6B 'k'
{ 3700, 3, 26, 9, 3, -25 }, // 0x6C 'l'
{ 3710, 31, 19, 37, 3, -18 }, // 0x6D 'm'
{ 3784, 17, 19, 24, 3, -18 }, // 0x6E 'n'
{ 3825, 18, 19, 22, 2, -18 }, // 0x6F 'o'
{ 3868, 19, 26, 24, 3, -18 }, // 0x70 'p'
{ 3930, 18, 26, 24, 2, -18 }, // 0x71 'q'
{ 3989, 10, 19, 14, 3, -18 }, // 0x72 'r'
{ 4013, 15, 19, 17, 1, -18 }, // 0x73 's'
{ 4049, 12, 22, 14, 1, -21 }, // 0x74 't'
{ 4082, 17, 18, 24, 3, -17 }, // 0x75 'u'
{ 4121, 19, 18, 19, 0, -17 }, // 0x76 'v'
{ 4164, 30, 18, 31, 0, -17 }, // 0x77 'w'
{ 4232, 17, 18, 19, 1, -17 }, // 0x78 'x'
{ 4271, 20, 25, 19, -1, -17 }, // 0x79 'y'
{ 4334, 15, 18, 18, 1, -17 }, // 0x7A 'z'
{ 4368, 9, 33, 12, 2, -25 }, // 0x7B '{'
{ 4406, 2, 33, 10, 4, -25 }, // 0x7C '|'
{ 4415, 9, 33, 12, 1, -25 }, // 0x7D '}'
{ 4453, 16, 5, 20, 2, -14 } }; // 0x7E '~'
const GFXfont Montserrat_Regular18pt7b PROGMEM = {
(uint8_t *)Montserrat_Regular18pt7bBitmaps,
(GFXglyph *)Montserrat_Regular18pt7bGlyphs,
0x20, 0x7E, 43 };
// Approx. 5135 bytes
#endif // MONTSERRAT18PT7B_H
@@ -0,0 +1,568 @@
#ifndef MONTSERRAT20PT7B_H
#define MONTSERRAT20PT7B_H
const uint8_t Montserrat_Regular20pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0x77, 0x77, 0x76, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, 0x00,
0x06, 0xFF, 0x70, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
0xC1, 0xE0, 0xC0, 0x00, 0xC0, 0x30, 0x00, 0x60, 0x18, 0x00, 0x30, 0x0C,
0x00, 0x18, 0x06, 0x00, 0x0C, 0x03, 0x00, 0x0E, 0x01, 0x80, 0x06, 0x01,
0xC0, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x80, 0xC0, 0x30, 0x00, 0x60,
0x18, 0x00, 0x30, 0x0C, 0x00, 0x18, 0x06, 0x00, 0x1C, 0x03, 0x00, 0x0C,
0x03, 0x80, 0x06, 0x01, 0x80, 0x03, 0x00, 0xC0, 0x7F, 0xFF, 0xFF, 0xBF,
0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xE0, 0x30, 0x0C, 0x00, 0x38, 0x06, 0x00,
0x18, 0x07, 0x00, 0x0C, 0x03, 0x00, 0x06, 0x01, 0x80, 0x03, 0x00, 0xC0,
0x01, 0x80, 0x60, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00,
0x06, 0x00, 0x00, 0x70, 0x00, 0x7F, 0xF0, 0x1F, 0xFF, 0xC3, 0xE6, 0x3E,
0x78, 0x60, 0x47, 0x06, 0x00, 0x70, 0x60, 0x0E, 0x06, 0x00, 0xE0, 0x60,
0x07, 0x06, 0x00, 0x70, 0x60, 0x07, 0xC6, 0x00, 0x3F, 0x60, 0x00, 0xFF,
0x00, 0x03, 0xFE, 0x00, 0x07, 0xF8, 0x00, 0x67, 0xE0, 0x06, 0x1E, 0x00,
0x60, 0xF0, 0x06, 0x07, 0x00, 0x60, 0x70, 0x06, 0x07, 0x00, 0x60, 0x7C,
0x06, 0x0F, 0xF0, 0x61, 0xE7, 0xE6, 0x7C, 0x3F, 0xFF, 0x80, 0x7F, 0xE0,
0x00, 0x60, 0x00, 0x06, 0x00, 0x00, 0x60, 0x00, 0x06, 0x00, 0x00, 0x60,
0x00, 0x00, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x18, 0x1E, 0x70, 0x01, 0x80,
0xC0, 0xC0, 0x1C, 0x0C, 0x06, 0x00, 0xC0, 0x60, 0x18, 0x0C, 0x03, 0x00,
0xC0, 0xE0, 0x18, 0x06, 0x06, 0x00, 0xC0, 0x30, 0x60, 0x06, 0x01, 0x87,
0x00, 0x30, 0x0C, 0x30, 0x01, 0x80, 0xC3, 0x00, 0x06, 0x0E, 0x38, 0x00,
0x3F, 0xE1, 0x81, 0x80, 0x7E, 0x18, 0x7F, 0x00, 0x01, 0xC7, 0x1C, 0x00,
0x0C, 0x70, 0x70, 0x00, 0xC3, 0x01, 0x80, 0x0E, 0x18, 0x0C, 0x00, 0xE1,
0x80, 0x30, 0x06, 0x0C, 0x01, 0x80, 0x60, 0x60, 0x0C, 0x07, 0x03, 0x00,
0x60, 0x30, 0x0C, 0x06, 0x03, 0x00, 0x60, 0x30, 0x38, 0x01, 0x83, 0x81,
0x80, 0x0F, 0xF8, 0x18, 0x00, 0x1F, 0x00, 0x00, 0x20, 0x00, 0x03, 0xFC,
0x00, 0x07, 0xFE, 0x00, 0x0E, 0x07, 0x00, 0x0C, 0x03, 0x00, 0x1C, 0x03,
0x80, 0x1C, 0x03, 0x80, 0x1C, 0x03, 0x00, 0x0C, 0x07, 0x00, 0x0E, 0x0E,
0x00, 0x07, 0x1C, 0x00, 0x03, 0xF8, 0x00, 0x03, 0xF0, 0x00, 0x03, 0xE0,
0x00, 0x0F, 0xF0, 0x00, 0x1E, 0x78, 0x00, 0x38, 0x3C, 0x0C, 0x70, 0x1E,
0x1C, 0xE0, 0x0F, 0x1C, 0xE0, 0x07, 0x98, 0xE0, 0x03, 0xF8, 0xE0, 0x01,
0xF0, 0xE0, 0x00, 0xF0, 0xE0, 0x00, 0xF8, 0x70, 0x01, 0xFC, 0x3C, 0x0F,
0x9E, 0x1F, 0xFF, 0x0E, 0x07, 0xFC, 0x06, 0xFF, 0xFF, 0xF0, 0x0E, 0x18,
0x70, 0xE3, 0x87, 0x0C, 0x38, 0x70, 0xE1, 0x83, 0x0E, 0x1C, 0x38, 0x70,
0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xC1, 0xC3, 0x87, 0x06,
0x0E, 0x1C, 0x18, 0x38, 0x70, 0x70, 0x60, 0xC1, 0xC1, 0xC3, 0x83, 0x07,
0x0E, 0x0C, 0x1C, 0x38, 0x70, 0x60, 0xC1, 0xC3, 0x87, 0x0E, 0x1C, 0x38,
0x70, 0xE1, 0xC3, 0x87, 0x0C, 0x38, 0x70, 0xE1, 0xC3, 0x0E, 0x1C, 0x30,
0xE1, 0x87, 0x0C, 0x00, 0x02, 0x00, 0x10, 0x00, 0x81, 0x84, 0x3F, 0x27,
0x9D, 0x70, 0x3E, 0x01, 0xF0, 0x3F, 0xE7, 0x93, 0xF8, 0x86, 0x04, 0x00,
0x20, 0x01, 0x00, 0x01, 0x80, 0x00, 0xC0, 0x00, 0x60, 0x00, 0x30, 0x00,
0x18, 0x00, 0x0C, 0x00, 0x06, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC0, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x0C, 0x00, 0x06, 0x00, 0x03,
0x00, 0x01, 0x80, 0x00, 0x7F, 0xF7, 0x76, 0x66, 0xCC, 0xFF, 0xFF, 0xFF,
0xFF, 0x80, 0x7F, 0xF7, 0x00, 0x06, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x60,
0x01, 0xC0, 0x03, 0x80, 0x06, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x60, 0x01,
0xC0, 0x03, 0x00, 0x06, 0x00, 0x1C, 0x00, 0x30, 0x00, 0x60, 0x01, 0xC0,
0x03, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x30, 0x00, 0xE0, 0x01, 0xC0, 0x03,
0x00, 0x0E, 0x00, 0x1C, 0x00, 0x30, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x00,
0x0E, 0x00, 0x18, 0x00, 0x30, 0x00, 0xE0, 0x01, 0x80, 0x03, 0x00, 0x0E,
0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x7F, 0xF8, 0x03, 0xC1,
0xF0, 0x1E, 0x01, 0xE0, 0xE0, 0x03, 0xC3, 0x80, 0x07, 0x1C, 0x00, 0x0E,
0x70, 0x00, 0x39, 0x80, 0x00, 0xEE, 0x00, 0x01, 0xB8, 0x00, 0x07, 0xE0,
0x00, 0x1F, 0x80, 0x00, 0x7E, 0x00, 0x01, 0xF8, 0x00, 0x07, 0xE0, 0x00,
0x1F, 0x80, 0x00, 0x7E, 0x00, 0x01, 0x9C, 0x00, 0x0E, 0x70, 0x00, 0x39,
0xC0, 0x01, 0xE3, 0x80, 0x07, 0x0F, 0x00, 0x3C, 0x1E, 0x01, 0xE0, 0x3F,
0x3F, 0x00, 0x7F, 0xF8, 0x00, 0x7F, 0x80, 0xFF, 0xFF, 0xF0, 0x1C, 0x07,
0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0,
0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C,
0x07, 0x01, 0xC0, 0x70, 0x1C, 0x00, 0x40, 0x00, 0xFF, 0xE0, 0x3F, 0xFF,
0x07, 0xC0, 0xF8, 0xF0, 0x03, 0xC4, 0x00, 0x1C, 0x00, 0x01, 0xC0, 0x00,
0x1C, 0x00, 0x01, 0xC0, 0x00, 0x1C, 0x00, 0x01, 0xC0, 0x00, 0x1C, 0x00,
0x03, 0x80, 0x00, 0x78, 0x00, 0x0F, 0x00, 0x01, 0xE0, 0x00, 0x3C, 0x00,
0x07, 0x80, 0x00, 0xF0, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00,
0x0F, 0x00, 0x01, 0xE0, 0x00, 0x3C, 0x00, 0x07, 0xFF, 0xFF, 0x7F, 0xFF,
0xF7, 0xFF, 0xFF, 0x7F, 0xFF, 0xE7, 0xFF, 0xFE, 0x00, 0x01, 0xC0, 0x00,
0x3C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00,
0x3C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0F, 0x80, 0x00, 0xFF, 0x00,
0x0F, 0xFC, 0x00, 0x03, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x70, 0x00, 0x07,
0x00, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x07, 0x60, 0x00,
0xEF, 0x80, 0x1E, 0x7F, 0x1F, 0xC1, 0xFF, 0xF8, 0x07, 0xFE, 0x00, 0x00,
0x07, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0xE0, 0x00, 0x03,
0x80, 0x00, 0x0F, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x70, 0x00, 0x01, 0xC0,
0x00, 0x07, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x38, 0x0E, 0x00, 0xE0, 0x1C,
0x03, 0x80, 0x38, 0x0E, 0x00, 0x70, 0x3C, 0x00, 0xE0, 0x70, 0x01, 0xC1,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x1C, 0x00,
0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00,
0x03, 0x80, 0x00, 0x07, 0x00, 0x1F, 0xFF, 0xC1, 0xFF, 0xFC, 0x1C, 0x00,
0x01, 0x80, 0x00, 0x18, 0x00, 0x01, 0x80, 0x00, 0x38, 0x00, 0x03, 0x80,
0x00, 0x38, 0x00, 0x03, 0x80, 0x00, 0x38, 0x00, 0x03, 0xFF, 0xC0, 0x3F,
0xFF, 0x00, 0x07, 0xF8, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xE0,
0x00, 0x0E, 0x00, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x60, 0x00, 0x0E,
0x40, 0x01, 0xEF, 0x00, 0x3C, 0x7F, 0x1F, 0x83, 0xFF, 0xF0, 0x07, 0xFC,
0x00, 0x00, 0x0C, 0x00, 0x0F, 0xFE, 0x01, 0xFF, 0xF8, 0x1F, 0x01, 0x81,
0xE0, 0x00, 0x1E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x70, 0x00,
0x03, 0x00, 0x00, 0x38, 0x00, 0x01, 0xC0, 0x00, 0x0E, 0x1F, 0xF0, 0x73,
0xFF, 0xE3, 0xBC, 0x0F, 0x9F, 0x80, 0x1C, 0xF8, 0x00, 0x77, 0x80, 0x03,
0xBC, 0x00, 0x0C, 0xE0, 0x00, 0x77, 0x00, 0x03, 0xB8, 0x00, 0x18, 0xE0,
0x01, 0xC7, 0x00, 0x0E, 0x1C, 0x00, 0xE0, 0x78, 0x1E, 0x01, 0xFF, 0xE0,
0x03, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x7E, 0x00,
0x0F, 0xE0, 0x00, 0xEE, 0x00, 0x0E, 0xE0, 0x01, 0xC0, 0x00, 0x1C, 0x00,
0x03, 0x80, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x0E, 0x00,
0x00, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xC0, 0x00, 0x1C, 0x00, 0x03, 0x80,
0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x00, 0xE0,
0x00, 0x1C, 0x00, 0x01, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0x80, 0x00, 0x00,
0x20, 0x00, 0x3F, 0xF8, 0x07, 0xFF, 0xF0, 0x7C, 0x07, 0xC3, 0x80, 0x0E,
0x38, 0x00, 0x39, 0xC0, 0x01, 0xCE, 0x00, 0x0E, 0x70, 0x00, 0x73, 0x80,
0x03, 0x9E, 0x00, 0x38, 0x78, 0x03, 0xC1, 0xF8, 0xFC, 0x03, 0xFF, 0x80,
0x7F, 0xFF, 0x07, 0x80, 0x7C, 0x78, 0x00, 0xF7, 0x80, 0x03, 0xB8, 0x00,
0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x80, 0x00, 0xEE,
0x00, 0x0E, 0x78, 0x00, 0xF1, 0xF0, 0x1F, 0x07, 0xFF, 0xF0, 0x0F, 0xFE,
0x00, 0x00, 0x60, 0x00, 0x3F, 0xF0, 0x07, 0xFF, 0xC0, 0x78, 0x0F, 0x07,
0x80, 0x1C, 0x38, 0x00, 0x73, 0x80, 0x03, 0x9C, 0x00, 0x0E, 0xE0, 0x00,
0x77, 0x00, 0x03, 0xB8, 0x00, 0x1C, 0xE0, 0x01, 0xF7, 0x00, 0x1F, 0x9C,
0x01, 0xDC, 0xFE, 0x7C, 0xE1, 0xFF, 0xC7, 0x03, 0xF8, 0x38, 0x00, 0x01,
0x80, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00,
0x03, 0x80, 0x00, 0x38, 0x00, 0x07, 0x81, 0xC0, 0xF8, 0x0F, 0xFF, 0x80,
0x3F, 0xF0, 0x00, 0x7F, 0xF7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
0xFF, 0x70, 0x7F, 0xF7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xFF,
0x77, 0x66, 0x6C, 0xC0, 0x00, 0x00, 0x80, 0x01, 0xC0, 0x07, 0xE0, 0x0F,
0xC0, 0x3F, 0x00, 0x7E, 0x01, 0xF8, 0x01, 0xE0, 0x00, 0xE0, 0x00, 0x7C,
0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x3E,
0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF,
0xFF, 0xE0, 0x00, 0x00, 0x70, 0x00, 0x3E, 0x00, 0x07, 0xE0, 0x00, 0xFC,
0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0x80, 0x0F, 0xC0,
0x1F, 0x80, 0x7E, 0x00, 0xFC, 0x03, 0xF0, 0x03, 0xE0, 0x01, 0x80, 0x00,
0x00, 0x60, 0x00, 0xFF, 0xC0, 0x7F, 0xFE, 0x3E, 0x03, 0xEF, 0x00, 0x1E,
0x40, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C,
0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x1E, 0x00, 0x07, 0x80,
0x00, 0xE0, 0x00, 0x38, 0x00, 0x0F, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00,
0x0F, 0x00, 0x01, 0xE0, 0x00, 0x38, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00,
0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7F, 0xDF, 0xE0, 0x00, 0x1F, 0x00, 0x07,
0x80, 0x03, 0xC0, 0x00, 0x1C, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x0E, 0x00,
0x00, 0x03, 0x01, 0xC0, 0x00, 0x00, 0x18, 0x18, 0x01, 0xF8, 0x71, 0xC3,
0x00, 0xFF, 0xE7, 0x0C, 0x30, 0x1F, 0x1F, 0x70, 0x66, 0x03, 0xC0, 0x3F,
0x06, 0x60, 0x78, 0x01, 0xF0, 0x76, 0x07, 0x00, 0x0F, 0x03, 0xE0, 0xE0,
0x00, 0x70, 0x3C, 0x0E, 0x00, 0x07, 0x03, 0xC0, 0xE0, 0x00, 0x70, 0x3C,
0x0E, 0x00, 0x07, 0x03, 0xC0, 0xE0, 0x00, 0x70, 0x3C, 0x0E, 0x00, 0x07,
0x03, 0xC0, 0xE0, 0x00, 0x70, 0x3C, 0x0E, 0x00, 0x07, 0x03, 0xE0, 0x70,
0x00, 0xF0, 0x36, 0x07, 0x00, 0x0F, 0x06, 0x60, 0x38, 0x03, 0xF0, 0x67,
0x01, 0xE0, 0x73, 0x8E, 0x30, 0x0F, 0xFE, 0x3F, 0xC3, 0x80, 0x3F, 0x81,
0xF8, 0x1C, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x07, 0x00,
0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x00, 0x40, 0x00,
0x07, 0xE0, 0x7C, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x3F, 0xC0,
0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x1F, 0x80, 0x00,
0x01, 0xF8, 0x00, 0x00, 0x39, 0xC0, 0x00, 0x03, 0x9C, 0x00, 0x00, 0x70,
0xE0, 0x00, 0x07, 0x0E, 0x00, 0x00, 0x60, 0x60, 0x00, 0x0E, 0x07, 0x00,
0x00, 0xC0, 0x70, 0x00, 0x1C, 0x03, 0x80, 0x01, 0xC0, 0x38, 0x00, 0x38,
0x01, 0xC0, 0x03, 0x80, 0x1C, 0x00, 0x70, 0x00, 0xE0, 0x07, 0x00, 0x0E,
0x00, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xF0, 0x1C,
0x00, 0x03, 0x81, 0xC0, 0x00, 0x38, 0x38, 0x00, 0x01, 0xC3, 0x80, 0x00,
0x1C, 0x70, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x70,
0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xC3, 0x80, 0x07, 0xC7, 0x00, 0x03, 0xCE,
0x00, 0x03, 0x9C, 0x00, 0x03, 0xB8, 0x00, 0x07, 0x70, 0x00, 0x0E, 0xE0,
0x00, 0x1D, 0xC0, 0x00, 0x73, 0x80, 0x01, 0xE7, 0x00, 0x0F, 0x8F, 0xFF,
0xFC, 0x1F, 0xFF, 0xFC, 0x38, 0x00, 0xFE, 0x70, 0x00, 0x1E, 0xE0, 0x00,
0x1F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00, 0x00, 0x7E, 0x00, 0x00,
0xFC, 0x00, 0x01, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x1E, 0xE0, 0x03, 0xF9,
0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0x00, 0x00, 0x02, 0x00, 0x00, 0x7F, 0xF0,
0x01, 0xFF, 0xFC, 0x07, 0xE0, 0x3E, 0x0F, 0x80, 0x0F, 0x1E, 0x00, 0x02,
0x3C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00,
0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00,
0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0xE0, 0x00, 0x00,
0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x38, 0x00, 0x00,
0x1C, 0x00, 0x02, 0x1E, 0x00, 0x07, 0x0F, 0x80, 0x0F, 0x07, 0xF8, 0xFE,
0x01, 0xFF, 0xF8, 0x00, 0x7F, 0xE0, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xF8,
0x0E, 0x00, 0x3F, 0x83, 0x80, 0x01, 0xF0, 0xE0, 0x00, 0x1E, 0x38, 0x00,
0x03, 0xCE, 0x00, 0x00, 0x73, 0x80, 0x00, 0x0E, 0xE0, 0x00, 0x03, 0xB8,
0x00, 0x00, 0x7E, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x07, 0xE0, 0x00, 0x01,
0xF8, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x07, 0xE0, 0x00,
0x01, 0xF8, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x3B, 0x80, 0x00, 0x0E, 0xE0,
0x00, 0x07, 0x38, 0x00, 0x03, 0xCE, 0x00, 0x01, 0xE3, 0x80, 0x01, 0xF0,
0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xF8, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF,
0xEF, 0xFF, 0xFE, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00,
0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0,
0x00, 0x0E, 0x00, 0x00, 0xFF, 0xFF, 0x8F, 0xFF, 0xF8, 0xE0, 0x00, 0x0E,
0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00,
0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00,
0x00, 0xE0, 0x00, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00,
0x01, 0xFF, 0xFF, 0x3F, 0xFF, 0xE7, 0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00,
0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00,
0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x7F, 0xFF, 0x00, 0xFC, 0x07, 0xE0,
0xF8, 0x00, 0x78, 0xF0, 0x00, 0x18, 0xF0, 0x00, 0x00, 0x70, 0x00, 0x00,
0x70, 0x00, 0x00, 0x38, 0x00, 0x00, 0x38, 0x00, 0x00, 0x1C, 0x00, 0x00,
0x0E, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x80, 0x00, 0x0D, 0xC0, 0x00,
0x06, 0xE0, 0x00, 0x03, 0x70, 0x00, 0x01, 0x9C, 0x00, 0x00, 0xCE, 0x00,
0x00, 0x67, 0x80, 0x00, 0x31, 0xC0, 0x00, 0x18, 0x70, 0x00, 0x0C, 0x3C,
0x00, 0x06, 0x0F, 0x80, 0x0F, 0x01, 0xFC, 0x3F, 0x80, 0x7F, 0xFF, 0x00,
0x07, 0xFC, 0x00, 0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F,
0x00, 0x00, 0x7E, 0x00, 0x00, 0xFC, 0x00, 0x01, 0xF8, 0x00, 0x03, 0xF0,
0x00, 0x07, 0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00,
0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x03, 0xF0, 0x00,
0x07, 0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00, 0x00,
0x7E, 0x00, 0x00, 0xFC, 0x00, 0x01, 0xF8, 0x00, 0x03, 0xF0, 0x00, 0x07,
0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x38, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x3F, 0xFE, 0x7F, 0xFC,
0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00,
0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03,
0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE8,
0x01, 0xD0, 0x03, 0xF8, 0x0E, 0x7C, 0x7C, 0x7F, 0xF0, 0x3F, 0x80, 0xE0,
0x00, 0x1C, 0xE0, 0x00, 0x38, 0xE0, 0x00, 0x70, 0xE0, 0x00, 0xE0, 0xE0,
0x01, 0xC0, 0xE0, 0x03, 0x80, 0xE0, 0x07, 0x00, 0xE0, 0x0E, 0x00, 0xE0,
0x1C, 0x00, 0xE0, 0x38, 0x00, 0xE0, 0x70, 0x00, 0xE0, 0xE0, 0x00, 0xE1,
0xE0, 0x00, 0xE3, 0xF0, 0x00, 0xE7, 0xF8, 0x00, 0xEF, 0x3C, 0x00, 0xFE,
0x1E, 0x00, 0xFC, 0x0E, 0x00, 0xF8, 0x07, 0x00, 0xF0, 0x03, 0x80, 0xE0,
0x03, 0xC0, 0xE0, 0x01, 0xE0, 0xE0, 0x00, 0xF0, 0xE0, 0x00, 0x78, 0xE0,
0x00, 0x38, 0xE0, 0x00, 0x1C, 0xE0, 0x00, 0x0E, 0xE0, 0x00, 0x1C, 0x00,
0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00,
0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00,
0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00,
0x1C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00,
0x38, 0x00, 0x07, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x80, 0xE0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x1F,
0xF0, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0xFF, 0xB8,
0x00, 0x0E, 0xFC, 0xC0, 0x00, 0x77, 0xE7, 0x00, 0x07, 0x3F, 0x1C, 0x00,
0x39, 0xF8, 0xE0, 0x03, 0x8F, 0xC3, 0x80, 0x18, 0x7E, 0x1C, 0x01, 0xC3,
0xF0, 0x70, 0x1C, 0x1F, 0x81, 0xC0, 0xE0, 0xFC, 0x0E, 0x0E, 0x07, 0xE0,
0x38, 0x60, 0x3F, 0x01, 0xC7, 0x01, 0xF8, 0x07, 0x30, 0x0F, 0xC0, 0x1B,
0x80, 0x7E, 0x00, 0xF8, 0x03, 0xF0, 0x03, 0xC0, 0x1F, 0x80, 0x1C, 0x00,
0xFC, 0x00, 0x40, 0x07, 0xE0, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xF8,
0x00, 0x00, 0x0E, 0xE0, 0x00, 0x0F, 0xE0, 0x00, 0x1F, 0xE0, 0x00, 0x3F,
0xE0, 0x00, 0x7F, 0xE0, 0x00, 0xFD, 0xC0, 0x01, 0xF9, 0xC0, 0x03, 0xF3,
0xC0, 0x07, 0xE3, 0xC0, 0x0F, 0xC3, 0xC0, 0x1F, 0x83, 0x80, 0x3F, 0x03,
0x80, 0x7E, 0x07, 0x80, 0xFC, 0x07, 0x81, 0xF8, 0x07, 0x83, 0xF0, 0x07,
0x07, 0xE0, 0x07, 0x0F, 0xC0, 0x0F, 0x1F, 0x80, 0x0F, 0x3F, 0x00, 0x0F,
0x7E, 0x00, 0x0E, 0xFC, 0x00, 0x0F, 0xF8, 0x00, 0x1F, 0xF0, 0x00, 0x1F,
0xE0, 0x00, 0x1F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x38, 0x00, 0x02, 0x00,
0x00, 0x03, 0xFF, 0x80, 0x00, 0x7F, 0xFF, 0x00, 0x0F, 0xC0, 0x7E, 0x00,
0xF0, 0x00, 0xF8, 0x0F, 0x00, 0x01, 0xE0, 0xF0, 0x00, 0x07, 0x07, 0x00,
0x00, 0x1C, 0x70, 0x00, 0x00, 0xE3, 0x80, 0x00, 0x03, 0xB8, 0x00, 0x00,
0x1D, 0xC0, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x00, 0x1F,
0x80, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x3F, 0x00,
0x00, 0x03, 0x9C, 0x00, 0x00, 0x1C, 0xE0, 0x00, 0x00, 0xE7, 0x80, 0x00,
0x0E, 0x1C, 0x00, 0x00, 0xF0, 0x70, 0x00, 0x0F, 0x03, 0xC0, 0x00, 0xF0,
0x0F, 0x80, 0x0F, 0x00, 0x1F, 0xC7, 0xF0, 0x00, 0x7F, 0xFF, 0x00, 0x00,
0x7F, 0xC0, 0x00, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0x0E, 0x00, 0x7E, 0x38,
0x00, 0x3C, 0xE0, 0x00, 0x7B, 0x80, 0x00, 0xEE, 0x00, 0x01, 0xF8, 0x00,
0x07, 0xE0, 0x00, 0x1F, 0x80, 0x00, 0x7E, 0x00, 0x01, 0xF8, 0x00, 0x07,
0xE0, 0x00, 0x3B, 0x80, 0x01, 0xEE, 0x00, 0x0F, 0x38, 0x01, 0xF8, 0xFF,
0xFF, 0xC3, 0xFF, 0xFC, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0xE0, 0x00,
0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0xE0, 0x00, 0x03,
0x80, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0xFF,
0xC0, 0x00, 0x1F, 0xFF, 0xC0, 0x01, 0xF8, 0x0F, 0xC0, 0x0F, 0x00, 0x0F,
0x80, 0x78, 0x00, 0x0F, 0x03, 0xC0, 0x00, 0x1C, 0x0E, 0x00, 0x00, 0x38,
0x70, 0x00, 0x00, 0xE1, 0xC0, 0x00, 0x01, 0xCE, 0x00, 0x00, 0x07, 0x38,
0x00, 0x00, 0x1C, 0xE0, 0x00, 0x00, 0x3B, 0x80, 0x00, 0x00, 0xEE, 0x00,
0x00, 0x03, 0xB8, 0x00, 0x00, 0x0E, 0xE0, 0x00, 0x00, 0x3B, 0x80, 0x00,
0x01, 0xC7, 0x00, 0x00, 0x07, 0x1C, 0x00, 0x00, 0x1C, 0x78, 0x00, 0x00,
0xE0, 0xE0, 0x00, 0x07, 0x81, 0xC0, 0x00, 0x3C, 0x07, 0x80, 0x01, 0xE0,
0x0F, 0x80, 0x0F, 0x00, 0x0F, 0xE3, 0xF8, 0x00, 0x1F, 0xFF, 0xC0, 0x00,
0x0F, 0xF8, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x07, 0x80, 0x20, 0x00,
0x0F, 0x83, 0xC0, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x1F, 0xE0, 0xFF, 0xFF,
0x03, 0xFF, 0xFF, 0x0E, 0x00, 0x7E, 0x38, 0x00, 0x3C, 0xE0, 0x00, 0x7B,
0x80, 0x00, 0xEE, 0x00, 0x01, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0x1F, 0x80,
0x00, 0x7E, 0x00, 0x01, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0x3B, 0x80, 0x01,
0xEE, 0x00, 0x0F, 0x38, 0x00, 0xF8, 0xFF, 0xFF, 0xC3, 0xFF, 0xFC, 0x0E,
0x00, 0x70, 0x38, 0x00, 0xE0, 0xE0, 0x03, 0xC3, 0x80, 0x07, 0x0E, 0x00,
0x0E, 0x38, 0x00, 0x1C, 0xE0, 0x00, 0x73, 0x80, 0x00, 0xEE, 0x00, 0x01,
0xC0, 0x00, 0x30, 0x00, 0x7F, 0xF0, 0x1F, 0xFF, 0xC3, 0xE0, 0x3E, 0x78,
0x00, 0x47, 0x00, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x07,
0x00, 0x00, 0x70, 0x00, 0x07, 0xC0, 0x00, 0x3F, 0x00, 0x00, 0xFF, 0x00,
0x03, 0xFE, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0x1E, 0x00, 0x00,
0xF0, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x7C, 0x00,
0x0F, 0xF0, 0x01, 0xE7, 0xE0, 0x7C, 0x3F, 0xFF, 0x80, 0x7F, 0xE0, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x38,
0x00, 0x00, 0xE0, 0x00, 0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00,
0x00, 0xE0, 0x00, 0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00,
0xE0, 0x00, 0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0xE0,
0x00, 0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0xE0, 0x00,
0x03, 0x80, 0x00, 0x0E, 0x00, 0x00, 0x38, 0x00, 0x00, 0xE0, 0x00, 0x03,
0x80, 0x00, 0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00,
0x00, 0x7E, 0x00, 0x00, 0xFC, 0x00, 0x01, 0xF8, 0x00, 0x03, 0xF0, 0x00,
0x07, 0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00, 0x00,
0x7E, 0x00, 0x00, 0xFC, 0x00, 0x01, 0xF8, 0x00, 0x03, 0xF0, 0x00, 0x07,
0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x33, 0x80, 0x00, 0xE7,
0x00, 0x01, 0xCF, 0x00, 0x07, 0x8E, 0x00, 0x1E, 0x0F, 0x00, 0x78, 0x1F,
0xC7, 0xE0, 0x0F, 0xFF, 0x80, 0x07, 0xFC, 0x00, 0xF0, 0x00, 0x00, 0xEE,
0x00, 0x00, 0x39, 0xC0, 0x00, 0x07, 0x1C, 0x00, 0x00, 0xC3, 0x80, 0x00,
0x38, 0x38, 0x00, 0x07, 0x07, 0x00, 0x01, 0xC0, 0x70, 0x00, 0x38, 0x0E,
0x00, 0x0E, 0x01, 0xE0, 0x01, 0xC0, 0x1C, 0x00, 0x70, 0x03, 0x80, 0x0E,
0x00, 0x38, 0x01, 0x80, 0x07, 0x00, 0x70, 0x00, 0x70, 0x0E, 0x00, 0x0E,
0x03, 0x80, 0x00, 0xE0, 0x70, 0x00, 0x1C, 0x1C, 0x00, 0x03, 0xC3, 0x80,
0x00, 0x38, 0xE0, 0x00, 0x07, 0x1C, 0x00, 0x00, 0x73, 0x00, 0x00, 0x0E,
0xE0, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x01, 0xE0, 0x00,
0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x1C, 0x00, 0x03, 0xB8, 0x00, 0x0F,
0x00, 0x01, 0x9C, 0x00, 0x0F, 0x80, 0x01, 0xC7, 0x00, 0x07, 0xC0, 0x00,
0xE3, 0x80, 0x03, 0x70, 0x00, 0x61, 0xC0, 0x03, 0xB8, 0x00, 0x70, 0x70,
0x01, 0xCC, 0x00, 0x38, 0x38, 0x00, 0xC7, 0x00, 0x18, 0x1C, 0x00, 0xE3,
0x80, 0x1C, 0x07, 0x00, 0x70, 0xC0, 0x0E, 0x03, 0x80, 0x30, 0x70, 0x0E,
0x01, 0xC0, 0x38, 0x38, 0x07, 0x00, 0x70, 0x1C, 0x0C, 0x03, 0x80, 0x38,
0x0C, 0x07, 0x03, 0x80, 0x1C, 0x0E, 0x03, 0x81, 0xC0, 0x07, 0x07, 0x00,
0xC0, 0xE0, 0x03, 0x83, 0x00, 0x70, 0xE0, 0x01, 0xC3, 0x80, 0x38, 0x70,
0x00, 0x71, 0xC0, 0x0C, 0x38, 0x00, 0x38, 0xC0, 0x07, 0x38, 0x00, 0x1C,
0xE0, 0x03, 0x9C, 0x00, 0x07, 0x70, 0x00, 0xEE, 0x00, 0x03, 0xB0, 0x00,
0x7E, 0x00, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x00, 0x7C, 0x00, 0x0F, 0x80,
0x00, 0x3C, 0x00, 0x07, 0x80, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x70,
0x00, 0x1E, 0x38, 0x00, 0x1C, 0x3C, 0x00, 0x38, 0x1C, 0x00, 0x70, 0x0E,
0x00, 0x70, 0x07, 0x00, 0xE0, 0x07, 0x81, 0xC0, 0x03, 0x83, 0x80, 0x01,
0xC3, 0x80, 0x01, 0xE7, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xEE, 0x00, 0x01,
0xE7, 0x00, 0x01, 0xC3, 0x80, 0x03, 0x83, 0xC0, 0x07, 0x01, 0xC0, 0x0F,
0x00, 0xE0, 0x0E, 0x00, 0xF0, 0x1C, 0x00, 0x78, 0x3C, 0x00, 0x38, 0x78,
0x00, 0x1C, 0x70, 0x00, 0x1E, 0xE0, 0x00, 0x0F, 0x70, 0x00, 0x07, 0x38,
0x00, 0x03, 0x8E, 0x00, 0x03, 0x87, 0x00, 0x01, 0x81, 0xC0, 0x01, 0xC0,
0x70, 0x01, 0xC0, 0x38, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x07, 0x00, 0xE0,
0x01, 0xC0, 0x70, 0x00, 0x70, 0x70, 0x00, 0x38, 0x38, 0x00, 0x0E, 0x38,
0x00, 0x07, 0xB8, 0x00, 0x01, 0xDC, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x3C,
0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0x00, 0x03, 0x80, 0x00, 0x01,
0xC0, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x70, 0x00, 0x00, 0x38, 0x00, 0x00,
0x1C, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF0, 0x00, 0x03, 0x80, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x00,
0x07, 0x80, 0x00, 0x3C, 0x00, 0x00, 0xE0, 0x00, 0x07, 0x00, 0x00, 0x3C,
0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0x38, 0x00, 0x01, 0xC0, 0x00,
0x0F, 0x00, 0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x70,
0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0x70, 0x00, 0x03, 0x80, 0x00,
0x1C, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF,
0xFF, 0xC0, 0x01, 0xC0, 0x03, 0x80, 0x03, 0x00, 0x07, 0x00, 0x06, 0x00,
0x0C, 0x00, 0x1C, 0x00, 0x18, 0x00, 0x30, 0x00, 0x70, 0x00, 0x60, 0x00,
0xE0, 0x01, 0xC0, 0x01, 0x80, 0x03, 0x80, 0x07, 0x00, 0x06, 0x00, 0x0E,
0x00, 0x1C, 0x00, 0x18, 0x00, 0x38, 0x00, 0x70, 0x00, 0x60, 0x00, 0xE0,
0x00, 0xC0, 0x01, 0x80, 0x03, 0x80, 0x03, 0x00, 0x06, 0x00, 0x0E, 0x00,
0x0C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x30, 0x00, 0x70, 0x00, 0xE0, 0xFF,
0xFC, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3,
0x87, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38, 0x70,
0xE1, 0xC3, 0x87, 0x0E, 0x1F, 0xFF, 0xFF, 0xE0, 0x01, 0xC0, 0x01, 0xC0,
0x03, 0xC0, 0x03, 0x60, 0x06, 0x60, 0x06, 0x70, 0x0E, 0x30, 0x0C, 0x30,
0x0C, 0x18, 0x18, 0x18, 0x18, 0x1C, 0x38, 0x0C, 0x30, 0x0E, 0x70, 0x06,
0x60, 0x06, 0x60, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3C, 0x07,
0x01, 0xC0, 0x78, 0x01, 0xC0, 0x0F, 0xFE, 0x1F, 0xFF, 0x8F, 0x01, 0xE2,
0x00, 0x78, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x03, 0x00, 0x01, 0x80, 0xFF,
0xC7, 0xFF, 0xE7, 0xE0, 0x37, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0,
0x07, 0xE0, 0x03, 0xB8, 0x03, 0xDE, 0x07, 0x67, 0xFF, 0x30, 0xFF, 0x18,
0xE0, 0x00, 0x07, 0x00, 0x00, 0x38, 0x00, 0x01, 0xC0, 0x00, 0x0E, 0x00,
0x00, 0x70, 0x00, 0x03, 0x80, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x70, 0x07,
0x1F, 0xF0, 0x3B, 0xFF, 0xE1, 0xFC, 0x07, 0x8F, 0x80, 0x1E, 0x78, 0x00,
0x73, 0xC0, 0x01, 0xDC, 0x00, 0x0E, 0xE0, 0x00, 0x37, 0x00, 0x01, 0xF8,
0x00, 0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x3B, 0x80, 0x01,
0xDE, 0x00, 0x1E, 0xF8, 0x00, 0xE7, 0xE0, 0x0E, 0x3B, 0xC3, 0xF1, 0xCF,
0xFE, 0x0E, 0x1F, 0xC0, 0x00, 0x00, 0xF0, 0x01, 0xFF, 0x80, 0xFF, 0xF8,
0x78, 0x0F, 0x38, 0x01, 0xDC, 0x00, 0x27, 0x00, 0x03, 0x80, 0x00, 0xE0,
0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x00, 0xE0, 0x00, 0x38, 0x00,
0x0E, 0x00, 0x01, 0xC0, 0x00, 0x78, 0x00, 0x8F, 0x00, 0x71, 0xF0, 0xF8,
0x3F, 0xFC, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0xC0, 0x00,
0x0E, 0x00, 0x00, 0x70, 0x00, 0x03, 0x80, 0x00, 0x1C, 0x00, 0x00, 0xE0,
0x00, 0x07, 0x00, 0x60, 0x38, 0x3F, 0xF1, 0xC7, 0xFF, 0xCE, 0x7C, 0x07,
0x73, 0x80, 0x1F, 0xB8, 0x00, 0x7D, 0xC0, 0x01, 0xFC, 0x00, 0x0F, 0xE0,
0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x03,
0xF0, 0x00, 0x3F, 0x80, 0x01, 0xEE, 0x00, 0x1F, 0x78, 0x00, 0xF9, 0xE0,
0x0F, 0xC7, 0xC3, 0xEE, 0x1F, 0xFE, 0x70, 0x3F, 0xC3, 0x80, 0x00, 0xE0,
0x00, 0x7F, 0xE0, 0x1F, 0xFF, 0x03, 0xC0, 0x78, 0x38, 0x01, 0xC7, 0x00,
0x0E, 0x60, 0x00, 0xEE, 0x00, 0x06, 0xE0, 0x00, 0x7E, 0x00, 0x07, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x07,
0x00, 0x00, 0x78, 0x00, 0x83, 0xC0, 0x1C, 0x1F, 0x87, 0xC0, 0xFF, 0xF8,
0x03, 0xFE, 0x00, 0x03, 0xF8, 0x1F, 0xE0, 0xF1, 0x83, 0x80, 0x1C, 0x00,
0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x03, 0xFF, 0xCF, 0xFF, 0x07, 0x00,
0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0,
0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70,
0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x00, 0x70, 0x00, 0x3F, 0xF1, 0xC7,
0xFF, 0xEE, 0x7C, 0x07, 0xF7, 0x80, 0x0F, 0xB8, 0x00, 0x3F, 0xC0, 0x01,
0xFC, 0x00, 0x07, 0xE0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0,
0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x3D, 0xC0, 0x01, 0xEF, 0x00, 0x1F,
0x3C, 0x01, 0xF8, 0xF8, 0x3D, 0xC3, 0xFF, 0xCE, 0x07, 0xF8, 0x70, 0x00,
0x03, 0x80, 0x00, 0x1C, 0x00, 0x01, 0xC0, 0x00, 0x0E, 0x30, 0x00, 0xF3,
0xE0, 0x0F, 0x0F, 0xFF, 0xF0, 0x1F, 0xFF, 0x00, 0x1F, 0x80, 0x00, 0xE0,
0x00, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0,
0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0xF0, 0x1C, 0xFF, 0xC3, 0xBF,
0xFC, 0x7E, 0x03, 0xCF, 0x80, 0x3D, 0xE0, 0x03, 0xB8, 0x00, 0x37, 0x00,
0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00,
0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00,
0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0E, 0xEF, 0xFE, 0x00, 0x00,
0x0E, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE0, 0x00,
0xE0, 0x0F, 0x00, 0xF0, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00,
0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00,
0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00,
0xE4, 0x1C, 0x7F, 0xC7, 0xF8, 0x1C, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x03,
0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07,
0x00, 0x00, 0xE0, 0x00, 0x5C, 0x00, 0x73, 0x80, 0x1C, 0x70, 0x07, 0x0E,
0x01, 0xC1, 0xC0, 0xF0, 0x38, 0x3C, 0x07, 0x0F, 0x00, 0xE3, 0xC0, 0x1C,
0xF8, 0x03, 0xBF, 0x80, 0x7F, 0x78, 0x0F, 0xC7, 0x01, 0xE0, 0x70, 0x38,
0x07, 0x07, 0x00, 0xF0, 0xE0, 0x0F, 0x1C, 0x00, 0xE3, 0x80, 0x0E, 0x70,
0x00, 0xEE, 0x00, 0x1E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0x00, 0x60, 0x00, 0xE0, 0x39, 0xFF, 0x81, 0xFF, 0x0E,
0xFF, 0xF1, 0xFF, 0xE3, 0xF0, 0x1E, 0xF0, 0x3C, 0xF8, 0x03, 0xF0, 0x07,
0xBC, 0x00, 0x78, 0x00, 0xEE, 0x00, 0x1E, 0x00, 0x1B, 0x80, 0x07, 0x80,
0x07, 0xE0, 0x01, 0xC0, 0x01, 0xF8, 0x00, 0x70, 0x00, 0x7E, 0x00, 0x1C,
0x00, 0x1F, 0x80, 0x07, 0x00, 0x07, 0xE0, 0x01, 0xC0, 0x01, 0xF8, 0x00,
0x70, 0x00, 0x7E, 0x00, 0x1C, 0x00, 0x1F, 0x80, 0x07, 0x00, 0x07, 0xE0,
0x01, 0xC0, 0x01, 0xF8, 0x00, 0x70, 0x00, 0x7E, 0x00, 0x1C, 0x00, 0x1F,
0x80, 0x07, 0x00, 0x07, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x00, 0xF0, 0x1C,
0xFF, 0xC3, 0xBF, 0xFC, 0x7E, 0x03, 0xCF, 0x80, 0x3D, 0xE0, 0x03, 0xB8,
0x00, 0x37, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0,
0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0,
0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0E, 0x00,
0x70, 0x00, 0x3F, 0xF0, 0x03, 0xFF, 0xE0, 0x3C, 0x07, 0x83, 0x80, 0x1E,
0x38, 0x00, 0x71, 0xC0, 0x01, 0xDC, 0x00, 0x0E, 0xE0, 0x00, 0x37, 0x00,
0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x3B,
0x80, 0x01, 0xCE, 0x00, 0x1E, 0x78, 0x00, 0xE1, 0xE0, 0x0E, 0x07, 0xC3,
0xE0, 0x1F, 0xFE, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x70, 0x07, 0x1F, 0xF0,
0x3B, 0xFF, 0xE1, 0xFC, 0x07, 0x8F, 0x80, 0x1E, 0x78, 0x00, 0x73, 0xC0,
0x01, 0xDC, 0x00, 0x0E, 0xE0, 0x00, 0x37, 0x00, 0x01, 0xF8, 0x00, 0x0F,
0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x3B, 0x80, 0x01, 0xDE, 0x00,
0x1E, 0xF8, 0x00, 0xE7, 0xE0, 0x0E, 0x3B, 0xC3, 0xF1, 0xCF, 0xFE, 0x0E,
0x1F, 0xC0, 0x70, 0x00, 0x03, 0x80, 0x00, 0x1C, 0x00, 0x00, 0xE0, 0x00,
0x07, 0x00, 0x00, 0x38, 0x00, 0x01, 0xC0, 0x00, 0x0E, 0x00, 0x00, 0x00,
0x00, 0x60, 0x00, 0x3F, 0xF1, 0xC7, 0xFF, 0xCE, 0x7C, 0x07, 0x73, 0x80,
0x1F, 0xB8, 0x00, 0x7D, 0xC0, 0x01, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0x3F,
0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00,
0x3F, 0x80, 0x01, 0xEE, 0x00, 0x1F, 0x78, 0x00, 0xF9, 0xE0, 0x0F, 0xC7,
0xC3, 0xEE, 0x1F, 0xFE, 0x70, 0x3F, 0xC3, 0x80, 0x00, 0x1C, 0x00, 0x00,
0xE0, 0x00, 0x07, 0x00, 0x00, 0x38, 0x00, 0x01, 0xC0, 0x00, 0x0E, 0x00,
0x00, 0x70, 0x00, 0x03, 0x80, 0x00, 0x79, 0xFE, 0xFF, 0xF8, 0xF8, 0x3C,
0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03,
0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x00, 0x01, 0xE0, 0x07, 0xFF,
0x0F, 0xFF, 0xCF, 0x00, 0xC7, 0x00, 0x03, 0x80, 0x01, 0x80, 0x00, 0xE0,
0x00, 0x78, 0x00, 0x1F, 0x80, 0x07, 0xFE, 0x00, 0x7F, 0xC0, 0x01, 0xF0,
0x00, 0x3C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0xB0, 0x03, 0xBF, 0x07,
0xCF, 0xFF, 0xC0, 0xFF, 0x80, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00,
0x1C, 0x03, 0xFF, 0xCF, 0xFF, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0,
0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x70,
0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x38, 0x00, 0xF1, 0x81, 0xFF, 0x03,
0xF8, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00,
0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C,
0x00, 0x0F, 0x00, 0x07, 0xE0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x1F, 0xC0,
0x0F, 0x78, 0x07, 0xCF, 0x8F, 0xB1, 0xFF, 0xCC, 0x3F, 0xC3, 0xE0, 0x00,
0x3B, 0x80, 0x03, 0x9C, 0x00, 0x1C, 0x70, 0x00, 0xC3, 0x80, 0x0E, 0x0E,
0x00, 0x60, 0x70, 0x07, 0x01, 0x80, 0x38, 0x0E, 0x03, 0x80, 0x70, 0x1C,
0x01, 0xC1, 0xC0, 0x0E, 0x0E, 0x00, 0x38, 0x60, 0x01, 0xC7, 0x00, 0x06,
0x30, 0x00, 0x3B, 0x80, 0x00, 0xDC, 0x00, 0x07, 0xC0, 0x00, 0x3E, 0x00,
0x00, 0xE0, 0x00, 0x60, 0x00, 0xE0, 0x01, 0xDC, 0x00, 0x78, 0x00, 0x67,
0x00, 0x1E, 0x00, 0x38, 0xC0, 0x0F, 0xC0, 0x0C, 0x38, 0x03, 0xB0, 0x03,
0x06, 0x00, 0xCE, 0x01, 0xC1, 0xC0, 0x73, 0x80, 0x60, 0x70, 0x18, 0x60,
0x38, 0x0C, 0x06, 0x1C, 0x0E, 0x03, 0x83, 0x83, 0x03, 0x00, 0xE0, 0xC0,
0xC1, 0xC0, 0x18, 0x70, 0x38, 0x60, 0x07, 0x1C, 0x06, 0x18, 0x00, 0xC6,
0x01, 0xCE, 0x00, 0x3B, 0x80, 0x73, 0x00, 0x0E, 0xC0, 0x0D, 0xC0, 0x01,
0xB0, 0x03, 0xF0, 0x00, 0x7C, 0x00, 0x78, 0x00, 0x1E, 0x00, 0x1E, 0x00,
0x03, 0x80, 0x07, 0x00, 0x70, 0x01, 0xC7, 0x00, 0x70, 0xF0, 0x1C, 0x0E,
0x07, 0x80, 0xE0, 0xE0, 0x0E, 0x38, 0x00, 0xEE, 0x00, 0x1F, 0x80, 0x01,
0xF0, 0x00, 0x1C, 0x00, 0x07, 0xC0, 0x01, 0xF8, 0x00, 0x3B, 0x80, 0x0E,
0x38, 0x03, 0x83, 0x80, 0xE0, 0x78, 0x3C, 0x07, 0x07, 0x00, 0x71, 0xC0,
0x07, 0x70, 0x00, 0x70, 0x70, 0x00, 0x1C, 0xE0, 0x00, 0xE3, 0x80, 0x03,
0x87, 0x00, 0x0C, 0x1C, 0x00, 0x70, 0x38, 0x01, 0x80, 0xE0, 0x0E, 0x01,
0x80, 0x38, 0x07, 0x01, 0xC0, 0x1C, 0x07, 0x00, 0x38, 0x38, 0x00, 0xE0,
0xE0, 0x01, 0xC3, 0x00, 0x07, 0x1C, 0x00, 0x0E, 0x60, 0x00, 0x3B, 0x80,
0x00, 0x6E, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xC0, 0x00, 0x0E, 0x00, 0x00,
0x38, 0x00, 0x00, 0xC0, 0x00, 0x07, 0x00, 0x00, 0x38, 0x00, 0x40, 0xE0,
0x03, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x07, 0x80, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x38, 0x00, 0x70, 0x00,
0xE0, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1E,
0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0x03, 0xC1, 0xF0, 0xF0, 0x38, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C,
0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x3F, 0x0F,
0x80, 0xF0, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70,
0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x03, 0x80, 0xFC, 0x1F, 0x00, 0xC0,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFE, 0xF0, 0x3E, 0x03, 0xC0, 0x70, 0x0E, 0x03, 0x80, 0xE0, 0x38,
0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03,
0xF0, 0x7C, 0x3C, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0,
0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x07, 0x0F, 0xC3, 0xE0, 0xC0,
0x00, 0x0E, 0x00, 0xCF, 0xE0, 0x37, 0xBC, 0x0D, 0x83, 0x86, 0x60, 0x7F,
0xB0, 0x0F, 0xC0 };
const GFXglyph Montserrat_Regular20pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 10, 0, 0 }, // 0x20 ' '
{ 1, 4, 27, 10, 3, -26 }, // 0x21 '!'
{ 15, 9, 10, 15, 3, -26 }, // 0x22 '"'
{ 27, 25, 27, 27, 1, -26 }, // 0x23 '#'
{ 112, 20, 37, 24, 2, -31 }, // 0x24 '$'
{ 205, 29, 28, 32, 2, -27 }, // 0x25 '%'
{ 307, 24, 28, 26, 2, -27 }, // 0x26 '&'
{ 391, 2, 10, 8, 3, -26 }, // 0x27 '''
{ 394, 7, 37, 13, 4, -28 }, // 0x28 '('
{ 427, 7, 37, 13, 2, -28 }, // 0x29 ')'
{ 460, 13, 14, 15, 1, -28 }, // 0x2A '*'
{ 483, 17, 17, 22, 3, -21 }, // 0x2B '+'
{ 520, 4, 10, 8, 2, -3 }, // 0x2C ','
{ 525, 11, 3, 15, 2, -11 }, // 0x2D '-'
{ 530, 4, 4, 8, 2, -3 }, // 0x2E '.'
{ 532, 15, 37, 13, -1, -32 }, // 0x2F '/'
{ 602, 22, 28, 26, 2, -27 }, // 0x30 '0'
{ 679, 10, 27, 14, 0, -26 }, // 0x31 '1'
{ 713, 20, 28, 22, 1, -27 }, // 0x32 '2'
{ 783, 20, 27, 22, 0, -26 }, // 0x33 '3'
{ 851, 23, 27, 26, 2, -26 }, // 0x34 '4'
{ 929, 20, 27, 22, 1, -26 }, // 0x35 '5'
{ 997, 21, 28, 24, 2, -27 }, // 0x36 '6'
{ 1071, 20, 27, 23, 1, -26 }, // 0x37 '7'
{ 1139, 21, 28, 25, 2, -27 }, // 0x38 '8'
{ 1213, 21, 28, 24, 1, -27 }, // 0x39 '9'
{ 1287, 4, 21, 8, 2, -20 }, // 0x3A ':'
{ 1298, 4, 27, 8, 2, -20 }, // 0x3B ';'
{ 1312, 17, 16, 22, 3, -21 }, // 0x3C '<'
{ 1346, 17, 11, 22, 3, -18 }, // 0x3D '='
{ 1370, 17, 16, 22, 3, -21 }, // 0x3E '>'
{ 1404, 19, 28, 22, 0, -27 }, // 0x3F '?'
{ 1471, 36, 36, 40, 2, -27 }, // 0x40 '@'
{ 1633, 28, 27, 28, 0, -26 }, // 0x41 'A'
{ 1728, 23, 27, 29, 4, -26 }, // 0x42 'B'
{ 1806, 24, 28, 28, 2, -27 }, // 0x43 'C'
{ 1890, 26, 27, 32, 4, -26 }, // 0x44 'D'
{ 1978, 20, 27, 26, 4, -26 }, // 0x45 'E'
{ 2046, 19, 27, 25, 4, -26 }, // 0x46 'F'
{ 2111, 25, 28, 30, 2, -27 }, // 0x47 'G'
{ 2199, 23, 27, 32, 4, -26 }, // 0x48 'H'
{ 2277, 3, 27, 12, 4, -26 }, // 0x49 'I'
{ 2288, 15, 27, 20, 0, -26 }, // 0x4A 'J'
{ 2339, 24, 27, 28, 4, -26 }, // 0x4B 'K'
{ 2420, 19, 27, 23, 4, -26 }, // 0x4C 'L'
{ 2485, 29, 27, 37, 4, -26 }, // 0x4D 'M'
{ 2583, 23, 27, 32, 4, -26 }, // 0x4E 'N'
{ 2661, 29, 28, 33, 2, -27 }, // 0x4F 'O'
{ 2763, 22, 27, 28, 4, -26 }, // 0x50 'P'
{ 2838, 30, 33, 33, 2, -27 }, // 0x51 'Q'
{ 2962, 22, 27, 28, 4, -26 }, // 0x52 'R'
{ 3037, 20, 28, 24, 2, -27 }, // 0x53 'S'
{ 3107, 22, 27, 22, 0, -26 }, // 0x54 'T'
{ 3182, 23, 27, 31, 4, -26 }, // 0x55 'U'
{ 3260, 27, 27, 27, 0, -26 }, // 0x56 'V'
{ 3352, 41, 27, 43, 1, -26 }, // 0x57 'W'
{ 3491, 24, 27, 26, 1, -26 }, // 0x58 'X'
{ 3572, 25, 27, 25, 0, -26 }, // 0x59 'Y'
{ 3657, 22, 27, 25, 2, -26 }, // 0x5A 'Z'
{ 3732, 8, 37, 12, 4, -28 }, // 0x5B '['
{ 3769, 15, 37, 13, -1, -32 }, // 0x5C '\'
{ 3839, 7, 37, 12, 1, -28 }, // 0x5D ']'
{ 3872, 16, 16, 22, 3, -21 }, // 0x5E '^'
{ 3904, 20, 2, 20, 0, 1 }, // 0x5F '_'
{ 3909, 9, 5, 23, 5, -28 }, // 0x60 '`'
{ 3915, 17, 21, 23, 2, -20 }, // 0x61 'a'
{ 3960, 21, 29, 26, 4, -28 }, // 0x62 'b'
{ 4037, 18, 21, 22, 2, -20 }, // 0x63 'c'
{ 4085, 21, 29, 26, 2, -28 }, // 0x64 'd'
{ 4162, 20, 21, 24, 2, -20 }, // 0x65 'e'
{ 4215, 14, 29, 13, 1, -28 }, // 0x66 'f'
{ 4266, 21, 29, 27, 2, -20 }, // 0x67 'g'
{ 4343, 19, 29, 26, 4, -28 }, // 0x68 'h'
{ 4412, 4, 29, 10, 4, -28 }, // 0x69 'i'
{ 4427, 12, 37, 11, -4, -28 }, // 0x6A 'j'
{ 4483, 19, 29, 23, 4, -28 }, // 0x6B 'k'
{ 4552, 3, 29, 10, 4, -28 }, // 0x6C 'l'
{ 4563, 34, 21, 41, 4, -20 }, // 0x6D 'm'
{ 4653, 19, 21, 26, 4, -20 }, // 0x6E 'n'
{ 4703, 21, 21, 24, 2, -20 }, // 0x6F 'o'
{ 4759, 21, 29, 26, 4, -20 }, // 0x70 'p'
{ 4836, 21, 29, 26, 2, -20 }, // 0x71 'q'
{ 4913, 10, 21, 16, 4, -20 }, // 0x72 'r'
{ 4940, 17, 21, 19, 1, -20 }, // 0x73 's'
{ 4985, 14, 25, 16, 1, -24 }, // 0x74 't'
{ 5029, 18, 20, 26, 4, -19 }, // 0x75 'u'
{ 5074, 21, 20, 21, 0, -19 }, // 0x76 'v'
{ 5127, 34, 20, 34, 0, -19 }, // 0x77 'w'
{ 5212, 19, 20, 21, 1, -19 }, // 0x78 'x'
{ 5260, 22, 28, 21, -1, -19 }, // 0x79 'y'
{ 5337, 16, 20, 20, 2, -19 }, // 0x7A 'z'
{ 5377, 10, 37, 13, 2, -28 }, // 0x7B '{'
{ 5424, 3, 37, 11, 4, -28 }, // 0x7C '|'
{ 5438, 10, 37, 13, 1, -28 }, // 0x7D '}'
{ 5485, 18, 6, 22, 2, -16 } }; // 0x7E '~'
const GFXfont Montserrat_Regular20pt7b PROGMEM = {
(uint8_t *)Montserrat_Regular20pt7bBitmaps,
(GFXglyph *)Montserrat_Regular20pt7bGlyphs,
0x20, 0x7E, 48 };
// Approx. 6171 bytes
#endif // MONTSERRAT20PT7B_H
@@ -0,0 +1,170 @@
#ifndef MONTSERRAT7PT7B_H
#define MONTSERRAT7PT7B_H
const uint8_t Montserrat_Regular7pt7bBitmaps[] PROGMEM = {
0x00, 0xAA, 0xA8, 0x30, 0xB6, 0xD0, 0x11, 0x08, 0x84, 0x4F, 0xF1, 0x20,
0x91, 0xFC, 0x44, 0x22, 0x11, 0x00, 0x10, 0xFB, 0x44, 0x89, 0x0E, 0x07,
0x09, 0x13, 0x25, 0xF0, 0x81, 0x00, 0x60, 0x24, 0x49, 0x22, 0x50, 0xB4,
0x12, 0xE1, 0x24, 0x51, 0x22, 0x50, 0xE0, 0x38, 0x44, 0x44, 0x48, 0x30,
0x50, 0x89, 0x86, 0x86, 0x79, 0xF0, 0x29, 0x25, 0x24, 0x49, 0x22, 0xA5,
0x55, 0x56, 0x80, 0x23, 0xDC, 0x52, 0x00, 0x00, 0x41, 0x3F, 0x10, 0x40,
0xE0, 0xF0, 0x80, 0x08, 0x44, 0x21, 0x10, 0x84, 0x42, 0x11, 0x08, 0x00,
0x38, 0x44, 0x82, 0x82, 0x83, 0x81, 0x82, 0x82, 0x46, 0x3C, 0xE4, 0x92,
0x49, 0x24, 0x3D, 0x8C, 0x08, 0x10, 0x41, 0x86, 0x18, 0x60, 0xFC, 0x7E,
0x08, 0x30, 0x41, 0x80, 0xC0, 0x81, 0x82, 0xF8, 0x04, 0x08, 0x10, 0x20,
0x44, 0x44, 0xFF, 0x04, 0x04, 0x04, 0x7E, 0x81, 0x02, 0x07, 0x80, 0xC0,
0x81, 0x02, 0xF8, 0x3C, 0x82, 0x04, 0x0B, 0xD8, 0xE0, 0xC1, 0x42, 0x78,
0xFF, 0x82, 0x82, 0x04, 0x04, 0x0C, 0x08, 0x08, 0x10, 0x10, 0x79, 0x8E,
0x0C, 0x17, 0xD8, 0xA0, 0xC1, 0x82, 0xF8, 0x3C, 0x42, 0x82, 0x83, 0x43,
0x3D, 0x01, 0x02, 0x02, 0x7C, 0x82, 0x83, 0x80, 0x04, 0x6E, 0x30, 0x38,
0x10, 0xFC, 0x00, 0x3F, 0x81, 0x81, 0xC3, 0x72, 0x00, 0x3D, 0x8C, 0x08,
0x10, 0x41, 0x04, 0x00, 0x00, 0x30, 0x0F, 0x81, 0x83, 0x10, 0x05, 0x1E,
0xA9, 0x0C, 0xC8, 0x26, 0x41, 0x32, 0x09, 0x90, 0xCC, 0x7B, 0x90, 0x00,
0x60, 0x00, 0xF8, 0x00, 0x0C, 0x03, 0x01, 0x20, 0x48, 0x12, 0x08, 0x43,
0xF1, 0x02, 0x40, 0xA0, 0x10, 0xFC, 0x82, 0x82, 0x82, 0x86, 0xFE, 0x81,
0x81, 0x83, 0xFE, 0x1E, 0x61, 0xC0, 0x80, 0x80, 0x80, 0x80, 0xC0, 0x61,
0x3E, 0xFC, 0x41, 0x20, 0x50, 0x18, 0x0C, 0x06, 0x03, 0x02, 0x83, 0x7E,
0x00, 0xFD, 0x02, 0x04, 0x08, 0x1F, 0x20, 0x40, 0x81, 0xFC, 0xFE, 0x08,
0x20, 0x83, 0xF8, 0x20, 0x82, 0x00, 0x1E, 0x30, 0xF0, 0x10, 0x08, 0x04,
0x0A, 0x05, 0x82, 0x61, 0x1F, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFD,
0x81, 0x81, 0x81, 0x81, 0xFF, 0xC0, 0x7C, 0x30, 0xC3, 0x0C, 0x30, 0xC2,
0x89, 0xE0, 0x82, 0x84, 0x88, 0x90, 0xA0, 0xF0, 0xC8, 0x8C, 0x86, 0x82,
0x82, 0x08, 0x20, 0x82, 0x08, 0x20, 0x83, 0xF0, 0x80, 0x60, 0x3C, 0x0F,
0x05, 0xA2, 0x64, 0x99, 0x46, 0x31, 0x88, 0x60, 0x10, 0x81, 0x81, 0xC1,
0xA1, 0x91, 0x99, 0x89, 0x85, 0x83, 0x81, 0x1E, 0x18, 0x6C, 0x0A, 0x01,
0x80, 0x60, 0x18, 0x07, 0x02, 0x61, 0x8F, 0x80, 0xF9, 0x0E, 0x0C, 0x18,
0x30, 0xFE, 0x40, 0x81, 0x00, 0x1E, 0x18, 0x6C, 0x0A, 0x01, 0x80, 0x60,
0x18, 0x07, 0x02, 0x61, 0x8F, 0x80, 0x60, 0x0F, 0xF9, 0x0E, 0x0C, 0x18,
0x30, 0xFE, 0x42, 0x85, 0x04, 0x7D, 0x82, 0x04, 0x06, 0x03, 0x80, 0x81,
0x82, 0xF8, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x82, 0xC2, 0x7C, 0x80, 0x50,
0x24, 0x08, 0x84, 0x21, 0x08, 0x81, 0x20, 0x58, 0x0C, 0x03, 0x00, 0x82,
0x06, 0x0C, 0x18, 0x30, 0x91, 0x42, 0x44, 0x89, 0x22, 0x42, 0x89, 0x0A,
0x14, 0x30, 0x60, 0x41, 0x80, 0x41, 0x30, 0x88, 0x82, 0x80, 0xC0, 0x60,
0x50, 0x44, 0x61, 0x20, 0xC0, 0x80, 0xA0, 0x98, 0x84, 0x41, 0x40, 0xA0,
0x20, 0x10, 0x08, 0x04, 0x00, 0xFF, 0x02, 0x04, 0x08, 0x18, 0x10, 0x20,
0x40, 0x80, 0xFF, 0xEA, 0xAA, 0xAA, 0xC0, 0x84, 0x20, 0x84, 0x20, 0x84,
0x20, 0x84, 0x20, 0x80, 0x64, 0x92, 0x49, 0x24, 0x9E, 0x30, 0xC2, 0x92,
0x4A, 0x10, 0xFE, 0x44, 0xF8, 0x10, 0x7F, 0x86, 0x37, 0x40, 0x80, 0x80,
0x80, 0xBE, 0xC2, 0x81, 0x81, 0xC1, 0xC2, 0xBC, 0x7E, 0x08, 0x20, 0x83,
0x17, 0x80, 0x02, 0x04, 0x0B, 0xF8, 0x30, 0x60, 0xC1, 0xC6, 0xF4, 0x7D,
0x0A, 0x0F, 0xF8, 0x18, 0x1F, 0x00, 0x39, 0x08, 0xE2, 0x10, 0x84, 0x21,
0x00, 0x7F, 0x06, 0x0C, 0x18, 0x38, 0xCE, 0x81, 0xC6, 0x70, 0x81, 0x02,
0x05, 0xEC, 0x30, 0x60, 0xC1, 0x83, 0x04, 0xC2, 0xAA, 0xA0, 0x30, 0x02,
0x22, 0x22, 0x22, 0x22, 0xC0, 0x81, 0x02, 0x04, 0x28, 0x92, 0x2E, 0x64,
0x85, 0x04, 0xFF, 0xC0, 0xBD, 0xF6, 0x10, 0xA0, 0x83, 0x04, 0x18, 0x20,
0xC1, 0x06, 0x08, 0x20, 0xBD, 0x86, 0x0C, 0x18, 0x30, 0x60, 0x80, 0x7D,
0x06, 0x0C, 0x18, 0x38, 0xDE, 0x00, 0xBE, 0xC2, 0x81, 0x81, 0xC1, 0xC2,
0xBC, 0x80, 0x80, 0x80, 0x7F, 0x06, 0x0C, 0x18, 0x38, 0xDE, 0x81, 0x02,
0x04, 0xBC, 0x88, 0x88, 0x80, 0x7D, 0x04, 0x0F, 0x04, 0x17, 0xC0, 0x21,
0x1C, 0x42, 0x10, 0x84, 0x38, 0x83, 0x06, 0x0C, 0x18, 0x28, 0xDE, 0x80,
0x82, 0x42, 0x44, 0x24, 0x28, 0x18, 0x18, 0x86, 0x14, 0x61, 0x45, 0x22,
0x92, 0x29, 0x43, 0x0C, 0x10, 0xC0, 0x46, 0x48, 0x60, 0x82, 0x8C, 0x90,
0x80, 0x82, 0x42, 0x44, 0x24, 0x28, 0x18, 0x18, 0x10, 0x30, 0xE0, 0xF8,
0x61, 0x08, 0x42, 0x0F, 0xC0, 0x69, 0x24, 0xB2, 0x49, 0x22, 0xFF, 0xF8,
0x62, 0x22, 0x22, 0x32, 0x22, 0x22, 0xC0, 0xE6, 0x70 };
const GFXglyph Montserrat_Regular7pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 4, 0, 0 }, // 0x20 ' '
{ 1, 2, 10, 4, 1, -9 }, // 0x21 '!'
{ 4, 3, 4, 5, 1, -9 }, // 0x22 '"'
{ 6, 9, 10, 10, 0, -9 }, // 0x23 '#'
{ 18, 7, 13, 9, 1, -10 }, // 0x24 '$'
{ 30, 10, 10, 12, 1, -9 }, // 0x25 '%'
{ 43, 8, 10, 9, 1, -9 }, // 0x26 '&'
{ 53, 1, 4, 3, 1, -9 }, // 0x27 '''
{ 54, 3, 13, 5, 1, -9 }, // 0x28 '('
{ 59, 2, 13, 5, 1, -9 }, // 0x29 ')'
{ 63, 5, 5, 5, 0, -9 }, // 0x2A '*'
{ 67, 6, 6, 8, 1, -7 }, // 0x2B '+'
{ 72, 1, 3, 3, 1, 0 }, // 0x2C ','
{ 73, 4, 1, 5, 1, -3 }, // 0x2D '-'
{ 74, 1, 1, 3, 1, 0 }, // 0x2E '.'
{ 75, 5, 13, 5, 0, -11 }, // 0x2F '/'
{ 84, 8, 10, 9, 1, -9 }, // 0x30 '0'
{ 94, 3, 10, 5, 0, -9 }, // 0x31 '1'
{ 98, 7, 10, 8, 0, -9 }, // 0x32 '2'
{ 107, 7, 10, 8, 0, -9 }, // 0x33 '3'
{ 116, 8, 10, 9, 1, -9 }, // 0x34 '4'
{ 126, 7, 10, 8, 0, -9 }, // 0x35 '5'
{ 135, 7, 10, 9, 1, -9 }, // 0x36 '6'
{ 144, 8, 10, 8, 0, -9 }, // 0x37 '7'
{ 154, 7, 10, 9, 1, -9 }, // 0x38 '8'
{ 163, 8, 10, 9, 0, -9 }, // 0x39 '9'
{ 173, 1, 7, 3, 1, -6 }, // 0x3A ':'
{ 174, 1, 9, 3, 1, -6 }, // 0x3B ';'
{ 176, 6, 6, 8, 1, -7 }, // 0x3C '<'
{ 181, 6, 4, 8, 1, -6 }, // 0x3D '='
{ 184, 6, 6, 8, 1, -7 }, // 0x3E '>'
{ 189, 7, 10, 8, 0, -9 }, // 0x3F '?'
{ 198, 13, 13, 14, 1, -9 }, // 0x40 '@'
{ 220, 10, 10, 10, 0, -9 }, // 0x41 'A'
{ 233, 8, 10, 11, 2, -9 }, // 0x42 'B'
{ 243, 8, 10, 10, 1, -9 }, // 0x43 'C'
{ 253, 9, 10, 12, 2, -9 }, // 0x44 'D'
{ 265, 7, 10, 9, 2, -9 }, // 0x45 'E'
{ 274, 6, 10, 9, 2, -9 }, // 0x46 'F'
{ 282, 9, 10, 11, 1, -9 }, // 0x47 'G'
{ 294, 8, 10, 11, 2, -9 }, // 0x48 'H'
{ 304, 1, 10, 4, 2, -9 }, // 0x49 'I'
{ 306, 6, 10, 7, 0, -9 }, // 0x4A 'J'
{ 314, 8, 10, 10, 2, -9 }, // 0x4B 'K'
{ 324, 6, 10, 8, 2, -9 }, // 0x4C 'L'
{ 332, 10, 10, 13, 2, -9 }, // 0x4D 'M'
{ 345, 8, 10, 11, 2, -9 }, // 0x4E 'N'
{ 355, 10, 10, 12, 1, -9 }, // 0x4F 'O'
{ 368, 7, 10, 10, 2, -9 }, // 0x50 'P'
{ 377, 10, 12, 12, 1, -9 }, // 0x51 'Q'
{ 392, 7, 10, 10, 2, -9 }, // 0x52 'R'
{ 401, 7, 10, 9, 1, -9 }, // 0x53 'S'
{ 410, 8, 10, 8, 0, -9 }, // 0x54 'T'
{ 420, 8, 10, 11, 2, -9 }, // 0x55 'U'
{ 430, 10, 10, 10, 0, -9 }, // 0x56 'V'
{ 443, 14, 10, 16, 1, -9 }, // 0x57 'W'
{ 461, 9, 10, 9, 0, -9 }, // 0x58 'X'
{ 473, 9, 10, 9, 0, -9 }, // 0x59 'Y'
{ 485, 8, 10, 9, 1, -9 }, // 0x5A 'Z'
{ 495, 2, 13, 4, 2, -9 }, // 0x5B '['
{ 499, 5, 13, 5, 0, -11 }, // 0x5C '\'
{ 508, 3, 13, 4, 0, -9 }, // 0x5D ']'
{ 513, 6, 6, 8, 1, -7 }, // 0x5E '^'
{ 518, 7, 1, 7, 0, 1 }, // 0x5F '_'
{ 519, 3, 2, 8, 2, -9 }, // 0x60 '`'
{ 520, 6, 7, 8, 1, -6 }, // 0x61 'a'
{ 526, 8, 10, 9, 1, -9 }, // 0x62 'b'
{ 536, 6, 7, 8, 1, -6 }, // 0x63 'c'
{ 542, 7, 10, 9, 1, -9 }, // 0x64 'd'
{ 551, 7, 7, 8, 1, -6 }, // 0x65 'e'
{ 558, 5, 10, 5, 0, -9 }, // 0x66 'f'
{ 565, 7, 10, 10, 1, -6 }, // 0x67 'g'
{ 574, 7, 10, 9, 1, -9 }, // 0x68 'h'
{ 583, 2, 10, 4, 1, -9 }, // 0x69 'i'
{ 586, 4, 13, 4, -1, -9 }, // 0x6A 'j'
{ 593, 7, 10, 8, 1, -9 }, // 0x6B 'k'
{ 602, 1, 10, 4, 1, -9 }, // 0x6C 'l'
{ 604, 13, 7, 15, 1, -6 }, // 0x6D 'm'
{ 616, 7, 7, 9, 1, -6 }, // 0x6E 'n'
{ 623, 7, 7, 9, 1, -6 }, // 0x6F 'o'
{ 630, 8, 10, 9, 1, -6 }, // 0x70 'p'
{ 640, 7, 10, 9, 1, -6 }, // 0x71 'q'
{ 649, 4, 7, 6, 1, -6 }, // 0x72 'r'
{ 653, 6, 7, 7, 0, -6 }, // 0x73 's'
{ 659, 5, 9, 6, 0, -8 }, // 0x74 't'
{ 665, 7, 7, 9, 1, -6 }, // 0x75 'u'
{ 672, 8, 7, 8, 0, -6 }, // 0x76 'v'
{ 679, 12, 7, 12, 0, -6 }, // 0x77 'w'
{ 690, 7, 7, 7, 0, -6 }, // 0x78 'x'
{ 697, 8, 10, 8, 0, -6 }, // 0x79 'y'
{ 707, 6, 7, 7, 1, -6 }, // 0x7A 'z'
{ 713, 3, 13, 5, 1, -9 }, // 0x7B '{'
{ 718, 1, 13, 4, 2, -9 }, // 0x7C '|'
{ 720, 4, 13, 5, 0, -9 }, // 0x7D '}'
{ 727, 6, 2, 8, 1, -5 } }; // 0x7E '~'
const GFXfont Montserrat_Regular7pt7b PROGMEM = {
(uint8_t *)Montserrat_Regular7pt7bBitmaps,
(GFXglyph *)Montserrat_Regular7pt7bGlyphs,
0x20, 0x7E, 17 };
// Approx. 1401 bytes
#endif // MONTSERRAT7PT7B_H
@@ -0,0 +1,210 @@
#ifndef MONTSERRAT9PT7B_H
#define MONTSERRAT9PT7B_H
const uint8_t Montserrat_Regular9pt7bBitmaps[] PROGMEM = {
0x00, 0x55, 0x55, 0x41, 0xC0, 0x99, 0x99, 0x90, 0x10, 0x82, 0x10, 0x42,
0x08, 0x8F, 0xFE, 0x22, 0x08, 0x41, 0x08, 0x21, 0x1F, 0xF8, 0x84, 0x10,
0x82, 0x20, 0x08, 0x04, 0x07, 0x8F, 0x7C, 0x84, 0x43, 0x20, 0xD0, 0x3C,
0x07, 0x82, 0x61, 0x10, 0x8E, 0x4D, 0xF8, 0x10, 0x08, 0x00, 0x30, 0x26,
0x43, 0x22, 0x11, 0x11, 0x08, 0x90, 0x44, 0x81, 0xC9, 0xC0, 0x93, 0x04,
0x88, 0x48, 0x44, 0x42, 0x21, 0x12, 0x07, 0x00, 0x1C, 0x06, 0x40, 0x8C,
0x11, 0x82, 0x60, 0x38, 0x0E, 0x03, 0x22, 0xC2, 0x50, 0x7A, 0x06, 0x61,
0xE3, 0xE6, 0xF8, 0x69, 0x69, 0x24, 0x92, 0x4C, 0x93, 0x89, 0x36, 0x49,
0x24, 0x96, 0x94, 0x11, 0xA8, 0xE1, 0xC5, 0x42, 0x00, 0x08, 0x08, 0x08,
0xFF, 0x08, 0x08, 0x08, 0x08, 0xF6, 0x80, 0xF8, 0xF0, 0x04, 0x08, 0x10,
0x40, 0x81, 0x04, 0x08, 0x30, 0x40, 0x83, 0x04, 0x08, 0x30, 0x40, 0x80,
0x0C, 0x0F, 0xC6, 0x1B, 0x02, 0xC0, 0xE0, 0x18, 0x06, 0x01, 0x80, 0x70,
0x34, 0x09, 0x84, 0x1E, 0x00, 0xFF, 0x11, 0x11, 0x11, 0x11, 0x11, 0x10,
0x1C, 0x1D, 0xC4, 0x18, 0x02, 0x00, 0x80, 0x60, 0x30, 0x18, 0x0C, 0x06,
0x03, 0x01, 0x80, 0x7F, 0xC0, 0x7F, 0xBF, 0xC0, 0xC0, 0x40, 0x40, 0x40,
0x3C, 0x03, 0x00, 0x80, 0x40, 0x38, 0x33, 0xE0, 0x03, 0x00, 0x40, 0x10,
0x04, 0x01, 0x80, 0x60, 0x08, 0x42, 0x08, 0x81, 0x1F, 0xFC, 0x04, 0x00,
0x80, 0x10, 0x3F, 0x9F, 0xC8, 0x04, 0x02, 0x03, 0x01, 0xFC, 0x03, 0x00,
0x80, 0x40, 0x3C, 0x33, 0xF0, 0x0F, 0x1C, 0x98, 0x08, 0x0C, 0x04, 0x62,
0xFD, 0x83, 0xC0, 0xE0, 0x50, 0x2C, 0x31, 0xF0, 0xFF, 0xFF, 0xE0, 0x50,
0x60, 0x20, 0x10, 0x10, 0x08, 0x0C, 0x04, 0x06, 0x02, 0x03, 0x00, 0x1C,
0x1C, 0xC4, 0x0B, 0x02, 0xC0, 0x98, 0x63, 0xE1, 0x06, 0x80, 0xA0, 0x38,
0x0B, 0x06, 0x3F, 0x00, 0x38, 0x33, 0x20, 0x50, 0x38, 0x1C, 0x0F, 0x0A,
0x79, 0x00, 0x80, 0xC0, 0x40, 0xCF, 0xC0, 0xF0, 0x00, 0xF0, 0xF0, 0x00,
0xF6, 0x80, 0x01, 0x0E, 0x38, 0xC0, 0x70, 0x1C, 0x03, 0xFF, 0x00, 0x00,
0x00, 0xFF, 0xC0, 0x70, 0x0E, 0x03, 0x07, 0x38, 0xE0, 0x1C, 0x39, 0x90,
0x60, 0x10, 0x18, 0x08, 0x08, 0x08, 0x0C, 0x00, 0x00, 0x01, 0x80, 0xC0,
0x03, 0xE0, 0x06, 0x0C, 0x0C, 0x01, 0x0C, 0x00, 0x44, 0x3C, 0x94, 0x21,
0x4A, 0x20, 0x63, 0x10, 0x11, 0x88, 0x08, 0xC4, 0x04, 0x62, 0x06, 0x58,
0x85, 0x24, 0x3C, 0xE1, 0x00, 0x00, 0xC0, 0x00, 0x1C, 0x60, 0x01, 0xC0,
0x00, 0x02, 0x00, 0x38, 0x01, 0x40, 0x1B, 0x00, 0x88, 0x0C, 0x40, 0x41,
0x02, 0x08, 0x20, 0x61, 0xFF, 0x18, 0x0C, 0x80, 0x2C, 0x01, 0x80, 0xFE,
0x1F, 0xF2, 0x03, 0x40, 0x28, 0x0D, 0x01, 0x3F, 0xC4, 0x06, 0x80, 0x50,
0x0E, 0x01, 0x40, 0x6F, 0xF8, 0x07, 0x03, 0xB9, 0x80, 0xA0, 0x0C, 0x01,
0x00, 0x20, 0x04, 0x00, 0xC0, 0x08, 0x01, 0x80, 0x18, 0x30, 0xF8, 0xFC,
0x0F, 0xF8, 0x80, 0x48, 0x02, 0x80, 0x38, 0x01, 0x80, 0x18, 0x01, 0x80,
0x38, 0x02, 0x80, 0x68, 0x1C, 0xFF, 0x00, 0xFF, 0xFF, 0xE0, 0x10, 0x08,
0x04, 0x03, 0xFD, 0x00, 0x80, 0x40, 0x20, 0x10, 0x0F, 0xF8, 0xFF, 0xFF,
0xE0, 0x10, 0x08, 0x04, 0x03, 0xFD, 0xFE, 0x80, 0x40, 0x20, 0x10, 0x08,
0x00, 0x07, 0x03, 0xBD, 0x80, 0xA0, 0x0C, 0x01, 0x00, 0x20, 0x04, 0x01,
0xC0, 0x28, 0x05, 0x80, 0x98, 0x30, 0xFC, 0x80, 0x70, 0x0E, 0x01, 0xC0,
0x38, 0x07, 0x00, 0xFF, 0xFC, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38,
0x06, 0xFF, 0xF8, 0x7E, 0xFC, 0x08, 0x10, 0x20, 0x40, 0x81, 0x02, 0x04,
0x0E, 0x37, 0xC0, 0x80, 0x50, 0x12, 0x04, 0x41, 0x08, 0x41, 0x10, 0x26,
0x05, 0xE0, 0xE6, 0x18, 0x62, 0x06, 0x40, 0x48, 0x04, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 0x80, 0x0E,
0x00, 0xF0, 0x07, 0x40, 0x7B, 0x02, 0xC8, 0x26, 0x61, 0x31, 0x11, 0x85,
0x8C, 0x28, 0x60, 0x83, 0x00, 0x18, 0x00, 0x80, 0x80, 0x78, 0x0F, 0x81,
0xD8, 0x39, 0x07, 0x10, 0xE3, 0x1C, 0x33, 0x83, 0x70, 0x2E, 0x03, 0xC0,
0x78, 0x06, 0x07, 0x00, 0xEF, 0x18, 0x0C, 0x80, 0x2C, 0x01, 0xC0, 0x06,
0x00, 0x30, 0x01, 0xC0, 0x0A, 0x00, 0xD8, 0x0C, 0x60, 0xC0, 0xFC, 0x00,
0xFC, 0x3F, 0xC8, 0x0A, 0x03, 0x80, 0x60, 0x18, 0x0E, 0x06, 0xFF, 0x20,
0x08, 0x02, 0x00, 0x80, 0x00, 0x07, 0x00, 0x77, 0x86, 0x03, 0x10, 0x04,
0xC0, 0x1A, 0x00, 0x28, 0x00, 0xA0, 0x02, 0xC0, 0x09, 0x00, 0x66, 0x03,
0x0C, 0x18, 0x0F, 0xC0, 0x06, 0x00, 0x0F, 0x80, 0x00, 0xFC, 0x3F, 0xC8,
0x0A, 0x03, 0x80, 0x60, 0x18, 0x0E, 0x06, 0xFF, 0x20, 0xC8, 0x12, 0x02,
0x80, 0xC0, 0x1E, 0x39, 0xF0, 0x10, 0x0C, 0x03, 0x00, 0xF0, 0x0E, 0x01,
0x80, 0x40, 0x38, 0x37, 0xE0, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03,
0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x00, 0x80, 0x60,
0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x70, 0x1C, 0x0D,
0x86, 0x3F, 0x00, 0xC0, 0x12, 0x00, 0x90, 0x0C, 0xC0, 0x42, 0x06, 0x18,
0x20, 0x43, 0x03, 0x10, 0x08, 0x80, 0x6C, 0x01, 0x40, 0x0E, 0x00, 0x60,
0x00, 0x80, 0xC0, 0x60, 0x30, 0x1C, 0x0C, 0x0D, 0x07, 0x82, 0x41, 0x20,
0x98, 0x48, 0x62, 0x33, 0x10, 0x88, 0x44, 0x32, 0x13, 0x05, 0x86, 0x81,
0x40, 0xA0, 0x70, 0x38, 0x08, 0x04, 0x00, 0x40, 0x26, 0x04, 0x30, 0xC1,
0x18, 0x09, 0x00, 0xE0, 0x06, 0x00, 0xE0, 0x09, 0x01, 0x18, 0x30, 0xC6,
0x04, 0x40, 0x20, 0x80, 0x28, 0x0D, 0x81, 0x10, 0x61, 0x08, 0x32, 0x02,
0xC0, 0x70, 0x04, 0x00, 0x80, 0x10, 0x02, 0x00, 0x40, 0xFF, 0xFF, 0xF0,
0x18, 0x04, 0x02, 0x01, 0x80, 0xC0, 0x60, 0x10, 0x08, 0x06, 0x03, 0x00,
0xFF, 0xC0, 0xF2, 0x49, 0x24, 0x92, 0x49, 0x27, 0x40, 0x81, 0x01, 0x02,
0x06, 0x04, 0x08, 0x18, 0x10, 0x20, 0x60, 0x40, 0x80, 0x81, 0x02, 0xF3,
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x18, 0x18, 0x14, 0x24, 0x22,
0x42, 0x42, 0xFF, 0x80, 0x60, 0x80, 0x18, 0x7E, 0x03, 0x01, 0x01, 0x7F,
0x81, 0x81, 0xC3, 0x7D, 0x80, 0x40, 0x20, 0x11, 0x0B, 0xF6, 0x0E, 0x03,
0x01, 0x80, 0xC0, 0x70, 0x7C, 0x6B, 0xE0, 0x08, 0x3F, 0x41, 0xC0, 0x80,
0x80, 0x80, 0xC0, 0x63, 0x3E, 0x00, 0x80, 0x40, 0x21, 0x17, 0xEA, 0x0F,
0x03, 0x01, 0x80, 0xC0, 0x70, 0x2C, 0x73, 0xE8, 0x08, 0x3F, 0x10, 0x50,
0x18, 0x0F, 0xFE, 0x01, 0x80, 0x61, 0x1F, 0x00, 0x1E, 0x40, 0x81, 0x0F,
0xC4, 0x08, 0x10, 0x20, 0x40, 0x81, 0x02, 0x00, 0x08, 0x1F, 0xF4, 0x1E,
0x03, 0x80, 0xE0, 0x38, 0x0F, 0x07, 0x7F, 0xC7, 0x30, 0x08, 0x02, 0x7F,
0x03, 0x00, 0x80, 0x40, 0x20, 0x11, 0x0B, 0xE6, 0x0A, 0x05, 0x02, 0x81,
0xC0, 0xE0, 0x70, 0x38, 0x18, 0xC0, 0x55, 0x55, 0x40, 0x18, 0x00, 0x00,
0x84, 0x21, 0x08, 0x42, 0x10, 0x84, 0x2F, 0x20, 0x80, 0x40, 0x20, 0x10,
0x28, 0x24, 0x22, 0x61, 0x60, 0xF8, 0x66, 0x21, 0x90, 0x48, 0x10, 0xFF,
0xF8, 0x08, 0x11, 0x7C, 0xFB, 0x0E, 0x0C, 0x08, 0x18, 0x10, 0x30, 0x20,
0x60, 0x40, 0xC0, 0x81, 0x81, 0x03, 0x02, 0x04, 0x08, 0x5F, 0x30, 0x50,
0x28, 0x14, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xC0, 0x08, 0x1F, 0x90, 0x78,
0x18, 0x0C, 0x06, 0x03, 0x81, 0x63, 0x1F, 0x00, 0x08, 0x5F, 0xB0, 0x70,
0x18, 0x0C, 0x06, 0x03, 0x83, 0xE3, 0x5F, 0x20, 0x10, 0x08, 0x00, 0x08,
0x3F, 0x50, 0x78, 0x18, 0x0C, 0x06, 0x03, 0x81, 0x63, 0x9F, 0x40, 0x20,
0x10, 0x08, 0x0D, 0xF1, 0x08, 0x42, 0x10, 0x84, 0x00, 0x08, 0x7F, 0x40,
0x40, 0x60, 0x1E, 0x03, 0x01, 0x43, 0x7E, 0x20, 0x40, 0x87, 0xE2, 0x04,
0x08, 0x10, 0x20, 0x40, 0xC0, 0xF0, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x81, 0xC3, 0x7D, 0xC0, 0x90, 0x26, 0x10, 0x84, 0x33, 0x04, 0x81, 0x60,
0x30, 0x0C, 0x00, 0xC1, 0x82, 0x41, 0x82, 0x42, 0xC6, 0x22, 0x44, 0x26,
0x44, 0x34, 0x28, 0x14, 0x28, 0x18, 0x28, 0x08, 0x10, 0x61, 0x91, 0x85,
0x81, 0x80, 0xC0, 0xB0, 0xC8, 0x42, 0x41, 0x80, 0xC0, 0x90, 0x26, 0x10,
0x84, 0x33, 0x04, 0x81, 0x60, 0x30, 0x0C, 0x02, 0x00, 0x83, 0xC0, 0x60,
0x00, 0xFE, 0x08, 0x30, 0xC1, 0x04, 0x18, 0x60, 0xFE, 0x39, 0x18, 0xC6,
0x31, 0x8C, 0xE3, 0x18, 0xC6, 0x30, 0x87, 0xFF, 0xFF, 0xE1, 0x0C, 0x63,
0x18, 0xC6, 0x39, 0x8C, 0x63, 0x18, 0x9C, 0x61, 0xD9, 0x8F };
const GFXglyph Montserrat_Regular9pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' '
{ 1, 2, 13, 5, 1, -12 }, // 0x21 '!'
{ 5, 4, 5, 7, 1, -12 }, // 0x22 '"'
{ 8, 11, 13, 13, 1, -12 }, // 0x23 '#'
{ 26, 9, 17, 11, 1, -14 }, // 0x24 '$'
{ 46, 13, 13, 15, 1, -12 }, // 0x25 '%'
{ 68, 11, 13, 12, 1, -12 }, // 0x26 '&'
{ 86, 1, 5, 4, 1, -12 }, // 0x27 '''
{ 87, 3, 16, 6, 2, -12 }, // 0x28 '('
{ 93, 3, 16, 6, 1, -12 }, // 0x29 ')'
{ 99, 7, 6, 7, 0, -12 }, // 0x2A '*'
{ 105, 8, 8, 10, 1, -9 }, // 0x2B '+'
{ 113, 2, 5, 4, 1, -1 }, // 0x2C ','
{ 115, 5, 1, 7, 1, -4 }, // 0x2D '-'
{ 116, 2, 2, 4, 1, -1 }, // 0x2E '.'
{ 117, 7, 17, 6, 0, -14 }, // 0x2F '/'
{ 132, 10, 13, 12, 1, -12 }, // 0x30 '0'
{ 149, 4, 13, 7, 0, -12 }, // 0x31 '1'
{ 156, 10, 13, 10, 0, -12 }, // 0x32 '2'
{ 173, 9, 13, 10, 0, -12 }, // 0x33 '3'
{ 188, 11, 13, 12, 1, -12 }, // 0x34 '4'
{ 206, 9, 13, 10, 0, -12 }, // 0x35 '5'
{ 221, 9, 13, 11, 1, -12 }, // 0x36 '6'
{ 236, 9, 13, 11, 1, -12 }, // 0x37 '7'
{ 251, 10, 13, 11, 1, -12 }, // 0x38 '8'
{ 268, 9, 13, 11, 1, -12 }, // 0x39 '9'
{ 283, 2, 10, 4, 1, -9 }, // 0x3A ':'
{ 286, 2, 13, 4, 1, -9 }, // 0x3B ';'
{ 290, 8, 7, 10, 1, -9 }, // 0x3C '<'
{ 297, 8, 5, 10, 1, -8 }, // 0x3D '='
{ 302, 8, 7, 10, 1, -9 }, // 0x3E '>'
{ 309, 9, 13, 10, 0, -12 }, // 0x3F '?'
{ 324, 17, 17, 19, 1, -12 }, // 0x40 '@'
{ 361, 13, 13, 13, 0, -12 }, // 0x41 'A'
{ 383, 11, 13, 14, 2, -12 }, // 0x42 'B'
{ 401, 11, 13, 13, 1, -12 }, // 0x43 'C'
{ 419, 12, 13, 15, 2, -12 }, // 0x44 'D'
{ 439, 9, 13, 12, 2, -12 }, // 0x45 'E'
{ 454, 9, 13, 11, 2, -12 }, // 0x46 'F'
{ 469, 11, 13, 14, 1, -12 }, // 0x47 'G'
{ 487, 11, 13, 15, 2, -12 }, // 0x48 'H'
{ 505, 1, 13, 5, 2, -12 }, // 0x49 'I'
{ 507, 7, 13, 9, 0, -12 }, // 0x4A 'J'
{ 519, 11, 13, 13, 2, -12 }, // 0x4B 'K'
{ 537, 8, 13, 11, 2, -12 }, // 0x4C 'L'
{ 550, 13, 13, 17, 2, -12 }, // 0x4D 'M'
{ 572, 11, 13, 15, 2, -12 }, // 0x4E 'N'
{ 590, 13, 13, 15, 1, -12 }, // 0x4F 'O'
{ 612, 10, 13, 13, 2, -12 }, // 0x50 'P'
{ 629, 14, 16, 15, 1, -12 }, // 0x51 'Q'
{ 657, 10, 13, 13, 2, -12 }, // 0x52 'R'
{ 674, 9, 13, 11, 1, -12 }, // 0x53 'S'
{ 689, 10, 13, 10, 0, -12 }, // 0x54 'T'
{ 706, 10, 13, 14, 2, -12 }, // 0x55 'U'
{ 723, 13, 13, 13, 0, -12 }, // 0x56 'V'
{ 745, 18, 13, 20, 1, -12 }, // 0x57 'W'
{ 775, 12, 13, 12, 0, -12 }, // 0x58 'X'
{ 795, 11, 13, 11, 0, -12 }, // 0x59 'Y'
{ 813, 10, 13, 12, 1, -12 }, // 0x5A 'Z'
{ 830, 3, 16, 6, 2, -12 }, // 0x5B '['
{ 836, 7, 17, 6, -1, -14 }, // 0x5C '\'
{ 851, 4, 16, 6, 0, -12 }, // 0x5D ']'
{ 859, 8, 7, 10, 1, -9 }, // 0x5E '^'
{ 866, 9, 1, 9, 0, 1 }, // 0x5F '_'
{ 868, 5, 2, 11, 2, -12 }, // 0x60 '`'
{ 870, 8, 10, 11, 1, -9 }, // 0x61 'a'
{ 880, 9, 13, 12, 2, -12 }, // 0x62 'b'
{ 895, 8, 10, 10, 1, -9 }, // 0x63 'c'
{ 905, 9, 13, 12, 1, -12 }, // 0x64 'd'
{ 920, 9, 10, 11, 1, -9 }, // 0x65 'e'
{ 932, 7, 13, 6, 0, -12 }, // 0x66 'f'
{ 944, 10, 14, 12, 1, -9 }, // 0x67 'g'
{ 962, 9, 13, 12, 2, -12 }, // 0x68 'h'
{ 977, 2, 13, 5, 1, -12 }, // 0x69 'i'
{ 981, 5, 17, 5, -2, -12 }, // 0x6A 'j'
{ 992, 9, 13, 11, 2, -12 }, // 0x6B 'k'
{ 1007, 1, 13, 5, 2, -12 }, // 0x6C 'l'
{ 1009, 15, 10, 19, 2, -9 }, // 0x6D 'm'
{ 1028, 9, 10, 12, 2, -9 }, // 0x6E 'n'
{ 1040, 9, 10, 11, 1, -9 }, // 0x6F 'o'
{ 1052, 9, 13, 12, 2, -9 }, // 0x70 'p'
{ 1067, 9, 13, 12, 1, -9 }, // 0x71 'q'
{ 1082, 5, 10, 7, 2, -9 }, // 0x72 'r'
{ 1089, 8, 10, 9, 0, -9 }, // 0x73 's'
{ 1099, 7, 12, 7, 0, -11 }, // 0x74 't'
{ 1110, 8, 9, 12, 2, -8 }, // 0x75 'u'
{ 1119, 10, 9, 10, 0, -8 }, // 0x76 'v'
{ 1131, 16, 9, 16, 0, -8 }, // 0x77 'w'
{ 1149, 9, 9, 10, 0, -8 }, // 0x78 'x'
{ 1160, 10, 13, 10, 0, -8 }, // 0x79 'y'
{ 1177, 7, 9, 9, 1, -8 }, // 0x7A 'z'
{ 1185, 5, 16, 6, 1, -12 }, // 0x7B '{'
{ 1195, 1, 16, 5, 2, -12 }, // 0x7C '|'
{ 1197, 5, 16, 6, 0, -12 }, // 0x7D '}'
{ 1207, 8, 3, 10, 1, -7 } }; // 0x7E '~'
const GFXfont Montserrat_Regular9pt7b PROGMEM = {
(uint8_t *)Montserrat_Regular9pt7bBitmaps,
(GFXglyph *)Montserrat_Regular9pt7bGlyphs,
0x20, 0x7E, 21 };
// Approx. 1882 bytes
#endif // MONTSERRAT9PT7B_H
@@ -0,0 +1,310 @@
#ifndef MONTSERRATBOLD12PT7B_H
#define MONTSERRATBOLD12PT7B_H
const uint8_t Montserrat_Bold12pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xF7, 0x39, 0xCE, 0x73, 0x9C, 0x00, 0x3B, 0xFF, 0x70,
0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0xE7, 0x07, 0x1C, 0x03, 0x8E, 0x01,
0xC7, 0x00, 0xE3, 0x87, 0xFF, 0xFB, 0xFF, 0xFD, 0xFF, 0xFE, 0x1C, 0x30,
0x0E, 0x38, 0x07, 0x1C, 0x03, 0x8E, 0x1F, 0xFF, 0xEF, 0xFF, 0xF0, 0x61,
0xC0, 0x70, 0xC0, 0x38, 0x60, 0x1C, 0x70, 0x00, 0x03, 0x00, 0x0C, 0x00,
0x30, 0x07, 0xF8, 0x3F, 0xF9, 0xFF, 0xCF, 0xB3, 0x3C, 0xC0, 0xF3, 0x03,
0xEC, 0x07, 0xF8, 0x0F, 0xFC, 0x1F, 0xF8, 0x0F, 0xE0, 0x37, 0xC0, 0xCF,
0xE3, 0x7B, 0xFF, 0xEF, 0xFF, 0x0F, 0xF8, 0x03, 0x00, 0x0C, 0x00, 0x30,
0x00, 0x3C, 0x03, 0x0F, 0xC0, 0xE3, 0x9C, 0x38, 0x63, 0x86, 0x0C, 0x31,
0xC1, 0x8E, 0x70, 0x31, 0xCC, 0x07, 0xF3, 0x80, 0x7C, 0xE7, 0x80, 0x39,
0xF8, 0x07, 0x73, 0x81, 0xCE, 0x30, 0x71, 0x86, 0x0E, 0x38, 0xC3, 0x87,
0x38, 0xE0, 0x7F, 0x1C, 0x07, 0xC0, 0x0F, 0xC0, 0x1F, 0xE0, 0x3F, 0xF0,
0x38, 0x70, 0x38, 0x70, 0x3C, 0xF0, 0x1F, 0xE0, 0x1F, 0xC0, 0x3F, 0x88,
0x7F, 0xCE, 0xF1, 0xEE, 0xF0, 0xFE, 0xF0, 0x7C, 0xF0, 0x7C, 0xFF, 0xFE,
0x7F, 0xFE, 0x1F, 0xC6, 0xFF, 0xFF, 0xF8, 0x1C, 0xF7, 0x9E, 0x73, 0xCF,
0x3C, 0xF3, 0x8E, 0x38, 0xE3, 0x8F, 0x3C, 0xF3, 0xC7, 0x1E, 0x38, 0xF1,
0xC0, 0xF0, 0xF1, 0xE1, 0xE3, 0xC7, 0x87, 0x0F, 0x1E, 0x3C, 0x78, 0xF1,
0xE3, 0xC7, 0x8F, 0x1C, 0x78, 0xF1, 0xC7, 0x8F, 0x3C, 0x00, 0x0C, 0x03,
0x06, 0xDF, 0xFF, 0x3F, 0x0F, 0xEF, 0xFD, 0xB2, 0x0C, 0x03, 0x00, 0x07,
0x00, 0x70, 0x07, 0x00, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x70, 0x07,
0x00, 0x70, 0x07, 0x00, 0xFF, 0xFF, 0x76, 0xEE, 0xFF, 0xFF, 0xF8, 0xFF,
0xFF, 0x00, 0xE0, 0x1C, 0x07, 0x80, 0xE0, 0x3C, 0x07, 0x00, 0xE0, 0x3C,
0x07, 0x00, 0xE0, 0x3C, 0x07, 0x00, 0xE0, 0x3C, 0x07, 0x00, 0xE0, 0x3C,
0x07, 0x00, 0xE0, 0x3C, 0x07, 0x00, 0xE0, 0x00, 0x0F, 0xC0, 0x7F, 0xC3,
0xFF, 0x9F, 0x3E, 0x78, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F,
0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0x78, 0x3D, 0xF1, 0xE3, 0xFF, 0x8F, 0xFC,
0x0F, 0xC0, 0xFF, 0xFF, 0xF8, 0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1C, 0x38,
0x70, 0xE1, 0xC3, 0x87, 0x0E, 0x1F, 0xC3, 0xFF, 0x3F, 0xFC, 0xF1, 0xF2,
0x07, 0x80, 0x3C, 0x01, 0xE0, 0x1E, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F,
0x01, 0xF0, 0x1F, 0x01, 0xFF, 0xEF, 0xFF, 0x7F, 0xF8, 0x7F, 0xFB, 0xFF,
0xDF, 0xFE, 0x01, 0xE0, 0x1E, 0x01, 0xE0, 0x1E, 0x00, 0xF8, 0x07, 0xF0,
0x3F, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0xB0, 0x7F, 0xFF, 0xFF, 0xFE, 0x3F,
0xC0, 0x01, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF8, 0x01, 0xE0,
0x07, 0x80, 0x1E, 0x3C, 0x7C, 0x78, 0xF0, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xE0, 0x0F, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x3F, 0xF8, 0xFF,
0xE3, 0xFF, 0x8F, 0x00, 0x3C, 0x00, 0xE0, 0x03, 0x80, 0x0F, 0xF8, 0x3F,
0xF9, 0xFF, 0xE0, 0x07, 0x80, 0x0F, 0x00, 0x3D, 0xC1, 0xE7, 0xFF, 0xBF,
0xFC, 0x3F, 0xE0, 0x07, 0xF0, 0x7F, 0xE3, 0xFF, 0x1F, 0x04, 0x78, 0x03,
0xC0, 0x0F, 0x10, 0x3F, 0xFC, 0xFF, 0xFB, 0xFB, 0xEF, 0x83, 0xFC, 0x0F,
0xF0, 0x3D, 0xE1, 0xF7, 0xFF, 0x8F, 0xFC, 0x0F, 0xE0, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xC0, 0xFE, 0x0F, 0x70, 0x78, 0x07, 0x80, 0x3C, 0x03, 0xE0,
0x1E, 0x01, 0xF0, 0x0F, 0x00, 0x78, 0x07, 0x80, 0x3C, 0x03, 0xE0, 0x1E,
0x00, 0x0F, 0xC0, 0xFF, 0xC7, 0xFF, 0x9E, 0x1E, 0xF0, 0x7B, 0xC1, 0xE7,
0x87, 0x8F, 0xFC, 0x3F, 0xF1, 0xFF, 0xEF, 0x07, 0xFC, 0x0F, 0xF0, 0x3F,
0xC1, 0xFF, 0xFF, 0x9F, 0xFC, 0x1F, 0xE0, 0x0F, 0xC0, 0xFF, 0xC7, 0xFF,
0x9E, 0x1E, 0x70, 0x3F, 0xC0, 0xF7, 0x83, 0xDF, 0x1F, 0x7F, 0xFC, 0xFF,
0xF0, 0xF3, 0xC0, 0x0F, 0x00, 0x7C, 0x83, 0xE3, 0xFF, 0x1F, 0xF8, 0x3F,
0xC0, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0x00, 0x00,
0x0F, 0xFF, 0xF7, 0x6E, 0xE0, 0x00, 0x30, 0x1F, 0x07, 0xF3, 0xFC, 0xFE,
0x0F, 0x00, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0x00, 0x70, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xE0, 0x0F, 0x80, 0xFF, 0x01, 0xFE, 0x07, 0xF0, 0x0F, 0x03, 0xF1,
0xFE, 0xFF, 0x0F, 0xC0, 0xE0, 0x00, 0x00, 0x1F, 0xC3, 0xFF, 0xBF, 0xFC,
0xE1, 0xF2, 0x07, 0x80, 0x3C, 0x03, 0xC0, 0x3E, 0x03, 0xE0, 0x1E, 0x01,
0xE0, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x00,
0xFE, 0x00, 0x0F, 0xFF, 0x80, 0x3E, 0x0F, 0x80, 0xF0, 0x03, 0x83, 0x80,
0x03, 0x8E, 0x1F, 0x7B, 0x9C, 0x7F, 0xF3, 0x71, 0xFF, 0xE6, 0xE7, 0x87,
0xCF, 0xCF, 0x07, 0x9F, 0x9C, 0x0F, 0x3F, 0x38, 0x1E, 0x7E, 0x78, 0x3C,
0xFC, 0xF0, 0xF9, 0xB8, 0xFF, 0xFF, 0x38, 0xFE, 0xFC, 0x70, 0xF8, 0xF0,
0x70, 0x00, 0x00, 0x78, 0x00, 0x00, 0x7E, 0x3C, 0x00, 0x7F, 0xF8, 0x00,
0x1F, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x3E, 0x00, 0x0F, 0xC0, 0x01, 0xFC,
0x00, 0x7F, 0x80, 0x0F, 0x70, 0x03, 0xCF, 0x00, 0x78, 0xE0, 0x0E, 0x1E,
0x03, 0xC3, 0xC0, 0x7F, 0xFC, 0x1F, 0xFF, 0x83, 0xFF, 0xF8, 0xF0, 0x0F,
0x1E, 0x00, 0xF7, 0x80, 0x1E, 0xF0, 0x03, 0xC0, 0xFF, 0xE1, 0xFF, 0xF3,
0xFF, 0xF7, 0x81, 0xEF, 0x01, 0xFE, 0x03, 0xBC, 0x0F, 0x7F, 0xFC, 0xFF,
0xF9, 0xFF, 0xFB, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFF, 0xFF,
0xFF, 0xFE, 0xFF, 0xF0, 0x03, 0xF8, 0x0F, 0xFC, 0x3F, 0xFF, 0x3F, 0x1E,
0x7C, 0x04, 0xF8, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0xF8, 0x00, 0x78, 0x04, 0x7E, 0x1E, 0x3F, 0xFF, 0x1F, 0xFE,
0x07, 0xF8, 0xFF, 0xC0, 0x7F, 0xFC, 0x3F, 0xFF, 0x1E, 0x1F, 0xCF, 0x01,
0xF7, 0x80, 0x7B, 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC,
0x01, 0xFE, 0x01, 0xEF, 0x01, 0xF7, 0x83, 0xF3, 0xFF, 0xF9, 0xFF, 0xF0,
0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x0F, 0x00, 0x78,
0x03, 0xC0, 0x1F, 0xFE, 0xFF, 0xF7, 0xFF, 0xBC, 0x01, 0xE0, 0x0F, 0x00,
0x78, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xFF, 0xF7, 0xFF, 0xBF,
0xFD, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x00, 0x03,
0xF8, 0x0F, 0xFE, 0x3F, 0xFF, 0x3F, 0x1E, 0x7C, 0x04, 0xF8, 0x00, 0xF0,
0x00, 0xF0, 0x00, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF8, 0x0F, 0x78,
0x0F, 0x7E, 0x0F, 0x3F, 0xFF, 0x1F, 0xFE, 0x07, 0xF8, 0xF0, 0x0F, 0xE0,
0x1F, 0xC0, 0x3F, 0x80, 0x7F, 0x00, 0xFE, 0x01, 0xFC, 0x03, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x3F, 0x80, 0x7F, 0x00, 0xFE, 0x01, 0xFC,
0x03, 0xF8, 0x07, 0xF0, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0x7F, 0xEF, 0xFD, 0xFF, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78,
0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0xC3, 0xFF, 0xF7, 0xFE,
0x3F, 0x80, 0xF0, 0x1E, 0xF0, 0x3C, 0xF0, 0x78, 0xF0, 0xF8, 0xF1, 0xF0,
0xF3, 0xE0, 0xF7, 0xC0, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0,
0xF9, 0xF0, 0xF0, 0xF0, 0xF0, 0x78, 0xF0, 0x7C, 0xF0, 0x3E, 0xF0, 0x1F,
0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00,
0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0xE0, 0x01, 0xFE, 0x00, 0x3F, 0xE0, 0x0F, 0xFC, 0x01, 0xFF,
0xC0, 0x7F, 0xF8, 0x0F, 0xFF, 0x83, 0xFF, 0xF8, 0xFF, 0xFF, 0x1D, 0xFE,
0xF7, 0xBF, 0xCE, 0xE7, 0xF9, 0xFC, 0xFF, 0x1F, 0x1F, 0xE1, 0xC3, 0xFC,
0x38, 0x7F, 0x80, 0x0F, 0xF0, 0x01, 0xE0, 0xE0, 0x0F, 0xE0, 0x1F, 0xE0,
0x3F, 0xE0, 0x7F, 0xE0, 0xFF, 0xE1, 0xFF, 0xC3, 0xFF, 0xC7, 0xF7, 0xCF,
0xE7, 0xDF, 0xC7, 0xFF, 0x87, 0xFF, 0x0F, 0xFE, 0x0F, 0xFC, 0x0F, 0xF8,
0x0F, 0xF0, 0x0E, 0x03, 0xF8, 0x03, 0xFF, 0x83, 0xFF, 0xF0, 0xFC, 0x7E,
0x7C, 0x07, 0xBE, 0x01, 0xFF, 0x00, 0x3F, 0xC0, 0x0F, 0xF0, 0x03, 0xFC,
0x00, 0xFF, 0x00, 0x3F, 0xE0, 0x0F, 0x78, 0x07, 0x9F, 0x87, 0xE3, 0xFF,
0xF0, 0x7F, 0xF8, 0x07, 0xF8, 0x00, 0xFF, 0xC1, 0xFF, 0xE3, 0xFF, 0xE7,
0x87, 0xEF, 0x03, 0xDE, 0x03, 0xFC, 0x07, 0xF8, 0x1E, 0xF0, 0x3D, 0xFF,
0xFB, 0xFF, 0xE7, 0xFF, 0x0F, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00,
0xF0, 0x00, 0x03, 0xF8, 0x01, 0xFF, 0xC0, 0xFF, 0xFC, 0x1F, 0x8F, 0xC7,
0xC0, 0x79, 0xF0, 0x0F, 0xBC, 0x00, 0xF7, 0x80, 0x1E, 0xF0, 0x03, 0xDE,
0x00, 0x7B, 0xC0, 0x0F, 0x7C, 0x01, 0xE7, 0x80, 0x78, 0xFC, 0x3F, 0x0F,
0xFF, 0xC0, 0xFF, 0xF0, 0x07, 0xF8, 0x00, 0x1F, 0x18, 0x01, 0xFF, 0x80,
0x1F, 0xE0, 0x00, 0xF8, 0xFF, 0x81, 0xFF, 0xE3, 0xFF, 0xE7, 0x87, 0xEF,
0x03, 0xDE, 0x03, 0xFC, 0x07, 0xF8, 0x1E, 0xF0, 0x3D, 0xFF, 0xFB, 0xFF,
0xE7, 0xFF, 0x0F, 0x0F, 0x1E, 0x1E, 0x3C, 0x1E, 0x78, 0x1E, 0xF0, 0x3E,
0x1F, 0xE0, 0xFF, 0xE7, 0xFF, 0x3E, 0x0C, 0xF0, 0x03, 0xC0, 0x0F, 0x80,
0x1F, 0xE0, 0x3F, 0xF0, 0x7F, 0xE0, 0x1F, 0x80, 0x1F, 0x00, 0x3F, 0x81,
0xEF, 0xFF, 0xBF, 0xFC, 0x3F, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8,
0x3C, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x0F,
0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0,
0x07, 0x80, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE,
0x03, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80,
0xFF, 0x01, 0xEF, 0x0F, 0x9F, 0xFF, 0x1F, 0xFC, 0x0F, 0xE0, 0xF0, 0x03,
0xFE, 0x00, 0xF7, 0x80, 0x79, 0xE0, 0x1E, 0x3C, 0x0F, 0x0F, 0x03, 0xC3,
0xE0, 0xE0, 0x78, 0x78, 0x1F, 0x1E, 0x03, 0xCF, 0x00, 0xF3, 0xC0, 0x1F,
0xE0, 0x07, 0xF8, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x01, 0xE0,
0x00, 0xF0, 0x1E, 0x01, 0xFC, 0x07, 0x80, 0xFF, 0x01, 0xF0, 0x3D, 0xE0,
0xFC, 0x0E, 0x78, 0x3F, 0x07, 0x9E, 0x0F, 0xE1, 0xE3, 0xC7, 0xF8, 0x70,
0xF1, 0xCE, 0x3C, 0x3C, 0x73, 0xCF, 0x07, 0xBC, 0xF3, 0x81, 0xEE, 0x1D,
0xE0, 0x7F, 0x87, 0xF8, 0x0F, 0xE1, 0xFC, 0x03, 0xF0, 0x3F, 0x00, 0xFC,
0x0F, 0xC0, 0x1F, 0x03, 0xE0, 0x07, 0x80, 0x78, 0x00, 0x78, 0x0F, 0x3E,
0x07, 0x8F, 0x07, 0x83, 0xC7, 0x81, 0xF7, 0xC0, 0x7F, 0xC0, 0x1F, 0xC0,
0x07, 0xC0, 0x03, 0xE0, 0x03, 0xF8, 0x01, 0xFC, 0x01, 0xEF, 0x01, 0xF7,
0xC0, 0xF1, 0xF0, 0xF0, 0x78, 0xF8, 0x1E, 0xF8, 0x0F, 0x80, 0xF0, 0x07,
0x7C, 0x07, 0x9E, 0x07, 0x87, 0x83, 0xC3, 0xC3, 0xC0, 0xF1, 0xC0, 0x7D,
0xE0, 0x1F, 0xE0, 0x07, 0xF0, 0x03, 0xF0, 0x00, 0xF0, 0x00, 0x78, 0x00,
0x3C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x00, 0xFF,
0xFD, 0xFF, 0xFB, 0xFF, 0xF0, 0x03, 0xE0, 0x0F, 0x80, 0x3E, 0x00, 0x78,
0x01, 0xE0, 0x07, 0x80, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x03, 0xC0, 0x0F,
0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0x8F, 0x1E,
0x3C, 0x78, 0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xC7,
0x8F, 0xFF, 0xFF, 0x80, 0xF0, 0x0E, 0x01, 0xC0, 0x3C, 0x03, 0x80, 0x70,
0x0F, 0x00, 0xE0, 0x1C, 0x03, 0xC0, 0x38, 0x07, 0x00, 0xF0, 0x0E, 0x01,
0xC0, 0x3C, 0x03, 0x80, 0x78, 0x07, 0x00, 0xE0, 0x1E, 0x01, 0xC0, 0xFF,
0xFF, 0xF8, 0xF1, 0xE3, 0xC7, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xC7,
0x8F, 0x1E, 0x3C, 0x78, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0x00, 0xF8, 0x1F,
0x81, 0xD8, 0x19, 0xC3, 0x9C, 0x38, 0xE7, 0x0E, 0x70, 0x7E, 0x07, 0xFF,
0xFF, 0xFF, 0x78, 0x78, 0x78, 0x3F, 0x8F, 0xFE, 0x7F, 0xE6, 0x0F, 0x00,
0xF0, 0xFF, 0x7F, 0xFF, 0xFF, 0xF0, 0xFF, 0x0F, 0xFB, 0xF7, 0xFF, 0x3F,
0x70, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x9F, 0x0F,
0xFF, 0x3F, 0xFE, 0xF8, 0xFB, 0xC1, 0xFF, 0x03, 0xF8, 0x0F, 0xF0, 0x3F,
0xC0, 0xFF, 0x87, 0xBF, 0xFE, 0xFF, 0xF3, 0xBF, 0x00, 0x0F, 0xC1, 0xFF,
0x9F, 0xFD, 0xF0, 0xEF, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07,
0xC3, 0x9F, 0xFC, 0x7F, 0xE0, 0xFC, 0x00, 0x00, 0x3C, 0x00, 0xF0, 0x03,
0xC0, 0x0F, 0x00, 0x3C, 0x7E, 0xF3, 0xFF, 0xDF, 0xFF, 0xF8, 0x7F, 0xC0,
0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x87, 0xDF, 0xFF, 0x3F,
0xFC, 0x7E, 0xF0, 0x0F, 0xC1, 0xFF, 0x1F, 0xFD, 0xF0, 0xFF, 0x03, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xC1, 0x1F, 0xFC, 0x7F, 0xE0, 0xFE,
0x00, 0x07, 0xC7, 0xF1, 0xF8, 0xF0, 0x3C, 0x3F, 0xEF, 0xFB, 0xFE, 0x3C,
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x00,
0x1F, 0xBC, 0xFF, 0xF7, 0xFF, 0xFE, 0x1F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03,
0xFC, 0x0F, 0xF8, 0x7D, 0xFF, 0xF7, 0xFF, 0xC7, 0xEF, 0x00, 0x3C, 0x00,
0xF7, 0x07, 0x9F, 0xFE, 0x7F, 0xF0, 0x3E, 0x00, 0xE0, 0x07, 0x00, 0x38,
0x01, 0xC0, 0x0E, 0x00, 0x73, 0xE3, 0xFF, 0xDF, 0xFE, 0xF8, 0xFF, 0x83,
0xFC, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F,
0x03, 0xC0, 0x77, 0xBF, 0xE0, 0x01, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE,
0x73, 0x9C, 0x07, 0x07, 0x83, 0xE1, 0xE0, 0x00, 0x00, 0x3C, 0x1E, 0x0F,
0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1,
0xE1, 0xE7, 0xF3, 0xF0, 0xF0, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00,
0xE0, 0x03, 0x83, 0xEE, 0x1F, 0x38, 0xF8, 0xE7, 0xC3, 0xBE, 0x0F, 0xF0,
0x3F, 0xE0, 0xFF, 0xC3, 0xEF, 0x0F, 0x1E, 0x38, 0x7C, 0xE0, 0xFB, 0x81,
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xE7, 0xC3, 0xE3, 0xFF,
0xBF, 0xCF, 0xFF, 0xFF, 0xBE, 0x3F, 0x1E, 0xF0, 0xF8, 0x7B, 0xC1, 0xE0,
0xFE, 0x07, 0x83, 0xF8, 0x1E, 0x0F, 0xE0, 0x78, 0x3F, 0x81, 0xE0, 0xFE,
0x07, 0x83, 0xF8, 0x1E, 0x0F, 0xE0, 0x78, 0x3C, 0xE7, 0xC7, 0xFF, 0xBF,
0xFD, 0xF1, 0xFF, 0x07, 0xF8, 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x03,
0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0x80, 0x0F, 0xC0, 0xFF, 0xC7, 0xFF, 0xBE,
0x1E, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xE1, 0xE7,
0xFF, 0x8F, 0xFC, 0x0F, 0xC0, 0xE7, 0xC3, 0xFF, 0xCF, 0xFF, 0xBE, 0x3E,
0xF0, 0x7F, 0xC0, 0xFE, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xE1, 0xEF, 0xFF,
0xBF, 0xFC, 0xE7, 0xC3, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80,
0x00, 0x1F, 0xBC, 0xFF, 0xF7, 0xFF, 0xFE, 0x1F, 0xF0, 0x3F, 0xC0, 0xFF,
0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xE1, 0xF7, 0xFF, 0xCF, 0xFF, 0x1F, 0xBC,
0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0xE7, 0xEF, 0xFF,
0xFC, 0xF0, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x1F, 0xE3,
0xFF, 0x7F, 0xE7, 0x82, 0x78, 0x07, 0xF8, 0x3F, 0xE1, 0xFF, 0x00, 0xF0,
0x07, 0x7F, 0xF7, 0xFE, 0x3F, 0xC0, 0x3C, 0x0F, 0x03, 0xC3, 0xFE, 0xFF,
0xBF, 0xE3, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0xE1,
0xFC, 0x3F, 0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F,
0x81, 0xFC, 0x0F, 0xF0, 0x7F, 0x87, 0xFF, 0xFE, 0xFF, 0xF3, 0xF7, 0x80,
0xF0, 0x1D, 0xE0, 0x79, 0xE0, 0xF3, 0xC3, 0xC3, 0x87, 0x87, 0x8E, 0x0F,
0x3C, 0x0F, 0x70, 0x1F, 0xE0, 0x1F, 0xC0, 0x3F, 0x00, 0x3E, 0x00, 0x78,
0x00, 0xF0, 0x38, 0x1D, 0xC1, 0xE0, 0x77, 0x07, 0xC3, 0xDE, 0x1F, 0x0E,
0x38, 0xFC, 0x38, 0xE3, 0xF9, 0xE3, 0xDE, 0xE7, 0x07, 0x73, 0xFC, 0x1D,
0xC7, 0xE0, 0x7F, 0x1F, 0x80, 0xF8, 0x7E, 0x03, 0xE0, 0xF0, 0x0F, 0x03,
0xC0, 0x78, 0x3D, 0xE1, 0xE3, 0xCF, 0x07, 0xF8, 0x0F, 0xE0, 0x3F, 0x00,
0x78, 0x03, 0xF0, 0x0F, 0xE0, 0x7F, 0xC3, 0xCF, 0x1E, 0x1E, 0xF8, 0x3C,
0xF0, 0x1D, 0xE0, 0x79, 0xE0, 0xF3, 0xC1, 0xC3, 0xC7, 0x87, 0x8E, 0x07,
0x3C, 0x0F, 0x70, 0x1F, 0xE0, 0x1F, 0xC0, 0x3F, 0x00, 0x3E, 0x00, 0x78,
0x00, 0xF0, 0x13, 0xC0, 0x7F, 0x80, 0xFE, 0x00, 0xF0, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
0xFF, 0xFF, 0xFF, 0xFE, 0x07, 0x1F, 0x3F, 0x3E, 0x3C, 0x3C, 0x3C, 0x3C,
0x3C, 0x3C, 0xF8, 0xF0, 0xFC, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3E,
0x3F, 0x1F, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8,
0xF0, 0xF8, 0xFC, 0x3C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x1F, 0x0F,
0x1F, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0x3C, 0x7C, 0xFC, 0xF8, 0xE0, 0x38,
0x37, 0xE3, 0x7F, 0xFE, 0x7E, 0xE1, 0xC0 };
const GFXglyph Montserrat_Bold12pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 7, 0, 0 }, // 0x20 ' '
{ 1, 5, 17, 7, 1, -16 }, // 0x21 '!'
{ 12, 8, 7, 10, 1, -16 }, // 0x22 '"'
{ 19, 17, 17, 17, 0, -16 }, // 0x23 '#'
{ 56, 14, 23, 15, 1, -19 }, // 0x24 '$'
{ 97, 19, 17, 21, 1, -16 }, // 0x25 '%'
{ 138, 16, 17, 17, 1, -16 }, // 0x26 '&'
{ 172, 3, 7, 6, 1, -16 }, // 0x27 '''
{ 175, 6, 23, 9, 2, -17 }, // 0x28 '('
{ 193, 7, 23, 9, 0, -17 }, // 0x29 ')'
{ 214, 10, 10, 10, 0, -17 }, // 0x2A '*'
{ 227, 12, 11, 14, 1, -13 }, // 0x2B '+'
{ 244, 4, 8, 6, 1, -3 }, // 0x2C ','
{ 248, 7, 3, 9, 1, -7 }, // 0x2D '-'
{ 251, 4, 4, 6, 1, -3 }, // 0x2E '.'
{ 253, 11, 22, 9, -1, -19 }, // 0x2F '/'
{ 284, 14, 17, 16, 1, -16 }, // 0x30 '0'
{ 314, 7, 17, 9, 0, -16 }, // 0x31 '1'
{ 329, 13, 17, 14, 0, -16 }, // 0x32 '2'
{ 357, 13, 17, 14, 0, -16 }, // 0x33 '3'
{ 385, 15, 17, 17, 1, -16 }, // 0x34 '4'
{ 417, 14, 17, 14, 0, -16 }, // 0x35 '5'
{ 447, 14, 17, 15, 1, -16 }, // 0x36 '6'
{ 477, 13, 17, 15, 1, -16 }, // 0x37 '7'
{ 505, 14, 17, 16, 1, -16 }, // 0x38 '8'
{ 535, 14, 17, 15, 0, -16 }, // 0x39 '9'
{ 565, 4, 13, 6, 1, -12 }, // 0x3A ':'
{ 572, 4, 17, 6, 1, -12 }, // 0x3B ';'
{ 581, 12, 12, 14, 1, -13 }, // 0x3C '<'
{ 599, 12, 9, 14, 1, -12 }, // 0x3D '='
{ 613, 12, 12, 14, 1, -13 }, // 0x3E '>'
{ 631, 13, 17, 14, 0, -16 }, // 0x3F '?'
{ 659, 23, 22, 25, 1, -16 }, // 0x40 '@'
{ 723, 19, 17, 18, 0, -16 }, // 0x41 'A'
{ 764, 15, 17, 18, 2, -16 }, // 0x42 'B'
{ 796, 16, 17, 17, 1, -16 }, // 0x43 'C'
{ 830, 17, 17, 20, 2, -16 }, // 0x44 'D'
{ 867, 13, 17, 16, 2, -16 }, // 0x45 'E'
{ 895, 13, 17, 15, 2, -16 }, // 0x46 'F'
{ 923, 16, 17, 19, 1, -16 }, // 0x47 'G'
{ 957, 15, 17, 19, 2, -16 }, // 0x48 'H'
{ 989, 4, 17, 8, 2, -16 }, // 0x49 'I'
{ 998, 11, 17, 13, 0, -16 }, // 0x4A 'J'
{ 1022, 16, 17, 18, 2, -16 }, // 0x4B 'K'
{ 1056, 12, 17, 15, 2, -16 }, // 0x4C 'L'
{ 1082, 19, 17, 23, 2, -16 }, // 0x4D 'M'
{ 1123, 15, 17, 19, 2, -16 }, // 0x4E 'N'
{ 1155, 18, 17, 20, 1, -16 }, // 0x4F 'O'
{ 1194, 15, 17, 18, 2, -16 }, // 0x50 'P'
{ 1226, 19, 21, 20, 1, -16 }, // 0x51 'Q'
{ 1276, 15, 17, 18, 2, -16 }, // 0x52 'R'
{ 1308, 14, 17, 15, 1, -16 }, // 0x53 'S'
{ 1338, 15, 17, 15, 0, -16 }, // 0x54 'T'
{ 1370, 15, 17, 19, 2, -16 }, // 0x55 'U'
{ 1402, 18, 17, 18, 0, -16 }, // 0x56 'V'
{ 1441, 26, 17, 28, 1, -16 }, // 0x57 'W'
{ 1497, 17, 17, 17, 0, -16 }, // 0x58 'X'
{ 1534, 17, 17, 16, 0, -16 }, // 0x59 'Y'
{ 1571, 15, 17, 16, 1, -16 }, // 0x5A 'Z'
{ 1603, 7, 23, 9, 2, -17 }, // 0x5B '['
{ 1624, 11, 22, 9, -1, -19 }, // 0x5C '\'
{ 1655, 7, 23, 9, 0, -17 }, // 0x5D ']'
{ 1676, 12, 10, 14, 1, -12 }, // 0x5E '^'
{ 1691, 12, 2, 12, 0, 1 }, // 0x5F '_'
{ 1694, 7, 3, 14, 2, -17 }, // 0x60 '`'
{ 1697, 12, 13, 15, 1, -12 }, // 0x61 'a'
{ 1717, 14, 18, 17, 2, -17 }, // 0x62 'b'
{ 1749, 13, 13, 14, 1, -12 }, // 0x63 'c'
{ 1771, 14, 18, 17, 1, -17 }, // 0x64 'd'
{ 1803, 13, 13, 15, 1, -12 }, // 0x65 'e'
{ 1825, 10, 18, 9, 0, -17 }, // 0x66 'f'
{ 1848, 14, 18, 17, 1, -12 }, // 0x67 'g'
{ 1880, 13, 18, 17, 2, -17 }, // 0x68 'h'
{ 1910, 5, 19, 7, 1, -18 }, // 0x69 'i'
{ 1922, 9, 24, 7, -2, -18 }, // 0x6A 'j'
{ 1949, 14, 18, 16, 2, -17 }, // 0x6B 'k'
{ 1981, 3, 18, 7, 2, -17 }, // 0x6C 'l'
{ 1988, 22, 13, 25, 2, -12 }, // 0x6D 'm'
{ 2024, 13, 13, 17, 2, -12 }, // 0x6E 'n'
{ 2046, 14, 13, 16, 1, -12 }, // 0x6F 'o'
{ 2069, 14, 18, 17, 2, -12 }, // 0x70 'p'
{ 2101, 14, 18, 17, 1, -12 }, // 0x71 'q'
{ 2133, 8, 13, 10, 2, -12 }, // 0x72 'r'
{ 2146, 12, 13, 13, 0, -12 }, // 0x73 's'
{ 2166, 10, 16, 10, 0, -15 }, // 0x74 't'
{ 2186, 13, 13, 16, 2, -12 }, // 0x75 'u'
{ 2208, 15, 13, 14, 0, -12 }, // 0x76 'v'
{ 2233, 22, 13, 22, 0, -12 }, // 0x77 'w'
{ 2269, 14, 13, 14, 0, -12 }, // 0x78 'x'
{ 2292, 15, 18, 14, 0, -12 }, // 0x79 'y'
{ 2326, 11, 13, 13, 1, -12 }, // 0x7A 'z'
{ 2344, 8, 23, 9, 1, -17 }, // 0x7B '{'
{ 2367, 3, 23, 7, 2, -17 }, // 0x7C '|'
{ 2376, 8, 23, 9, 0, -17 }, // 0x7D '}'
{ 2399, 12, 5, 14, 1, -10 } }; // 0x7E '~'
const GFXfont Montserrat_Bold12pt7b PROGMEM = {
(uint8_t *)Montserrat_Bold12pt7bBitmaps,
(GFXglyph *)Montserrat_Bold12pt7bGlyphs,
0x20, 0x7E, 29 };
// Approx. 3079 bytes
#endif // MONTSERRATBOLD12PT7B_H
@@ -0,0 +1,536 @@
#ifndef MONTSERRATBOLD18PT7B_H
#define MONTSERRATBOLD18PT7B_H
const uint8_t Montserrat_Bold18pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0x7D, 0xE7,
0x9E, 0x78, 0x00, 0x1E, 0xFF, 0xFF, 0xFF, 0x78, 0xF1, 0xFE, 0x3F, 0xC7,
0xF8, 0xFF, 0x1F, 0xE3, 0xFC, 0x7F, 0x8F, 0xF1, 0xFE, 0x3C, 0x01, 0xE0,
0xF0, 0x03, 0xC0, 0xF0, 0x03, 0xC1, 0xE0, 0x03, 0xC1, 0xE0, 0x03, 0xC1,
0xE0, 0x03, 0xC1, 0xE0, 0x7F, 0xFF, 0xFE, 0x7F, 0xFF, 0xFE, 0x7F, 0xFF,
0xFE, 0x7F, 0xFF, 0xFE, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x83,
0xC0, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, 0x07, 0x83, 0xC0, 0xFF, 0xFF,
0xFC, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFC, 0x0F, 0x07, 0x80, 0x0F, 0x07,
0x80, 0x0F, 0x07, 0x80, 0x0F, 0x07, 0x80, 0x0F, 0x07, 0x80, 0x0F, 0x07,
0x80, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x07, 0x00, 0x01,
0xFE, 0x00, 0xFF, 0xFC, 0x1F, 0xFF, 0xE3, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7,
0xE7, 0x1C, 0x7C, 0x70, 0x4F, 0xC7, 0x00, 0xFC, 0x70, 0x07, 0xF7, 0x00,
0x7F, 0xF0, 0x03, 0xFF, 0xE0, 0x1F, 0xFF, 0x80, 0xFF, 0xFE, 0x01, 0xFF,
0xE0, 0x07, 0xFF, 0x00, 0x73, 0xF0, 0x07, 0x1F, 0x00, 0x71, 0xF7, 0x07,
0x3F, 0x7E, 0x77, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xE7, 0xFF, 0xF8, 0x0F,
0xFF, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00,
0x0F, 0x00, 0x07, 0x81, 0xFE, 0x00, 0x78, 0x1F, 0xF8, 0x07, 0x80, 0xF3,
0xC0, 0x3C, 0x0F, 0x0F, 0x03, 0xC0, 0x78, 0x78, 0x3C, 0x03, 0x81, 0xC1,
0xE0, 0x1C, 0x0E, 0x1E, 0x00, 0xF0, 0xF1, 0xE0, 0x07, 0x87, 0x9F, 0x00,
0x1E, 0x78, 0xF0, 0x00, 0xFF, 0xCF, 0x00, 0x03, 0xFC, 0xF8, 0xFC, 0x07,
0x87, 0x9F, 0xF0, 0x00, 0x78, 0xFF, 0xC0, 0x07, 0xCF, 0x1E, 0x00, 0x3C,
0x70, 0x78, 0x03, 0xC3, 0x83, 0xC0, 0x3E, 0x1C, 0x1E, 0x01, 0xE0, 0xE0,
0xF0, 0x1E, 0x07, 0x07, 0x81, 0xE0, 0x3C, 0x78, 0x0F, 0x00, 0xFF, 0xC0,
0xF0, 0x07, 0xFC, 0x0F, 0x00, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x03, 0xFF,
0x00, 0x0F, 0xFF, 0x80, 0x0F, 0xFF, 0x80, 0x1F, 0x87, 0xC0, 0x1F, 0x07,
0xC0, 0x1F, 0x07, 0xC0, 0x1F, 0x0F, 0xC0, 0x0F, 0x9F, 0x80, 0x0F, 0xFF,
0x00, 0x07, 0xFE, 0x00, 0x07, 0xFC, 0x00, 0x0F, 0xFC, 0x00, 0x1F, 0xFE,
0x3C, 0x3F, 0x7F, 0x3E, 0x7E, 0x3F, 0xBE, 0x7C, 0x1F, 0xFC, 0xFC, 0x0F,
0xFC, 0xFC, 0x07, 0xF8, 0xFC, 0x03, 0xF8, 0x7E, 0x07, 0xFC, 0x7F, 0xFF,
0xFE, 0x3F, 0xFF, 0xFE, 0x1F, 0xFF, 0x9C, 0x07, 0xFE, 0x0C, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x0F, 0x8F, 0x8F, 0xC7, 0xC3, 0xE3, 0xF1, 0xF0, 0xF8,
0xFC, 0x7E, 0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x3E,
0x1F, 0x0F, 0x87, 0xC3, 0xE1, 0xF8, 0xFC, 0x3E, 0x1F, 0x0F, 0xC3, 0xE1,
0xF8, 0x7C, 0x3E, 0x0F, 0x80, 0x7C, 0x1F, 0x03, 0xE0, 0xFC, 0x3F, 0x07,
0xC1, 0xF8, 0x7E, 0x0F, 0x83, 0xE0, 0xFC, 0x3F, 0x0F, 0xC1, 0xF0, 0x7C,
0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x3F, 0x0F, 0xC3, 0xF0, 0xF8, 0x3E, 0x0F,
0x87, 0xE1, 0xF8, 0x7C, 0x3F, 0x0F, 0x83, 0xE1, 0xF0, 0xFC, 0x00, 0x03,
0x80, 0x07, 0x00, 0x8E, 0x23, 0xDC, 0xE7, 0xFF, 0xE7, 0xFF, 0x87, 0xFC,
0x0F, 0xF8, 0x7F, 0xFC, 0xFF, 0xF9, 0xCE, 0x71, 0x1C, 0x40, 0x38, 0x00,
0x70, 0x00, 0x03, 0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E,
0x00, 0x1F, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0,
0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0,
0x10, 0xFB, 0xFF, 0xFF, 0xEF, 0xDF, 0x1E, 0x3C, 0xF1, 0xE3, 0x80, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x10, 0xFB, 0xFF, 0xFF, 0xEF, 0xDF, 0x00, 0x00,
0x1F, 0x00, 0x1F, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x7C, 0x00,
0x7C, 0x00, 0x78, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF0, 0x01, 0xF0, 0x01,
0xF0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x07, 0xC0, 0x07, 0xC0, 0x07,
0xC0, 0x0F, 0x80, 0x0F, 0x80, 0x0F, 0x80, 0x1F, 0x00, 0x1F, 0x00, 0x1F,
0x00, 0x3E, 0x00, 0x3E, 0x00, 0x3C, 0x00, 0x7C, 0x00, 0x7C, 0x00, 0x78,
0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0xFC, 0x00, 0x1F, 0xF8, 0x03, 0xFF,
0xE0, 0x3F, 0xFF, 0x81, 0xFF, 0xFE, 0x1F, 0xC3, 0xF9, 0xFC, 0x0F, 0xCF,
0xC0, 0x3F, 0x7E, 0x01, 0xFB, 0xE0, 0x0F, 0xFF, 0x00, 0x3F, 0xF8, 0x01,
0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0x7F, 0xF0, 0x03, 0xEF, 0x80, 0x3F, 0x7C,
0x01, 0xFB, 0xF0, 0x0F, 0xDF, 0x80, 0xFC, 0x7E, 0x07, 0xE3, 0xFC, 0xFF,
0x0F, 0xFF, 0xF0, 0x3F, 0xFF, 0x00, 0xFF, 0xF0, 0x03, 0xFE, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0,
0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC,
0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0x03, 0xF8,
0x00, 0xFF, 0xF0, 0x3F, 0xFF, 0x87, 0xFF, 0xFC, 0xFF, 0xFF, 0xC7, 0xC0,
0xFE, 0x18, 0x07, 0xE0, 0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00, 0x7E, 0x00,
0x0F, 0xC0, 0x00, 0xFC, 0x00, 0x3F, 0x80, 0x07, 0xF0, 0x00, 0xFE, 0x00,
0x1F, 0xC0, 0x03, 0xF8, 0x00, 0x7F, 0x00, 0x0F, 0xE0, 0x01, 0xFC, 0x00,
0x3F, 0xFF, 0xF7, 0xFF, 0xFF, 0x7F, 0xFF, 0xF7, 0xFF, 0xFF, 0x7F, 0xFF,
0xF0, 0x7F, 0xFF, 0xCF, 0xFF, 0xF9, 0xFF, 0xFF, 0x3F, 0xFF, 0xE7, 0xFF,
0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x1F,
0x80, 0x07, 0xE0, 0x00, 0xFF, 0x80, 0x1F, 0xF8, 0x03, 0xFF, 0x80, 0x7F,
0xF8, 0x00, 0x3F, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x98, 0x03,
0xF7, 0xE1, 0xFE, 0xFF, 0xFF, 0xBF, 0xFF, 0xF3, 0xFF, 0xF8, 0x1F, 0xFE,
0x00, 0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0,
0x00, 0x07, 0xE0, 0x00, 0x1F, 0x80, 0x00, 0x7E, 0x00, 0x01, 0xFC, 0x00,
0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x00, 0x00, 0xFE, 0x3F, 0x01,
0xF8, 0x7E, 0x07, 0xE0, 0xFC, 0x1F, 0x81, 0xF8, 0x7F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00,
0x7E, 0x00, 0x00, 0xFC, 0x00, 0x01, 0xF8, 0x00, 0x03, 0xF0, 0x00, 0x07,
0xE0, 0x1F, 0xFF, 0xC1, 0xFF, 0xFC, 0x1F, 0xFF, 0xC1, 0xFF, 0xFC, 0x1F,
0xFF, 0xC1, 0xF0, 0x00, 0x1F, 0x00, 0x01, 0xF0, 0x00, 0x1F, 0x00, 0x01,
0xF0, 0x00, 0x1F, 0xFE, 0x03, 0xFF, 0xF8, 0x3F, 0xFF, 0xC3, 0xFF, 0xFE,
0x00, 0x3F, 0xE0, 0x00, 0x7F, 0x00, 0x03, 0xF0, 0x00, 0x3F, 0x00, 0x03,
0xF3, 0x00, 0x7F, 0x3F, 0x1F, 0xE7, 0xFF, 0xFE, 0xFF, 0xFF, 0xC7, 0xFF,
0xF8, 0x0F, 0xFE, 0x00, 0x00, 0x7F, 0x80, 0x0F, 0xFF, 0x01, 0xFF, 0xF8,
0x1F, 0xFF, 0xC1, 0xFF, 0xFC, 0x1F, 0xE0, 0x20, 0xFC, 0x00, 0x0F, 0xC0,
0x00, 0x7E, 0x00, 0x03, 0xE0, 0x00, 0x1F, 0x3F, 0xC1, 0xFF, 0xFF, 0x8F,
0xFF, 0xFE, 0x7F, 0xFF, 0xFB, 0xFC, 0x1F, 0xDF, 0xC0, 0x7E, 0x7E, 0x01,
0xFB, 0xF0, 0x0F, 0xDF, 0x80, 0x7E, 0xFC, 0x03, 0xE3, 0xF0, 0x3F, 0x0F,
0xFF, 0xF0, 0x7F, 0xFF, 0x80, 0xFF, 0xF8, 0x03, 0xFF, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0x80,
0x7E, 0xF8, 0x0F, 0xEF, 0x80, 0xFC, 0xF8, 0x0F, 0xC0, 0x01, 0xF8, 0x00,
0x1F, 0x80, 0x03, 0xF0, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0x7E, 0x00,
0x0F, 0xE0, 0x00, 0xFC, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x1F, 0x80,
0x03, 0xF0, 0x00, 0x3F, 0x00, 0x07, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xE0,
0x00, 0x01, 0xFC, 0x00, 0x7F, 0xFC, 0x07, 0xFF, 0xF0, 0x7F, 0xFF, 0xC3,
0xF8, 0xFE, 0x3F, 0x01, 0xF9, 0xF8, 0x0F, 0xCF, 0xC0, 0x7E, 0x7E, 0x03,
0xF1, 0xF8, 0x3F, 0x8F, 0xFF, 0xF8, 0x3F, 0xFF, 0x81, 0xFF, 0xFC, 0x1F,
0xFF, 0xF1, 0xFE, 0x1F, 0xCF, 0xC0, 0x7E, 0xFC, 0x01, 0xFF, 0xE0, 0x0F,
0xFF, 0x00, 0x7F, 0xF8, 0x03, 0xF7, 0xE0, 0x3F, 0x3F, 0xFF, 0xF8, 0xFF,
0xFF, 0x83, 0xFF, 0xF8, 0x07, 0xFF, 0x00, 0x03, 0xF0, 0x01, 0xFF, 0xE0,
0x3F, 0xFF, 0x07, 0xFF, 0xF8, 0x7F, 0x3F, 0xCF, 0xC0, 0x7E, 0xFC, 0x07,
0xEF, 0x80, 0x3E, 0xF8, 0x03, 0xFF, 0xC0, 0x7F, 0xFC, 0x07, 0xFF, 0xFB,
0xFF, 0x7F, 0xFF, 0xF3, 0xFF, 0xFF, 0x1F, 0xFB, 0xF0, 0x7E, 0x3F, 0x00,
0x03, 0xE0, 0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x38, 0x7F, 0xC3,
0xFF, 0xF8, 0x7F, 0xFF, 0x07, 0xFF, 0xE0, 0x3F, 0xF8, 0x00, 0x10, 0xFB,
0xFF, 0xFF, 0xEF, 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1F, 0x7F,
0xFF, 0xFD, 0xFB, 0xE0, 0x10, 0xFB, 0xFF, 0xFF, 0xEF, 0xDF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x02, 0x1F, 0x7F, 0xFF, 0xFD, 0xFB, 0xE3, 0xC7, 0x9E,
0x3C, 0x70, 0x00, 0x00, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x1F, 0xF0, 0x7F,
0xF8, 0xFF, 0xE3, 0xFF, 0x81, 0xFF, 0x00, 0xFC, 0x00, 0x7F, 0x00, 0x3F,
0xF0, 0x0F, 0xFF, 0x00, 0xFF, 0xF0, 0x0F, 0xFC, 0x01, 0xFE, 0x00, 0x1F,
0x00, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x80, 0x00, 0x78, 0x00, 0x3F,
0x00, 0x1F, 0xF0, 0x0F, 0xFF, 0x00, 0xFF, 0xE0, 0x0F, 0xFE, 0x01, 0xFF,
0x00, 0x1F, 0x80, 0x1F, 0xC0, 0x7F, 0xE1, 0xFF, 0xE7, 0xFF, 0x87, 0xFE,
0x03, 0xFC, 0x01, 0xF0, 0x00, 0xC0, 0x00, 0x00, 0x03, 0xF8, 0x01, 0xFF,
0xE0, 0xFF, 0xFE, 0x3F, 0xFF, 0xEF, 0xFF, 0xFC, 0xF8, 0x1F, 0xC6, 0x01,
0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x1F,
0xC0, 0x07, 0xF0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xC0, 0x00, 0xF8,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1F, 0x80, 0x03, 0xF8,
0x00, 0x7F, 0x00, 0x0F, 0xC0, 0x00, 0xF8, 0x00, 0x00, 0x07, 0xF8, 0x00,
0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFE, 0x00, 0x0F, 0xFE, 0xFF,
0xC0, 0x07, 0xF0, 0x01, 0xF8, 0x03, 0xF0, 0x00, 0x1F, 0x01, 0xF0, 0x00,
0x03, 0xE0, 0x78, 0x00, 0x00, 0x7C, 0x3E, 0x0F, 0xF7, 0xCF, 0x0F, 0x07,
0xFF, 0xF1, 0xE7, 0x83, 0xFF, 0xFC, 0x79, 0xE1, 0xFF, 0xFF, 0x0E, 0x78,
0x7C, 0x0F, 0xC3, 0xDE, 0x3E, 0x01, 0xF0, 0xFF, 0x0F, 0x80, 0x7C, 0x3F,
0xC3, 0xE0, 0x1F, 0x0F, 0xF0, 0xF8, 0x07, 0xC3, 0xFC, 0x3E, 0x01, 0xF0,
0xFF, 0x0F, 0x80, 0x7C, 0x3D, 0xE3, 0xF0, 0x3F, 0x0E, 0x78, 0x7E, 0x1F,
0xC7, 0x9E, 0x1F, 0xFF, 0xFF, 0xE3, 0xC3, 0xFF, 0xFF, 0xF0, 0xF0, 0x7F,
0xE7, 0xF8, 0x1E, 0x0F, 0xE0, 0xFC, 0x07, 0xC0, 0x00, 0x00, 0x00, 0xF8,
0x00, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x00, 0x03, 0xFC, 0x0F, 0x00, 0x00,
0x7F, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00,
0x00, 0x1F, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x3F,
0xE0, 0x00, 0x07, 0xFC, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x3E, 0xF8, 0x00,
0x0F, 0xDF, 0x00, 0x01, 0xF3, 0xF0, 0x00, 0x3E, 0x3E, 0x00, 0x0F, 0xC7,
0xE0, 0x01, 0xF0, 0x7C, 0x00, 0x7E, 0x0F, 0xC0, 0x0F, 0x81, 0xF8, 0x03,
0xF0, 0x1F, 0x00, 0x7F, 0xFF, 0xF0, 0x1F, 0xFF, 0xFE, 0x03, 0xFF, 0xFF,
0xE0, 0x7F, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0xC3, 0xE0, 0x01, 0xF8, 0xFC,
0x00, 0x1F, 0x9F, 0x80, 0x03, 0xF7, 0xE0, 0x00, 0x3E, 0xFC, 0x00, 0x07,
0xE0, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0x0F, 0xFF, 0xFE, 0x3F, 0xFF, 0xFC,
0xFF, 0xFF, 0xFB, 0xF0, 0x0F, 0xEF, 0xC0, 0x1F, 0xBF, 0x00, 0x7E, 0xFC,
0x01, 0xFB, 0xF0, 0x07, 0xEF, 0xC0, 0xFF, 0x3F, 0xFF, 0xF8, 0xFF, 0xFF,
0xE3, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xBF, 0x00, 0x3F, 0xFC, 0x00, 0xFF,
0xF0, 0x01, 0xFF, 0xC0, 0x07, 0xFF, 0x00, 0x3F, 0xFC, 0x03, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xF8, 0xFF, 0xFF, 0x80, 0x00, 0x3F,
0x80, 0x01, 0xFF, 0xF0, 0x03, 0xFF, 0xFC, 0x0F, 0xFF, 0xFE, 0x1F, 0xFF,
0xFF, 0x1F, 0xE0, 0x7E, 0x3F, 0x80, 0x1C, 0x7F, 0x00, 0x00, 0x7E, 0x00,
0x00, 0x7E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00,
0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00,
0x00, 0x7F, 0x00, 0x00, 0x3F, 0x00, 0x18, 0x3F, 0xC0, 0x3C, 0x1F, 0xF9,
0xFE, 0x0F, 0xFF, 0xFE, 0x07, 0xFF, 0xFC, 0x03, 0xFF, 0xF8, 0x00, 0xFF,
0xE0, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xC0, 0x3F, 0xFF, 0xF8, 0x1F, 0xFF,
0xFE, 0x0F, 0xFF, 0xFF, 0x87, 0xE0, 0x3F, 0xE3, 0xF0, 0x03, 0xF9, 0xF8,
0x00, 0xFC, 0xFC, 0x00, 0x3F, 0x7E, 0x00, 0x1F, 0xBF, 0x00, 0x07, 0xDF,
0x80, 0x03, 0xEF, 0xC0, 0x01, 0xFF, 0xE0, 0x00, 0xFF, 0xF0, 0x00, 0x7D,
0xF8, 0x00, 0x7E, 0xFC, 0x00, 0x3F, 0x7E, 0x00, 0x3F, 0xBF, 0x00, 0x3F,
0x9F, 0x80, 0x3F, 0xCF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF,
0xC1, 0xFF, 0xFF, 0x80, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xDF, 0xFF,
0xFB, 0xFF, 0xFF, 0x7F, 0xFF, 0xEF, 0xFF, 0xFD, 0xF8, 0x00, 0x3F, 0x00,
0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xFF, 0xFE, 0x7F, 0xFF,
0xCF, 0xFF, 0xF9, 0xFF, 0xFF, 0x3F, 0xFF, 0xE7, 0xE0, 0x00, 0xFC, 0x00,
0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0xC0, 0x03,
0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFF,
0xFF, 0xBF, 0xFF, 0xEF, 0xFF, 0xFB, 0xFF, 0xFE, 0xFC, 0x00, 0x3F, 0x00,
0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03,
0xF0, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x01, 0xFF, 0xF0, 0x03,
0xFF, 0xFC, 0x0F, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0x1F, 0xE0, 0x7E, 0x3F,
0x80, 0x1C, 0x7F, 0x00, 0x08, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C,
0x00, 0x00, 0xFC, 0x00, 0x00, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC,
0x00, 0x3F, 0x7E, 0x00, 0x3F, 0x7E, 0x00, 0x3F, 0x7F, 0x00, 0x3F, 0x3F,
0x00, 0x3F, 0x3F, 0xC0, 0x3F, 0x1F, 0xF9, 0xFF, 0x0F, 0xFF, 0xFF, 0x07,
0xFF, 0xFE, 0x03, 0xFF, 0xFC, 0x00, 0xFF, 0xE0, 0xFC, 0x00, 0x7F, 0xF0,
0x01, 0xFF, 0xC0, 0x07, 0xFF, 0x00, 0x1F, 0xFC, 0x00, 0x7F, 0xF0, 0x01,
0xFF, 0xC0, 0x07, 0xFF, 0x00, 0x1F, 0xFC, 0x00, 0x7F, 0xF0, 0x01, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0x1F, 0xFC, 0x00, 0x7F, 0xF0, 0x01, 0xFF, 0xC0, 0x07,
0xFF, 0x00, 0x1F, 0xFC, 0x00, 0x7F, 0xF0, 0x01, 0xFF, 0xC0, 0x07, 0xFF,
0x00, 0x1F, 0xFC, 0x00, 0x7C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x1F, 0xFF, 0x8F, 0xFF, 0xC7, 0xFF, 0xE3, 0xFF, 0xF1, 0xFF, 0xF8, 0x00,
0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xE0,
0x01, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F,
0x80, 0x07, 0xC4, 0x07, 0xE7, 0x03, 0xF3, 0xE3, 0xFB, 0xFF, 0xF9, 0xFF,
0xFC, 0x7F, 0xFC, 0x0F, 0xF8, 0x00, 0xFC, 0x00, 0xFF, 0xF8, 0x03, 0xFB,
0xF0, 0x0F, 0xE7, 0xE0, 0x1F, 0x8F, 0xC0, 0x7E, 0x1F, 0x81, 0xF8, 0x3F,
0x07, 0xE0, 0x7E, 0x1F, 0x80, 0xFC, 0x7E, 0x01, 0xF9, 0xF8, 0x03, 0xF7,
0xE0, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0x80, 0x1F, 0xFF, 0x80, 0x3F, 0xFF,
0x80, 0x7F, 0xFF, 0x80, 0xFF, 0x3F, 0x81, 0xFC, 0x3F, 0x03, 0xF0, 0x7F,
0x07, 0xE0, 0x7F, 0x0F, 0xC0, 0x7F, 0x1F, 0x80, 0x7F, 0x3F, 0x00, 0x7E,
0x7E, 0x00, 0xFE, 0xFC, 0x00, 0xFE, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0,
0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00,
0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F,
0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0,
0x03, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xC0, 0xF8, 0x00, 0x01, 0xEF, 0x80, 0x00, 0x3E, 0xFC, 0x00,
0x03, 0xEF, 0xC0, 0x00, 0x7E, 0xFE, 0x00, 0x0F, 0xEF, 0xF0, 0x00, 0xFE,
0xFF, 0x00, 0x1F, 0xEF, 0xF8, 0x01, 0xFE, 0xFF, 0x80, 0x3F, 0xEF, 0xFC,
0x07, 0xFE, 0xFF, 0xE0, 0x7F, 0xEF, 0xBE, 0x0F, 0xBE, 0xFB, 0xF0, 0xFB,
0xEF, 0x9F, 0x1F, 0x3E, 0xF8, 0xFB, 0xF3, 0xEF, 0x8F, 0xFE, 0x3E, 0xF8,
0x7F, 0xC3, 0xEF, 0x87, 0xFC, 0x3E, 0xF8, 0x3F, 0x83, 0xEF, 0x81, 0xF8,
0x3F, 0xF8, 0x1F, 0x03, 0xFF, 0x80, 0xF0, 0x3F, 0xF8, 0x00, 0x03, 0xFF,
0x80, 0x00, 0x3F, 0xF8, 0x00, 0x03, 0xF0, 0xF8, 0x00, 0x7F, 0xE0, 0x01,
0xFF, 0xC0, 0x07, 0xFF, 0x80, 0x1F, 0xFF, 0x00, 0x7F, 0xFE, 0x01, 0xFF,
0xFC, 0x07, 0xFF, 0xF0, 0x1F, 0xFF, 0xE0, 0x7F, 0xFF, 0xC1, 0xFF, 0xFF,
0x87, 0xFF, 0x7F, 0x1F, 0xFD, 0xFC, 0x7F, 0xF3, 0xF9, 0xFF, 0xC7, 0xF7,
0xFF, 0x0F, 0xFF, 0xFC, 0x1F, 0xFF, 0xF0, 0x3F, 0xFF, 0xC0, 0xFF, 0xFF,
0x01, 0xFF, 0xFC, 0x03, 0xFF, 0xF0, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0x00,
0x3F, 0xFC, 0x00, 0x7C, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0xFE, 0x00, 0x0F,
0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xF0, 0x3F, 0xC0, 0xFF,
0x0F, 0xE0, 0x07, 0xF3, 0xF8, 0x00, 0x7E, 0x7E, 0x00, 0x0F, 0xCF, 0xC0,
0x00, 0xFD, 0xF0, 0x00, 0x1F, 0xFE, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x7F,
0xF8, 0x00, 0x0F, 0xFF, 0x00, 0x01, 0xFB, 0xF0, 0x00, 0x3F, 0x7E, 0x00,
0x07, 0xEF, 0xE0, 0x01, 0xF8, 0xFC, 0x00, 0x7F, 0x1F, 0xE0, 0x1F, 0xC1,
0xFF, 0x9F, 0xF8, 0x1F, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0x80, 0x1F, 0xFF,
0xC0, 0x00, 0xFF, 0xE0, 0x00, 0xFF, 0xE0, 0x07, 0xFF, 0xF8, 0x3F, 0xFF,
0xF1, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0x7E, 0x03, 0xFB, 0xF0, 0x0F, 0xFF,
0x80, 0x3F, 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xFF, 0x00, 0x7F, 0xF8, 0x03,
0xFF, 0xC0, 0x3F, 0xFE, 0x0F, 0xFB, 0xFF, 0xFF, 0xDF, 0xFF, 0xFC, 0xFF,
0xFF, 0x87, 0xFF, 0xF0, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00,
0x7E, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x80, 0x00, 0xFC, 0x00, 0x00, 0x00,
0x3F, 0x80, 0x00, 0x1F, 0xFF, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0xFF, 0xFF,
0xE0, 0x1F, 0xFF, 0xFF, 0x01, 0xFE, 0x07, 0xF8, 0x3F, 0x80, 0x1F, 0xC7,
0xF0, 0x00, 0xFC, 0x7E, 0x00, 0x0F, 0xC7, 0xE0, 0x00, 0x7E, 0x7C, 0x00,
0x07, 0xEF, 0xC0, 0x00, 0x7E, 0xFC, 0x00, 0x07, 0xEF, 0xC0, 0x00, 0x7E,
0xFC, 0x00, 0x07, 0xE7, 0xE0, 0x00, 0x7E, 0x7E, 0x00, 0x07, 0xE7, 0xF0,
0x00, 0xFC, 0x3F, 0x00, 0x1F, 0xC3, 0xFC, 0x03, 0xF8, 0x1F, 0xF9, 0xFF,
0x80, 0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0x80, 0x00,
0xFF, 0xE0, 0x00, 0x00, 0xFE, 0x06, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x3F,
0xFF, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x07, 0x00,
0xFF, 0xE0, 0x03, 0xFF, 0xFC, 0x0F, 0xFF, 0xFC, 0x3F, 0xFF, 0xF8, 0xFF,
0xFF, 0xF3, 0xF0, 0x1F, 0xCF, 0xC0, 0x3F, 0xBF, 0x00, 0x7E, 0xFC, 0x01,
0xFB, 0xF0, 0x07, 0xEF, 0xC0, 0x1F, 0xBF, 0x00, 0x7E, 0xFC, 0x03, 0xFB,
0xF0, 0x7F, 0xCF, 0xFF, 0xFF, 0x3F, 0xFF, 0xF8, 0xFF, 0xFF, 0x83, 0xFF,
0xFC, 0x0F, 0xC1, 0xF8, 0x3F, 0x03, 0xF0, 0xFC, 0x0F, 0xC3, 0xF0, 0x1F,
0x8F, 0xC0, 0x3F, 0x3F, 0x00, 0xFE, 0xFC, 0x01, 0xF8, 0x01, 0xFE, 0x00,
0xFF, 0xFC, 0x1F, 0xFF, 0xE3, 0xFF, 0xFE, 0x7F, 0xFF, 0xC7, 0xE0, 0x1C,
0x7C, 0x00, 0x4F, 0xC0, 0x00, 0xFC, 0x00, 0x07, 0xF0, 0x00, 0x7F, 0xE0,
0x03, 0xFF, 0xE0, 0x1F, 0xFF, 0x80, 0xFF, 0xFE, 0x01, 0xFF, 0xE0, 0x01,
0xFF, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x00, 0x01, 0xF7, 0x00, 0x3F, 0x7E,
0x07, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xE7, 0xFF, 0xF8, 0x0F, 0xFF, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x80, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x80, 0x00, 0xFC, 0x00,
0x07, 0xE0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x7E,
0x00, 0x03, 0xF0, 0x00, 0x1F, 0x80, 0x00, 0xFC, 0x00, 0x07, 0xE0, 0x00,
0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0,
0x00, 0x1F, 0x80, 0x00, 0xFC, 0x00, 0xF8, 0x00, 0xFF, 0xE0, 0x03, 0xFF,
0x80, 0x0F, 0xFE, 0x00, 0x3F, 0xF8, 0x00, 0xFF, 0xE0, 0x03, 0xFF, 0x80,
0x0F, 0xFE, 0x00, 0x3F, 0xF8, 0x00, 0xFF, 0xE0, 0x03, 0xFF, 0x80, 0x0F,
0xFE, 0x00, 0x3F, 0xF8, 0x00, 0xFF, 0xE0, 0x03, 0xFF, 0x80, 0x0F, 0xFE,
0x00, 0x3F, 0xFC, 0x00, 0xFF, 0xF0, 0x03, 0xFF, 0xC0, 0x1F, 0x9F, 0x80,
0xFE, 0x7F, 0xDF, 0xF8, 0xFF, 0xFF, 0xC1, 0xFF, 0xFE, 0x03, 0xFF, 0xF0,
0x03, 0xFF, 0x00, 0xFC, 0x00, 0x07, 0xFF, 0x00, 0x03, 0xF7, 0xE0, 0x00,
0xFD, 0xF8, 0x00, 0x3E, 0x7F, 0x00, 0x1F, 0x8F, 0xC0, 0x07, 0xC3, 0xF0,
0x03, 0xF0, 0x7E, 0x00, 0xF8, 0x1F, 0x80, 0x7E, 0x03, 0xF0, 0x1F, 0x80,
0xFC, 0x0F, 0xC0, 0x3F, 0x83, 0xF0, 0x07, 0xE0, 0xF8, 0x01, 0xF8, 0x7E,
0x00, 0x3F, 0x1F, 0x00, 0x0F, 0xCF, 0xC0, 0x01, 0xFB, 0xF0, 0x00, 0x7F,
0xF8, 0x00, 0x1F, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x00, 0xFF, 0xC0, 0x00,
0x1F, 0xE0, 0x00, 0x07, 0xF8, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x3F, 0x00,
0x00, 0xFC, 0x00, 0x7C, 0x00, 0x3F, 0xF8, 0x00, 0xFC, 0x00, 0xFF, 0xF0,
0x03, 0xF8, 0x01, 0xF3, 0xF0, 0x07, 0xF0, 0x03, 0xE7, 0xE0, 0x0F, 0xE0,
0x0F, 0xCF, 0xC0, 0x3F, 0xE0, 0x1F, 0x0F, 0xC0, 0x7F, 0xC0, 0x3E, 0x1F,
0x80, 0xFF, 0x80, 0xFC, 0x3F, 0x03, 0xFF, 0x81, 0xF0, 0x3F, 0x07, 0xDF,
0x03, 0xE0, 0x7E, 0x0F, 0xBE, 0x0F, 0xC0, 0xFC, 0x3E, 0x7E, 0x1F, 0x00,
0xFC, 0x7C, 0x7C, 0x3E, 0x01, 0xF8, 0xF8, 0xF8, 0xFC, 0x03, 0xF3, 0xE1,
0xF9, 0xF0, 0x03, 0xE7, 0xC1, 0xF3, 0xE0, 0x07, 0xEF, 0x83, 0xEF, 0xC0,
0x0F, 0xFE, 0x07, 0xFF, 0x00, 0x0F, 0xFC, 0x07, 0xFE, 0x00, 0x1F, 0xF8,
0x0F, 0xFC, 0x00, 0x3F, 0xE0, 0x1F, 0xF0, 0x00, 0x3F, 0xC0, 0x1F, 0xE0,
0x00, 0x7F, 0x80, 0x3F, 0xC0, 0x00, 0xFE, 0x00, 0x7F, 0x00, 0x00, 0xFC,
0x00, 0x7E, 0x00, 0x7E, 0x00, 0x3F, 0x3F, 0x80, 0x3F, 0x8F, 0xC0, 0x1F,
0x83, 0xF0, 0x1F, 0x81, 0xFC, 0x1F, 0x80, 0x7F, 0x0F, 0xC0, 0x1F, 0x8F,
0xC0, 0x07, 0xEF, 0xC0, 0x03, 0xFF, 0xE0, 0x00, 0xFF, 0xE0, 0x00, 0x3F,
0xE0, 0x00, 0x1F, 0xE0, 0x00, 0x07, 0xF0, 0x00, 0x07, 0xFC, 0x00, 0x03,
0xFE, 0x00, 0x03, 0xFF, 0x80, 0x03, 0xFF, 0xE0, 0x01, 0xFB, 0xF0, 0x01,
0xF8, 0xFC, 0x01, 0xF8, 0x3F, 0x01, 0xFC, 0x1F, 0xC0, 0xFC, 0x07, 0xE0,
0xFC, 0x01, 0xF8, 0xFE, 0x00, 0xFE, 0xFE, 0x00, 0x3F, 0x80, 0xFC, 0x00,
0x1F, 0xFC, 0x00, 0x3F, 0x7E, 0x00, 0x7E, 0x7E, 0x00, 0x7C, 0x3F, 0x00,
0xFC, 0x1F, 0x80, 0xF8, 0x1F, 0x81, 0xF8, 0x0F, 0xC3, 0xF0, 0x0F, 0xC3,
0xE0, 0x07, 0xE7, 0xE0, 0x03, 0xF7, 0xC0, 0x03, 0xFF, 0xC0, 0x01, 0xFF,
0x80, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E,
0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E,
0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7E,
0x00, 0x7F, 0xFF, 0xF9, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0x9F, 0xFF, 0xFE,
0x7F, 0xFF, 0xF8, 0x00, 0x1F, 0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00,
0x1F, 0xC0, 0x00, 0xFE, 0x00, 0x07, 0xF0, 0x00, 0x3F, 0x80, 0x00, 0xFC,
0x00, 0x07, 0xF0, 0x00, 0x3F, 0x80, 0x01, 0xFC, 0x00, 0x0F, 0xE0, 0x00,
0x7F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x7F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x87, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F,
0x87, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE1,
0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
0x7C, 0x00, 0x3E, 0x00, 0x0F, 0x00, 0x07, 0xC0, 0x03, 0xE0, 0x00, 0xF0,
0x00, 0x7C, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xE0, 0x00,
0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xE0,
0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x01,
0xE0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x1E, 0x00, 0x0F, 0x80, 0x07, 0xC0,
0x01, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0xFF,
0xFF, 0xFF, 0xFF, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE1,
0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C,
0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x80, 0x03, 0xE0, 0x01, 0xF0, 0x01, 0xFC, 0x00, 0xFE, 0x00, 0x7F, 0x00,
0x7B, 0xC0, 0x3D, 0xE0, 0x3C, 0x78, 0x1E, 0x3C, 0x1F, 0x1F, 0x0F, 0x07,
0x87, 0x83, 0xC7, 0x80, 0xF3, 0xC0, 0x7B, 0xC0, 0x1E, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFC, 0x7E, 0x07, 0xE0, 0x3E, 0x03, 0xE0, 0x3C, 0x07,
0xF8, 0x0F, 0xFF, 0x87, 0xFF, 0xF0, 0xFF, 0xFE, 0x3E, 0x3F, 0xC4, 0x03,
0xF0, 0x00, 0xFC, 0x00, 0x1F, 0x0F, 0xFF, 0xCF, 0xFF, 0xF7, 0xFF, 0xFD,
0xF8, 0x1F, 0xFC, 0x07, 0xFF, 0x03, 0xFF, 0xC0, 0xFD, 0xFC, 0xFF, 0x7F,
0xFF, 0xCF, 0xFD, 0xF1, 0xFE, 0x7C, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8,
0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F,
0x9F, 0xC0, 0xFB, 0xFF, 0x0F, 0xFF, 0xF8, 0xFF, 0xFF, 0xCF, 0xF9, 0xFE,
0xFE, 0x07, 0xEF, 0xC0, 0x3F, 0xF8, 0x03, 0xFF, 0x80, 0x3F, 0xF8, 0x03,
0xFF, 0x80, 0x3F, 0xF8, 0x03, 0xFF, 0xC0, 0x3F, 0xFC, 0x07, 0xEF, 0xF1,
0xFE, 0xFF, 0xFF, 0xCF, 0xFF, 0xF8, 0xFF, 0xFF, 0x0F, 0x9F, 0xE0, 0x01,
0xFC, 0x00, 0xFF, 0xE0, 0x7F, 0xFF, 0x1F, 0xFF, 0xE7, 0xFC, 0xFE, 0xFC,
0x07, 0x9F, 0x00, 0x47, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0,
0x00, 0x7E, 0x00, 0x07, 0xC0, 0x00, 0xFC, 0x07, 0x1F, 0xE3, 0xF9, 0xFF,
0xFF, 0x1F, 0xFF, 0xC1, 0xFF, 0xF0, 0x0F, 0xF8, 0x00, 0x00, 0x01, 0xF8,
0x00, 0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x80, 0x00,
0xFC, 0x00, 0x07, 0xE0, 0x7F, 0x3F, 0x0F, 0xFF, 0xF8, 0xFF, 0xFF, 0xCF,
0xFF, 0xFE, 0xFF, 0x9F, 0xF7, 0xE0, 0x3F, 0xBF, 0x01, 0xFF, 0xF0, 0x07,
0xFF, 0x80, 0x3F, 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xFF, 0x00, 0x7E, 0xF8,
0x03, 0xF7, 0xE0, 0x3F, 0xBF, 0xC7, 0xFC, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF,
0x0F, 0xFF, 0xF8, 0x1F, 0xCF, 0xC0, 0x03, 0xFC, 0x00, 0xFF, 0xF0, 0x1F,
0xFF, 0x83, 0xFF, 0xFC, 0x7F, 0x0F, 0xE7, 0xE0, 0x3E, 0x7C, 0x03, 0xFF,
0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00,
0x7C, 0x00, 0x07, 0xE0, 0x10, 0x7F, 0x87, 0x83, 0xFF, 0xFC, 0x1F, 0xFF,
0xC0, 0xFF, 0xF8, 0x03, 0xFE, 0x00, 0x01, 0xFC, 0x0F, 0xF8, 0x3F, 0xF0,
0x7F, 0xE1, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0xFF, 0xF9, 0xFF,
0xF3, 0xFF, 0xE7, 0xFF, 0xC1, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0,
0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07,
0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x03, 0xF8, 0xF8, 0x7F, 0xF7,
0xC7, 0xFF, 0xFE, 0x7F, 0xFF, 0xF7, 0xF8, 0xFF, 0xBF, 0x01, 0xFF, 0xF0,
0x07, 0xFF, 0x80, 0x3F, 0xFC, 0x00, 0xFF, 0xE0, 0x07, 0xFF, 0x00, 0x7F,
0xF8, 0x03, 0xF7, 0xE0, 0x3F, 0xBF, 0xE7, 0xFC, 0xFF, 0xFF, 0xE3, 0xFF,
0xFF, 0x0F, 0xFF, 0xF8, 0x1F, 0xCF, 0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF1,
0x80, 0x3F, 0x1F, 0x8F, 0xF8, 0xFF, 0xFF, 0x8F, 0xFF, 0xF8, 0x1F, 0xFF,
0x80, 0x3F, 0xF0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7C,
0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0x3E, 0x00, 0x07, 0xC7, 0xE0, 0xFB,
0xFF, 0x1F, 0xFF, 0xF3, 0xFF, 0xFF, 0x7F, 0xFF, 0xEF, 0xE0, 0xFD, 0xF8,
0x0F, 0xFE, 0x01, 0xFF, 0xC0, 0x3F, 0xF8, 0x07, 0xFF, 0x00, 0xFF, 0xE0,
0x1F, 0xFC, 0x03, 0xFF, 0x80, 0x7F, 0xF0, 0x0F, 0xFE, 0x01, 0xFF, 0xC0,
0x3F, 0xF8, 0x07, 0xFF, 0x00, 0xFC, 0x10, 0xFB, 0xFF, 0xFF, 0xEF, 0x84,
0x00, 0x00, 0xF9, 0xF3, 0xE7, 0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE7,
0xCF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3, 0xE0, 0x00, 0x80, 0x3E, 0x07, 0xF0,
0x7F, 0x07, 0xF0, 0x3E, 0x00, 0x80, 0x00, 0x00, 0x00, 0x3E, 0x03, 0xE0,
0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0,
0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x3E, 0x03, 0xE0,
0x3E, 0x03, 0xE0, 0x7E, 0x47, 0xE7, 0xFC, 0xFF, 0xCF, 0xF8, 0x7E, 0x00,
0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00,
0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x7E, 0xF8, 0x0F, 0xCF, 0x83,
0xF8, 0xF8, 0x7F, 0x0F, 0x8F, 0xE0, 0xF9, 0xFC, 0x0F, 0xBF, 0x80, 0xFF,
0xF0, 0x0F, 0xFF, 0x00, 0xFF, 0xF8, 0x0F, 0xFF, 0x80, 0xFF, 0xFC, 0x0F,
0xEF, 0xE0, 0xFC, 0x7F, 0x0F, 0x83, 0xF8, 0xF8, 0x1F, 0x8F, 0x80, 0xFC,
0xF8, 0x0F, 0xEF, 0x80, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xF9, 0xFC,
0x0F, 0xE1, 0xF7, 0xFE, 0x7F, 0xF3, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF,
0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0xFE, 0x0F, 0xFF, 0x03, 0xF8,
0x1F, 0xFC, 0x07, 0xE0, 0x1F, 0xF8, 0x07, 0xC0, 0x3F, 0xF0, 0x0F, 0x80,
0x7F, 0xE0, 0x1F, 0x00, 0xFF, 0xC0, 0x3E, 0x01, 0xFF, 0x80, 0x7C, 0x03,
0xFF, 0x00, 0xF8, 0x07, 0xFE, 0x01, 0xF0, 0x0F, 0xFC, 0x03, 0xE0, 0x1F,
0xF8, 0x07, 0xC0, 0x3F, 0xF0, 0x0F, 0x80, 0x7F, 0xE0, 0x1F, 0x00, 0xF8,
0xF8, 0xFC, 0x1F, 0x7F, 0xE3, 0xFF, 0xFE, 0x7F, 0xFF, 0xEF, 0xFF, 0xFD,
0xFC, 0x1F, 0xBF, 0x01, 0xFF, 0xC0, 0x3F, 0xF8, 0x07, 0xFF, 0x00, 0xFF,
0xE0, 0x1F, 0xFC, 0x03, 0xFF, 0x80, 0x7F, 0xF0, 0x0F, 0xFE, 0x01, 0xFF,
0xC0, 0x3F, 0xF8, 0x07, 0xFF, 0x00, 0xFF, 0xE0, 0x1F, 0x80, 0x01, 0xFC,
0x00, 0x3F, 0xF8, 0x07, 0xFF, 0xF0, 0x7F, 0xFF, 0xC7, 0xF8, 0xFE, 0x3F,
0x01, 0xF9, 0xF0, 0x0F, 0xDF, 0x80, 0x3F, 0xFC, 0x01, 0xFF, 0xE0, 0x0F,
0xFF, 0x00, 0x7F, 0xF8, 0x03, 0xF7, 0xC0, 0x1F, 0x3F, 0x01, 0xF9, 0xFE,
0x3F, 0xC7, 0xFF, 0xFC, 0x1F, 0xFF, 0xC0, 0x7F, 0xFC, 0x00, 0xFF, 0x80,
0xF9, 0xFC, 0x0F, 0xBF, 0xF0, 0xFF, 0xFF, 0x8F, 0xFF, 0xFC, 0xFF, 0x9F,
0xEF, 0xE0, 0x7E, 0xFC, 0x03, 0xFF, 0x80, 0x3F, 0xF8, 0x03, 0xFF, 0x80,
0x3F, 0xF8, 0x03, 0xFF, 0x80, 0x3F, 0xFC, 0x03, 0xFF, 0xC0, 0x7E, 0xFF,
0x1F, 0xEF, 0xFF, 0xFC, 0xFF, 0xFF, 0x8F, 0xFF, 0xF0, 0xF9, 0xFE, 0x0F,
0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00, 0xF8, 0x00, 0x0F, 0x80, 0x00,
0xF8, 0x00, 0x0F, 0x80, 0x00, 0x03, 0xF9, 0xF8, 0x7F, 0xFF, 0xC7, 0xFF,
0xFE, 0x7F, 0xFF, 0xF7, 0xF9, 0xFF, 0xBF, 0x01, 0xFF, 0xF0, 0x0F, 0xFF,
0x80, 0x3F, 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xFF, 0x00, 0x7F, 0xF8, 0x03,
0xFF, 0xC0, 0x1F, 0xBF, 0x01, 0xFD, 0xFE, 0x3F, 0xE7, 0xFF, 0xFF, 0x1F,
0xFF, 0xF8, 0x7F, 0xFF, 0xC0, 0xFE, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x1F,
0x80, 0x00, 0xFC, 0x00, 0x07, 0xE0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00,
0x0F, 0xC0, 0xF8, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3F, 0x07,
0xC0, 0xF8, 0x1F, 0x03, 0xE0, 0x7C, 0x0F, 0x81, 0xF0, 0x3E, 0x07, 0xC0,
0xF8, 0x1F, 0x03, 0xE0, 0x00, 0x07, 0xFC, 0x0F, 0xFF, 0x9F, 0xFF, 0xCF,
0xFF, 0xCF, 0xC0, 0xE7, 0xC0, 0x03, 0xF0, 0x01, 0xFE, 0x00, 0x7F, 0xF8,
0x3F, 0xFF, 0x07, 0xFF, 0xC0, 0x3F, 0xE0, 0x01, 0xFA, 0x00, 0x7D, 0xC0,
0x7F, 0xFF, 0xFE, 0xFF, 0xFF, 0x7F, 0xFF, 0x0F, 0xFE, 0x00, 0x1F, 0x80,
0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x0F, 0xFF, 0x9F, 0xFF, 0x3F, 0xFE, 0x7F,
0xFC, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0,
0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7F, 0x00, 0x7F, 0xE0,
0xFF, 0xC0, 0xFF, 0x80, 0xFF, 0x00, 0xFC, 0x03, 0xFF, 0x80, 0x7F, 0xF0,
0x0F, 0xFE, 0x01, 0xFF, 0xC0, 0x3F, 0xF8, 0x07, 0xFF, 0x00, 0xFF, 0xE0,
0x1F, 0xFC, 0x03, 0xFF, 0x80, 0x7F, 0xF0, 0x0F, 0xFE, 0x01, 0xF7, 0xC0,
0x7E, 0xFC, 0x0F, 0xDF, 0xEF, 0xFB, 0xFF, 0xFF, 0x3F, 0xFF, 0xE3, 0xFF,
0xFC, 0x1F, 0xCF, 0x80, 0xFC, 0x00, 0xFF, 0xE0, 0x0F, 0xDF, 0x00, 0x7C,
0xFC, 0x03, 0xE3, 0xE0, 0x3E, 0x1F, 0x81, 0xF0, 0xFC, 0x1F, 0x83, 0xE0,
0xF8, 0x1F, 0x8F, 0xC0, 0x7C, 0x7C, 0x03, 0xF3, 0xE0, 0x1F, 0xBE, 0x00,
0x7D, 0xF0, 0x03, 0xFF, 0x80, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x01, 0xFC,
0x00, 0x0F, 0xE0, 0x00, 0x7E, 0x00, 0xF8, 0x03, 0xE0, 0x0F, 0xBE, 0x01,
0xF0, 0x0F, 0x9F, 0x01, 0xFC, 0x07, 0xCF, 0x80, 0xFE, 0x03, 0xE3, 0xE0,
0x7F, 0x03, 0xE1, 0xF0, 0x7F, 0xC1, 0xF0, 0xF8, 0x3F, 0xE0, 0xF0, 0x3E,
0x1F, 0xF0, 0xF8, 0x1F, 0x1F, 0x7C, 0x7C, 0x0F, 0x8F, 0xBE, 0x3C, 0x03,
0xEF, 0x8F, 0xBE, 0x01, 0xF7, 0xC7, 0xDF, 0x00, 0xFB, 0xE3, 0xFF, 0x00,
0x3F, 0xE0, 0xFF, 0x80, 0x1F, 0xF0, 0x7F, 0xC0, 0x07, 0xF0, 0x3F, 0xC0,
0x03, 0xF8, 0x0F, 0xE0, 0x01, 0xFC, 0x07, 0xE0, 0x00, 0x7C, 0x03, 0xF0,
0x00, 0x7E, 0x03, 0xF3, 0xF0, 0x1F, 0x0F, 0xC1, 0xF8, 0x3F, 0x1F, 0x80,
0xFD, 0xF8, 0x07, 0xEF, 0x80, 0x1F, 0xFC, 0x00, 0x7F, 0xC0, 0x01, 0xFC,
0x00, 0x0F, 0xE0, 0x00, 0x7F, 0x00, 0x07, 0xFC, 0x00, 0x7F, 0xF0, 0x07,
0xEF, 0xC0, 0x3E, 0x7E, 0x03, 0xF1, 0xF8, 0x3F, 0x07, 0xE3, 0xF0, 0x3F,
0x9F, 0x00, 0xFC, 0xFC, 0x00, 0xFF, 0xE0, 0x0F, 0xDF, 0x00, 0x7C, 0xFC,
0x03, 0xE3, 0xE0, 0x3E, 0x1F, 0x81, 0xF0, 0xFC, 0x1F, 0x83, 0xE0, 0xF8,
0x1F, 0x8F, 0xC0, 0x7C, 0x7C, 0x03, 0xF3, 0xE0, 0x0F, 0xBE, 0x00, 0x7D,
0xF0, 0x03, 0xFF, 0x80, 0x0F, 0xF8, 0x00, 0x7F, 0xC0, 0x01, 0xFC, 0x00,
0x0F, 0xE0, 0x00, 0x3E, 0x00, 0x01, 0xF0, 0x00, 0x1F, 0x80, 0x39, 0xF8,
0x01, 0xFF, 0xC0, 0x1F, 0xFC, 0x00, 0xFF, 0xC0, 0x01, 0xF8, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xF0, 0x03,
0xF0, 0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF8, 0x01, 0xF8, 0x01,
0xF8, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0xF8, 0x01, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x03, 0xE1, 0xFC, 0x7F, 0x8F, 0xF1, 0xF8,
0x3E, 0x07, 0xC0, 0xF8, 0x1F, 0x03, 0xE0, 0x7C, 0x0F, 0x81, 0xF0, 0x7E,
0x3F, 0xC7, 0xF0, 0xFC, 0x1F, 0xC3, 0xFC, 0x1F, 0x81, 0xF0, 0x3E, 0x07,
0xC0, 0xF8, 0x1F, 0x03, 0xE0, 0x7C, 0x0F, 0x81, 0xFC, 0x3F, 0xC3, 0xF8,
0x3F, 0x01, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8,
0xF8, 0x1F, 0x83, 0xF8, 0x7F, 0x87, 0xF0, 0x7E, 0x07, 0xC0, 0xF8, 0x1F,
0x03, 0xE0, 0x7C, 0x0F, 0x81, 0xF0, 0x3E, 0x07, 0xF8, 0x7F, 0x07, 0xE3,
0xFC, 0x7F, 0x8F, 0x81, 0xF0, 0x3E, 0x07, 0xC0, 0xF8, 0x1F, 0x03, 0xE0,
0x7C, 0x1F, 0x8F, 0xF1, 0xFE, 0x3F, 0x87, 0xE0, 0xF0, 0x00, 0x0C, 0x00,
0x1F, 0xC1, 0xDF, 0xF1, 0xFF, 0xFF, 0xFF, 0x3F, 0xF7, 0x07, 0xFB, 0x81,
0xF8 };
const GFXglyph Montserrat_Bold18pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 10, 0, 0 }, // 0x20 ' '
{ 1, 6, 25, 10, 2, -24 }, // 0x21 '!'
{ 20, 11, 10, 15, 2, -24 }, // 0x22 '"'
{ 34, 24, 25, 25, 1, -24 }, // 0x23 '#'
{ 109, 20, 33, 22, 1, -28 }, // 0x24 '$'
{ 192, 29, 25, 31, 1, -24 }, // 0x25 '%'
{ 283, 24, 25, 25, 1, -24 }, // 0x26 '&'
{ 358, 4, 10, 8, 2, -24 }, // 0x27 '''
{ 363, 9, 33, 13, 3, -25 }, // 0x28 '('
{ 401, 10, 33, 13, 0, -25 }, // 0x29 ')'
{ 443, 15, 14, 15, 0, -25 }, // 0x2A '*'
{ 470, 17, 16, 21, 2, -19 }, // 0x2B '+'
{ 504, 7, 12, 9, 1, -6 }, // 0x2C ','
{ 515, 10, 4, 14, 2, -11 }, // 0x2D '-'
{ 520, 7, 7, 9, 1, -6 }, // 0x2E '.'
{ 527, 16, 33, 14, -1, -28 }, // 0x2F '/'
{ 593, 21, 25, 24, 1, -24 }, // 0x30 '0'
{ 659, 11, 25, 14, 0, -24 }, // 0x31 '1'
{ 694, 20, 25, 21, 0, -24 }, // 0x32 '2'
{ 757, 19, 25, 21, 0, -24 }, // 0x33 '3'
{ 817, 23, 25, 24, 1, -24 }, // 0x34 '4'
{ 889, 20, 25, 21, 0, -24 }, // 0x35 '5'
{ 952, 21, 25, 22, 1, -24 }, // 0x36 '6'
{ 1018, 20, 25, 22, 1, -24 }, // 0x37 '7'
{ 1081, 21, 25, 23, 1, -24 }, // 0x38 '8'
{ 1147, 20, 25, 22, 1, -24 }, // 0x39 '9'
{ 1210, 7, 20, 9, 1, -19 }, // 0x3A ':'
{ 1228, 7, 25, 9, 1, -19 }, // 0x3B ';'
{ 1250, 17, 17, 21, 2, -20 }, // 0x3C '<'
{ 1287, 17, 13, 21, 2, -18 }, // 0x3D '='
{ 1315, 17, 17, 21, 2, -20 }, // 0x3E '>'
{ 1352, 19, 25, 21, 0, -24 }, // 0x3F '?'
{ 1412, 34, 32, 36, 1, -24 }, // 0x40 '@'
{ 1548, 27, 25, 27, 0, -24 }, // 0x41 'A'
{ 1633, 22, 25, 27, 3, -24 }, // 0x42 'B'
{ 1702, 24, 25, 25, 1, -24 }, // 0x43 'C'
{ 1777, 25, 25, 29, 3, -24 }, // 0x44 'D'
{ 1856, 19, 25, 23, 3, -24 }, // 0x45 'E'
{ 1916, 18, 25, 22, 3, -24 }, // 0x46 'F'
{ 1973, 24, 25, 27, 1, -24 }, // 0x47 'G'
{ 2048, 22, 25, 28, 3, -24 }, // 0x48 'H'
{ 2117, 6, 25, 11, 3, -24 }, // 0x49 'I'
{ 2136, 17, 25, 19, -1, -24 }, // 0x4A 'J'
{ 2190, 23, 25, 26, 3, -24 }, // 0x4B 'K'
{ 2262, 18, 25, 21, 3, -24 }, // 0x4C 'L'
{ 2319, 28, 25, 33, 3, -24 }, // 0x4D 'M'
{ 2407, 22, 25, 28, 3, -24 }, // 0x4E 'N'
{ 2476, 27, 25, 30, 1, -24 }, // 0x4F 'O'
{ 2561, 21, 25, 26, 3, -24 }, // 0x50 'P'
{ 2627, 28, 31, 30, 1, -24 }, // 0x51 'Q'
{ 2736, 22, 25, 26, 3, -24 }, // 0x52 'R'
{ 2805, 20, 25, 22, 1, -24 }, // 0x53 'S'
{ 2868, 21, 25, 22, 0, -24 }, // 0x54 'T'
{ 2934, 22, 25, 28, 3, -24 }, // 0x55 'U'
{ 3003, 26, 25, 26, 0, -24 }, // 0x56 'V'
{ 3085, 39, 25, 41, 1, -24 }, // 0x57 'W'
{ 3207, 25, 25, 25, 0, -24 }, // 0x58 'X'
{ 3286, 24, 25, 24, 0, -24 }, // 0x59 'Y'
{ 3361, 22, 25, 23, 1, -24 }, // 0x5A 'Z'
{ 3430, 9, 33, 13, 3, -25 }, // 0x5B '['
{ 3468, 17, 33, 14, -2, -28 }, // 0x5C '\'
{ 3539, 9, 33, 13, 1, -25 }, // 0x5D ']'
{ 3577, 17, 15, 21, 2, -19 }, // 0x5E '^'
{ 3609, 18, 3, 18, 0, 1 }, // 0x5F '_'
{ 3616, 11, 5, 21, 3, -25 }, // 0x60 '`'
{ 3623, 18, 19, 22, 1, -18 }, // 0x61 'a'
{ 3666, 20, 26, 24, 3, -25 }, // 0x62 'b'
{ 3731, 19, 19, 21, 1, -18 }, // 0x63 'c'
{ 3777, 21, 26, 24, 1, -25 }, // 0x64 'd'
{ 3846, 20, 19, 22, 1, -18 }, // 0x65 'e'
{ 3894, 15, 26, 14, 0, -25 }, // 0x66 'f'
{ 3943, 21, 26, 25, 1, -18 }, // 0x67 'g'
{ 4012, 19, 26, 24, 3, -25 }, // 0x68 'h'
{ 4074, 7, 28, 11, 2, -27 }, // 0x69 'i'
{ 4099, 12, 35, 11, -3, -27 }, // 0x6A 'j'
{ 4152, 20, 26, 23, 3, -25 }, // 0x6B 'k'
{ 4217, 5, 26, 11, 3, -25 }, // 0x6C 'l'
{ 4234, 31, 19, 37, 3, -18 }, // 0x6D 'm'
{ 4308, 19, 19, 24, 3, -18 }, // 0x6E 'n'
{ 4354, 21, 19, 23, 1, -18 }, // 0x6F 'o'
{ 4404, 20, 26, 24, 3, -18 }, // 0x70 'p'
{ 4469, 21, 26, 24, 1, -18 }, // 0x71 'q'
{ 4538, 11, 19, 15, 3, -18 }, // 0x72 'r'
{ 4565, 17, 19, 19, 1, -18 }, // 0x73 's'
{ 4606, 15, 23, 15, 0, -22 }, // 0x74 't'
{ 4650, 19, 19, 24, 2, -18 }, // 0x75 'u'
{ 4696, 21, 19, 21, 0, -18 }, // 0x76 'v'
{ 4746, 33, 19, 33, 0, -18 }, // 0x77 'w'
{ 4825, 21, 19, 21, 0, -18 }, // 0x78 'x'
{ 4875, 21, 26, 21, 0, -18 }, // 0x79 'y'
{ 4944, 17, 19, 19, 1, -18 }, // 0x7A 'z'
{ 4985, 11, 33, 14, 2, -25 }, // 0x7B '{'
{ 5031, 5, 33, 11, 3, -25 }, // 0x7C '|'
{ 5052, 11, 33, 14, 1, -25 }, // 0x7D '}'
{ 5098, 17, 7, 21, 2, -15 } }; // 0x7E '~'
const GFXfont Montserrat_Bold18pt7b PROGMEM = {
(uint8_t *)Montserrat_Bold18pt7bBitmaps,
(GFXglyph *)Montserrat_Bold18pt7bGlyphs,
0x20, 0x7E, 43 };
// Approx. 5785 bytes
#endif // MONTSERRATBOLD18PT7B_H
@@ -0,0 +1,745 @@
#ifndef MONTSERRATBOLD22PT7B_H
#define MONTSERRATBOLD22PT7B_H
const uint8_t Montserrat_Bold22pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x3E, 0x00, 0x00, 0x00,
0x7E, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0x3E, 0xFC, 0x7F, 0xF8, 0xFF, 0xF1,
0xFF, 0xE3, 0xFF, 0xC7, 0xFF, 0x8F, 0xFF, 0x1F, 0xFE, 0x3F, 0xFC, 0x7F,
0xF0, 0xFB, 0xE1, 0xF3, 0xC1, 0xE0, 0x00, 0xF8, 0x1F, 0x00, 0x07, 0xC0,
0xF8, 0x00, 0x3E, 0x07, 0xC0, 0x01, 0xF0, 0x3E, 0x00, 0x0F, 0x81, 0xF0,
0x00, 0x7C, 0x0F, 0x80, 0x03, 0xC0, 0x7C, 0x0F, 0xFF, 0xFF, 0xFF, 0x7F,
0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFE, 0x03, 0xE0,
0x7C, 0x00, 0x1F, 0x03, 0xE0, 0x00, 0xF8, 0x1F, 0x00, 0x07, 0x80, 0xF8,
0x00, 0x7C, 0x07, 0x80, 0x03, 0xE0, 0x7C, 0x00, 0x1F, 0x03, 0xE0, 0x3F,
0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0xC0, 0xF8, 0x0F, 0x00, 0x07, 0xC0, 0xF8,
0x00, 0x3E, 0x07, 0xC0, 0x01, 0xF0, 0x3E, 0x00, 0x0F, 0x81, 0xF0, 0x00,
0x7C, 0x0F, 0x80, 0x03, 0xE0, 0x7C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0F,
0x00, 0x00, 0x07, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x0F,
0xFF, 0xC0, 0x1F, 0xFF, 0xF8, 0x3F, 0xFF, 0xFE, 0x1F, 0xFF, 0xFE, 0x1F,
0xFF, 0xFF, 0x1F, 0xF7, 0x9F, 0x8F, 0xE3, 0xC1, 0x87, 0xF1, 0xE0, 0x03,
0xF8, 0xF0, 0x01, 0xFC, 0x78, 0x00, 0xFF, 0x3C, 0x00, 0x7F, 0xFE, 0x00,
0x1F, 0xFF, 0x00, 0x0F, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0x00, 0x7F, 0xFF,
0xE0, 0x0F, 0xFF, 0xF8, 0x00, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0x00, 0x1E,
0x7F, 0x80, 0x0F, 0x1F, 0xC0, 0x07, 0x8F, 0xE6, 0x03, 0xC7, 0xF3, 0xC1,
0xE3, 0xFB, 0xFC, 0xF7, 0xFD, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFC, 0x7F,
0xFF, 0xFC, 0x0F, 0xFF, 0xFC, 0x01, 0xFF, 0xF8, 0x00, 0x03, 0xC0, 0x00,
0x01, 0xE0, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3C, 0x00,
0x0F, 0xE0, 0x00, 0x7C, 0x01, 0xFF, 0x80, 0x0F, 0xC0, 0x3F, 0xFC, 0x00,
0xF8, 0x07, 0xC7, 0xC0, 0x1F, 0x00, 0x78, 0x3E, 0x03, 0xF0, 0x0F, 0x83,
0xE0, 0x3E, 0x00, 0xF8, 0x1E, 0x07, 0xC0, 0x0F, 0x81, 0xE0, 0xFC, 0x00,
0xF8, 0x1E, 0x0F, 0x80, 0x0F, 0x81, 0xE1, 0xF0, 0x00, 0xF8, 0x3E, 0x3E,
0x00, 0x07, 0x83, 0xC3, 0xE0, 0x00, 0x7E, 0xFC, 0x7C, 0x00, 0x03, 0xFF,
0x8F, 0x80, 0x00, 0x1F, 0xF0, 0xF8, 0x7E, 0x00, 0xFE, 0x1F, 0x1F, 0xF8,
0x00, 0x03, 0xE3, 0xFF, 0xC0, 0x00, 0x3E, 0x3E, 0x7E, 0x00, 0x07, 0xC7,
0xC3, 0xE0, 0x00, 0xF8, 0x78, 0x1E, 0x00, 0x1F, 0x87, 0x81, 0xE0, 0x01,
0xF0, 0x78, 0x1F, 0x00, 0x3E, 0x07, 0x81, 0xF0, 0x07, 0xE0, 0x78, 0x1E,
0x00, 0x7C, 0x07, 0x81, 0xE0, 0x0F, 0x80, 0x7C, 0x3E, 0x01, 0xF8, 0x03,
0xE7, 0xE0, 0x1F, 0x00, 0x3F, 0xFC, 0x03, 0xE0, 0x01, 0xFF, 0x80, 0x7C,
0x00, 0x0F, 0xF0, 0x01, 0xFF, 0x80, 0x00, 0x3F, 0xFE, 0x00, 0x07, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x1F, 0xE3, 0xF8, 0x01, 0xFC, 0x1F, 0x80,
0x1F, 0x81, 0xF8, 0x01, 0xF8, 0x1F, 0x80, 0x1F, 0xC1, 0xF8, 0x00, 0xFC,
0x7F, 0x00, 0x0F, 0xEF, 0xF0, 0x00, 0x7F, 0xFE, 0x00, 0x07, 0xFF, 0xC0,
0x00, 0x3F, 0xF0, 0x00, 0x0F, 0xFF, 0x00, 0x01, 0xFF, 0xF8, 0x3C, 0x3F,
0xFF, 0xC3, 0xE7, 0xF9, 0xFE, 0x7E, 0xFE, 0x0F, 0xF7, 0xEF, 0xE0, 0x7F,
0xFE, 0xFC, 0x03, 0xFF, 0xCF, 0xC0, 0x1F, 0xFC, 0xFC, 0x00, 0xFF, 0x8F,
0xE0, 0x07, 0xF8, 0xFF, 0x01, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
0xFF, 0xF3, 0xFF, 0xFF, 0xFE, 0x1F, 0xFF, 0xE1, 0xC0, 0x7F, 0xF8, 0x0C,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF,
0x9E, 0x07, 0xF0, 0x7E, 0x0F, 0xE0, 0xFC, 0x1F, 0xC1, 0xF8, 0x3F, 0x83,
0xF8, 0x3F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7E, 0x07, 0xE0, 0xFE, 0x0F,
0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F,
0xE0, 0xFE, 0x0F, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xF0, 0x7F, 0x03,
0xF0, 0x3F, 0x83, 0xF8, 0x1F, 0x81, 0xFC, 0x1F, 0xC0, 0xFC, 0x0F, 0xE0,
0x7E, 0x7E, 0x07, 0xF0, 0x3F, 0x03, 0xF8, 0x1F, 0x81, 0xFC, 0x1F, 0xC0,
0xFC, 0x0F, 0xE0, 0xFE, 0x07, 0xE0, 0x7E, 0x07, 0xF0, 0x7F, 0x07, 0xF0,
0x7F, 0x07, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0,
0x3F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7E, 0x0F, 0xE0,
0xFE, 0x0F, 0xE0, 0xFC, 0x1F, 0xC1, 0xF8, 0x3F, 0x83, 0xF8, 0x7F, 0x07,
0xE0, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x0C, 0x78, 0xEF, 0xBC, 0xF7,
0xFF, 0xFF, 0xFF, 0xFC, 0x7F, 0xF8, 0x0F, 0xF8, 0x0F, 0xFE, 0x1F, 0xFF,
0xDF, 0xFF, 0xFF, 0xBD, 0xF3, 0x9E, 0x38, 0x0F, 0x00, 0x07, 0x80, 0x03,
0xC0, 0x00, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00, 0x1F, 0x80,
0x01, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x1F,
0x80, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x01,
0xF8, 0x00, 0x1F, 0x80, 0x1E, 0x3F, 0x9F, 0xEF, 0xF7, 0xFB, 0xFD, 0xFC,
0x7E, 0x1F, 0x1F, 0x0F, 0x87, 0x83, 0xC3, 0xE1, 0xE0, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x1E, 0x3F, 0x9F, 0xFF, 0xFF, 0xFB,
0xFD, 0xFC, 0x7C, 0x00, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00,
0xFC, 0x00, 0x0F, 0xC0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00,
0x1F, 0x80, 0x03, 0xF0, 0x00, 0x3F, 0x00, 0x03, 0xF0, 0x00, 0x7E, 0x00,
0x07, 0xE0, 0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x00, 0xFC, 0x00, 0x0F, 0xC0,
0x01, 0xF8, 0x00, 0x1F, 0x80, 0x03, 0xF8, 0x00, 0x3F, 0x00, 0x03, 0xF0,
0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x00, 0xFC,
0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00, 0x3F,
0x00, 0x03, 0xF0, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0x7E, 0x00, 0x07,
0xE0, 0x00, 0xFC, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x08, 0x00, 0x00, 0xFF,
0xE0, 0x00, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xC0, 0xFF,
0xFF, 0xF0, 0xFF, 0x8F, 0xF8, 0xFF, 0x01, 0xFE, 0x7F, 0x00, 0x7F, 0x3F,
0x80, 0x3F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x07, 0xFF, 0xE0, 0x03, 0xFF,
0xF0, 0x01, 0xFF, 0xF8, 0x00, 0xFF, 0xFC, 0x00, 0x7F, 0xFE, 0x00, 0x3F,
0xFF, 0x00, 0x1F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x07, 0xFF, 0xE0, 0x03,
0xFF, 0xF0, 0x01, 0xFD, 0xFC, 0x01, 0xFE, 0xFE, 0x00, 0xFE, 0x7F, 0x80,
0xFF, 0x1F, 0xFB, 0xFF, 0x07, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0x80, 0xFF,
0xFF, 0x80, 0x1F, 0xFF, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x38, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x81, 0xFC, 0x0F, 0xE0, 0x7F,
0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F, 0x81, 0xFC, 0x0F, 0xE0,
0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F, 0x81, 0xFC, 0x0F,
0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F, 0x81, 0xFC,
0x00, 0x18, 0x00, 0x03, 0xFF, 0xC0, 0x0F, 0xFF, 0xF0, 0x3F, 0xFF, 0xF8,
0x7F, 0xFF, 0xFC, 0xFF, 0xFF, 0xFC, 0x7F, 0x87, 0xFE, 0x3E, 0x01, 0xFE,
0x0C, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE,
0x00, 0x01, 0xFE, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xFC, 0x00, 0x07, 0xF8,
0x00, 0x0F, 0xF0, 0x00, 0x1F, 0xE0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0x80,
0x00, 0xFF, 0x00, 0x01, 0xFE, 0x00, 0x03, 0xFC, 0x00, 0x07, 0xF8, 0x00,
0x0F, 0xF0, 0x00, 0x3F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF,
0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFE,
0x7F, 0xFF, 0xFE, 0x7F, 0xFF, 0xFE, 0x7F, 0xFF, 0xFE, 0x7F, 0xFF, 0xFC,
0x00, 0x03, 0xFC, 0x00, 0x07, 0xF8, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xE0,
0x00, 0x1F, 0xC0, 0x00, 0x3F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0xFF, 0xC0,
0x00, 0xFF, 0xF0, 0x00, 0xFF, 0xF8, 0x00, 0xFF, 0xFC, 0x00, 0xFF, 0xFE,
0x00, 0x03, 0xFE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F,
0x00, 0x00, 0x7F, 0x30, 0x00, 0xFF, 0x38, 0x00, 0xFE, 0x7F, 0x87, 0xFE,
0x7F, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xF0,
0x0F, 0xFF, 0xC0, 0x00, 0x18, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x7F,
0x80, 0x00, 0x07, 0xF0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x1F, 0xC0, 0x00,
0x03, 0xFC, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x07, 0xF0, 0x00, 0x00, 0xFF,
0x00, 0x00, 0x1F, 0xE0, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x3F, 0x80, 0x00,
0x07, 0xF8, 0x7E, 0x00, 0xFF, 0x07, 0xE0, 0x0F, 0xE0, 0x7E, 0x01, 0xFC,
0x07, 0xE0, 0x3F, 0xC0, 0x7E, 0x07, 0xF8, 0x07, 0xE0, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x07,
0xE0, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x7E, 0x00,
0x00, 0x07, 0xE0, 0x0F, 0xFF, 0xFE, 0x0F, 0xFF, 0xFE, 0x0F, 0xFF, 0xFE,
0x0F, 0xFF, 0xFE, 0x0F, 0xFF, 0xFE, 0x0F, 0xC0, 0x00, 0x0F, 0xC0, 0x00,
0x0F, 0xC0, 0x00, 0x1F, 0xC0, 0x00, 0x1F, 0xC0, 0x00, 0x1F, 0xC0, 0x00,
0x1F, 0xFF, 0x00, 0x1F, 0xFF, 0xE0, 0x1F, 0xFF, 0xF8, 0x1F, 0xFF, 0xFC,
0x1F, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x7F,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x10, 0x00, 0x7F,
0x3C, 0x00, 0xFF, 0x3F, 0xC7, 0xFF, 0x7F, 0xFF, 0xFE, 0x7F, 0xFF, 0xFC,
0x7F, 0xFF, 0xF8, 0x3F, 0xFF, 0xF0, 0x07, 0xFF, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x03, 0x80, 0x00, 0x3F, 0xFE, 0x00, 0x7F, 0xFF, 0x80, 0xFF, 0xFF,
0xC0, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xE0, 0xFF, 0xC0, 0x60, 0x7F, 0x80,
0x00, 0x7F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0xC0, 0x00, 0x1F, 0xC0,
0x00, 0x0F, 0xE1, 0xF8, 0x07, 0xF7, 0xFF, 0x83, 0xFF, 0xFF, 0xE1, 0xFF,
0xFF, 0xF8, 0xFF, 0xFF, 0xFE, 0x7F, 0xF1, 0xFF, 0xBF, 0xE0, 0x3F, 0xDF,
0xE0, 0x0F, 0xEF, 0xF0, 0x03, 0xF7, 0xF8, 0x01, 0xFF, 0xF8, 0x00, 0xFC,
0xFE, 0x00, 0xFE, 0x7F, 0x00, 0x7F, 0x1F, 0xE0, 0x7F, 0x8F, 0xFF, 0xFF,
0x83, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0x80, 0x07, 0xFF,
0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00,
0xFE, 0xFC, 0x01, 0xFE, 0xFC, 0x01, 0xFC, 0xFC, 0x01, 0xFC, 0x00, 0x03,
0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x0F,
0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x1F, 0xE0, 0x00, 0x1F, 0xE0, 0x00, 0x1F,
0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x3F, 0x80, 0x00, 0x7F, 0x80, 0x00, 0x7F,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFE, 0x00, 0x01, 0xFE,
0x00, 0x01, 0xFC, 0x00, 0x03, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x0E,
0x00, 0x00, 0x7F, 0xF8, 0x00, 0x7F, 0xFF, 0x80, 0x3F, 0xFF, 0xF0, 0x1F,
0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xC3, 0xFC, 0x07, 0xF0, 0xFE, 0x01, 0xFE,
0x3F, 0x80, 0x3F, 0x8F, 0xE0, 0x0F, 0xE3, 0xF8, 0x03, 0xF8, 0xFE, 0x01,
0xFC, 0x3F, 0xE0, 0xFF, 0x07, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xC0, 0x3F,
0xFF, 0xF0, 0x1F, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xC7, 0xFC, 0x07, 0xF9,
0xFC, 0x00, 0xFE, 0x7F, 0x00, 0x3F, 0xDF, 0xC0, 0x07, 0xFF, 0xF0, 0x01,
0xFD, 0xFC, 0x00, 0x7F, 0x7F, 0x00, 0x3F, 0xDF, 0xE0, 0x1F, 0xE3, 0xFF,
0xFF, 0xF8, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0x00,
0x1F, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x01, 0xFF, 0xC0,
0x03, 0xFF, 0xF8, 0x03, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0x83, 0xFF, 0xFF,
0xE1, 0xFC, 0x07, 0xF9, 0xFC, 0x01, 0xFC, 0xFE, 0x00, 0x7F, 0x7F, 0x00,
0x3F, 0xBF, 0x80, 0x1F, 0xDF, 0xC0, 0x0F, 0xEF, 0xE0, 0x0F, 0xFF, 0xF8,
0x0F, 0xFD, 0xFF, 0x9F, 0xFE, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x8F,
0xFF, 0xDF, 0xC1, 0xFF, 0xCF, 0xE0, 0x3F, 0x0F, 0xE0, 0x00, 0x07, 0xF0,
0x00, 0x03, 0xF8, 0x00, 0x03, 0xFC, 0x00, 0x03, 0xFC, 0x10, 0x03, 0xFE,
0x0E, 0x07, 0xFE, 0x0F, 0xFF, 0xFE, 0x07, 0xFF, 0xFE, 0x07, 0xFF, 0xFE,
0x03, 0xFF, 0xFE, 0x00, 0x7F, 0xF8, 0x00, 0x01, 0x80, 0x00, 0x1E, 0x3F,
0x9F, 0xFF, 0xFF, 0xFB, 0xFD, 0xFC, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3C, 0x7F, 0x3F, 0xFF, 0xFF, 0xF7, 0xFB, 0xF8, 0xF8,
0x1E, 0x3F, 0x9F, 0xFF, 0xFF, 0xFB, 0xFD, 0xFC, 0x7C, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x7F, 0x3F, 0xDF, 0xEF, 0xF7, 0xFB,
0xF8, 0xFC, 0x3E, 0x3E, 0x1F, 0x0F, 0x07, 0x87, 0xC3, 0xC0, 0x00, 0x00,
0x00, 0x00, 0x07, 0x00, 0x01, 0xF0, 0x00, 0xFF, 0x00, 0x7F, 0xF0, 0x1F,
0xFF, 0x0F, 0xFF, 0xC7, 0xFF, 0xE0, 0xFF, 0xF8, 0x0F, 0xFC, 0x00, 0xFE,
0x00, 0x0F, 0xE0, 0x00, 0xFF, 0xC0, 0x0F, 0xFF, 0x80, 0x3F, 0xFF, 0x00,
0xFF, 0xFC, 0x01, 0xFF, 0xF0, 0x03, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0x1F,
0x00, 0x00, 0x70, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x0E,
0x00, 0x00, 0xF8, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0xE0, 0x0F, 0xFF, 0x80,
0x3F, 0xFF, 0x00, 0xFF, 0xFC, 0x01, 0xFF, 0xF0, 0x03, 0xFF, 0x00, 0x07,
0xF0, 0x00, 0xFF, 0x00, 0x3F, 0xF0, 0x1F, 0xFF, 0x0F, 0xFF, 0xC7, 0xFF,
0xF0, 0xFF, 0xF8, 0x0F, 0xFC, 0x00, 0xFF, 0x00, 0x0F, 0x80, 0x00, 0xC0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x07, 0xFF, 0x80, 0x3F, 0xFF,
0xC1, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xDF, 0xE0, 0xFF,
0x9F, 0x00, 0xFF, 0x0C, 0x00, 0xFE, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8,
0x00, 0x0F, 0xE0, 0x00, 0x3F, 0xC0, 0x00, 0xFF, 0x00, 0x03, 0xFC, 0x00,
0x0F, 0xF0, 0x00, 0x1F, 0xC0, 0x00, 0x7F, 0x00, 0x00, 0xFC, 0x00, 0x03,
0xF8, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x3E, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFE, 0x00, 0x07, 0xFC,
0x00, 0x07, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x00, 0x00,
0x1C, 0x00, 0x00, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x07, 0xFF, 0xFF,
0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xFF, 0xFC, 0x00,
0x1F, 0xF0, 0x00, 0xFF, 0x00, 0x1F, 0xC0, 0x00, 0x1F, 0xC0, 0x1F, 0xC0,
0x00, 0x03, 0xF0, 0x1F, 0x80, 0x00, 0x00, 0xFC, 0x0F, 0x80, 0x00, 0x00,
0x3E, 0x0F, 0xC0, 0x7F, 0x9F, 0x8F, 0x8F, 0xC0, 0xFF, 0xEF, 0xC7, 0xC7,
0xC0, 0xFF, 0xFF, 0xE1, 0xF3, 0xE0, 0xFF, 0xFF, 0xF0, 0xFB, 0xE0, 0xFF,
0xFF, 0xF8, 0x3D, 0xF0, 0x7F, 0x03, 0xFC, 0x1E, 0xF8, 0x7F, 0x00, 0xFE,
0x0F, 0xFC, 0x3F, 0x00, 0x3F, 0x07, 0xFE, 0x1F, 0x80, 0x1F, 0x83, 0xFF,
0x0F, 0xC0, 0x0F, 0xC1, 0xFF, 0x87, 0xE0, 0x07, 0xE0, 0xFF, 0xC3, 0xF0,
0x03, 0xF0, 0x7F, 0xE1, 0xF8, 0x01, 0xF8, 0x3F, 0xF0, 0xFC, 0x00, 0xFC,
0x1E, 0xF8, 0x7F, 0x00, 0xFE, 0x0F, 0x7C, 0x1F, 0xC0, 0xFF, 0x8F, 0x9F,
0x0F, 0xFF, 0xFF, 0xEF, 0x8F, 0x83, 0xFF, 0xFF, 0xFF, 0xC7, 0xE0, 0xFF,
0xF9, 0xFF, 0xC1, 0xF0, 0x3F, 0xF8, 0xFF, 0xC0, 0xFC, 0x07, 0xF8, 0x1F,
0xC0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x03,
0xF8, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x06, 0x00, 0x00, 0x3F, 0xF8,
0x7F, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xFF, 0xE0,
0x00, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x00,
0x07, 0xF0, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x03, 0xFE, 0x00, 0x00,
0x03, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x00, 0xFF, 0xE0, 0x00,
0x00, 0xFF, 0xF8, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x7F, 0x7F, 0x00,
0x00, 0x3F, 0x1F, 0x80, 0x00, 0x3F, 0x8F, 0xE0, 0x00, 0x1F, 0x87, 0xF0,
0x00, 0x1F, 0xC1, 0xFC, 0x00, 0x0F, 0xE0, 0xFE, 0x00, 0x07, 0xE0, 0x3F,
0x00, 0x07, 0xF0, 0x1F, 0xC0, 0x03, 0xF0, 0x0F, 0xE0, 0x03, 0xF8, 0x03,
0xF8, 0x01, 0xFF, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF,
0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF,
0xFF, 0xF8, 0x3F, 0x80, 0x00, 0xFE, 0x1F, 0xC0, 0x00, 0x7F, 0x1F, 0xC0,
0x00, 0x1F, 0xCF, 0xE0, 0x00, 0x0F, 0xEF, 0xE0, 0x00, 0x07, 0xFF, 0xF0,
0x00, 0x01, 0xFC, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0x83, 0xFF, 0xFF,
0xF8, 0x7F, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xF9, 0xF8, 0x01, 0xFF, 0x3F,
0x00, 0x0F, 0xF7, 0xE0, 0x01, 0xFE, 0xFC, 0x00, 0x1F, 0xDF, 0x80, 0x03,
0xF3, 0xF0, 0x00, 0xFE, 0x7E, 0x00, 0x3F, 0xCF, 0xFF, 0xFF, 0xF1, 0xFF,
0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF,
0x9F, 0x80, 0x0F, 0xFB, 0xF0, 0x00, 0x7F, 0xFE, 0x00, 0x07, 0xFF, 0xC0,
0x00, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0xFF,
0xFC, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
0xFF, 0xCF, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x01, 0x80,
0x00, 0x03, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFC, 0x07,
0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x1F, 0xFC, 0x3F, 0xF3, 0xFE, 0x00,
0x7C, 0x7F, 0xC0, 0x01, 0x87, 0xF8, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x0F,
0xF0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0xFE, 0x00,
0x00, 0x0F, 0xE0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00,
0xFE, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x07, 0xF0,
0x00, 0x00, 0x7F, 0x80, 0x01, 0x03, 0xFC, 0x00, 0x3C, 0x3F, 0xF0, 0x07,
0xE1, 0xFF, 0xE7, 0xFF, 0x0F, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFE, 0x03,
0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xF0, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x08,
0x00, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xE0,
0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xFF, 0x8F,
0xE0, 0x07, 0xFE, 0x3F, 0x80, 0x07, 0xFC, 0xFE, 0x00, 0x0F, 0xFB, 0xF8,
0x00, 0x1F, 0xEF, 0xE0, 0x00, 0x3F, 0xBF, 0x80, 0x00, 0xFE, 0xFE, 0x00,
0x01, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0x80, 0x00,
0x7F, 0xFE, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x3F,
0xBF, 0x80, 0x00, 0xFE, 0xFE, 0x00, 0x07, 0xFB, 0xF8, 0x00, 0x3F, 0xCF,
0xE0, 0x01, 0xFF, 0x3F, 0x80, 0x1F, 0xF8, 0xFF, 0xFF, 0xFF, 0xE3, 0xFF,
0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0x80, 0xFF, 0xFF,
0xF8, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFB,
0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xDF, 0x80, 0x00, 0x3F,
0x00, 0x00, 0x7E, 0x00, 0x00, 0xFC, 0x00, 0x01, 0xF8, 0x00, 0x03, 0xF0,
0x00, 0x07, 0xE0, 0x00, 0x0F, 0xFF, 0xFF, 0x1F, 0xFF, 0xFE, 0x3F, 0xFF,
0xFC, 0x7F, 0xFF, 0xF8, 0xFF, 0xFF, 0xF1, 0xF8, 0x00, 0x03, 0xF0, 0x00,
0x07, 0xE0, 0x00, 0x0F, 0xC0, 0x00, 0x1F, 0x80, 0x00, 0x3F, 0x00, 0x00,
0x7E, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8,
0x00, 0x0F, 0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00,
0x0F, 0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xFF, 0xFF, 0xCF,
0xFF, 0xFF, 0x3F, 0xFF, 0xFC, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xCF, 0xFF,
0xFF, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x0F, 0xE0, 0x00,
0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x3F,
0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x01, 0xC0, 0x00,
0x01, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x7F,
0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFC, 0x7F, 0xF0, 0xFF, 0xC7, 0xFE, 0x00,
0xFC, 0x7F, 0xC0, 0x01, 0xC3, 0xFC, 0x00, 0x04, 0x1F, 0xC0, 0x00, 0x01,
0xFE, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x03, 0xF8,
0x00, 0x00, 0x1F, 0xC0, 0x00, 0x7E, 0xFE, 0x00, 0x03, 0xF7, 0xF0, 0x00,
0x1F, 0xBF, 0x80, 0x00, 0xFD, 0xFC, 0x00, 0x07, 0xEF, 0xF0, 0x00, 0x3F,
0x3F, 0x80, 0x01, 0xF9, 0xFE, 0x00, 0x0F, 0xC7, 0xF8, 0x00, 0x7E, 0x3F,
0xF0, 0x03, 0xF0, 0xFF, 0xFB, 0xFF, 0x83, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF,
0xFF, 0xE0, 0x3F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0xFF, 0xF8,
0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x0F, 0xFF, 0xC0, 0x01, 0xFF, 0xF8,
0x00, 0x3F, 0xFF, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0xFF, 0xFC, 0x00, 0x1F,
0xFF, 0x80, 0x03, 0xFF, 0xF0, 0x00, 0x7F, 0xFE, 0x00, 0x0F, 0xFF, 0xC0,
0x01, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0x00, 0x07, 0xFF,
0xE0, 0x00, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0x80, 0x03, 0xFF, 0xF0, 0x00,
0x7F, 0xFE, 0x00, 0x0F, 0xFF, 0xC0, 0x01, 0xFF, 0xF8, 0x00, 0x3F, 0xFF,
0x00, 0x07, 0xFF, 0xE0, 0x00, 0xFF, 0xFC, 0x00, 0x1F, 0xC0, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC0, 0x1F, 0xFF, 0xF8, 0xFF, 0xFF, 0xC7, 0xFF, 0xFE, 0x3F, 0xFF, 0xF1,
0xFF, 0xFF, 0x80, 0x01, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0x7F, 0x00, 0x03,
0xF8, 0x00, 0x1F, 0xC0, 0x00, 0xFE, 0x00, 0x07, 0xF0, 0x00, 0x3F, 0x80,
0x01, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0x7F, 0x00, 0x03, 0xF8, 0x00, 0x1F,
0xC0, 0x00, 0xFE, 0x00, 0x07, 0xF0, 0x00, 0x3F, 0x80, 0x01, 0xFC, 0x60,
0x0F, 0xE7, 0x80, 0xFF, 0x3F, 0x0F, 0xF3, 0xFF, 0xFF, 0x9F, 0xFF, 0xF8,
0x7F, 0xFF, 0x81, 0xFF, 0xF8, 0x03, 0xFF, 0x80, 0x00, 0x00, 0x00, 0xFC,
0x00, 0x1F, 0xEF, 0xC0, 0x03, 0xFC, 0xFC, 0x00, 0x7F, 0x8F, 0xC0, 0x0F,
0xF0, 0xFC, 0x01, 0xFE, 0x0F, 0xC0, 0x3F, 0xC0, 0xFC, 0x03, 0xF8, 0x0F,
0xC0, 0x7F, 0x80, 0xFC, 0x0F, 0xF0, 0x0F, 0xC1, 0xFE, 0x00, 0xFC, 0x3F,
0xC0, 0x0F, 0xC7, 0xF8, 0x00, 0xFC, 0xFF, 0x00, 0x0F, 0xDF, 0xE0, 0x00,
0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF,
0xFC, 0x00, 0xFF, 0xDF, 0xE0, 0x0F, 0xF8, 0xFF, 0x00, 0xFF, 0x0F, 0xF8,
0x0F, 0xE0, 0x7F, 0xC0, 0xFC, 0x03, 0xFC, 0x0F, 0xC0, 0x1F, 0xE0, 0xFC,
0x00, 0xFF, 0x0F, 0xC0, 0x0F, 0xF8, 0xFC, 0x00, 0x7F, 0xCF, 0xC0, 0x03,
0xFC, 0xFC, 0x00, 0x1F, 0xEF, 0xC0, 0x00, 0xFF, 0xFE, 0x00, 0x03, 0xF8,
0x00, 0x0F, 0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00,
0x0F, 0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x0F,
0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x0F, 0xE0,
0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x0F, 0xE0, 0x00,
0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x3F,
0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFC, 0x00, 0x00, 0x1F, 0xBF,
0x00, 0x00, 0x07, 0xEF, 0xE0, 0x00, 0x03, 0xFB, 0xFC, 0x00, 0x00, 0xFE,
0xFF, 0x00, 0x00, 0x7F, 0xBF, 0xE0, 0x00, 0x3F, 0xEF, 0xF8, 0x00, 0x0F,
0xFB, 0xFF, 0x00, 0x07, 0xFE, 0xFF, 0xE0, 0x01, 0xFF, 0xBF, 0xF8, 0x00,
0xFF, 0xEF, 0xFF, 0x00, 0x7F, 0xFB, 0xFF, 0xC0, 0x1F, 0xFE, 0xFF, 0xF8,
0x0F, 0xFF, 0xBF, 0x7F, 0x03, 0xF7, 0xEF, 0xDF, 0xC1, 0xF9, 0xFB, 0xF3,
0xF8, 0xFE, 0x7E, 0xFC, 0x7E, 0x3F, 0x1F, 0xBF, 0x1F, 0xDF, 0xC7, 0xEF,
0xC3, 0xFF, 0xE1, 0xFB, 0xF0, 0xFF, 0xF0, 0x7E, 0xFC, 0x1F, 0xFC, 0x1F,
0xBF, 0x03, 0xFE, 0x07, 0xEF, 0xC0, 0xFF, 0x81, 0xFB, 0xF0, 0x1F, 0xC0,
0x7E, 0xFC, 0x03, 0xE0, 0x1F, 0xBF, 0x00, 0xF8, 0x07, 0xEF, 0xC0, 0x1C,
0x01, 0xFB, 0xF0, 0x00, 0x00, 0x7E, 0xFC, 0x00, 0x00, 0x1F, 0xBF, 0x00,
0x00, 0x07, 0xE0, 0xFC, 0x00, 0x0F, 0xFF, 0xC0, 0x01, 0xFF, 0xF8, 0x00,
0x3F, 0xFF, 0x80, 0x07, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0x80, 0x1F, 0xFF,
0xF8, 0x03, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0x01,
0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0x07, 0xFF, 0xDF, 0xF0, 0xFF, 0xF9,
0xFE, 0x1F, 0xFF, 0x1F, 0xE3, 0xFF, 0xE1, 0xFE, 0x7F, 0xFC, 0x3F, 0xEF,
0xFF, 0x83, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xC0,
0x3F, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xE0, 0x07, 0xFF,
0xFC, 0x00, 0x7F, 0xFF, 0x80, 0x07, 0xFF, 0xF0, 0x00, 0x7F, 0xFE, 0x00,
0x0F, 0xFF, 0xC0, 0x00, 0xFF, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x01, 0x80,
0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x7F, 0xFF,
0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xC0, 0x7F, 0xF0,
0xFF, 0xE0, 0x7F, 0xC0, 0x0F, 0xF8, 0x7F, 0xC0, 0x03, 0xFE, 0x3F, 0xC0,
0x00, 0xFF, 0x1F, 0xC0, 0x00, 0x3F, 0xDF, 0xE0, 0x00, 0x0F, 0xEF, 0xE0,
0x00, 0x07, 0xF7, 0xF0, 0x00, 0x03, 0xFB, 0xF8, 0x00, 0x01, 0xFF, 0xFC,
0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x3F, 0xFF,
0x80, 0x00, 0x1F, 0xDF, 0xC0, 0x00, 0x0F, 0xEF, 0xF0, 0x00, 0x07, 0xF3,
0xF8, 0x00, 0x07, 0xF9, 0xFE, 0x00, 0x07, 0xF8, 0x7F, 0x80, 0x07, 0xFC,
0x3F, 0xF0, 0x07, 0xFC, 0x0F, 0xFF, 0x3F, 0xFC, 0x03, 0xFF, 0xFF, 0xFE,
0x00, 0xFF, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xFC,
0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x80,
0x3F, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF,
0xFF, 0x3F, 0xFF, 0xFF, 0xCF, 0xE0, 0x0F, 0xFB, 0xF8, 0x00, 0xFE, 0xFE,
0x00, 0x3F, 0xBF, 0x80, 0x0F, 0xFF, 0xE0, 0x01, 0xFF, 0xF8, 0x00, 0x7F,
0xFE, 0x00, 0x3F, 0xFF, 0x80, 0x0F, 0xEF, 0xE0, 0x07, 0xFB, 0xF8, 0x03,
0xFE, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xE3, 0xFF,
0xFF, 0xE0, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, 0x80, 0x0F, 0xE0, 0x00, 0x03,
0xF8, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xE0, 0x00,
0x03, 0xF8, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x00, 0x00,
0x01, 0x80, 0x00, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x0F, 0xFF, 0xF8, 0x00,
0x0F, 0xFF, 0xFF, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0xFE,
0x01, 0xFF, 0xC3, 0xFF, 0x80, 0xFF, 0x80, 0x1F, 0xF0, 0x7F, 0xC0, 0x03,
0xFE, 0x1F, 0xE0, 0x00, 0x7F, 0x87, 0xF0, 0x00, 0x0F, 0xF3, 0xFC, 0x00,
0x01, 0xFC, 0xFE, 0x00, 0x00, 0x7F, 0x3F, 0x80, 0x00, 0x1F, 0xCF, 0xE0,
0x00, 0x07, 0xFB, 0xF8, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0x3F, 0xBF,
0x80, 0x00, 0x1F, 0xEF, 0xE0, 0x00, 0x07, 0xF3, 0xF8, 0x00, 0x01, 0xFC,
0xFF, 0x00, 0x00, 0x7F, 0x1F, 0xC0, 0x00, 0x3F, 0xC7, 0xF8, 0x00, 0x1F,
0xE0, 0xFF, 0x00, 0x0F, 0xF8, 0x3F, 0xF0, 0x07, 0xFC, 0x07, 0xFF, 0x9F,
0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFF, 0x80, 0x03, 0xFF,
0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x00,
0x0F, 0xF8, 0x0C, 0x00, 0x01, 0xFF, 0x8F, 0x80, 0x00, 0x3F, 0xFF, 0xF0,
0x00, 0x07, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0x0F, 0xFF,
0x00, 0x00, 0x00, 0xFE, 0x00, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFC, 0x0F,
0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF,
0xCF, 0xE0, 0x0F, 0xFB, 0xF8, 0x00, 0xFE, 0xFE, 0x00, 0x3F, 0xBF, 0x80,
0x0F, 0xFF, 0xE0, 0x01, 0xFF, 0xF8, 0x00, 0x7F, 0xFE, 0x00, 0x3F, 0xFF,
0x80, 0x0F, 0xEF, 0xE0, 0x07, 0xFB, 0xF8, 0x03, 0xFE, 0xFF, 0xFF, 0xFF,
0x3F, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF,
0xF0, 0x3F, 0xFF, 0xFC, 0x0F, 0xE0, 0x3F, 0x83, 0xF8, 0x0F, 0xF0, 0xFE,
0x01, 0xFC, 0x3F, 0x80, 0x3F, 0x8F, 0xE0, 0x0F, 0xF3, 0xF8, 0x01, 0xFE,
0xFE, 0x00, 0x3F, 0xBF, 0x80, 0x0F, 0xF0, 0x00, 0x0E, 0x00, 0x00, 0xFF,
0xFC, 0x01, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xE1, 0xFF,
0xFF, 0xF1, 0xFF, 0x01, 0xF8, 0xFE, 0x00, 0x18, 0x7F, 0x00, 0x00, 0x3F,
0x80, 0x00, 0x1F, 0xC0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xFE, 0x00, 0x01,
0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xF0, 0x07, 0xFF, 0xFE,
0x00, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x00, 0x7F, 0xF0, 0x00, 0x07,
0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x60, 0x00, 0x7F, 0x3C, 0x00,
0x3F, 0xBF, 0xC0, 0x7F, 0xDF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xC7, 0xFF,
0xFF, 0xC0, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0x80, 0x00, 0x18, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xF8, 0x00, 0x00, 0xFE,
0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xF8, 0x00, 0x00,
0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xF8, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xF8,
0x00, 0x00, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x03,
0xF8, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xE0, 0x00,
0x03, 0xF8, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xE0,
0x00, 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, 0xF0, 0x00, 0xFE, 0x7F,
0x00, 0x0F, 0xE7, 0xF0, 0x00, 0xFE, 0x7F, 0x80, 0x1F, 0xE3, 0xFC, 0x03,
0xFC, 0x3F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0x00,
0x7F, 0xFF, 0xE0, 0x03, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F, 0x7F, 0x80, 0x00, 0x3F, 0x9F, 0xC0,
0x00, 0x3F, 0x8F, 0xF0, 0x00, 0x1F, 0xC3, 0xF8, 0x00, 0x0F, 0xE1, 0xFE,
0x00, 0x0F, 0xE0, 0xFF, 0x00, 0x07, 0xF0, 0x3F, 0x80, 0x07, 0xF0, 0x1F,
0xE0, 0x03, 0xF8, 0x07, 0xF0, 0x03, 0xF8, 0x03, 0xFC, 0x01, 0xFC, 0x00,
0xFE, 0x00, 0xFE, 0x00, 0x7F, 0x00, 0xFE, 0x00, 0x3F, 0xC0, 0x7F, 0x00,
0x0F, 0xE0, 0x7F, 0x00, 0x07, 0xF8, 0x3F, 0x80, 0x01, 0xFC, 0x3F, 0x80,
0x00, 0xFF, 0x1F, 0xC0, 0x00, 0x3F, 0x8F, 0xC0, 0x00, 0x1F, 0xCF, 0xE0,
0x00, 0x0F, 0xF7, 0xF0, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xF8,
0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x00, 0x0F, 0xFC,
0x00, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF,
0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0xFE, 0x00, 0x07, 0xF0, 0x00, 0x7F,
0xFF, 0x00, 0x07, 0xF0, 0x00, 0x7F, 0x7F, 0x00, 0x0F, 0xF0, 0x00, 0x7E,
0x7F, 0x00, 0x0F, 0xF8, 0x00, 0xFE, 0x7F, 0x80, 0x1F, 0xF8, 0x00, 0xFE,
0x3F, 0x80, 0x1F, 0xF8, 0x00, 0xFC, 0x3F, 0x80, 0x1F, 0xFC, 0x01, 0xFC,
0x3F, 0xC0, 0x3F, 0xFC, 0x01, 0xFC, 0x1F, 0xC0, 0x3F, 0xFC, 0x01, 0xF8,
0x1F, 0xC0, 0x3F, 0xFE, 0x03, 0xF8, 0x1F, 0xE0, 0x7F, 0xFE, 0x03, 0xF8,
0x0F, 0xE0, 0x7E, 0x7E, 0x03, 0xF0, 0x0F, 0xE0, 0x7E, 0x7F, 0x07, 0xF0,
0x0F, 0xF0, 0xFE, 0x7F, 0x07, 0xF0, 0x07, 0xF0, 0xFC, 0x3F, 0x07, 0xE0,
0x07, 0xF0, 0xFC, 0x3F, 0x8F, 0xE0, 0x07, 0xF1, 0xFC, 0x3F, 0x8F, 0xE0,
0x03, 0xF9, 0xF8, 0x1F, 0x8F, 0xC0, 0x03, 0xF9, 0xF8, 0x1F, 0xDF, 0xC0,
0x03, 0xFB, 0xF8, 0x1F, 0xDF, 0xC0, 0x01, 0xFF, 0xF0, 0x0F, 0xDF, 0x80,
0x01, 0xFF, 0xF0, 0x0F, 0xFF, 0x80, 0x01, 0xFF, 0xF0, 0x0F, 0xFF, 0x80,
0x00, 0xFF, 0xE0, 0x07, 0xFF, 0x00, 0x00, 0xFF, 0xE0, 0x07, 0xFF, 0x00,
0x00, 0xFF, 0xE0, 0x07, 0xFF, 0x00, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00,
0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00,
0x00, 0x3F, 0x80, 0x01, 0xFC, 0x00, 0x7F, 0x80, 0x03, 0xF8, 0x7F, 0x80,
0x0F, 0xF0, 0x7F, 0x00, 0x3F, 0xC0, 0xFF, 0x00, 0x7F, 0x00, 0xFF, 0x01,
0xFE, 0x00, 0xFF, 0x07, 0xF8, 0x01, 0xFE, 0x0F, 0xE0, 0x01, 0xFE, 0x3F,
0x80, 0x01, 0xFE, 0xFF, 0x00, 0x01, 0xFD, 0xFC, 0x00, 0x03, 0xFF, 0xF0,
0x00, 0x03, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x07, 0xFE, 0x00,
0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x3F, 0xF8, 0x00,
0x00, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xF0, 0x00,
0x1F, 0xEF, 0xF0, 0x00, 0x7F, 0x8F, 0xE0, 0x00, 0xFE, 0x1F, 0xE0, 0x03,
0xFC, 0x1F, 0xE0, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x3F, 0xC0, 0x7F,
0x80, 0x3F, 0xC1, 0xFE, 0x00, 0x3F, 0xC7, 0xF8, 0x00, 0x7F, 0xDF, 0xE0,
0x00, 0x7F, 0x80, 0x7F, 0x00, 0x01, 0xFC, 0xFF, 0x00, 0x03, 0xF8, 0xFE,
0x00, 0x0F, 0xE0, 0xFE, 0x00, 0x1F, 0xC1, 0xFE, 0x00, 0x7F, 0x01, 0xFC,
0x01, 0xFC, 0x03, 0xFC, 0x03, 0xF8, 0x03, 0xF8, 0x0F, 0xE0, 0x03, 0xF8,
0x1F, 0xC0, 0x07, 0xF8, 0x7F, 0x00, 0x07, 0xF1, 0xFC, 0x00, 0x0F, 0xF3,
0xF8, 0x00, 0x0F, 0xEF, 0xE0, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x1F, 0xFF,
0x00, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0x3F, 0xE0,
0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xFE, 0x00,
0x00, 0x01, 0xFC, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x07, 0xF0, 0x00,
0x00, 0x0F, 0xE0, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x3F, 0x80, 0x00,
0x00, 0x7F, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x01, 0xFC, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF,
0xFE, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xF0, 0x00,
0x07, 0xF8, 0x00, 0x03, 0xFC, 0x00, 0x01, 0xFE, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x7F, 0x80, 0x00, 0x3F, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xF8,
0x00, 0x03, 0xFC, 0x00, 0x01, 0xFE, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x7F,
0xC0, 0x00, 0x1F, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xF8, 0x00, 0x03,
0xFC, 0x00, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0x07,
0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0,
0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC,
0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F,
0x83, 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x07,
0xE0, 0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00, 0x3F, 0x00, 0x03, 0xF0, 0x00,
0x3F, 0x00, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x00, 0xFC, 0x00, 0x0F, 0xC0,
0x00, 0xFC, 0x00, 0x07, 0xE0, 0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00, 0x3F,
0x00, 0x03, 0xF0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x01,
0xF8, 0x00, 0x0F, 0xC0, 0x00, 0xFC, 0x00, 0x0F, 0xC0, 0x00, 0x7E, 0x00,
0x07, 0xE0, 0x00, 0x3E, 0x00, 0x03, 0xF0, 0x00, 0x3F, 0x00, 0x01, 0xF8,
0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0xFC, 0x00, 0x0F,
0xC0, 0x00, 0x7E, 0x00, 0x07, 0xE0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00,
0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xC1, 0xF8, 0x3F,
0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07,
0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0,
0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC,
0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0xFC, 0x00, 0x07,
0xE0, 0x00, 0x7F, 0x80, 0x03, 0xFC, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80,
0x1F, 0x7C, 0x00, 0xF9, 0xF0, 0x07, 0xCF, 0x80, 0x7C, 0x3E, 0x03, 0xE1,
0xF0, 0x3E, 0x07, 0xC1, 0xF0, 0x3E, 0x1F, 0x01, 0xF0, 0xF8, 0x07, 0xCF,
0xC0, 0x3E, 0x7C, 0x00, 0xFB, 0xE0, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFC, 0x07, 0xF0,
0x0F, 0xC0, 0x3F, 0x00, 0xF8, 0x0F, 0xFF, 0x00, 0xFF, 0xFF, 0x07, 0xFF,
0xFE, 0x1F, 0xFF, 0xFC, 0x3F, 0xFF, 0xF8, 0xF0, 0x1F, 0xE1, 0x00, 0x3F,
0x80, 0x00, 0x7E, 0x00, 0x01, 0xFC, 0x03, 0xFF, 0xF1, 0xFF, 0xFF, 0xCF,
0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFC, 0x07, 0xFF, 0xE0, 0x1F, 0xFF, 0x00,
0x7F, 0xFC, 0x03, 0xFF, 0xF8, 0x0F, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
0x7F, 0xFF, 0xFC, 0xFF, 0xF7, 0xF0, 0xFF, 0x9F, 0xC0, 0xFE, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x0F, 0xE0, 0x00,
0x07, 0xF0, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00,
0x00, 0x7F, 0x3F, 0xF0, 0x3F, 0xBF, 0xFC, 0x1F, 0xFF, 0xFF, 0x8F, 0xFF,
0xFF, 0xE7, 0xFF, 0xFF, 0xF3, 0xFF, 0x07, 0xFD, 0xFF, 0x01, 0xFE, 0xFF,
0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x07, 0xFF,
0xE0, 0x03, 0xFF, 0xF0, 0x01, 0xFF, 0xF8, 0x00, 0xFF, 0xFC, 0x00, 0x7F,
0xFF, 0x00, 0x7F, 0xFF, 0xC0, 0x7F, 0xBF, 0xF8, 0x7F, 0xDF, 0xFF, 0xFF,
0xCF, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xC3, 0xFB, 0xFF, 0xC1, 0xFC, 0xFF,
0x80, 0x00, 0xFF, 0xE0, 0x03, 0xFF, 0xF0, 0x0F, 0xFF, 0xFC, 0x1F, 0xFF,
0xFC, 0x1F, 0xFF, 0xFE, 0x3F, 0xE1, 0xFE, 0x7F, 0x80, 0x7C, 0x7F, 0x00,
0x30, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00,
0x30, 0x7F, 0x80, 0x7C, 0x3F, 0xE1, 0xFF, 0x1F, 0xFF, 0xFE, 0x1F, 0xFF,
0xFC, 0x07, 0xFF, 0xFC, 0x03, 0xFF, 0xF0, 0x00, 0xFF, 0xC0, 0x00, 0x00,
0x1F, 0xC0, 0x00, 0x07, 0xF0, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x1F, 0xC0, 0x00, 0x07, 0xF0, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x7F,
0x00, 0x00, 0x1F, 0xC0, 0x7F, 0xE7, 0xF0, 0x7F, 0xFD, 0xFC, 0x3F, 0xFF,
0xFF, 0x1F, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xF3, 0xFE, 0x1F, 0xFD, 0xFE,
0x01, 0xFF, 0x7F, 0x00, 0x3F, 0xDF, 0xC0, 0x07, 0xF7, 0xE0, 0x01, 0xFF,
0xF8, 0x00, 0x7F, 0xFE, 0x00, 0x1F, 0xFF, 0x80, 0x07, 0xF7, 0xF0, 0x01,
0xFD, 0xFC, 0x00, 0xFF, 0x7F, 0x00, 0x3F, 0xDF, 0xE0, 0x1F, 0xF3, 0xFE,
0x1F, 0xFC, 0xFF, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xC3, 0xFF, 0xFF, 0xF0,
0x3F, 0xFD, 0xFC, 0x07, 0xFC, 0x7F, 0x00, 0xFF, 0xC0, 0x01, 0xFF, 0xF8,
0x03, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xE1, 0xFE, 0x07,
0xF1, 0xFC, 0x01, 0xFC, 0xFE, 0x00, 0x7E, 0x7E, 0x00, 0x3F, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFB, 0xF0,
0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F, 0x80, 0x10, 0x1F,
0xF0, 0x3C, 0x07, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xC0,
0x1F, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0x00, 0x7F, 0x80, 0x7F, 0xF0, 0x3F,
0xF8, 0x1F, 0xFE, 0x07, 0xFF, 0x83, 0xFC, 0x00, 0xFE, 0x00, 0x3F, 0x80,
0x0F, 0xC0, 0x3F, 0xFF, 0xCF, 0xFF, 0xF3, 0xFF, 0xFC, 0xFF, 0xFF, 0x3F,
0xFF, 0xCF, 0xFF, 0xF0, 0x3F, 0x80, 0x0F, 0xE0, 0x03, 0xF8, 0x00, 0xFE,
0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x80,
0x0F, 0xE0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x03,
0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x01, 0xFF, 0x8F, 0xC1, 0xFF, 0xF3,
0xF0, 0xFF, 0xFE, 0xFC, 0x7F, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xCF, 0xF8,
0x3F, 0xF7, 0xF8, 0x03, 0xFD, 0xFC, 0x00, 0xFF, 0x7F, 0x00, 0x1F, 0xFF,
0x80, 0x07, 0xFF, 0xE0, 0x01, 0xFF, 0xF8, 0x00, 0x7F, 0xFE, 0x00, 0x1F,
0xDF, 0xC0, 0x07, 0xF7, 0xF8, 0x03, 0xFD, 0xFF, 0x01, 0xFF, 0x3F, 0xFF,
0xFF, 0xC7, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0x03,
0xFF, 0x9F, 0xC0, 0x1F, 0x87, 0xF0, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x7E,
0x08, 0x00, 0x3F, 0x87, 0xC0, 0x1F, 0xE1, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF,
0xFC, 0x3F, 0xFF, 0xFE, 0x07, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0x00, 0x00,
0xFC, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE,
0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE,
0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x7F, 0xE0, 0xFE, 0xFF, 0xF0, 0xFF,
0xFF, 0xF8, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xE7, 0xFE, 0xFF,
0x80, 0xFE, 0xFF, 0x00, 0xFF, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE,
0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE,
0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE,
0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE,
0x00, 0x7F, 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x18, 0x00, 0x00,
0x00, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0x00, 0x78, 0x01, 0xF8, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0,
0x3F, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x1F,
0xC0, 0x3F, 0x80, 0x7F, 0x00, 0xFE, 0x01, 0xFC, 0x03, 0xF8, 0x07, 0xF0,
0x0F, 0xE0, 0x1F, 0xC0, 0x3F, 0x80, 0x7F, 0x00, 0xFE, 0x01, 0xFC, 0x03,
0xF8, 0x07, 0xF0, 0x0F, 0xE0, 0x1F, 0xC0, 0x3F, 0x80, 0x7F, 0x00, 0xFE,
0x01, 0xFC, 0x03, 0xF8, 0x07, 0xF0, 0x0F, 0xE0, 0x1F, 0xCF, 0xFF, 0x9F,
0xFE, 0x3F, 0xF8, 0xFF, 0xF1, 0xFF, 0x80, 0x38, 0x00, 0xFE, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x0F, 0xE0, 0x00,
0x07, 0xF0, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00,
0x00, 0x7F, 0x00, 0x7F, 0xBF, 0x80, 0x7F, 0x9F, 0xC0, 0x7F, 0x8F, 0xE0,
0x7F, 0x87, 0xF0, 0x7F, 0x83, 0xF8, 0x7F, 0x81, 0xFC, 0x7F, 0x80, 0xFE,
0x7F, 0x80, 0x7F, 0xFF, 0x80, 0x3F, 0xFF, 0x80, 0x1F, 0xFF, 0xE0, 0x0F,
0xFF, 0xF0, 0x07, 0xFF, 0xFC, 0x03, 0xFF, 0xFF, 0x01, 0xFF, 0x7F, 0xC0,
0xFF, 0x1F, 0xF0, 0x7F, 0x07, 0xF8, 0x3F, 0x81, 0xFE, 0x1F, 0xC0, 0x7F,
0x8F, 0xE0, 0x1F, 0xE7, 0xF0, 0x0F, 0xF3, 0xF8, 0x03, 0xFD, 0xFC, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x7F, 0xC0, 0x7F, 0xC1, 0xFD, 0xFF,
0xE3, 0xFF, 0xE3, 0xFF, 0xFF, 0xEF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xFF,
0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFF, 0xE0,
0x7F, 0xE0, 0x7F, 0xFF, 0x80, 0x7F, 0x80, 0x7F, 0xFE, 0x00, 0xFE, 0x00,
0xFF, 0xFC, 0x01, 0xFC, 0x01, 0xFF, 0xF8, 0x03, 0xF8, 0x03, 0xFF, 0xF0,
0x07, 0xF0, 0x07, 0xFF, 0xE0, 0x0F, 0xE0, 0x0F, 0xFF, 0xC0, 0x1F, 0xC0,
0x1F, 0xFF, 0x80, 0x3F, 0x80, 0x3F, 0xFF, 0x00, 0x7F, 0x00, 0x7F, 0xFE,
0x00, 0xFE, 0x00, 0xFF, 0xFC, 0x01, 0xFC, 0x01, 0xFF, 0xF8, 0x03, 0xF8,
0x03, 0xFF, 0xF0, 0x07, 0xF0, 0x07, 0xFF, 0xE0, 0x0F, 0xE0, 0x0F, 0xFF,
0xC0, 0x1F, 0xC0, 0x1F, 0xFF, 0x80, 0x3F, 0x80, 0x3F, 0x80, 0xFE, 0x7F,
0xE0, 0xFE, 0xFF, 0xF0, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF,
0xFE, 0xFF, 0xE7, 0xFE, 0xFF, 0x80, 0xFE, 0xFF, 0x00, 0xFF, 0xFE, 0x00,
0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00,
0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00,
0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00,
0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0x00, 0xFF, 0xC0, 0x00, 0xFF,
0xFC, 0x00, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0x0F,
0xF8, 0x7F, 0xC7, 0xF8, 0x07, 0xF9, 0xFC, 0x00, 0xFE, 0x7F, 0x00, 0x3F,
0xBF, 0x80, 0x07, 0xFF, 0xE0, 0x01, 0xFF, 0xF8, 0x00, 0x7F, 0xFE, 0x00,
0x1F, 0xDF, 0x80, 0x07, 0xF7, 0xF0, 0x03, 0xF9, 0xFC, 0x00, 0xFE, 0x7F,
0x80, 0x7F, 0x8F, 0xF8, 0x7F, 0xC1, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xF8,
0x07, 0xFF, 0xFC, 0x00, 0xFF, 0xFC, 0x00, 0x0F, 0xFC, 0x00, 0xFE, 0x7F,
0xE0, 0x7F, 0x7F, 0xF8, 0x3F, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0xCF, 0xFF,
0xFF, 0xE7, 0xFE, 0x0F, 0xFB, 0xFE, 0x03, 0xFD, 0xFE, 0x00, 0xFF, 0xFE,
0x00, 0x3F, 0xFF, 0x00, 0x1F, 0xFF, 0x80, 0x0F, 0xFF, 0xC0, 0x07, 0xFF,
0xE0, 0x03, 0xFF, 0xF0, 0x01, 0xFF, 0xF8, 0x00, 0xFF, 0xFE, 0x00, 0xFF,
0xFF, 0x80, 0xFF, 0x7F, 0xF0, 0xFF, 0xBF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF,
0xCF, 0xFF, 0xFF, 0xC7, 0xF7, 0xFF, 0x83, 0xF9, 0xFF, 0x01, 0xFC, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0xC0,
0x00, 0x0F, 0xE0, 0x00, 0x07, 0xF0, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x01,
0xFF, 0x9F, 0xC1, 0xFF, 0xF7, 0xF0, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xFF,
0x3F, 0xFF, 0xFF, 0xCF, 0xF8, 0x7F, 0xF7, 0xF8, 0x07, 0xFD, 0xFC, 0x00,
0xFF, 0x7F, 0x00, 0x3F, 0xFF, 0x80, 0x07, 0xFF, 0xE0, 0x01, 0xFF, 0xF8,
0x00, 0x7F, 0xFE, 0x00, 0x1F, 0xFF, 0x80, 0x07, 0xF7, 0xF0, 0x03, 0xFD,
0xFC, 0x00, 0xFF, 0x7F, 0x80, 0x7F, 0xCF, 0xF8, 0x7F, 0xF3, 0xFF, 0xFF,
0xFC, 0x7F, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xC1, 0xFF, 0xF7, 0xF0, 0x1F,
0xF1, 0xFC, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x07, 0xF0,
0x00, 0x01, 0xFC, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x07,
0xF0, 0x00, 0x01, 0xFC, 0xFE, 0x3F, 0xFB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0xC0, 0xFF, 0x03, 0xF8, 0x0F, 0xE0, 0x3F,
0x80, 0xFE, 0x03, 0xF8, 0x0F, 0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, 0x0F,
0xE0, 0x3F, 0x80, 0xFE, 0x03, 0xF8, 0x0F, 0xE0, 0x00, 0x07, 0xFF, 0xC0,
0xFF, 0xFF, 0x8F, 0xFF, 0xFC, 0xFF, 0xFF, 0xC7, 0xFF, 0xFE, 0x3F, 0x00,
0x63, 0xF8, 0x00, 0x1F, 0xC0, 0x00, 0x7F, 0x80, 0x03, 0xFF, 0xE0, 0x1F,
0xFF, 0xE0, 0x7F, 0xFF, 0xC0, 0xFF, 0xFF, 0x00, 0xFF, 0xF8, 0x00, 0x3F,
0xE0, 0x00, 0x7F, 0x20, 0x03, 0xFB, 0xC0, 0x1F, 0xDF, 0xFF, 0xFD, 0xFF,
0xFF, 0xEF, 0xFF, 0xFE, 0x3F, 0xFF, 0xE0, 0x3F, 0xFC, 0x00, 0x0F, 0xE0,
0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x3F, 0xFF, 0xCF,
0xFF, 0xF3, 0xFF, 0xFC, 0xFF, 0xFF, 0x3F, 0xFF, 0xC0, 0xFE, 0x00, 0x3F,
0x80, 0x0F, 0xE0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x0F, 0xE0,
0x03, 0xF8, 0x00, 0xFE, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x03, 0xF8, 0x00,
0xFF, 0x00, 0x3F, 0xFE, 0x07, 0xFF, 0x81, 0xFF, 0xE0, 0x3F, 0xFC, 0x03,
0xFE, 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, 0x1F, 0xFF, 0x80, 0x3F, 0xFF, 0x00, 0x7F, 0xFF,
0x01, 0xFE, 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF3, 0xFF,
0xFF, 0xE3, 0xFF, 0xEF, 0xC1, 0xFF, 0x1F, 0x80, 0xFE, 0x00, 0x1F, 0xFF,
0x80, 0x07, 0xE7, 0xF0, 0x03, 0xF9, 0xFC, 0x00, 0xFE, 0x3F, 0x00, 0x3F,
0x0F, 0xE0, 0x1F, 0xC3, 0xF8, 0x07, 0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0,
0xFC, 0x03, 0xF0, 0x3F, 0x00, 0xFE, 0x1F, 0xC0, 0x1F, 0x87, 0xE0, 0x07,
0xF3, 0xF8, 0x01, 0xFC, 0xFC, 0x00, 0x3F, 0xFF, 0x00, 0x0F, 0xFF, 0x80,
0x01, 0xFF, 0xE0, 0x00, 0x7F, 0xF8, 0x00, 0x1F, 0xFC, 0x00, 0x03, 0xFF,
0x00, 0x00, 0xFF, 0x80, 0x00, 0x1F, 0xE0, 0x00, 0x07, 0xF8, 0x00, 0xFE,
0x00, 0x7E, 0x00, 0x3F, 0x7E, 0x00, 0x7F, 0x00, 0x3F, 0x7E, 0x00, 0x7F,
0x00, 0x7E, 0x7F, 0x00, 0xFF, 0x00, 0x7E, 0x3F, 0x00, 0xFF, 0x80, 0x7E,
0x3F, 0x01, 0xFF, 0x80, 0xFC, 0x3F, 0x81, 0xFF, 0xC0, 0xFC, 0x1F, 0x81,
0xFF, 0xC0, 0xF8, 0x1F, 0x83, 0xFF, 0xC1, 0xF8, 0x0F, 0xC3, 0xF7, 0xE1,
0xF8, 0x0F, 0xC3, 0xF7, 0xE3, 0xF0, 0x0F, 0xC7, 0xE7, 0xE3, 0xF0, 0x07,
0xE7, 0xE3, 0xF3, 0xF0, 0x07, 0xE7, 0xC3, 0xF7, 0xE0, 0x07, 0xEF, 0xC3,
0xF7, 0xE0, 0x03, 0xFF, 0xC1, 0xFF, 0xE0, 0x03, 0xFF, 0x81, 0xFF, 0xC0,
0x03, 0xFF, 0x81, 0xFF, 0xC0, 0x01, 0xFF, 0x80, 0xFF, 0xC0, 0x01, 0xFF,
0x00, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0xFF, 0x80, 0x00, 0xFE, 0x00, 0x7F,
0x00, 0x00, 0xFE, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x9F, 0xC0, 0x3F,
0x8F, 0xF0, 0x3F, 0x83, 0xFC, 0x3F, 0x80, 0xFE, 0x3F, 0xC0, 0x3F, 0x9F,
0xC0, 0x1F, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x01, 0xFF, 0xE0, 0x00, 0x7F,
0xE0, 0x00, 0x3F, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF8, 0x00, 0x0F,
0xFE, 0x00, 0x07, 0xFF, 0x80, 0x07, 0xFF, 0xE0, 0x07, 0xF7, 0xF8, 0x07,
0xF9, 0xFC, 0x03, 0xF8, 0x7F, 0x03, 0xF8, 0x3F, 0xC3, 0xF8, 0x0F, 0xF3,
0xFC, 0x03, 0xF9, 0xFC, 0x01, 0xFE, 0xFE, 0x00, 0x1F, 0xFF, 0x80, 0x07,
0xE7, 0xF0, 0x03, 0xF9, 0xFC, 0x00, 0xFE, 0x3F, 0x80, 0x3F, 0x0F, 0xE0,
0x1F, 0xC3, 0xF8, 0x07, 0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFC, 0x03,
0xF8, 0x3F, 0x00, 0xFE, 0x1F, 0xC0, 0x1F, 0x87, 0xE0, 0x07, 0xF3, 0xF8,
0x01, 0xFC, 0xFC, 0x00, 0x3F, 0xBF, 0x00, 0x0F, 0xFF, 0x80, 0x01, 0xFF,
0xE0, 0x00, 0x7F, 0xF8, 0x00, 0x0F, 0xFC, 0x00, 0x03, 0xFF, 0x00, 0x00,
0x7F, 0x80, 0x00, 0x1F, 0xE0, 0x00, 0x07, 0xF0, 0x00, 0x00, 0xFC, 0x00,
0x00, 0x7F, 0x00, 0x08, 0x3F, 0x80, 0x07, 0xFF, 0xE0, 0x01, 0xFF, 0xF0,
0x00, 0xFF, 0xF8, 0x00, 0x3F, 0xFC, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x3C,
0x00, 0x00, 0x7F, 0xFF, 0xFB, 0xFF, 0xFF, 0xDF, 0xFF, 0xFE, 0xFF, 0xFF,
0xF7, 0xFF, 0xFF, 0x00, 0x07, 0xF0, 0x00, 0x7F, 0x80, 0x07, 0xF8, 0x00,
0x7F, 0x80, 0x07, 0xF8, 0x00, 0x3F, 0x80, 0x03, 0xF8, 0x00, 0x3F, 0xC0,
0x03, 0xFC, 0x00, 0x3F, 0xC0, 0x03, 0xFC, 0x00, 0x1F, 0xC0, 0x01, 0xFC,
0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xE0, 0x00, 0xFC, 0x0F, 0xF0, 0x7F, 0xC3, 0xFF, 0x0F, 0xFC,
0x3F, 0xC0, 0xFE, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0,
0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x1F, 0xC0, 0xFF, 0x0F, 0xFC,
0x3F, 0xE0, 0xFF, 0x03, 0xFE, 0x0F, 0xFC, 0x07, 0xF0, 0x0F, 0xC0, 0x3F,
0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x0F,
0xC0, 0x3F, 0x80, 0xFE, 0x03, 0xFF, 0x0F, 0xFC, 0x1F, 0xF0, 0x3F, 0xC0,
0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xFC, 0x0F, 0xF8,
0x3F, 0xE0, 0xFF, 0xC1, 0xFF, 0x01, 0xFC, 0x07, 0xF0, 0x0F, 0xC0, 0x3F,
0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x0F,
0xC0, 0x3F, 0xC0, 0xFF, 0xC1, 0xFF, 0x03, 0xFC, 0x3F, 0xF0, 0xFF, 0xC3,
0xF8, 0x0F, 0xC0, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00,
0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x7F, 0x03, 0xFC, 0x3F, 0xF0, 0xFF, 0xC3,
0xFE, 0x0F, 0xF0, 0x3F, 0x80, 0x1F, 0xC0, 0x7C, 0xFF, 0x81, 0xF7, 0xFF,
0x87, 0x9F, 0xFF, 0xFE, 0x7F, 0xFF, 0xFB, 0xE1, 0xFF, 0xCF, 0x81, 0xFE,
0x3C, 0x03, 0xF0 };
const GFXglyph Montserrat_Bold22pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 12, 0, 0 }, // 0x20 ' '
{ 1, 8, 30, 12, 2, -29 }, // 0x21 '!'
{ 31, 15, 12, 19, 2, -29 }, // 0x22 '"'
{ 54, 29, 30, 31, 1, -29 }, // 0x23 '#'
{ 163, 25, 40, 27, 1, -34 }, // 0x24 '$'
{ 288, 36, 30, 38, 1, -29 }, // 0x25 '%'
{ 423, 28, 31, 31, 2, -29 }, // 0x26 '&'
{ 532, 6, 12, 10, 2, -29 }, // 0x27 '''
{ 541, 12, 40, 15, 3, -31 }, // 0x28 '('
{ 601, 12, 40, 15, 0, -31 }, // 0x29 ')'
{ 661, 17, 17, 19, 1, -31 }, // 0x2A '*'
{ 698, 20, 20, 26, 3, -24 }, // 0x2B '+'
{ 748, 9, 15, 11, 1, -7 }, // 0x2C ','
{ 765, 12, 6, 17, 2, -14 }, // 0x2D '-'
{ 774, 9, 8, 11, 1, -7 }, // 0x2E '.'
{ 783, 20, 40, 17, -1, -35 }, // 0x2F '/'
{ 883, 25, 32, 29, 2, -30 }, // 0x30 '0'
{ 983, 13, 30, 17, 0, -29 }, // 0x31 '1'
{ 1032, 24, 31, 25, 0, -30 }, // 0x32 '2'
{ 1125, 24, 31, 25, 0, -29 }, // 0x33 '3'
{ 1218, 28, 30, 30, 1, -29 }, // 0x34 '4'
{ 1323, 24, 31, 26, 0, -29 }, // 0x35 '5'
{ 1416, 25, 32, 27, 2, -30 }, // 0x36 '6'
{ 1516, 24, 30, 27, 1, -29 }, // 0x37 '7'
{ 1606, 26, 32, 28, 1, -30 }, // 0x38 '8'
{ 1710, 25, 32, 27, 1, -30 }, // 0x39 '9'
{ 1810, 9, 23, 11, 1, -22 }, // 0x3A ':'
{ 1836, 9, 30, 11, 1, -22 }, // 0x3B ';'
{ 1870, 20, 22, 26, 3, -25 }, // 0x3C '<'
{ 1925, 20, 16, 26, 3, -22 }, // 0x3D '='
{ 1965, 20, 22, 26, 3, -25 }, // 0x3E '>'
{ 2020, 23, 31, 25, 0, -30 }, // 0x3F '?'
{ 2110, 41, 40, 45, 2, -30 }, // 0x40 '@'
{ 2315, 33, 30, 33, 0, -29 }, // 0x41 'A'
{ 2439, 27, 30, 33, 4, -29 }, // 0x42 'B'
{ 2541, 28, 32, 31, 2, -30 }, // 0x43 'C'
{ 2653, 30, 30, 36, 4, -29 }, // 0x44 'D'
{ 2766, 23, 30, 29, 4, -29 }, // 0x45 'E'
{ 2853, 22, 30, 27, 4, -29 }, // 0x46 'F'
{ 2936, 29, 32, 33, 2, -30 }, // 0x47 'G'
{ 3052, 27, 30, 35, 4, -29 }, // 0x48 'H'
{ 3154, 7, 30, 14, 4, -29 }, // 0x49 'I'
{ 3181, 21, 31, 23, -1, -29 }, // 0x4A 'J'
{ 3263, 28, 30, 32, 4, -29 }, // 0x4B 'K'
{ 3368, 22, 30, 26, 4, -29 }, // 0x4C 'L'
{ 3451, 34, 30, 41, 4, -29 }, // 0x4D 'M'
{ 3579, 27, 30, 35, 4, -29 }, // 0x4E 'N'
{ 3681, 33, 32, 36, 2, -30 }, // 0x4F 'O'
{ 3813, 26, 30, 31, 4, -29 }, // 0x50 'P'
{ 3911, 34, 38, 36, 2, -30 }, // 0x51 'Q'
{ 4073, 26, 30, 32, 4, -29 }, // 0x52 'R'
{ 4171, 25, 32, 27, 1, -30 }, // 0x53 'S'
{ 4271, 26, 30, 27, 0, -29 }, // 0x54 'T'
{ 4369, 28, 31, 34, 3, -29 }, // 0x55 'U'
{ 4478, 33, 30, 32, 0, -29 }, // 0x56 'V'
{ 4602, 48, 30, 50, 1, -29 }, // 0x57 'W'
{ 4782, 31, 30, 31, 0, -29 }, // 0x58 'X'
{ 4899, 31, 30, 29, -1, -29 }, // 0x59 'Y'
{ 5016, 26, 30, 29, 2, -29 }, // 0x5A 'Z'
{ 5114, 11, 40, 16, 4, -31 }, // 0x5B '['
{ 5169, 20, 40, 17, -2, -35 }, // 0x5C '\'
{ 5269, 11, 40, 16, 1, -31 }, // 0x5D ']'
{ 5324, 21, 18, 26, 2, -23 }, // 0x5E '^'
{ 5372, 22, 4, 22, 0, 1 }, // 0x5F '_'
{ 5383, 13, 6, 26, 4, -31 }, // 0x60 '`'
{ 5393, 22, 23, 27, 2, -22 }, // 0x61 'a'
{ 5457, 25, 32, 30, 3, -31 }, // 0x62 'b'
{ 5557, 24, 23, 25, 1, -22 }, // 0x63 'c'
{ 5626, 26, 32, 30, 1, -31 }, // 0x64 'd'
{ 5730, 25, 23, 27, 1, -22 }, // 0x65 'e'
{ 5802, 18, 32, 17, 0, -31 }, // 0x66 'f'
{ 5874, 26, 32, 30, 1, -22 }, // 0x67 'g'
{ 5978, 24, 32, 30, 3, -31 }, // 0x68 'h'
{ 6074, 8, 34, 13, 3, -33 }, // 0x69 'i'
{ 6108, 15, 43, 13, -4, -33 }, // 0x6A 'j'
{ 6189, 25, 32, 28, 3, -31 }, // 0x6B 'k'
{ 6289, 7, 32, 13, 3, -31 }, // 0x6C 'l'
{ 6317, 39, 23, 45, 3, -22 }, // 0x6D 'm'
{ 6430, 24, 23, 30, 3, -22 }, // 0x6E 'n'
{ 6499, 26, 23, 28, 1, -22 }, // 0x6F 'o'
{ 6574, 25, 31, 30, 3, -22 }, // 0x70 'p'
{ 6671, 26, 31, 30, 1, -22 }, // 0x71 'q'
{ 6772, 14, 23, 19, 3, -22 }, // 0x72 'r'
{ 6813, 21, 23, 23, 1, -22 }, // 0x73 's'
{ 6874, 18, 28, 19, 0, -27 }, // 0x74 't'
{ 6937, 23, 23, 30, 3, -22 }, // 0x75 'u'
{ 7004, 26, 23, 26, 0, -22 }, // 0x76 'v'
{ 7079, 40, 23, 40, 0, -22 }, // 0x77 'w'
{ 7194, 25, 23, 26, 0, -22 }, // 0x78 'x'
{ 7266, 26, 32, 26, 0, -22 }, // 0x79 'y'
{ 7370, 21, 23, 23, 1, -22 }, // 0x7A 'z'
{ 7431, 14, 40, 17, 2, -31 }, // 0x7B '{'
{ 7501, 6, 40, 13, 4, -31 }, // 0x7C '|'
{ 7531, 14, 40, 17, 1, -31 }, // 0x7D '}'
{ 7601, 22, 8, 26, 2, -18 } }; // 0x7E '~'
const GFXfont Montserrat_Bold22pt7b PROGMEM = {
(uint8_t *)Montserrat_Bold22pt7bBitmaps,
(GFXglyph *)Montserrat_Bold22pt7bGlyphs,
0x20, 0x7E, 53 };
// Approx. 8295 bytes
#endif // MONTSERRATBOLD22PT7B_H
@@ -0,0 +1,873 @@
#ifndef MONTSERRATBOLD24PT7B_H
#define MONTSERRATBOLD24PT7B_H
const uint8_t Montserrat_Bold24pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD, 0xFE, 0xFF, 0x7F, 0xBF,
0xDF, 0xCF, 0xE7, 0xF3, 0xF9, 0xFC, 0xFE, 0x3F, 0x1F, 0x8F, 0xC7, 0xE3,
0xF1, 0xF8, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0xCF, 0xFF, 0xFF, 0xFD, 0xFE,
0xFF, 0x3F, 0x00, 0xFE, 0x3F, 0xFF, 0x1F, 0xFF, 0x0F, 0xDF, 0x87, 0xEF,
0xC3, 0xF7, 0xE1, 0xF9, 0xF0, 0x7C, 0xF8, 0x3E, 0x7C, 0x1F, 0x3E, 0x0F,
0x9F, 0x07, 0xCF, 0x83, 0xE7, 0xC1, 0xF0, 0x00, 0x7C, 0x07, 0xE0, 0x00,
0x7C, 0x07, 0xE0, 0x00, 0x7C, 0x07, 0xC0, 0x00, 0x7C, 0x07, 0xC0, 0x00,
0x7C, 0x07, 0xC0, 0x00, 0x7C, 0x07, 0xC0, 0x00, 0xFC, 0x07, 0xC0, 0x00,
0xFC, 0x0F, 0xC0, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F,
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0x00,
0xF8, 0x0F, 0x80, 0x01, 0xF8, 0x0F, 0x80, 0x01, 0xF8, 0x1F, 0x80, 0x01,
0xF0, 0x1F, 0x80, 0x01, 0xF0, 0x1F, 0x80, 0x01, 0xF0, 0x1F, 0x00, 0x01,
0xF0, 0x1F, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF,
0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFC, 0x03,
0xE0, 0x3F, 0x00, 0x03, 0xE0, 0x3E, 0x00, 0x03, 0xE0, 0x3E, 0x00, 0x03,
0xE0, 0x3E, 0x00, 0x03, 0xE0, 0x3E, 0x00, 0x07, 0xE0, 0x3E, 0x00, 0x07,
0xE0, 0x7E, 0x00, 0x07, 0xE0, 0x7E, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00,
0xF8, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x0F, 0x80,
0x00, 0x00, 0xF8, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xF8, 0x0F,
0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF, 0x83, 0xFF, 0xFF,
0xF8, 0x3F, 0xCF, 0x8F, 0x87, 0xF8, 0xF8, 0x30, 0x7F, 0x8F, 0x80, 0x07,
0xF8, 0xF8, 0x00, 0x7F, 0x8F, 0x80, 0x07, 0xFC, 0xF8, 0x00, 0x7F, 0xFF,
0x80, 0x03, 0xFF, 0xF8, 0x00, 0x3F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xC0,
0x0F, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xC0, 0x00,
0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xF9, 0xFF, 0x00, 0x0F, 0x8F,
0xF0, 0x00, 0xF8, 0xFF, 0x10, 0x0F, 0x8F, 0xF3, 0x80, 0xF8, 0xFE, 0x3F,
0x0F, 0x9F, 0xE7, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF,
0xF8, 0x7F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xF8, 0x00,
0x00, 0xF8, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x0F,
0x80, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x07, 0xF0, 0x00,
0x0F, 0x80, 0x3F, 0xF8, 0x00, 0x3F, 0x00, 0xFF, 0xF8, 0x00, 0xFC, 0x01,
0xFF, 0xF0, 0x01, 0xF0, 0x07, 0xC1, 0xF0, 0x07, 0xE0, 0x0F, 0x83, 0xE0,
0x1F, 0x80, 0x3E, 0x03, 0xC0, 0x3E, 0x00, 0x7C, 0x07, 0xC0, 0xFC, 0x00,
0xF8, 0x0F, 0x83, 0xF0, 0x01, 0xF0, 0x1F, 0x07, 0xC0, 0x03, 0xE0, 0x3C,
0x1F, 0x80, 0x03, 0xC0, 0x78, 0x7E, 0x00, 0x07, 0xC1, 0xF0, 0xF8, 0x00,
0x0F, 0xC7, 0xE3, 0xE0, 0x00, 0x0F, 0xFF, 0x8F, 0xC0, 0x00, 0x0F, 0xFE,
0x1F, 0x03, 0xC0, 0x0F, 0xF8, 0x7C, 0x3F, 0xE0, 0x07, 0xC1, 0xF8, 0xFF,
0xE0, 0x00, 0x07, 0xE3, 0xFF, 0xE0, 0x00, 0x0F, 0x87, 0xC7, 0xE0, 0x00,
0x3F, 0x1F, 0x07, 0xC0, 0x00, 0xFC, 0x3E, 0x07, 0xC0, 0x01, 0xF0, 0x78,
0x0F, 0x80, 0x07, 0xE0, 0xF0, 0x1F, 0x00, 0x1F, 0x81, 0xE0, 0x3E, 0x00,
0x3E, 0x03, 0xC0, 0x7C, 0x00, 0xFC, 0x07, 0xC0, 0xF8, 0x03, 0xF0, 0x0F,
0x81, 0xF0, 0x07, 0xC0, 0x1F, 0x87, 0xC0, 0x1F, 0x80, 0x1F, 0xFF, 0x80,
0x7E, 0x00, 0x1F, 0xFE, 0x00, 0xF8, 0x00, 0x3F, 0xF8, 0x03, 0xF0, 0x00,
0x1F, 0xE0, 0x00, 0x7F, 0xE0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x0F, 0xFF,
0xE0, 0x00, 0x3F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0xE0, 0x01, 0xFC, 0x1F,
0xC0, 0x03, 0xF0, 0x1F, 0x80, 0x07, 0xE0, 0x3F, 0x00, 0x0F, 0xC0, 0x7E,
0x00, 0x1F, 0xC1, 0xFC, 0x00, 0x3F, 0x87, 0xF0, 0x00, 0x7F, 0xBF, 0xE0,
0x00, 0x7F, 0xFF, 0x80, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xF8, 0x00,
0x01, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xC0, 0xC0, 0x3F, 0xFF, 0xC1, 0xF0,
0xFF, 0xFF, 0xC3, 0xF3, 0xFC, 0x7F, 0xC7, 0xE7, 0xF0, 0x7F, 0xDF, 0xDF,
0xC0, 0x7F, 0xFF, 0x3F, 0x80, 0x7F, 0xFE, 0x7F, 0x00, 0x7F, 0xF8, 0xFE,
0x00, 0x7F, 0xF1, 0xFC, 0x00, 0x7F, 0xE3, 0xFC, 0x00, 0xFF, 0xE7, 0xFE,
0x0F, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xC7, 0xFF,
0xFF, 0x3F, 0x07, 0xFF, 0xFC, 0x3C, 0x03, 0xFF, 0xE0, 0x30, 0x00, 0x30,
0x00, 0x00, 0xFF, 0xFF, 0xF7, 0xEF, 0xDF, 0x9F, 0x3E, 0x7C, 0xF9, 0xF3,
0xE7, 0xC0, 0x03, 0xF8, 0x3F, 0xC1, 0xFC, 0x1F, 0xE0, 0xFE, 0x0F, 0xF0,
0x7F, 0x03, 0xF8, 0x3F, 0xC1, 0xFC, 0x0F, 0xE0, 0x7F, 0x07, 0xF8, 0x3F,
0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC1, 0xFE, 0x0F, 0xF0,
0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07,
0xF0, 0x3F, 0x81, 0xFC, 0x0F, 0xF0, 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F,
0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x81, 0xFC, 0x0F, 0xE0, 0x3F, 0x81, 0xFC,
0x07, 0xF0, 0x7F, 0x03, 0xF8, 0x0F, 0xE0, 0x7F, 0x01, 0xFC, 0x0F, 0xE0,
0x7F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x03,
0xFC, 0x0F, 0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F,
0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0,
0x3F, 0x81, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF0, 0x3F, 0x81, 0xFC, 0x1F,
0xE0, 0xFE, 0x07, 0xF0, 0x7F, 0x03, 0xF8, 0x3F, 0xC1, 0xFC, 0x1F, 0xC0,
0xFE, 0x00, 0x01, 0xE0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x30, 0xF0, 0xC7,
0x9E, 0x3D, 0xFB, 0xDF, 0xBF, 0xFF, 0xFB, 0xFF, 0xFC, 0x1F, 0xFE, 0x00,
0xFF, 0x80, 0x7F, 0xFC, 0x3F, 0xFF, 0xEF, 0xFF, 0xFF, 0xFB, 0xDF, 0x9C,
0x78, 0xE1, 0x0F, 0x04, 0x01, 0xE0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x00,
0x00, 0xFC, 0x00, 0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x00, 0x00,
0xFC, 0x00, 0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x00, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x03,
0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x1C, 0x3F,
0x3F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0x1F, 0x0F, 0x8F, 0xC7,
0xC3, 0xE1, 0xE1, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF0, 0x18, 0x3F, 0x3F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFE,
0x7E, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0xC0, 0x00,
0x7E, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x3F, 0x00, 0x01, 0xFC,
0x00, 0x07, 0xF0, 0x00, 0x1F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00,
0x0F, 0xC0, 0x00, 0x7F, 0x00, 0x01, 0xFC, 0x00, 0x07, 0xE0, 0x00, 0x3F,
0x80, 0x00, 0xFE, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0xC0, 0x00, 0x7E, 0x00,
0x01, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x07,
0xF0, 0x00, 0x1F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x0F, 0xC0,
0x00, 0x7F, 0x00, 0x01, 0xFC, 0x00, 0x07, 0xE0, 0x00, 0x3F, 0x80, 0x00,
0xFE, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0xC0, 0x00, 0x7F, 0x00, 0x01, 0xF8,
0x00, 0x0F, 0xE0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x07, 0xF0, 0x00,
0x1F, 0x80, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x1F, 0xFF,
0x80, 0x07, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0x01,
0xFF, 0xFF, 0xF8, 0x3F, 0xF0, 0xFF, 0xC3, 0xFC, 0x03, 0xFC, 0x7F, 0x80,
0x1F, 0xE7, 0xF8, 0x01, 0xFE, 0xFF, 0x00, 0x0F, 0xEF, 0xF0, 0x00, 0xFF,
0xFF, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xF0,
0x00, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x0F,
0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF,
0x00, 0x0F, 0xE7, 0xF8, 0x01, 0xFE, 0x7F, 0x80, 0x1F, 0xE3, 0xFC, 0x03,
0xFC, 0x3F, 0xE0, 0x7F, 0xC1, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0x80,
0xFF, 0xFF, 0xF0, 0x07, 0xFF, 0xFE, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0xFF,
0xE0, 0x00, 0x00, 0x60, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFC,
0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01,
0xFE, 0x03, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F,
0x80, 0xFF, 0x01, 0xFE, 0x03, 0xFC, 0x07, 0xF8, 0x0F, 0xF0, 0x1F, 0xE0,
0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x01, 0xFE, 0x01, 0xFF, 0xE0, 0x01, 0xFF,
0xFE, 0x01, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0x3F,
0xFF, 0xFF, 0xE7, 0xF8, 0x1F, 0xF8, 0x78, 0x01, 0xFE, 0x0C, 0x00, 0x7F,
0x80, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFE, 0x00, 0x00,
0x7F, 0x80, 0x00, 0x1F, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xFC, 0x00,
0x03, 0xFE, 0x00, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x7F, 0xC0,
0x00, 0x3F, 0xE0, 0x00, 0x3F, 0xF0, 0x00, 0x1F, 0xF8, 0x00, 0x0F, 0xFC,
0x00, 0x07, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x01, 0xFF, 0x80, 0x00, 0xFF,
0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFC,
0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xFF, 0x8F, 0xFF,
0xFF, 0xE3, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0x8F,
0xFF, 0xFF, 0xC0, 0x00, 0x1F, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x03, 0xFC,
0x00, 0x01, 0xFE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x3F,
0xC0, 0x00, 0x1F, 0xE0, 0x00, 0x07, 0xFF, 0x80, 0x01, 0xFF, 0xF0, 0x00,
0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0xFF, 0xF8, 0x00, 0x03, 0xFF,
0x00, 0x00, 0x3F, 0xC0, 0x00, 0x0F, 0xF0, 0x00, 0x03, 0xFC, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x3F, 0xCE, 0x00, 0x1F, 0xF3, 0xF0, 0x0F, 0xF9, 0xFF,
0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0xE0,
0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F,
0xC0, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x07, 0xF8,
0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x03, 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x1F, 0xE0, 0x00,
0x00, 0x7F, 0x80, 0x00, 0x01, 0xFE, 0x0F, 0xF0, 0x07, 0xFC, 0x1F, 0xE0,
0x0F, 0xF0, 0x3F, 0xC0, 0x3F, 0xC0, 0x7F, 0x80, 0xFF, 0x80, 0xFF, 0x01,
0xFE, 0x01, 0xFE, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFC, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00,
0x03, 0xFC, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00,
0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x07, 0xFF, 0xFF, 0x81, 0xFF, 0xFF,
0xF0, 0x3F, 0xFF, 0xFE, 0x07, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xF8, 0x1F,
0xFF, 0xFF, 0x03, 0xF8, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x0F, 0xE0, 0x00,
0x01, 0xFC, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x07, 0xF0, 0x00, 0x01, 0xFF,
0xE0, 0x00, 0x3F, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xF8,
0x1F, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFF, 0x00, 0x00,
0x3F, 0xE0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07, 0xF8,
0x00, 0x00, 0xFF, 0x10, 0x00, 0x1F, 0xE3, 0x80, 0x07, 0xF8, 0xFC, 0x01,
0xFF, 0x1F, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFE, 0x1F,
0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xF0, 0x00, 0x01, 0x80,
0x00, 0x00, 0x3F, 0xFE, 0x00, 0x1F, 0xFF, 0xF0, 0x0F, 0xFF, 0xFE, 0x03,
0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFE, 0x07, 0xFE, 0x01,
0x81, 0xFF, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x0F, 0xF0, 0x00, 0x01, 0xFE,
0x00, 0x00, 0x7F, 0x80, 0x00, 0x0F, 0xF0, 0x3C, 0x01, 0xFE, 0x7F, 0xF0,
0x3F, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF,
0xFF, 0xFB, 0xFF, 0xC1, 0xFF, 0x7F, 0xE0, 0x1F, 0xFF, 0xF8, 0x01, 0xFF,
0xFF, 0x00, 0x3F, 0xFF, 0xC0, 0x03, 0xFB, 0xF8, 0x00, 0x7F, 0x7F, 0x80,
0x1F, 0xEF, 0xF0, 0x03, 0xFC, 0xFF, 0x00, 0xFF, 0x1F, 0xF8, 0x7F, 0xE1,
0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF,
0xE0, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0x80, 0x0F, 0xF7, 0xF0, 0x03, 0xFE, 0xFE,
0x00, 0x7F, 0x9F, 0xC0, 0x1F, 0xF3, 0xF8, 0x03, 0xFC, 0x7F, 0x00, 0x7F,
0x80, 0x00, 0x1F, 0xE0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x1F, 0xE0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3F, 0xE0,
0x00, 0x07, 0xF8, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07,
0xF8, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x0F, 0xF8, 0x00,
0x01, 0xFE, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x0F, 0xF0, 0x00, 0x01, 0xFE,
0x00, 0x00, 0x7F, 0x80, 0x00, 0x0F, 0xF0, 0x00, 0x03, 0xFE, 0x00, 0x00,
0x01, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xF8, 0x0F, 0xFF,
0xFF, 0x83, 0xFF, 0xFF, 0xF8, 0xFF, 0xC1, 0xFF, 0x9F, 0xF0, 0x0F, 0xF3,
0xFC, 0x01, 0xFE, 0x7F, 0x00, 0x1F, 0xCF, 0xE0, 0x03, 0xF9, 0xFE, 0x00,
0xFF, 0x3F, 0xC0, 0x1F, 0xE3, 0xFC, 0x07, 0xF8, 0x7F, 0xFF, 0xFF, 0x07,
0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0x07, 0xFF, 0xFF,
0xF1, 0xFF, 0xFF, 0xFF, 0x3F, 0xC0, 0x1F, 0xEF, 0xF0, 0x01, 0xFF, 0xFE,
0x00, 0x3F, 0xFF, 0x80, 0x03, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0x00, 0x1F,
0xFF, 0xE0, 0x03, 0xFF, 0xFE, 0x00, 0xFF, 0xBF, 0xF0, 0x7F, 0xE7, 0xFF,
0xFF, 0xFC, 0x7F, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xF0,
0x01, 0xFF, 0xF0, 0x00, 0x00, 0xA0, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0xFF,
0xFE, 0x00, 0x3F, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xF0,
0xFF, 0xC3, 0xFF, 0x1F, 0xE0, 0x1F, 0xE7, 0xF8, 0x01, 0xFE, 0xFF, 0x00,
0x3F, 0xDF, 0xC0, 0x03, 0xFB, 0xF8, 0x00, 0x7F, 0xFF, 0x80, 0x1F, 0xFF,
0xF0, 0x03, 0xFF, 0xFF, 0x00, 0xFF, 0xDF, 0xF0, 0x3F, 0xFB, 0xFF, 0xFF,
0xFF, 0x3F, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0x81,
0xFF, 0xCF, 0xF0, 0x07, 0xC1, 0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F,
0xF0, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x1F, 0xF0, 0x20,
0x0F, 0xFC, 0x0F, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xE0, 0x7F, 0xFF, 0xF8,
0x0F, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0x80, 0x00, 0x0C,
0x00, 0x00, 0x18, 0x3F, 0x3F, 0xDF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFE, 0x7E,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x1F, 0x9F,
0xEF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x3F, 0x00, 0x18, 0x3F, 0x3F, 0xDF,
0xFF, 0xFF, 0xFF, 0xFD, 0xFE, 0x7E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0E, 0x1F, 0x9F, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x1F, 0x8F, 0x87, 0xC7, 0xE3, 0xE1, 0xF0, 0xF0, 0xF8, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xC0, 0x01, 0xFF, 0x00, 0x3F, 0xFC,
0x03, 0xFF, 0xF0, 0x7F, 0xFF, 0x87, 0xFF, 0xF0, 0xFF, 0xFE, 0x03, 0xFF,
0xC0, 0x0F, 0xFC, 0x00, 0x3F, 0x80, 0x00, 0xFF, 0x80, 0x03, 0xFF, 0xC0,
0x0F, 0xFF, 0xE0, 0x0F, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xF0,
0x03, 0xFF, 0xC0, 0x01, 0xFF, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xF0, 0x00,
0x00, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 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,
0xFC, 0x80, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0xE0, 0x00, 0x3F, 0xE0, 0x00,
0xFF, 0xF0, 0x03, 0xFF, 0xF0, 0x03, 0xFF, 0xF8, 0x03, 0xFF, 0xFC, 0x01,
0xFF, 0xFC, 0x00, 0xFF, 0xF0, 0x00, 0x7F, 0xC0, 0x00, 0x7F, 0x00, 0x07,
0xFC, 0x00, 0xFF, 0xF0, 0x1F, 0xFF, 0xC1, 0xFF, 0xFC, 0x3F, 0xFF, 0x83,
0xFF, 0xF8, 0x0F, 0xFF, 0x00, 0x3F, 0xE0, 0x00, 0xFE, 0x00, 0x03, 0xC0,
0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0xFF, 0xE0, 0x03, 0xFF, 0xFC, 0x07,
0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFD,
0xFE, 0x03, 0xFE, 0x3C, 0x00, 0xFF, 0x0C, 0x00, 0x7F, 0x80, 0x00, 0x1F,
0xC0, 0x00, 0x1F, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F,
0xF0, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xF8, 0x00, 0x0F, 0xF8, 0x00, 0x0F,
0xF0, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xF8, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0F, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xFC, 0x00,
0x03, 0xFE, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x1F, 0x80,
0x00, 0x00, 0x00, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xF8, 0x00,
0x00, 0x07, 0xFF, 0xFF, 0xF8, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x00,
0x1F, 0xFC, 0x01, 0xFF, 0xC0, 0x01, 0xFF, 0x00, 0x01, 0xFF, 0x00, 0x1F,
0xE0, 0x00, 0x03, 0xFC, 0x01, 0xFE, 0x00, 0x00, 0x07, 0xF0, 0x0F, 0xC0,
0x00, 0x00, 0x1F, 0x80, 0xFC, 0x00, 0x00, 0x00, 0x7E, 0x0F, 0xC0, 0x3F,
0xE3, 0xF1, 0xF0, 0x7E, 0x03, 0xFF, 0xDF, 0x87, 0xC7, 0xE0, 0x7F, 0xFF,
0xFC, 0x3E, 0x3F, 0x07, 0xFF, 0xFF, 0xE0, 0xF9, 0xF0, 0x3F, 0xFF, 0xFF,
0x07, 0xDF, 0x83, 0xFE, 0x0F, 0xF8, 0x3E, 0xFC, 0x1F, 0xC0, 0x3F, 0xC0,
0xFF, 0xC1, 0xFC, 0x00, 0xFE, 0x07, 0xFE, 0x0F, 0xE0, 0x03, 0xF0, 0x3F,
0xF0, 0x7F, 0x00, 0x1F, 0x81, 0xFF, 0x83, 0xF0, 0x00, 0xFC, 0x0F, 0xFC,
0x1F, 0x80, 0x07, 0xE0, 0x7F, 0xE0, 0xFC, 0x00, 0x3F, 0x03, 0xFF, 0x07,
0xF0, 0x01, 0xF8, 0x1F, 0xF8, 0x3F, 0x80, 0x1F, 0xC0, 0xF7, 0xE1, 0xFC,
0x00, 0xFE, 0x0F, 0xBF, 0x07, 0xF0, 0x0F, 0xF0, 0x7C, 0xF8, 0x3F, 0xE1,
0xFF, 0xC7, 0xE7, 0xE0, 0xFF, 0xFF, 0xFF, 0xFE, 0x3F, 0x07, 0xFF, 0xFF,
0xFF, 0xE0, 0xFC, 0x1F, 0xFF, 0xDF, 0xFF, 0x07, 0xE0, 0x3F, 0xFC, 0x7F,
0xF0, 0x1F, 0x80, 0xFF, 0x81, 0xFE, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x00,
0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00,
0x3F, 0xC0, 0x00, 0x10, 0x00, 0x00, 0xFF, 0xC0, 0x07, 0x80, 0x00, 0x03,
0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x0F,
0xFF, 0xFF, 0x80, 0x00, 0x00, 0x1F, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x03,
0xE0, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0xC0, 0x00,
0x00, 0x07, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x00, 0x0F, 0xFF,
0x00, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x01,
0xFF, 0xF8, 0x00, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0x03, 0xF9, 0xFC, 0x00,
0x00, 0x3F, 0x9F, 0xC0, 0x00, 0x07, 0xF0, 0xFE, 0x00, 0x00, 0x7F, 0x0F,
0xE0, 0x00, 0x0F, 0xE0, 0xFF, 0x00, 0x00, 0xFE, 0x07, 0xF0, 0x00, 0x1F,
0xE0, 0x7F, 0x80, 0x01, 0xFC, 0x03, 0xF8, 0x00, 0x3F, 0xC0, 0x3F, 0xC0,
0x03, 0xF8, 0x03, 0xFC, 0x00, 0x3F, 0x80, 0x1F, 0xC0, 0x07, 0xFF, 0xFF,
0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xFF, 0x00, 0xFF,
0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xFF, 0xF8,
0x3F, 0xC0, 0x00, 0x3F, 0xC3, 0xFC, 0x00, 0x03, 0xFC, 0x3F, 0x80, 0x00,
0x1F, 0xC7, 0xF8, 0x00, 0x01, 0xFE, 0x7F, 0x00, 0x00, 0x1F, 0xEF, 0xF0,
0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0xFF, 0xFF, 0xF8, 0x03,
0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0xF0, 0xFF,
0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0xFF, 0xCF, 0xE0, 0x01, 0xFF, 0x3F, 0x80,
0x03, 0xFC, 0xFE, 0x00, 0x07, 0xF3, 0xF8, 0x00, 0x1F, 0xCF, 0xE0, 0x00,
0x7F, 0x3F, 0x80, 0x03, 0xFC, 0xFE, 0x00, 0x1F, 0xF3, 0xF8, 0x03, 0xFF,
0x8F, 0xFF, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xC3,
0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFF, 0x3F, 0x80, 0x07, 0xFE, 0xFE,
0x00, 0x07, 0xFB, 0xF8, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0x80,
0x00, 0xFF, 0xFE, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xE0, 0x00,
0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFF,
0xCF, 0xFF, 0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFC, 0x00,
0x00, 0x1F, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xC0,
0x1F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0xC7,
0xFF, 0x81, 0xFF, 0x1F, 0xF8, 0x00, 0x7C, 0x3F, 0xE0, 0x00, 0x70, 0xFF,
0x80, 0x00, 0x41, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x0F, 0xF0,
0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x7F, 0x80,
0x00, 0x00, 0xFF, 0x00, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x03, 0xFC, 0x00,
0x00, 0x07, 0xF8, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x1F, 0xF0, 0x00,
0x00, 0x1F, 0xE0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x10, 0x3F, 0xE0, 0x00,
0x70, 0x7F, 0xE0, 0x01, 0xF0, 0x7F, 0xF0, 0x0F, 0xF0, 0x7F, 0xFF, 0xFF,
0xF0, 0x7F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xFC,
0x00, 0x3F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0x00, 0x00, 0x00, 0xA0, 0x00,
0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xFF, 0xE0,
0x1F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xFF,
0xC3, 0xFC, 0x03, 0xFF, 0xF1, 0xFE, 0x00, 0x1F, 0xF8, 0xFF, 0x00, 0x03,
0xFE, 0x7F, 0x80, 0x00, 0xFF, 0xBF, 0xC0, 0x00, 0x3F, 0xDF, 0xE0, 0x00,
0x1F, 0xEF, 0xF0, 0x00, 0x07, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xFC, 0x00,
0x01, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x80,
0x00, 0x3F, 0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xF0,
0x00, 0x07, 0xFF, 0xF8, 0x00, 0x07, 0xFB, 0xFC, 0x00, 0x03, 0xFD, 0xFE,
0x00, 0x03, 0xFE, 0xFF, 0x00, 0x03, 0xFE, 0x7F, 0x80, 0x07, 0xFF, 0x3F,
0xC0, 0x1F, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0x07,
0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFF, 0xFC, 0x00,
0xFF, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00, 0x00,
0x3F, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x0F, 0xE0, 0x00, 0x07, 0xFF, 0xFF,
0xF3, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF,
0xFF, 0x3F, 0xFF, 0xFF, 0x9F, 0xC0, 0x00, 0x0F, 0xE0, 0x00, 0x07, 0xF0,
0x00, 0x03, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F,
0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x01, 0xFE,
0x00, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x3F, 0xC0, 0x00, 0x1F,
0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xF8, 0x00, 0x03, 0xFC, 0x00, 0x01,
0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF,
0x9F, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xE7, 0xF8, 0x00, 0x03, 0xFC, 0x00,
0x01, 0xFE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x3F, 0xC0,
0x00, 0x1F, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xF8, 0x00, 0x03, 0xFC,
0x00, 0x01, 0xFE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xFF,
0x00, 0x00, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0xF8, 0x03, 0xFF, 0xFF,
0xFC, 0x07, 0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xFE, 0x1F, 0xFE, 0x03,
0xFC, 0x3F, 0xF0, 0x00, 0xF8, 0x3F, 0xE0, 0x00, 0x70, 0x7F, 0xC0, 0x00,
0x00, 0x7F, 0x80, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00,
0xFE, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0x80, 0x00,
0xFE, 0x7F, 0x80, 0x00, 0xFE, 0x7F, 0xC0, 0x00, 0xFE, 0x3F, 0xE0, 0x00,
0xFE, 0x3F, 0xF0, 0x00, 0xFE, 0x1F, 0xFC, 0x03, 0xFE, 0x0F, 0xFF, 0xFF,
0xFE, 0x07, 0xFF, 0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xFE, 0x01, 0xFF, 0xFF,
0xF8, 0x00, 0x7F, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x70,
0x00, 0xFF, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x3F,
0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x0F, 0xFF,
0xF0, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFC,
0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00,
0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x0F, 0xFF,
0xF0, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFC,
0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0x00,
0x03, 0xFF, 0xFC, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xC0, 0x00,
0xFF, 0xFF, 0x00, 0x03, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x0F, 0xFF, 0xFE, 0x1F, 0xFF, 0xFC, 0x3F, 0xFF, 0xF8, 0x7F,
0xFF, 0xF0, 0xFF, 0xFF, 0xE1, 0xFF, 0xFF, 0xC0, 0x00, 0x7F, 0x80, 0x00,
0xFF, 0x00, 0x01, 0xFE, 0x00, 0x03, 0xFC, 0x00, 0x07, 0xF8, 0x00, 0x0F,
0xF0, 0x00, 0x1F, 0xE0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0x80, 0x00, 0xFF,
0x00, 0x01, 0xFE, 0x00, 0x03, 0xFC, 0x00, 0x07, 0xF8, 0x00, 0x0F, 0xF0,
0x00, 0x1F, 0xE0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0x80, 0x00, 0xFF, 0x08,
0x01, 0xFE, 0x38, 0x07, 0xF8, 0xFC, 0x1F, 0xF3, 0xFF, 0xFF, 0xEF, 0xFF,
0xFF, 0x8F, 0xFF, 0xFF, 0x0F, 0xFF, 0xFC, 0x0F, 0xFF, 0xF0, 0x07, 0xFF,
0x80, 0x00, 0x70, 0x00, 0xFE, 0x00, 0x03, 0xFD, 0xFC, 0x00, 0x0F, 0xF3,
0xF8, 0x00, 0x3F, 0xC7, 0xF0, 0x00, 0xFF, 0x0F, 0xE0, 0x03, 0xFC, 0x1F,
0xC0, 0x0F, 0xF0, 0x3F, 0x80, 0x3F, 0xE0, 0x7F, 0x00, 0xFF, 0x80, 0xFE,
0x03, 0xFE, 0x01, 0xFC, 0x0F, 0xF8, 0x03, 0xF8, 0x3F, 0xE0, 0x07, 0xF0,
0xFF, 0x80, 0x0F, 0xE3, 0xFE, 0x00, 0x1F, 0xCF, 0xF8, 0x00, 0x3F, 0xBF,
0xE0, 0x00, 0x7F, 0xFF, 0xC0, 0x00, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF,
0xC0, 0x03, 0xFF, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF,
0x80, 0x1F, 0xFC, 0xFF, 0x80, 0x3F, 0xF0, 0xFF, 0x80, 0x7F, 0xC0, 0xFF,
0x80, 0xFF, 0x01, 0xFF, 0x81, 0xFC, 0x01, 0xFF, 0x03, 0xF8, 0x01, 0xFF,
0x07, 0xF0, 0x01, 0xFF, 0x0F, 0xE0, 0x01, 0xFF, 0x1F, 0xC0, 0x01, 0xFF,
0x3F, 0x80, 0x03, 0xFE, 0x7F, 0x00, 0x03, 0xFE, 0xFE, 0x00, 0x03, 0xFE,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x00, 0x1F,
0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x00, 0x0F, 0xFF, 0xF8, 0x00,
0x00, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF,
0xFC, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x03,
0xFF, 0xFF, 0xFC, 0x00, 0x3F, 0xFF, 0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0xFF,
0xC0, 0x1F, 0xFF, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFB, 0xF8, 0x0F, 0xEF,
0xFF, 0xDF, 0xC0, 0xFE, 0x7F, 0xFE, 0x7F, 0x07, 0xF3, 0xFF, 0xF3, 0xFC,
0x7F, 0x1F, 0xFF, 0x8F, 0xE3, 0xF8, 0xFF, 0xFC, 0x3F, 0xBF, 0x87, 0xFF,
0xE1, 0xFF, 0xF8, 0x3F, 0xFF, 0x07, 0xFF, 0xC1, 0xFF, 0xF8, 0x3F, 0xFC,
0x0F, 0xFF, 0xC0, 0xFF, 0xE0, 0x7F, 0xFE, 0x03, 0xFE, 0x03, 0xFF, 0xF0,
0x1F, 0xF0, 0x1F, 0xFF, 0x80, 0x7F, 0x00, 0xFF, 0xFC, 0x03, 0xF0, 0x07,
0xFF, 0xE0, 0x0F, 0x80, 0x3F, 0xFF, 0x00, 0x38, 0x01, 0xFF, 0xF8, 0x00,
0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x03, 0xF8,
0xFE, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x1F, 0xFF,
0xE0, 0x00, 0x7F, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE,
0x00, 0x1F, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xF8, 0x01, 0xFF, 0xFF, 0xF0,
0x07, 0xFF, 0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xFF, 0x01,
0xFF, 0xFB, 0xFE, 0x07, 0xFF, 0xE7, 0xFC, 0x1F, 0xFF, 0x9F, 0xF8, 0x7F,
0xFE, 0x3F, 0xF1, 0xFF, 0xF8, 0x7F, 0xC7, 0xFF, 0xE0, 0xFF, 0x9F, 0xFF,
0x81, 0xFF, 0x7F, 0xFE, 0x03, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xE0,
0x1F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xF8, 0x00,
0xFF, 0xFF, 0xE0, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0x0F,
0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0x80, 0x00, 0x7F,
0xFE, 0x00, 0x01, 0xFC, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x07, 0xFF, 0xFE,
0x00, 0x01, 0xFF, 0xFF, 0xF0, 0x00, 0x3F, 0xFF, 0xFF, 0xC0, 0x07, 0xFF,
0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x1F, 0xFE, 0x07, 0xFF, 0x83,
0xFF, 0x00, 0x1F, 0xF8, 0x3F, 0xE0, 0x00, 0x7F, 0xC7, 0xFC, 0x00, 0x03,
0xFC, 0x7F, 0x80, 0x00, 0x3F, 0xE7, 0xF8, 0x00, 0x01, 0xFE, 0xFF, 0x00,
0x00, 0x1F, 0xEF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF,
0xF0, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00,
0xFF, 0xFF, 0x00, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0x00,
0x00, 0x1F, 0xE7, 0xF8, 0x00, 0x01, 0xFE, 0x7F, 0x80, 0x00, 0x3F, 0xE7,
0xFC, 0x00, 0x03, 0xFC, 0x3F, 0xE0, 0x00, 0x7F, 0xC3, 0xFF, 0x00, 0x1F,
0xF8, 0x1F, 0xFC, 0x07, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xF0, 0x07, 0xFF,
0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xF8, 0x00,
0x07, 0xFF, 0xFE, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x07, 0x00,
0x00, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0x0F,
0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFE, 0xFF, 0x01,
0xFF, 0xEF, 0xF0, 0x01, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF,
0xFF, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0x00, 0x07, 0xFF, 0xF0,
0x00, 0x7F, 0xFF, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x1F,
0xFF, 0xF0, 0x1F, 0xFE, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFC, 0xFF,
0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFE,
0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F,
0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF,
0x00, 0x00, 0x03, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFF, 0xFC, 0x00, 0x07,
0xFF, 0xFF, 0xF8, 0x00, 0x7F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xFF,
0x80, 0x7F, 0xF8, 0x1F, 0xFE, 0x07, 0xFE, 0x00, 0x3F, 0xF0, 0x3F, 0xE0,
0x00, 0x7F, 0xC3, 0xFE, 0x00, 0x01, 0xFE, 0x1F, 0xE0, 0x00, 0x0F, 0xF8,
0xFF, 0x00, 0x00, 0x3F, 0xCF, 0xF0, 0x00, 0x01, 0xFE, 0x7F, 0x80, 0x00,
0x07, 0xFB, 0xFC, 0x00, 0x00, 0x3F, 0xDF, 0xE0, 0x00, 0x01, 0xFE, 0xFF,
0x00, 0x00, 0x0F, 0xF7, 0xF8, 0x00, 0x00, 0x7F, 0xBF, 0xC0, 0x00, 0x03,
0xFD, 0xFE, 0x00, 0x00, 0x1F, 0xEF, 0xF0, 0x00, 0x01, 0xFE, 0x3F, 0xC0,
0x00, 0x0F, 0xF1, 0xFE, 0x00, 0x00, 0xFF, 0x8F, 0xF8, 0x00, 0x07, 0xF8,
0x3F, 0xE0, 0x00, 0x7F, 0xC1, 0xFF, 0x80, 0x0F, 0xFC, 0x07, 0xFF, 0x01,
0xFF, 0xE0, 0x1F, 0xFF, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xFF, 0xE0, 0x01,
0xFF, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xFC,
0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00, 0x0F, 0xFC, 0x03, 0x00, 0x00,
0x3F, 0xF8, 0x7C, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00, 0x03, 0xFF, 0xFF,
0x80, 0x00, 0x07, 0xFF, 0xFC, 0x00, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0x00,
0x3F, 0xF8, 0x00, 0x00, 0x00, 0x08, 0x00, 0xFF, 0xFF, 0xC0, 0x07, 0xFF,
0xFF, 0xE0, 0x3F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF,
0xFC, 0x7F, 0xFF, 0xFF, 0xF3, 0xFC, 0x07, 0xFF, 0x9F, 0xE0, 0x03, 0xFE,
0xFF, 0x00, 0x0F, 0xF7, 0xF8, 0x00, 0x7F, 0xBF, 0xC0, 0x01, 0xFD, 0xFE,
0x00, 0x0F, 0xEF, 0xF0, 0x00, 0x7F, 0x7F, 0x80, 0x03, 0xFB, 0xFC, 0x00,
0x3F, 0xDF, 0xE0, 0x01, 0xFE, 0xFF, 0x00, 0x1F, 0xF7, 0xF8, 0x07, 0xFF,
0x3F, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xF8, 0x7F,
0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0x80, 0xFF, 0x01,
0xFE, 0x07, 0xF8, 0x07, 0xF8, 0x3F, 0xC0, 0x3F, 0xE1, 0xFE, 0x00, 0xFF,
0x0F, 0xF0, 0x03, 0xFC, 0x7F, 0x80, 0x1F, 0xF3, 0xFC, 0x00, 0x7F, 0x9F,
0xE0, 0x01, 0xFE, 0xFF, 0x00, 0x0F, 0xF8, 0x00, 0xFF, 0xFC, 0x00, 0x3F,
0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xFC, 0x1F, 0xFF, 0xFF,
0x83, 0xFF, 0xFF, 0xF8, 0x3F, 0xC0, 0x0F, 0x87, 0xF8, 0x00, 0x30, 0x7F,
0x80, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x07, 0xFC, 0x00,
0x00, 0x7F, 0xF0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xE0, 0x01,
0xFF, 0xFF, 0xC0, 0x0F, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0xF8, 0x00, 0xFF,
0xFF, 0xC0, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x01, 0xFF,
0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x10, 0x00, 0x0F, 0xF3, 0x80,
0x00, 0xFE, 0x3F, 0x00, 0x1F, 0xE7, 0xFF, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF,
0xCF, 0xFF, 0xFF, 0xF8, 0x7F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xE0, 0x03,
0xFF, 0xF8, 0x00, 0x00, 0x40, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x7F, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00,
0x1F, 0xC0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x3F,
0x80, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x03, 0xF8, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0xFE, 0x00, 0x00,
0x07, 0xF0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x0F,
0xE0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x1F, 0xC0,
0x00, 0x00, 0xFE, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x3F, 0x80, 0x00,
0x01, 0xFC, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x03,
0xF8, 0x00, 0x00, 0x1F, 0xC0, 0x00, 0xFE, 0x00, 0x03, 0xFF, 0xF0, 0x00,
0x1F, 0xFF, 0x80, 0x00, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x3F,
0xFF, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0x7F, 0xFE,
0x00, 0x03, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0xFF, 0xFC, 0x00,
0x07, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x0F,
0xFF, 0xC0, 0x00, 0x7F, 0xFE, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x1F, 0xFF,
0x80, 0x00, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0x80,
0x03, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0xFF, 0xFF, 0x80, 0x0F,
0xFB, 0xFE, 0x00, 0xFF, 0x9F, 0xF8, 0x0F, 0xFC, 0x7F, 0xFF, 0xFF, 0xC3,
0xFF, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, 0xFE, 0x00, 0x7F,
0xFF, 0xC0, 0x00, 0xFF, 0xF8, 0x00, 0x00, 0x50, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x0F, 0xEF, 0xF0, 0x00, 0x01, 0xFE, 0x7F, 0x80, 0x00, 0x1F, 0xE7,
0xF8, 0x00, 0x03, 0xFC, 0x7F, 0xC0, 0x00, 0x3F, 0xC3, 0xFC, 0x00, 0x03,
0xF8, 0x3F, 0xE0, 0x00, 0x7F, 0x81, 0xFE, 0x00, 0x07, 0xF0, 0x1F, 0xE0,
0x00, 0xFF, 0x00, 0xFF, 0x00, 0x0F, 0xE0, 0x0F, 0xF0, 0x01, 0xFE, 0x00,
0xFF, 0x80, 0x1F, 0xE0, 0x07, 0xF8, 0x01, 0xFC, 0x00, 0x7F, 0xC0, 0x3F,
0xC0, 0x03, 0xFC, 0x03, 0xF8, 0x00, 0x3F, 0xC0, 0x7F, 0x80, 0x01, 0xFE,
0x07, 0xF0, 0x00, 0x1F, 0xE0, 0xFF, 0x00, 0x00, 0xFF, 0x0F, 0xF0, 0x00,
0x0F, 0xF0, 0xFE, 0x00, 0x00, 0xFF, 0x1F, 0xE0, 0x00, 0x07, 0xF9, 0xFC,
0x00, 0x00, 0x7F, 0xBF, 0xC0, 0x00, 0x03, 0xFF, 0xF8, 0x00, 0x00, 0x3F,
0xFF, 0x80, 0x00, 0x01, 0xFF, 0xF8, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00,
0x01, 0xFF, 0xF0, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0xFF, 0xE0,
0x00, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x00, 0x03,
0xFC, 0x00, 0x00, 0xFF, 0x00, 0x01, 0xFC, 0x00, 0x07, 0xF7, 0xF8, 0x00,
0x0F, 0xF0, 0x00, 0x3F, 0x9F, 0xE0, 0x00, 0xFF, 0x80, 0x01, 0xFC, 0xFF,
0x00, 0x07, 0xFC, 0x00, 0x1F, 0xE7, 0xF8, 0x00, 0x3F, 0xF0, 0x00, 0xFE,
0x1F, 0xE0, 0x03, 0xFF, 0x80, 0x07, 0xF0, 0xFF, 0x00, 0x1F, 0xFC, 0x00,
0x7F, 0x87, 0xF8, 0x00, 0xFF, 0xF0, 0x03, 0xF8, 0x1F, 0xE0, 0x0F, 0xFF,
0x80, 0x1F, 0xC0, 0xFF, 0x00, 0x7F, 0xFC, 0x01, 0xFE, 0x07, 0xF8, 0x03,
0xFF, 0xF0, 0x0F, 0xE0, 0x1F, 0xE0, 0x3F, 0xBF, 0x80, 0x7F, 0x00, 0xFF,
0x01, 0xFD, 0xFC, 0x07, 0xF8, 0x07, 0xF8, 0x0F, 0xEF, 0xE0, 0x3F, 0x80,
0x1F, 0xE0, 0xFE, 0x3F, 0x81, 0xFC, 0x00, 0xFF, 0x07, 0xF1, 0xFC, 0x1F,
0xE0, 0x07, 0xF8, 0x3F, 0x8F, 0xE0, 0xFE, 0x00, 0x1F, 0xE3, 0xF8, 0x3F,
0x87, 0xF0, 0x00, 0xFF, 0x1F, 0xC1, 0xFC, 0x7F, 0x80, 0x07, 0xF8, 0xFE,
0x0F, 0xE3, 0xF8, 0x00, 0x1F, 0xCF, 0xE0, 0x3F, 0x9F, 0xC0, 0x00, 0xFF,
0x7F, 0x01, 0xFD, 0xFE, 0x00, 0x07, 0xFB, 0xF8, 0x0F, 0xEF, 0xE0, 0x00,
0x1F, 0xFF, 0x80, 0x3F, 0xFF, 0x00, 0x00, 0xFF, 0xFC, 0x01, 0xFF, 0xF8,
0x00, 0x07, 0xFF, 0xE0, 0x0F, 0xFF, 0x80, 0x00, 0x1F, 0xFE, 0x00, 0x3F,
0xFC, 0x00, 0x00, 0xFF, 0xF0, 0x01, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0x00,
0x0F, 0xFE, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0xFF,
0xC0, 0x01, 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x00, 0x0F, 0xF8, 0x00, 0x00,
0x1F, 0xE0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0xC0, 0x00, 0xFF, 0x1F, 0xE0,
0x00, 0xFF, 0x8F, 0xF8, 0x00, 0x7F, 0x83, 0xFE, 0x00, 0x7F, 0x80, 0xFF,
0x80, 0x7F, 0x80, 0x3F, 0xC0, 0x3F, 0xC0, 0x1F, 0xF0, 0x3F, 0xC0, 0x07,
0xFC, 0x3F, 0xC0, 0x01, 0xFE, 0x3F, 0xE0, 0x00, 0xFF, 0x9F, 0xE0, 0x00,
0x3F, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xF0, 0x00,
0x01, 0xFF, 0xF0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x1F, 0xF8, 0x00,
0x00, 0x0F, 0xFC, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x07, 0xFF, 0x80,
0x00, 0x07, 0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x07, 0xFF, 0xFC,
0x00, 0x03, 0xFD, 0xFF, 0x00, 0x03, 0xFC, 0x7F, 0xC0, 0x03, 0xFE, 0x1F,
0xE0, 0x01, 0xFE, 0x0F, 0xF8, 0x01, 0xFE, 0x03, 0xFE, 0x01, 0xFF, 0x00,
0xFF, 0x01, 0xFF, 0x00, 0x7F, 0xC0, 0xFF, 0x00, 0x1F, 0xF0, 0xFF, 0x80,
0x07, 0xFC, 0xFF, 0x80, 0x01, 0xFE, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x7F,
0x80, 0x00, 0x3F, 0xBF, 0xC0, 0x00, 0x3F, 0xCF, 0xF0, 0x00, 0x1F, 0xC7,
0xF8, 0x00, 0x1F, 0xC1, 0xFE, 0x00, 0x1F, 0xE0, 0x7F, 0x80, 0x0F, 0xE0,
0x3F, 0xC0, 0x0F, 0xF0, 0x0F, 0xF0, 0x07, 0xF0, 0x07, 0xF8, 0x07, 0xF0,
0x01, 0xFE, 0x07, 0xF8, 0x00, 0x7F, 0x83, 0xF8, 0x00, 0x3F, 0xC3, 0xFC,
0x00, 0x0F, 0xF1, 0xFC, 0x00, 0x07, 0xF9, 0xFC, 0x00, 0x01, 0xFF, 0xFE,
0x00, 0x00, 0x7F, 0xFE, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x0F, 0xFF,
0x00, 0x00, 0x07, 0xFF, 0x00, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x00, 0x7F,
0x80, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F,
0xF0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x01,
0xFE, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x00,
0x3F, 0xC0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00,
0x07, 0xF8, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xFF, 0xBF,
0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF,
0xFF, 0xF0, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0xFF,
0x80, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x07, 0xFC, 0x00,
0x00, 0x7F, 0xC0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x07,
0xFC, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x3F, 0xE0,
0x00, 0x03, 0xFE, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x03, 0xFE, 0x00, 0x00,
0x3F, 0xE0, 0x00, 0x01, 0xFF, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x01, 0xFF,
0x00, 0x00, 0x1F, 0xF0, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F, 0x81, 0xFC, 0x0F,
0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F, 0x81, 0xFC,
0x0F, 0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F, 0x81,
0xFC, 0x0F, 0xE0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0xFE, 0x07, 0xF0, 0x3F,
0x81, 0xFC, 0x0F, 0xE0, 0x7F, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xF0, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xE0, 0x00,
0x1F, 0xC0, 0x00, 0x7F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x0F,
0xE0, 0x00, 0x1F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0,
0x00, 0x0F, 0xE0, 0x00, 0x1F, 0x80, 0x00, 0x7E, 0x00, 0x01, 0xFC, 0x00,
0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x80, 0x00, 0x7E, 0x00, 0x01,
0xFC, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xC0, 0x00, 0x3F, 0x80, 0x00, 0xFE,
0x00, 0x01, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0x00,
0x00, 0xFE, 0x00, 0x01, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0x1F, 0xC0, 0x00,
0x3F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xE0, 0x00, 0x1F,
0x80, 0x00, 0x7F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x0F, 0xE0,
0x00, 0x1F, 0x80, 0x00, 0x7F, 0x00, 0x01, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07,
0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07,
0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07,
0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07,
0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0xFC, 0x00, 0x03, 0xFC, 0x00, 0x07, 0xF8, 0x00, 0x0F,
0xF8, 0x00, 0x3F, 0xF0, 0x00, 0x7F, 0xF0, 0x01, 0xFB, 0xE0, 0x03, 0xE7,
0xC0, 0x0F, 0xCF, 0xC0, 0x1F, 0x0F, 0x80, 0x7E, 0x1F, 0x80, 0xFC, 0x1F,
0x01, 0xF0, 0x3F, 0x07, 0xE0, 0x7E, 0x0F, 0x80, 0x7C, 0x3F, 0x00, 0xFC,
0x7E, 0x00, 0xF9, 0xF8, 0x01, 0xFB, 0xF0, 0x01, 0xF0, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x80, 0xFF,
0x00, 0xFE, 0x01, 0xFC, 0x03, 0xF8, 0x07, 0xF0, 0x00, 0x7C, 0x00, 0x07,
0xFF, 0xC0, 0x3F, 0xFF, 0xF0, 0x7F, 0xFF, 0xF8, 0x7F, 0xFF, 0xFC, 0x3F,
0xFF, 0xFC, 0x3F, 0x07, 0xFE, 0x18, 0x01, 0xFE, 0x00, 0x00, 0xFE, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x01, 0xFF, 0xFF, 0x1F, 0xFF, 0xFF, 0x3F,
0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0x00, 0xFF, 0xFE,
0x00, 0xFF, 0xFE, 0x00, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0x03, 0xFF, 0xFF,
0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x3F, 0xFF, 0x7F, 0x1F, 0xFE, 0x7F, 0x0F,
0xFC, 0x7F, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF,
0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x38,
0x00, 0xFF, 0x3F, 0xF8, 0x0F, 0xF7, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0x0F,
0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0xCF, 0xFF, 0x9F, 0xFC, 0xFF, 0xC0,
0x3F, 0xEF, 0xF8, 0x01, 0xFE, 0xFF, 0x80, 0x0F, 0xEF, 0xF0, 0x00, 0xFF,
0xFF, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xF0,
0x00, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x80, 0x1F,
0xEF, 0xF8, 0x01, 0xFE, 0xFF, 0xE0, 0x7F, 0xEF, 0xFF, 0xFF, 0xFC, 0xFF,
0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xF8, 0xFE, 0xFF, 0xFF, 0x0F, 0xE7, 0xFF,
0xC0, 0xFE, 0x1F, 0xF0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x3F, 0xFE, 0x00,
0x3F, 0xFF, 0xC0, 0x1F, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0x87, 0xFF, 0xFF,
0xE3, 0xFF, 0x8F, 0xFC, 0xFF, 0x80, 0xFE, 0x7F, 0xC0, 0x1E, 0x1F, 0xE0,
0x02, 0x07, 0xF0, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3F,
0xC0, 0x00, 0x07, 0xF0, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x7F, 0x80, 0x00,
0x1F, 0xE0, 0x02, 0x07, 0xFC, 0x01, 0xE0, 0xFF, 0x80, 0xFE, 0x1F, 0xFF,
0xFF, 0xC7, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xF8, 0x01,
0xFF, 0xFC, 0x00, 0x1F, 0xFC, 0x00, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x01,
0xFC, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x07, 0xF0, 0x00, 0x00, 0xFE, 0x00,
0x00, 0x1F, 0xC0, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x0F,
0xE0, 0x03, 0x81, 0xFC, 0x07, 0xFE, 0x3F, 0x83, 0xFF, 0xF7, 0xF0, 0xFF,
0xFF, 0xFE, 0x3F, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFB, 0xFF, 0x8F, 0xFF,
0x7F, 0xC0, 0x7F, 0xFF, 0xF0, 0x07, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0x00,
0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0x80, 0x03, 0xFF,
0xF0, 0x00, 0x7F, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x03, 0xFF, 0xFC, 0x00,
0x7F, 0xFF, 0xC0, 0x1F, 0xF7, 0xFC, 0x07, 0xFE, 0xFF, 0xFF, 0xFF, 0xCF,
0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFD,
0xFC, 0x07, 0xFE, 0x3F, 0x80, 0x00, 0x06, 0x00, 0x00, 0x1F, 0xFE, 0x00,
0x0F, 0xFF, 0xF0, 0x03, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF,
0xFF, 0x0F, 0xF8, 0x1F, 0xE1, 0xFE, 0x01, 0xFE, 0x7F, 0x80, 0x1F, 0xCF,
0xE0, 0x01, 0xFD, 0xFC, 0x00, 0x3F, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFB, 0xF8, 0x00, 0x00, 0x7F,
0x00, 0x00, 0x0F, 0xF0, 0x00, 0x01, 0xFF, 0x00, 0x10, 0x1F, 0xF0, 0x0F,
0x01, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0xE0, 0x3F,
0xFF, 0xF8, 0x01, 0xFF, 0xFE, 0x00, 0x0F, 0xFE, 0x00, 0x00, 0x3F, 0xE0,
0x0F, 0xFF, 0x01, 0xFF, 0xE0, 0x3F, 0xFE, 0x07, 0xFF, 0xC0, 0x7F, 0xFC,
0x07, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0xFF, 0xFF,
0xCF, 0xFF, 0xFC, 0xFF, 0xFF, 0xCF, 0xFF, 0xFC, 0xFF, 0xFF, 0xCF, 0xFF,
0xFC, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F,
0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00,
0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00,
0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0,
0x00, 0x00, 0x0E, 0x00, 0x00, 0x1F, 0xFE, 0x3F, 0x03, 0xFF, 0xF3, 0xF0,
0xFF, 0xFF, 0xBF, 0x1F, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x3F, 0xF8,
0xFF, 0xF7, 0xFE, 0x01, 0xFF, 0x7F, 0x80, 0x0F, 0xF7, 0xF8, 0x00, 0xFF,
0x7F, 0x00, 0x07, 0xF7, 0xF0, 0x00, 0x7F, 0xFF, 0x00, 0x07, 0xF7, 0xF0,
0x00, 0x7F, 0x7F, 0x00, 0x07, 0xF7, 0xF8, 0x00, 0x7F, 0x7F, 0x80, 0x0F,
0xF7, 0xFC, 0x01, 0xFF, 0x3F, 0xF8, 0x7F, 0xF1, 0xFF, 0xFF, 0xFF, 0x1F,
0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0x03, 0xFF, 0xF7, 0xF0, 0x1F, 0xFE,
0x7F, 0x00, 0x1F, 0x07, 0xF0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x0F, 0xF0,
0xC0, 0x00, 0xFF, 0x0F, 0x00, 0x1F, 0xE1, 0xFF, 0x1F, 0xFE, 0x1F, 0xFF,
0xFF, 0xC3, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xE0,
0x01, 0xFF, 0xF8, 0x00, 0x00, 0x60, 0x00, 0xFF, 0x00, 0x00, 0x3F, 0xC0,
0x00, 0x0F, 0xF0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3F,
0xC0, 0x00, 0x0F, 0xF0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x3F, 0xC0, 0xE0, 0x0F, 0xF3, 0xFF, 0x83, 0xFD, 0xFF, 0xF8, 0xFF, 0xFF,
0xFF, 0x3F, 0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xFB, 0xFF, 0xFF, 0xFE, 0xFF,
0xE0, 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xF8, 0x03, 0xFF, 0xFC, 0x00, 0x7F,
0xFF, 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0xFF, 0xF0, 0x01, 0xFF, 0xFC, 0x00,
0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0xFF, 0xF0, 0x01, 0xFF, 0xFC,
0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0xFF, 0xF0, 0x01, 0xFF,
0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0xFF, 0xF0, 0x01,
0xFC, 0x3C, 0x7F, 0xBF, 0xDF, 0xFF, 0xFF, 0xFB, 0xFC, 0xFC, 0x00, 0x00,
0x00, 0x00, 0x0F, 0xF7, 0xFB, 0xFD, 0xFE, 0xFF, 0x7F, 0xBF, 0xDF, 0xEF,
0xF7, 0xFB, 0xFD, 0xFE, 0xFF, 0x7F, 0xBF, 0xDF, 0xEF, 0xF7, 0xFB, 0xFD,
0xFE, 0xFF, 0x7F, 0xBF, 0xDF, 0xEF, 0xF0, 0x00, 0x78, 0x01, 0xFE, 0x01,
0xFE, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFE, 0x01, 0xFE, 0x00, 0xFC, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x00, 0xFE, 0x00,
0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00,
0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00,
0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00,
0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00, 0xFE, 0x00,
0xFE, 0x01, 0xFE, 0x63, 0xFE, 0x7F, 0xFC, 0x7F, 0xFC, 0xFF, 0xF8, 0xFF,
0xF0, 0xFF, 0xC0, 0x04, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00,
0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0,
0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x3F, 0xEF, 0xF0, 0x07, 0xF8, 0xFF,
0x01, 0xFF, 0x0F, 0xF0, 0x3F, 0xE0, 0xFF, 0x07, 0xFC, 0x0F, 0xF0, 0xFF,
0xC0, 0xFF, 0x1F, 0xF8, 0x0F, 0xF3, 0xFF, 0x00, 0xFF, 0x7F, 0xE0, 0x0F,
0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0x80, 0x0F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF,
0xC0, 0x0F, 0xFF, 0xFE, 0x00, 0xFF, 0xFF, 0xF0, 0x0F, 0xFE, 0xFF, 0x80,
0xFF, 0xCF, 0xF8, 0x0F, 0xF8, 0x7F, 0xC0, 0xFF, 0x03, 0xFE, 0x0F, 0xF0,
0x1F, 0xF0, 0xFF, 0x00, 0xFF, 0x8F, 0xF0, 0x0F, 0xF8, 0xFF, 0x00, 0x7F,
0xCF, 0xF0, 0x03, 0xFE, 0xFF, 0x00, 0x1F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0x00, 0x00, 0xC0,
0x1F, 0xC7, 0xFE, 0x03, 0xFF, 0x83, 0xF9, 0xFF, 0xF0, 0xFF, 0xFC, 0x7F,
0x7F, 0xFF, 0x3F, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFE, 0x07, 0xFF,
0x81, 0xFF, 0xFF, 0x80, 0x7F, 0xE0, 0x1F, 0xFF, 0xE0, 0x07, 0xF8, 0x03,
0xFF, 0xFC, 0x00, 0xFF, 0x00, 0x3F, 0xFF, 0x80, 0x1F, 0xE0, 0x07, 0xFF,
0xF0, 0x03, 0xF8, 0x00, 0xFF, 0xFE, 0x00, 0x7F, 0x00, 0x1F, 0xFF, 0xC0,
0x0F, 0xE0, 0x03, 0xFF, 0xF8, 0x01, 0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x3F,
0x80, 0x0F, 0xFF, 0xE0, 0x07, 0xF0, 0x01, 0xFF, 0xFC, 0x00, 0xFE, 0x00,
0x3F, 0xFF, 0x80, 0x1F, 0xC0, 0x07, 0xFF, 0xF0, 0x03, 0xF8, 0x00, 0xFF,
0xFE, 0x00, 0x7F, 0x00, 0x1F, 0xFF, 0xC0, 0x0F, 0xE0, 0x03, 0xFF, 0xF8,
0x01, 0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x3F, 0x80, 0x0F, 0xFF, 0xE0, 0x07,
0xF0, 0x01, 0xFC, 0x00, 0x03, 0x80, 0x3F, 0x8F, 0xFE, 0x0F, 0xE7, 0xFF,
0xE3, 0xFB, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xEF, 0xFF,
0xFF, 0xFB, 0xFF, 0x81, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xE0, 0x0F, 0xFF,
0xF0, 0x01, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0xC0, 0x07,
0xFF, 0xF0, 0x01, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0xC0,
0x07, 0xFF, 0xF0, 0x01, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF,
0xC0, 0x07, 0xFF, 0xF0, 0x01, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x1F,
0xFF, 0xC0, 0x07, 0xF0, 0x00, 0x07, 0x00, 0x00, 0x0F, 0xFF, 0x00, 0x03,
0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0x81, 0xFF, 0xFF,
0xFC, 0x3F, 0xF8, 0xFF, 0xC3, 0xFE, 0x03, 0xFE, 0x7F, 0xC0, 0x1F, 0xE7,
0xF8, 0x00, 0xFF, 0x7F, 0x00, 0x0F, 0xF7, 0xF0, 0x00, 0x7F, 0xFF, 0x00,
0x07, 0xFF, 0xF0, 0x00, 0x7F, 0x7F, 0x00, 0x07, 0xF7, 0xF0, 0x00, 0x7F,
0x7F, 0x80, 0x0F, 0xF7, 0xF8, 0x00, 0xFF, 0x3F, 0xC0, 0x1F, 0xE3, 0xFE,
0x03, 0xFE, 0x1F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF,
0x80, 0x7F, 0xFF, 0xE0, 0x01, 0xFF, 0xFC, 0x00, 0x07, 0xFF, 0x00, 0x00,
0x03, 0x80, 0x0F, 0xE3, 0xFF, 0x80, 0xFE, 0x7F, 0xFE, 0x0F, 0xFF, 0xFF,
0xF0, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xFC, 0xFF, 0xF9, 0xFF, 0xCF,
0xFC, 0x03, 0xFE, 0xFF, 0x80, 0x1F, 0xEF, 0xF8, 0x00, 0xFE, 0xFF, 0x00,
0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF,
0xFF, 0x00, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0x00, 0x0F, 0xFF, 0xF8,
0x01, 0xFE, 0xFF, 0x80, 0x1F, 0xEF, 0xFE, 0x07, 0xFE, 0xFF, 0xFF, 0xFF,
0xCF, 0xFF, 0xFF, 0xF8, 0xFF, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xF0, 0xFF,
0x7F, 0xFC, 0x0F, 0xF1, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00,
0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F,
0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x0F, 0xFC, 0x7F, 0x03, 0xFF, 0xF7,
0xF0, 0x7F, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x3F,
0xF8, 0xFF, 0xF3, 0xFE, 0x03, 0xFF, 0x7F, 0xC0, 0x1F, 0xF7, 0xF8, 0x00,
0xFF, 0x7F, 0x00, 0x0F, 0xF7, 0xF0, 0x00, 0x7F, 0xFF, 0x00, 0x07, 0xFF,
0xF0, 0x00, 0x7F, 0x7F, 0x00, 0x07, 0xF7, 0xF0, 0x00, 0x7F, 0x7F, 0x80,
0x0F, 0xF7, 0xF8, 0x00, 0xFF, 0x7F, 0xC0, 0x1F, 0xF3, 0xFE, 0x03, 0xFF,
0x3F, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xF0, 0x7F,
0xFF, 0xFF, 0x03, 0xFF, 0xE7, 0xF0, 0x0F, 0xFC, 0x7F, 0x00, 0x00, 0x07,
0xF0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x07, 0xF0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x01, 0xFE, 0x3F, 0xFE, 0x7F, 0xFE,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xC0, 0xFF,
0x80, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x3E, 0x00,
0x07, 0xFF, 0xE0, 0x3F, 0xFF, 0xF0, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0x8F,
0xFF, 0xFF, 0x1F, 0xE0, 0x1C, 0x3F, 0x80, 0x08, 0x7F, 0x00, 0x00, 0xFE,
0x00, 0x01, 0xFF, 0x80, 0x03, 0xFF, 0xFC, 0x03, 0xFF, 0xFE, 0x03, 0xFF,
0xFF, 0x03, 0xFF, 0xFF, 0x00, 0xFF, 0xFE, 0x00, 0x07, 0xFE, 0x00, 0x03,
0xFC, 0x80, 0x03, 0xF9, 0xC0, 0x07, 0xF7, 0xF0, 0x3F, 0xCF, 0xFF, 0xFF,
0xBF, 0xFF, 0xFE, 0x7F, 0xFF, 0xF8, 0x7F, 0xFF, 0xE0, 0x1F, 0xFF, 0x00,
0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0,
0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xCF, 0xFF, 0xFC, 0xFF, 0xFF, 0xCF, 0xFF,
0xFC, 0xFF, 0xFF, 0xC0, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F,
0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00,
0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00,
0x0F, 0xF0, 0x00, 0x7F, 0xDC, 0x07, 0xFF, 0xC0, 0x7F, 0xFE, 0x03, 0xFF,
0xE0, 0x1F, 0xFF, 0x00, 0x7F, 0xC0, 0xFF, 0x00, 0x1F, 0xFF, 0xC0, 0x07,
0xFF, 0xF0, 0x01, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF, 0xC0,
0x07, 0xFF, 0xF0, 0x01, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x1F, 0xFF,
0xC0, 0x07, 0xFF, 0xF0, 0x01, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0x00, 0x1F,
0xFF, 0xC0, 0x0F, 0xFF, 0xF0, 0x03, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0x00,
0x7F, 0xDF, 0xE0, 0x1F, 0xF7, 0xFC, 0x1F, 0xFD, 0xFF, 0xFF, 0xFF, 0x3F,
0xFF, 0xFF, 0xCF, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xFC, 0x3F, 0xFE, 0x7F,
0x03, 0xFE, 0x1F, 0xC0, 0xFF, 0x00, 0x07, 0xFF, 0xF0, 0x00, 0x7F, 0x7F,
0x00, 0x0F, 0xE7, 0xF8, 0x00, 0xFE, 0x3F, 0x80, 0x1F, 0xC3, 0xFC, 0x01,
0xFC, 0x3F, 0xC0, 0x1F, 0xC1, 0xFC, 0x03, 0xF8, 0x1F, 0xE0, 0x3F, 0x80,
0xFE, 0x07, 0xF0, 0x0F, 0xF0, 0x7F, 0x00, 0x7F, 0x0F, 0xF0, 0x07, 0xF0,
0xFE, 0x00, 0x7F, 0x8F, 0xE0, 0x03, 0xF9, 0xFC, 0x00, 0x3F, 0xDF, 0xC0,
0x01, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0xFF, 0xF8, 0x00, 0x0F,
0xFF, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x07, 0xFE, 0x00, 0x00, 0x7F, 0xE0,
0x00, 0x03, 0xFC, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0xFE, 0x00, 0x1F, 0xC0,
0x07, 0xF7, 0xF0, 0x03, 0xFC, 0x00, 0x7E, 0x7F, 0x00, 0x3F, 0xC0, 0x0F,
0xE7, 0xF0, 0x03, 0xFE, 0x00, 0xFE, 0x3F, 0x80, 0x7F, 0xE0, 0x0F, 0xC3,
0xF8, 0x07, 0xFE, 0x01, 0xFC, 0x3F, 0x80, 0x7F, 0xF0, 0x1F, 0xC1, 0xFC,
0x0F, 0xFF, 0x01, 0xF8, 0x1F, 0xC0, 0xFF, 0xF0, 0x3F, 0x80, 0xFC, 0x0F,
0xFF, 0x83, 0xF0, 0x0F, 0xE1, 0xFD, 0xF8, 0x3F, 0x00, 0xFE, 0x1F, 0x9F,
0x87, 0xF0, 0x07, 0xE3, 0xF9, 0xFC, 0x7E, 0x00, 0x7F, 0x3F, 0x8F, 0xC7,
0xE0, 0x07, 0xF3, 0xF0, 0xFE, 0xFE, 0x00, 0x3F, 0x7F, 0x0F, 0xEF, 0xC0,
0x03, 0xFF, 0xE0, 0x7F, 0xFC, 0x00, 0x3F, 0xFE, 0x07, 0xFF, 0xC0, 0x01,
0xFF, 0xE0, 0x7F, 0xF8, 0x00, 0x1F, 0xFC, 0x03, 0xFF, 0x80, 0x00, 0xFF,
0xC0, 0x3F, 0xF0, 0x00, 0x0F, 0xFC, 0x03, 0xFF, 0x00, 0x00, 0xFF, 0x80,
0x1F, 0xF0, 0x00, 0x07, 0xF8, 0x01, 0xFE, 0x00, 0x00, 0x7F, 0x00, 0x0F,
0xE0, 0x00, 0x7F, 0x80, 0x1F, 0xE3, 0xFC, 0x03, 0xFC, 0x1F, 0xE0, 0x3F,
0x81, 0xFF, 0x07, 0xF8, 0x0F, 0xF0, 0xFF, 0x00, 0x7F, 0x9F, 0xE0, 0x03,
0xFD, 0xFC, 0x00, 0x3F, 0xFF, 0x80, 0x01, 0xFF, 0xF8, 0x00, 0x0F, 0xFF,
0x00, 0x00, 0x7F, 0xE0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0x3F, 0xC0, 0x00,
0x07, 0xFE, 0x00, 0x00, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0x80, 0x01, 0xFF,
0xF8, 0x00, 0x3F, 0xFF, 0xC0, 0x07, 0xF9, 0xFE, 0x00, 0xFF, 0x0F, 0xF0,
0x0F, 0xF0, 0xFF, 0x01, 0xFE, 0x07, 0xF8, 0x3F, 0xC0, 0x3F, 0xC7, 0xF8,
0x03, 0xFE, 0x7F, 0x80, 0x1F, 0xE0, 0xFF, 0x00, 0x07, 0xFF, 0xF0, 0x00,
0x7F, 0x7F, 0x00, 0x0F, 0xE7, 0xF8, 0x00, 0xFE, 0x3F, 0x80, 0x1F, 0xC3,
0xFC, 0x01, 0xFC, 0x1F, 0xC0, 0x1F, 0xC1, 0xFC, 0x03, 0xF8, 0x1F, 0xE0,
0x3F, 0x80, 0xFE, 0x07, 0xF0, 0x0F, 0xF0, 0x7F, 0x00, 0x7F, 0x07, 0xE0,
0x07, 0xF0, 0xFE, 0x00, 0x3F, 0x8F, 0xE0, 0x03, 0xF9, 0xFC, 0x00, 0x3F,
0xDF, 0xC0, 0x01, 0xFF, 0xF8, 0x00, 0x1F, 0xFF, 0x80, 0x00, 0xFF, 0xF8,
0x00, 0x0F, 0xFF, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x07, 0xFE, 0x00, 0x00,
0x7F, 0xE0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x03, 0xFC,
0x00, 0x00, 0x3F, 0x80, 0x02, 0x07, 0xF8, 0x00, 0x7D, 0xFF, 0x00, 0x07,
0xFF, 0xF0, 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xC0, 0x00, 0xFF, 0xF8,
0x00, 0x03, 0xFE, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00,
0x3F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE,
0x00, 0x0F, 0xF0, 0x00, 0x7F, 0xC0, 0x03, 0xFE, 0x00, 0x0F, 0xF0, 0x00,
0x7F, 0x80, 0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xFC,
0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x3F, 0x01, 0xFF, 0x03, 0xFF,
0x07, 0xFF, 0x07, 0xFF, 0x0F, 0xFF, 0x0F, 0xF8, 0x0F, 0xF0, 0x0F, 0xE0,
0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0,
0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0xFF, 0xE0, 0xFF, 0xE0,
0xFF, 0xC0, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0, 0x1F, 0xE0, 0x0F, 0xE0,
0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0,
0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF,
0x07, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x01, 0xFF, 0x00, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xFC, 0x01, 0xFE, 0x03, 0xFE, 0x07, 0xFE, 0x0F, 0xFE, 0x1F, 0xFC,
0x07, 0xF8, 0x07, 0xF0, 0x0F, 0xE0, 0x1F, 0xC0, 0x3F, 0x80, 0x7F, 0x00,
0xFE, 0x01, 0xFC, 0x03, 0xF8, 0x07, 0xF0, 0x0F, 0xE0, 0x1F, 0xC0, 0x3F,
0xC0, 0x7F, 0xF0, 0x7F, 0xE0, 0x7F, 0xC0, 0xFF, 0x83, 0xFF, 0x0F, 0xFE,
0x1F, 0xE0, 0x3F, 0x80, 0x7F, 0x00, 0xFE, 0x01, 0xFC, 0x03, 0xF8, 0x07,
0xF0, 0x0F, 0xE0, 0x1F, 0xC0, 0x3F, 0x80, 0x7F, 0x00, 0xFE, 0x03, 0xFC,
0x3F, 0xF8, 0x7F, 0xF0, 0xFF, 0xC1, 0xFF, 0x83, 0xFC, 0x07, 0xF0, 0x00,
0x0F, 0xC0, 0x1F, 0x1F, 0xF0, 0x1F, 0x3F, 0xF8, 0x1F, 0x7F, 0xFE, 0x3E,
0x7F, 0xFF, 0xFE, 0x7C, 0x7F, 0xFE, 0x78, 0x1F, 0xFC, 0xF8, 0x0F, 0xF8,
0xF8, 0x03, 0xF0 };
const GFXglyph Montserrat_Bold24pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 13, 0, 0 }, // 0x20 ' '
{ 1, 9, 33, 14, 2, -32 }, // 0x21 '!'
{ 39, 17, 13, 21, 2, -32 }, // 0x22 '"'
{ 67, 32, 33, 34, 1, -32 }, // 0x23 '#'
{ 199, 28, 45, 30, 1, -38 }, // 0x24 '$'
{ 357, 39, 33, 41, 1, -32 }, // 0x25 '%'
{ 518, 31, 34, 34, 2, -32 }, // 0x26 '&'
{ 650, 7, 13, 11, 2, -32 }, // 0x27 '''
{ 662, 13, 44, 17, 3, -34 }, // 0x28 '('
{ 734, 13, 44, 17, 0, -34 }, // 0x29 ')'
{ 806, 19, 19, 20, 1, -34 }, // 0x2A '*'
{ 852, 22, 21, 28, 3, -26 }, // 0x2B '+'
{ 910, 9, 16, 12, 2, -8 }, // 0x2C ','
{ 928, 14, 6, 18, 2, -15 }, // 0x2D '-'
{ 939, 9, 9, 12, 2, -8 }, // 0x2E '.'
{ 950, 22, 45, 18, -2, -39 }, // 0x2F '/'
{ 1074, 28, 34, 32, 2, -32 }, // 0x30 '0'
{ 1193, 15, 33, 18, 0, -32 }, // 0x31 '1'
{ 1255, 26, 33, 28, 0, -32 }, // 0x32 '2'
{ 1363, 26, 34, 28, 0, -32 }, // 0x33 '3'
{ 1474, 31, 33, 32, 1, -32 }, // 0x34 '4'
{ 1602, 27, 34, 28, 0, -32 }, // 0x35 '5'
{ 1717, 27, 34, 30, 2, -32 }, // 0x36 '6'
{ 1832, 27, 33, 29, 1, -32 }, // 0x37 '7'
{ 1944, 27, 34, 31, 2, -32 }, // 0x38 '8'
{ 2059, 27, 34, 30, 1, -32 }, // 0x39 '9'
{ 2174, 9, 26, 12, 2, -25 }, // 0x3A ':'
{ 2204, 9, 33, 12, 2, -25 }, // 0x3B ';'
{ 2242, 22, 23, 28, 3, -27 }, // 0x3C '<'
{ 2306, 22, 17, 28, 3, -24 }, // 0x3D '='
{ 2353, 22, 23, 28, 3, -27 }, // 0x3E '>'
{ 2417, 25, 33, 28, 0, -32 }, // 0x3F '?'
{ 2521, 45, 43, 49, 2, -32 }, // 0x40 '@'
{ 2763, 36, 33, 36, 0, -32 }, // 0x41 'A'
{ 2912, 30, 33, 36, 4, -32 }, // 0x42 'B'
{ 3036, 31, 34, 34, 2, -32 }, // 0x43 'C'
{ 3168, 33, 33, 39, 4, -32 }, // 0x44 'D'
{ 3305, 25, 33, 32, 4, -32 }, // 0x45 'E'
{ 3409, 25, 33, 30, 4, -32 }, // 0x46 'F'
{ 3513, 32, 34, 36, 2, -32 }, // 0x47 'G'
{ 3649, 30, 33, 38, 4, -32 }, // 0x48 'H'
{ 3773, 8, 33, 15, 4, -32 }, // 0x49 'I'
{ 3806, 23, 34, 25, -1, -32 }, // 0x4A 'J'
{ 3904, 31, 33, 35, 4, -32 }, // 0x4B 'K'
{ 4032, 24, 33, 28, 4, -32 }, // 0x4C 'L'
{ 4131, 37, 33, 45, 4, -32 }, // 0x4D 'M'
{ 4284, 30, 33, 38, 4, -32 }, // 0x4E 'N'
{ 4408, 36, 34, 40, 2, -32 }, // 0x4F 'O'
{ 4561, 28, 33, 34, 4, -32 }, // 0x50 'P'
{ 4677, 37, 41, 40, 2, -32 }, // 0x51 'Q'
{ 4867, 29, 33, 35, 4, -32 }, // 0x52 'R'
{ 4987, 28, 34, 30, 1, -32 }, // 0x53 'S'
{ 5106, 29, 33, 29, 0, -32 }, // 0x54 'T'
{ 5226, 29, 34, 37, 4, -32 }, // 0x55 'U'
{ 5350, 36, 33, 35, 0, -32 }, // 0x56 'V'
{ 5499, 53, 33, 55, 1, -32 }, // 0x57 'W'
{ 5718, 33, 33, 34, 0, -32 }, // 0x58 'X'
{ 5855, 33, 33, 32, -1, -32 }, // 0x59 'Y'
{ 5992, 29, 33, 32, 2, -32 }, // 0x5A 'Z'
{ 6112, 13, 44, 17, 4, -34 }, // 0x5B '['
{ 6184, 22, 45, 18, -2, -39 }, // 0x5C '\'
{ 6308, 12, 44, 17, 1, -34 }, // 0x5D ']'
{ 6374, 23, 19, 28, 3, -25 }, // 0x5E '^'
{ 6429, 24, 4, 24, 0, 1 }, // 0x5F '_'
{ 6441, 14, 6, 28, 4, -34 }, // 0x60 '`'
{ 6452, 24, 26, 29, 2, -25 }, // 0x61 'a'
{ 6530, 28, 35, 32, 3, -34 }, // 0x62 'b'
{ 6653, 26, 26, 28, 1, -25 }, // 0x63 'c'
{ 6738, 27, 35, 33, 2, -34 }, // 0x64 'd'
{ 6857, 27, 26, 30, 1, -25 }, // 0x65 'e'
{ 6945, 20, 35, 18, 0, -34 }, // 0x66 'f'
{ 7033, 28, 36, 33, 1, -25 }, // 0x67 'g'
{ 7159, 26, 35, 32, 3, -34 }, // 0x68 'h'
{ 7273, 9, 37, 14, 3, -36 }, // 0x69 'i'
{ 7315, 16, 47, 14, -4, -36 }, // 0x6A 'j'
{ 7409, 28, 35, 31, 3, -34 }, // 0x6B 'k'
{ 7532, 8, 35, 14, 3, -34 }, // 0x6C 'l'
{ 7567, 43, 26, 49, 3, -25 }, // 0x6D 'm'
{ 7707, 26, 26, 32, 3, -25 }, // 0x6E 'n'
{ 7792, 28, 26, 31, 1, -25 }, // 0x6F 'o'
{ 7883, 28, 35, 32, 3, -25 }, // 0x70 'p'
{ 8006, 28, 35, 32, 1, -25 }, // 0x71 'q'
{ 8129, 16, 26, 20, 3, -25 }, // 0x72 'r'
{ 8181, 23, 26, 25, 1, -25 }, // 0x73 's'
{ 8256, 20, 31, 20, 0, -30 }, // 0x74 't'
{ 8334, 26, 25, 32, 3, -24 }, // 0x75 'u'
{ 8416, 28, 25, 28, 0, -24 }, // 0x76 'v'
{ 8504, 44, 25, 44, 0, -24 }, // 0x77 'w'
{ 8642, 28, 25, 28, 0, -24 }, // 0x78 'x'
{ 8730, 28, 35, 28, 0, -24 }, // 0x79 'y'
{ 8853, 22, 25, 26, 2, -24 }, // 0x7A 'z'
{ 8922, 16, 44, 18, 2, -34 }, // 0x7B '{'
{ 9010, 7, 44, 15, 4, -34 }, // 0x7C '|'
{ 9049, 15, 44, 18, 1, -34 }, // 0x7D '}'
{ 9132, 24, 9, 28, 2, -20 } }; // 0x7E '~'
const GFXfont Montserrat_Bold24pt7b PROGMEM = {
(uint8_t *)Montserrat_Bold24pt7bBitmaps,
(GFXglyph *)Montserrat_Bold24pt7bGlyphs,
0x20, 0x7E, 57 };
// Approx. 9831 bytes
#endif // MONTSERRATBOLD24PT7B_H
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,182 @@
#ifndef MONTSERRATBOLD7PT7B_H
#define MONTSERRATBOLD7PT7B_H
const uint8_t Montserrat_Bold7pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFC, 0xF0, 0xDC, 0xA5, 0x20, 0x19, 0x04, 0x47, 0xFD, 0xFF,
0x13, 0x0C, 0xCF, 0xFB, 0xFE, 0x32, 0x08, 0x80, 0x08, 0x1F, 0x1F, 0xCD,
0x06, 0x83, 0xE0, 0xFC, 0x16, 0x0B, 0xBF, 0x9F, 0x81, 0x00, 0x80, 0x70,
0xC5, 0x88, 0xC9, 0x8C, 0xB0, 0x7A, 0x00, 0x6E, 0x0D, 0xB0, 0x93, 0x19,
0xB3, 0x0E, 0x1C, 0x0F, 0x83, 0x30, 0xD8, 0x1C, 0x1F, 0x36, 0x79, 0x8E,
0x7F, 0xCF, 0xA0, 0xEA, 0x66, 0xEC, 0xCC, 0xCC, 0xCE, 0x66, 0x30, 0x66,
0x73, 0x33, 0x33, 0x37, 0x66, 0xC0, 0x33, 0xF7, 0xBF, 0x30, 0x30, 0x63,
0xFF, 0xF3, 0x06, 0x00, 0x4D, 0xB4, 0xFF, 0x5D, 0x80, 0x0C, 0x31, 0x86,
0x18, 0xC3, 0x0C, 0x61, 0x86, 0x30, 0xC0, 0x3C, 0x7E, 0xE6, 0xC7, 0xC3,
0xC3, 0xC3, 0xC7, 0xFE, 0x7C, 0xFF, 0x33, 0x33, 0x33, 0x33, 0x3C, 0xFE,
0x47, 0x07, 0x06, 0x0C, 0x18, 0x30, 0x7F, 0xFF, 0xFE, 0xFE, 0x0E, 0x1C,
0x1C, 0x1E, 0x07, 0x07, 0xFE, 0x7C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x33,
0x1C, 0xCF, 0xFF, 0xFF, 0x03, 0x00, 0xC0, 0x7E, 0x7E, 0x60, 0x60, 0x7E,
0x7F, 0x03, 0x03, 0xFF, 0x7E, 0x3E, 0x7E, 0xE0, 0xC0, 0xFC, 0xFE, 0xC7,
0xC7, 0xFE, 0x7C, 0xFF, 0xFF, 0xC7, 0xC6, 0x06, 0x0E, 0x0C, 0x1C, 0x18,
0x38, 0x3E, 0x3F, 0x98, 0xCC, 0x63, 0xF3, 0xF9, 0x8E, 0xC7, 0x7F, 0x1F,
0x00, 0x3C, 0x7E, 0xE3, 0xE3, 0x67, 0x7F, 0x03, 0x07, 0x7E, 0x7C, 0x5D,
0x80, 0xBB, 0x5D, 0x80, 0x9B, 0x68, 0x0E, 0x7B, 0xC7, 0x07, 0xC1, 0xC0,
0x80, 0xFE, 0x00, 0x07, 0xFF, 0xE0, 0xC1, 0xF0, 0x78, 0xF7, 0x9C, 0x00,
0x00, 0x3C, 0xFE, 0x46, 0x06, 0x0E, 0x1C, 0x18, 0x00, 0x18, 0x18, 0x0F,
0x81, 0xC7, 0x18, 0x0D, 0x9D, 0xA9, 0xFD, 0xCC, 0x6E, 0x43, 0x33, 0x1B,
0x9F, 0xD6, 0x7B, 0x98, 0x00, 0x73, 0x00, 0xF8, 0x00, 0x0E, 0x01, 0xC0,
0x7C, 0x0D, 0x83, 0x30, 0x63, 0x1F, 0xE3, 0xFE, 0x60, 0xD8, 0x1C, 0xFE,
0x7F, 0xB0, 0xF8, 0x7F, 0xF7, 0xFB, 0x07, 0x83, 0xFF, 0xFF, 0x80, 0x1E,
0x3F, 0xF8, 0x58, 0x0C, 0x06, 0x03, 0x01, 0xC2, 0x7F, 0x9F, 0x80, 0xFE,
0x3F, 0xCC, 0x3B, 0x07, 0xC0, 0xF0, 0x3C, 0x1F, 0x06, 0xFF, 0xBF, 0x80,
0xFF, 0xFF, 0xC0, 0xC0, 0xFE, 0xFE, 0xC0, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0x1E, 0x3F, 0xF8, 0x58,
0x0C, 0x06, 0x0F, 0x07, 0xC3, 0x7F, 0x9F, 0x80, 0xC1, 0xE0, 0xF0, 0x78,
0x3F, 0xFF, 0xFF, 0x07, 0x83, 0xC1, 0xE0, 0xC0, 0xFF, 0xFF, 0xF0, 0x7E,
0xFC, 0x38, 0x70, 0xE1, 0xC3, 0x86, 0xFC, 0xF0, 0xC3, 0xB0, 0xCC, 0x63,
0x30, 0xD8, 0x3F, 0x0E, 0xE3, 0x1C, 0xC3, 0x30, 0xE0, 0xC1, 0x83, 0x06,
0x0C, 0x18, 0x30, 0x60, 0xFF, 0xFC, 0xC0, 0x7C, 0x0F, 0x83, 0xF8, 0xFF,
0x9F, 0xB6, 0xF3, 0xDE, 0x73, 0xC4, 0x78, 0x0C, 0xC1, 0xF0, 0xFC, 0x7F,
0x3D, 0xDE, 0x6F, 0x3F, 0x8F, 0xC3, 0xE0, 0xC0, 0x1E, 0x1F, 0xEE, 0x1F,
0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x87, 0x7F, 0x8F, 0xC0, 0xFC, 0x7F, 0xB0,
0xD8, 0x7C, 0x3F, 0xFB, 0xF9, 0x80, 0xC0, 0x60, 0x00, 0x1E, 0x0F, 0xF3,
0x87, 0x60, 0x6C, 0x0D, 0x81, 0xB0, 0x37, 0x0E, 0x7F, 0x87, 0xE0, 0x3D,
0x01, 0xE0, 0xFC, 0x7F, 0xB0, 0xD8, 0x7C, 0x3F, 0xFB, 0xF9, 0x8C, 0xC7,
0x61, 0x80, 0x3E, 0x3F, 0x98, 0x0C, 0x07, 0xC1, 0xF8, 0x0C, 0x07, 0x7F,
0x3F, 0x00, 0xFF, 0xFF, 0xC6, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18,
0x0C, 0x00, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0xC7, 0x7F,
0x1F, 0x00, 0xC0, 0xDC, 0x19, 0x87, 0x38, 0xC3, 0x38, 0x76, 0x06, 0xC0,
0xF0, 0x1E, 0x01, 0xC0, 0xE1, 0x83, 0x61, 0xC7, 0x63, 0xC6, 0x73, 0xC6,
0x33, 0x6E, 0x36, 0x6C, 0x3E, 0x6C, 0x1E, 0x3C, 0x1C, 0x38, 0x1C, 0x38,
0xE1, 0xDC, 0xE3, 0x30, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0xCC, 0x73, 0xB8,
0x70, 0xC1, 0x98, 0x67, 0x30, 0xDC, 0x3E, 0x07, 0x00, 0xC0, 0x30, 0x0C,
0x03, 0x00, 0xFF, 0xFF, 0x06, 0x0C, 0x1C, 0x38, 0x70, 0xE0, 0xFF, 0xFF,
0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCF, 0xF0, 0xC0, 0xC1, 0x81, 0x03, 0x06,
0x06, 0x0C, 0x18, 0x18, 0x30, 0x60, 0x60, 0xF3, 0x33, 0x33, 0x33, 0x33,
0x3F, 0xF0, 0x30, 0x71, 0xE3, 0x6C, 0xD8, 0x80, 0xFE, 0xE3, 0x10, 0x31,
0xFA, 0x38, 0x7F, 0xF9, 0xF3, 0xFB, 0xC0, 0xC0, 0xDC, 0xFE, 0xE7, 0xC3,
0xC3, 0xE3, 0xFF, 0xFE, 0x1C, 0x3F, 0x63, 0x60, 0xE0, 0x62, 0x7F, 0x3E,
0x03, 0x81, 0xC6, 0xEF, 0xF6, 0x3B, 0x1F, 0x86, 0xC7, 0x7F, 0x9E, 0xC0,
0x1C, 0x3E, 0x63, 0x63, 0xFF, 0x60, 0x7E, 0x3E, 0x00, 0xF7, 0x18, 0xF9,
0x86, 0x18, 0x61, 0x86, 0x00, 0x19, 0xBF, 0xD8, 0xFC, 0x3E, 0x1B, 0x1D,
0xFE, 0x33, 0x03, 0xBF, 0x8F, 0x80, 0xC0, 0xC0, 0xCC, 0xFE, 0xE7, 0xC7,
0xC3, 0xC3, 0xC3, 0xC3, 0xDC, 0x6D, 0xB6, 0xDB, 0x00, 0x31, 0xC0, 0x63,
0x18, 0xC6, 0x31, 0x8C, 0x6F, 0x70, 0xC0, 0xC0, 0xC7, 0xCE, 0xDC, 0xF8,
0xFC, 0xEC, 0xCE, 0xC7, 0xFF, 0xFF, 0xF0, 0xD8, 0x67, 0xFF, 0xB9, 0xCF,
0x8E, 0x3C, 0x61, 0xE3, 0x0F, 0x18, 0x78, 0xC3, 0xCC, 0xFE, 0xE7, 0xC7,
0xC3, 0xC3, 0xC3, 0xC3, 0x1C, 0x1F, 0x98, 0xCC, 0x7E, 0x1B, 0x1D, 0xFC,
0x7C, 0xDC, 0xFE, 0xE7, 0xC3, 0xC3, 0xE3, 0xFF, 0xDE, 0xC0, 0xC0, 0xC0,
0x19, 0xBF, 0xD8, 0xEC, 0x7E, 0x1B, 0x1D, 0xFE, 0x7F, 0x03, 0x81, 0xC0,
0xE0, 0xCF, 0xF9, 0x8C, 0x63, 0x18, 0x18, 0xFF, 0x83, 0x87, 0xE0, 0xDF,
0xBE, 0x63, 0xEF, 0x98, 0x61, 0x86, 0x1E, 0x3C, 0xC7, 0xC7, 0xC7, 0xC7,
0xC7, 0xC7, 0xFF, 0x7B, 0xC3, 0xE3, 0x63, 0x66, 0x36, 0x3C, 0x3C, 0x1C,
0xC3, 0x1E, 0x38, 0xD9, 0xCC, 0xCF, 0x66, 0xDB, 0x1E, 0xF0, 0xE3, 0x83,
0x1C, 0xE3, 0x66, 0x3E, 0x3C, 0x1C, 0x3C, 0x76, 0xE7, 0xC3, 0xE3, 0x63,
0x66, 0x36, 0x3C, 0x3C, 0x18, 0x18, 0xF8, 0xE0, 0x7E, 0xFC, 0x30, 0xE3,
0x8E, 0x1F, 0xFF, 0x76, 0x66, 0x6E, 0xE6, 0x66, 0x67, 0x30, 0xFF, 0xFF,
0xFF, 0xC0, 0xE3, 0x9C, 0xE7, 0x1C, 0xEE, 0x73, 0x9D, 0xCC, 0x00, 0xF7,
0x38 };
const GFXglyph Montserrat_Bold7pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 4, 0, 0 }, // 0x20 ' '
{ 1, 2, 10, 4, 1, -9 }, // 0x21 '!'
{ 4, 5, 4, 6, 1, -9 }, // 0x22 '"'
{ 7, 10, 10, 10, 0, -9 }, // 0x23 '#'
{ 20, 9, 13, 9, 0, -10 }, // 0x24 '$'
{ 35, 12, 10, 12, 0, -9 }, // 0x25 '%'
{ 50, 10, 10, 10, 0, -9 }, // 0x26 '&'
{ 63, 2, 4, 3, 1, -9 }, // 0x27 '''
{ 64, 4, 13, 5, 1, -9 }, // 0x28 '('
{ 71, 4, 13, 5, 0, -9 }, // 0x29 ')'
{ 78, 6, 5, 6, 0, -9 }, // 0x2A '*'
{ 82, 7, 6, 8, 1, -7 }, // 0x2B '+'
{ 88, 3, 5, 4, 0, -2 }, // 0x2C ','
{ 90, 4, 2, 5, 1, -4 }, // 0x2D '-'
{ 91, 3, 3, 4, 0, -2 }, // 0x2E '.'
{ 93, 6, 13, 5, 0, -11 }, // 0x2F '/'
{ 103, 8, 10, 10, 1, -9 }, // 0x30 '0'
{ 113, 4, 10, 5, 0, -9 }, // 0x31 '1'
{ 118, 8, 10, 8, 0, -9 }, // 0x32 '2'
{ 128, 8, 10, 8, 0, -9 }, // 0x33 '3'
{ 138, 10, 10, 10, 0, -9 }, // 0x34 '4'
{ 151, 8, 10, 8, 0, -9 }, // 0x35 '5'
{ 161, 8, 10, 9, 1, -9 }, // 0x36 '6'
{ 171, 8, 10, 9, 0, -9 }, // 0x37 '7'
{ 181, 9, 10, 9, 0, -9 }, // 0x38 '8'
{ 193, 8, 10, 9, 0, -9 }, // 0x39 '9'
{ 203, 3, 8, 4, 0, -7 }, // 0x3A ':'
{ 206, 3, 10, 4, 0, -7 }, // 0x3B ';'
{ 210, 7, 7, 8, 1, -7 }, // 0x3C '<'
{ 217, 7, 5, 8, 1, -6 }, // 0x3D '='
{ 222, 7, 7, 8, 1, -7 }, // 0x3E '>'
{ 229, 8, 10, 8, 0, -9 }, // 0x3F '?'
{ 239, 13, 13, 14, 1, -9 }, // 0x40 '@'
{ 261, 11, 10, 11, 0, -9 }, // 0x41 'A'
{ 275, 9, 10, 11, 1, -9 }, // 0x42 'B'
{ 287, 9, 10, 10, 1, -9 }, // 0x43 'C'
{ 299, 10, 10, 12, 1, -9 }, // 0x44 'D'
{ 312, 8, 10, 9, 1, -9 }, // 0x45 'E'
{ 322, 8, 10, 9, 1, -9 }, // 0x46 'F'
{ 332, 9, 10, 11, 1, -9 }, // 0x47 'G'
{ 344, 9, 10, 11, 1, -9 }, // 0x48 'H'
{ 356, 2, 10, 5, 1, -9 }, // 0x49 'I'
{ 359, 7, 10, 8, 0, -9 }, // 0x4A 'J'
{ 368, 10, 10, 10, 1, -9 }, // 0x4B 'K'
{ 381, 7, 10, 8, 1, -9 }, // 0x4C 'L'
{ 390, 11, 10, 13, 1, -9 }, // 0x4D 'M'
{ 404, 9, 10, 11, 1, -9 }, // 0x4E 'N'
{ 416, 10, 10, 12, 1, -9 }, // 0x4F 'O'
{ 429, 9, 10, 10, 1, -9 }, // 0x50 'P'
{ 441, 11, 12, 12, 1, -9 }, // 0x51 'Q'
{ 458, 9, 10, 10, 1, -9 }, // 0x52 'R'
{ 470, 9, 10, 9, 0, -9 }, // 0x53 'S'
{ 482, 9, 10, 9, 0, -9 }, // 0x54 'T'
{ 494, 9, 10, 11, 1, -9 }, // 0x55 'U'
{ 506, 11, 10, 10, 0, -9 }, // 0x56 'V'
{ 520, 16, 10, 16, 0, -9 }, // 0x57 'W'
{ 540, 10, 10, 10, 0, -9 }, // 0x58 'X'
{ 553, 10, 10, 9, 0, -9 }, // 0x59 'Y'
{ 566, 8, 10, 9, 1, -9 }, // 0x5A 'Z'
{ 576, 4, 13, 5, 1, -9 }, // 0x5B '['
{ 583, 7, 13, 5, -1, -11 }, // 0x5C '\'
{ 595, 4, 13, 5, 0, -9 }, // 0x5D ']'
{ 602, 7, 6, 8, 1, -7 }, // 0x5E '^'
{ 608, 7, 1, 7, 0, 1 }, // 0x5F '_'
{ 609, 4, 3, 8, 1, -10 }, // 0x60 '`'
{ 611, 7, 8, 9, 1, -7 }, // 0x61 'a'
{ 618, 8, 10, 10, 1, -9 }, // 0x62 'b'
{ 628, 8, 8, 8, 0, -7 }, // 0x63 'c'
{ 636, 9, 10, 10, 0, -9 }, // 0x64 'd'
{ 648, 8, 8, 9, 0, -7 }, // 0x65 'e'
{ 656, 6, 11, 5, 0, -10 }, // 0x66 'f'
{ 665, 9, 11, 10, 0, -7 }, // 0x67 'g'
{ 678, 8, 10, 10, 1, -9 }, // 0x68 'h'
{ 688, 3, 11, 4, 1, -10 }, // 0x69 'i'
{ 693, 5, 14, 4, -1, -10 }, // 0x6A 'j'
{ 702, 8, 10, 9, 1, -9 }, // 0x6B 'k'
{ 712, 2, 10, 4, 1, -9 }, // 0x6C 'l'
{ 715, 13, 8, 15, 1, -7 }, // 0x6D 'm'
{ 728, 8, 8, 10, 1, -7 }, // 0x6E 'n'
{ 736, 9, 8, 9, 0, -7 }, // 0x6F 'o'
{ 745, 8, 11, 10, 1, -7 }, // 0x70 'p'
{ 756, 9, 11, 10, 0, -7 }, // 0x71 'q'
{ 769, 5, 8, 6, 1, -7 }, // 0x72 'r'
{ 774, 7, 8, 7, 0, -7 }, // 0x73 's'
{ 781, 6, 9, 6, 0, -8 }, // 0x74 't'
{ 788, 8, 8, 10, 1, -7 }, // 0x75 'u'
{ 796, 8, 8, 8, 0, -7 }, // 0x76 'v'
{ 804, 13, 8, 13, 0, -7 }, // 0x77 'w'
{ 817, 8, 8, 8, 0, -7 }, // 0x78 'x'
{ 825, 8, 11, 8, 0, -7 }, // 0x79 'y'
{ 836, 7, 8, 8, 0, -7 }, // 0x7A 'z'
{ 843, 4, 13, 5, 1, -9 }, // 0x7B '{'
{ 850, 2, 13, 4, 1, -9 }, // 0x7C '|'
{ 854, 5, 13, 5, 0, -9 }, // 0x7D '}'
{ 863, 7, 2, 8, 1, -5 } }; // 0x7E '~'
const GFXfont Montserrat_Bold7pt7b PROGMEM = {
(uint8_t *)Montserrat_Bold7pt7bBitmaps,
(GFXglyph *)Montserrat_Bold7pt7bGlyphs,
0x20, 0x7E, 17 };
// Approx. 1537 bytes
#endif // MONTSERRATBOLD7PT7B_H
@@ -0,0 +1,227 @@
#ifndef MONTSERRATBOLD9PT7B_H
#define MONTSERRATBOLD9PT7B_H
const uint8_t Montserrat_Bold9pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xFF, 0xE3, 0xFE, 0xCF, 0x3C, 0xF3, 0xCF, 0x30, 0x0C,
0x60, 0x66, 0x03, 0x30, 0xFF, 0xF7, 0xFF, 0x8C, 0x60, 0x63, 0x03, 0x18,
0xFF, 0xF7, 0xFF, 0x86, 0x60, 0x33, 0x03, 0x18, 0x00, 0x06, 0x00, 0xC0,
0x3E, 0x1F, 0xE7, 0xFC, 0xEC, 0x1D, 0x83, 0xF0, 0x3F, 0x81, 0xF8, 0x1F,
0x83, 0x76, 0x6E, 0xFF, 0x8F, 0xE0, 0x30, 0x06, 0x00, 0x38, 0x18, 0xF8,
0x71, 0x98, 0xC6, 0x33, 0x04, 0x6C, 0x0D, 0x98, 0x0F, 0x67, 0x01, 0x9F,
0x03, 0x66, 0x0C, 0xCC, 0x31, 0x98, 0x63, 0xB1, 0x83, 0xC0, 0x1E, 0x03,
0xF0, 0x73, 0x87, 0x38, 0x77, 0x03, 0xE0, 0x3C, 0x0F, 0xE6, 0xE7, 0xEC,
0x3E, 0xE1, 0xEF, 0xFF, 0x7F, 0x60, 0xFF, 0xF0, 0x39, 0x9C, 0xE6, 0x73,
0x9C, 0xE7, 0x38, 0xC7, 0x38, 0xC7, 0x63, 0x9C, 0x73, 0x9C, 0xE7, 0x39,
0xCE, 0x73, 0x99, 0xCC, 0x18, 0x5E, 0x7E, 0x3C, 0xFE, 0x5A, 0x18, 0x1C,
0x0E, 0x07, 0x1F, 0xFF, 0xF8, 0xE0, 0x70, 0x38, 0xFF, 0xFD, 0x80, 0xFF,
0xC0, 0xFF, 0x80, 0x03, 0x81, 0x81, 0xC0, 0xE0, 0x60, 0x70, 0x38, 0x18,
0x1C, 0x0C, 0x06, 0x07, 0x03, 0x01, 0x81, 0xC0, 0xC0, 0x60, 0x00, 0x1E,
0x07, 0xF1, 0xFE, 0x70, 0xEE, 0x1D, 0xC3, 0xB8, 0x37, 0x06, 0xE1, 0xDC,
0x39, 0xCF, 0x3F, 0xC3, 0xF0, 0xFF, 0xFF, 0xC7, 0x1C, 0x71, 0xC7, 0x1C,
0x71, 0xC7, 0x1C, 0x1E, 0x1F, 0xEF, 0xF8, 0x07, 0x01, 0xC0, 0xE0, 0x78,
0x3C, 0x1E, 0x0F, 0x07, 0x81, 0xFF, 0x7F, 0xC0, 0x7F, 0x9F, 0xE7, 0xF8,
0x1C, 0x0E, 0x03, 0x81, 0xF8, 0x7F, 0x01, 0xC0, 0x76, 0x3F, 0xFE, 0x7F,
0x00, 0x07, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0xC0, 0x70, 0x1C, 0xE7, 0x1C,
0xFF, 0xFF, 0xFC, 0x0E, 0x01, 0xC0, 0x38, 0x3F, 0x8F, 0xE3, 0xF9, 0xC0,
0x70, 0x1F, 0xC7, 0xF8, 0x1F, 0x01, 0xC0, 0x76, 0x3F, 0xFE, 0x7F, 0x00,
0x0F, 0x0F, 0xE7, 0xFB, 0xC0, 0xE0, 0x3B, 0xCF, 0xFB, 0xCF, 0xE1, 0xF8,
0x7F, 0x1D, 0xFE, 0x3F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x70, 0xEE, 0x3C,
0x07, 0x00, 0xE0, 0x38, 0x07, 0x01, 0xC0, 0x38, 0x0F, 0x01, 0xC0, 0x1E,
0x1F, 0xEF, 0x3F, 0x87, 0xE1, 0xDF, 0xE7, 0xFB, 0xCF, 0xE1, 0xF8, 0x7E,
0x1F, 0xFE, 0x3F, 0x00, 0x1E, 0x07, 0xF1, 0xCF, 0x70, 0xEE, 0x1E, 0xE3,
0xDF, 0xF9, 0xF7, 0x00, 0xE0, 0x38, 0x0F, 0x3F, 0xC7, 0xF0, 0xFF, 0x80,
0x3F, 0xE0, 0xFF, 0x80, 0x3F, 0xFF, 0x60, 0x00, 0x83, 0xC7, 0xFF, 0x8E,
0x07, 0xC0, 0xFC, 0x1F, 0x01, 0x80, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x07,
0xFF, 0xFE, 0x80, 0x70, 0x3F, 0x03, 0xF0, 0x38, 0x7D, 0xF9, 0xE0, 0xC0,
0x00, 0x1E, 0x1F, 0xEF, 0xF8, 0x07, 0x01, 0xC0, 0xE0, 0x70, 0x38, 0x0E,
0x00, 0x00, 0xE0, 0x38, 0x0E, 0x00, 0x03, 0xE0, 0x0F, 0xFC, 0x0E, 0x07,
0x8E, 0x00, 0xC6, 0x3F, 0xB6, 0x3F, 0xCF, 0x38, 0xE7, 0x98, 0x73, 0xCC,
0x39, 0xE6, 0x1C, 0xF3, 0x8E, 0x79, 0xFF, 0xE6, 0x3D, 0xE3, 0x80, 0x00,
0xF0, 0x40, 0x1F, 0xE0, 0x03, 0xC0, 0x00, 0x07, 0x00, 0x1E, 0x00, 0x78,
0x03, 0xF0, 0x0D, 0xC0, 0x73, 0x81, 0xCE, 0x0E, 0x1C, 0x3F, 0xF1, 0xFF,
0xC7, 0x03, 0x98, 0x0E, 0xE0, 0x1C, 0xFF, 0x0F, 0xFC, 0xFF, 0xEE, 0x0E,
0xE0, 0xEE, 0x1E, 0xFF, 0xCF, 0xFE, 0xE0, 0x7E, 0x07, 0xE0, 0xFF, 0xFE,
0xFF, 0xC0, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06, 0xE0, 0x0E, 0x00, 0xE0,
0x0E, 0x00, 0xE0, 0x0F, 0x00, 0x78, 0xE3, 0xFE, 0x1F, 0xC0, 0xFF, 0x07,
0xFE, 0x3F, 0xFD, 0xC0, 0xEE, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0,
0x3F, 0x03, 0xF8, 0x7D, 0xFF, 0xCF, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0x80, 0xE0, 0x3F, 0xEF, 0xFB, 0xFE, 0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF,
0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x38, 0x0F, 0xFB, 0xFE, 0xE0,
0x38, 0x0E, 0x03, 0x80, 0xE0, 0x00, 0x0F, 0x83, 0xFE, 0x7F, 0xF7, 0x06,
0xE0, 0x0E, 0x00, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0x07, 0x78, 0xF3, 0xFF,
0x1F, 0xC0, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7F, 0xFF, 0xFF,
0xFF, 0xFF, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x70, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0x7F, 0x7F, 0x7F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0xC7, 0xFF, 0x7E, 0xE0, 0x77, 0x07, 0x38, 0x71, 0xC7, 0x0E, 0x70,
0x77, 0x03, 0xF8, 0x1F, 0xE0, 0xFF, 0x87, 0x9E, 0x38, 0x79, 0xC1, 0xCE,
0x07, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80,
0xE0, 0x38, 0x0E, 0x03, 0xFF, 0xFF, 0xC0, 0xE0, 0x0F, 0xE0, 0x1F, 0xC0,
0x7F, 0xC1, 0xFF, 0x83, 0xFF, 0x8F, 0xFB, 0x9B, 0xF7, 0x77, 0xE7, 0xCF,
0xC7, 0x9F, 0x8E, 0x3F, 0x08, 0x7E, 0x00, 0xE0, 0xE0, 0x7F, 0x07, 0xF8,
0x7F, 0x87, 0xFC, 0x7F, 0xE7, 0xEF, 0x7E, 0x7F, 0xE3, 0xFE, 0x1F, 0xE0,
0xFE, 0x0F, 0xE0, 0x70, 0x0F, 0x81, 0xFF, 0x1F, 0xFC, 0xE0, 0xFE, 0x03,
0xF0, 0x1F, 0x80, 0x7C, 0x07, 0xE0, 0x3F, 0x81, 0xDE, 0x3C, 0x7F, 0xC1,
0xFC, 0x00, 0xFE, 0x1F, 0xFB, 0xFF, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F,
0xFF, 0xFF, 0xDF, 0xC3, 0x80, 0x70, 0x0E, 0x00, 0x0F, 0x80, 0xFF, 0x87,
0xFF, 0x1C, 0x1E, 0xE0, 0x3B, 0x80, 0xEE, 0x01, 0xB8, 0x0E, 0xE0, 0x3B,
0xC0, 0xE7, 0x8F, 0x0F, 0xF8, 0x1F, 0xC0, 0x0F, 0x20, 0x1F, 0xC0, 0x1E,
0xFE, 0x0F, 0xFC, 0xFF, 0xEE, 0x0E, 0xE0, 0xEE, 0x0E, 0xE0, 0xEF, 0xFE,
0xFF, 0xCE, 0x38, 0xE1, 0xCE, 0x1E, 0xE0, 0xE0, 0x0F, 0x87, 0xF9, 0xFF,
0x38, 0x07, 0x00, 0xF8, 0x0F, 0xE0, 0x7E, 0x01, 0xE0, 0x1D, 0x83, 0xBF,
0xE3, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0x87, 0x00, 0xE0, 0x1C, 0x03, 0x80,
0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0xE0, 0x7E, 0x07, 0xE0,
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE0, 0x77, 0x0F, 0x79,
0xE3, 0xFE, 0x1F, 0x80, 0xE0, 0x1F, 0x80, 0xE7, 0x03, 0x9C, 0x1C, 0x38,
0x70, 0xE1, 0x83, 0xCE, 0x07, 0x38, 0x1D, 0xC0, 0x3F, 0x00, 0xF8, 0x01,
0xE0, 0x07, 0x00, 0xE0, 0x70, 0x3B, 0x83, 0x83, 0x9C, 0x1E, 0x1C, 0xE1,
0xF0, 0xE3, 0x8D, 0x8E, 0x1C, 0x6E, 0x70, 0xE7, 0x73, 0x83, 0xB3, 0xB8,
0x1D, 0x8F, 0xC0, 0xFC, 0x7E, 0x03, 0xC3, 0xE0, 0x1E, 0x0F, 0x00, 0xF0,
0x78, 0x00, 0xF0, 0x73, 0x83, 0x8E, 0x38, 0x7B, 0x81, 0xFC, 0x07, 0xC0,
0x1C, 0x01, 0xF0, 0x1F, 0xC0, 0xEE, 0x0E, 0x38, 0xE1, 0xEF, 0x07, 0x00,
0xE0, 0x3F, 0x07, 0x70, 0xE3, 0x8E, 0x39, 0xC1, 0xD8, 0x1F, 0x80, 0xF0,
0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0xFF, 0xDF, 0xFB, 0xFF,
0x01, 0xC0, 0x78, 0x1E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0xC0, 0x7F,
0xFF, 0xFE, 0xFF, 0xF9, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0xFF,
0xE0, 0x30, 0x1C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x03,
0x01, 0xC0, 0x60, 0x38, 0x1C, 0x06, 0x03, 0x80, 0xFF, 0xCE, 0x73, 0x9C,
0xE7, 0x39, 0xCE, 0x73, 0x9F, 0xFF, 0x1C, 0x0E, 0x0D, 0x86, 0xC6, 0x73,
0x1B, 0x8C, 0xFF, 0xFF, 0xC0, 0xE3, 0x8E, 0x3C, 0x7F, 0x99, 0xE0, 0x73,
0xFF, 0xFF, 0x8F, 0x87, 0xFF, 0xBF, 0xC0, 0xE0, 0x1C, 0x03, 0x80, 0x77,
0x8F, 0xF9, 0xF7, 0xBC, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0xC7, 0x7F, 0xEE,
0xF8, 0x1E, 0x3F, 0xFF, 0xFC, 0x2C, 0x06, 0x03, 0x81, 0xE7, 0x7F, 0x9F,
0x80, 0x01, 0xC0, 0x70, 0x1C, 0x77, 0x7F, 0xFF, 0xFE, 0x1F, 0x87, 0xC1,
0xF8, 0x7F, 0x3D, 0xFF, 0x3F, 0xC0, 0x1E, 0x1F, 0xCF, 0x3B, 0x87, 0xFF,
0xFF, 0xFE, 0x03, 0xC4, 0x7F, 0x8F, 0xC0, 0x00, 0x1E, 0x3E, 0x30, 0x30,
0xFE, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1C, 0xDF, 0xFF,
0xFF, 0x87, 0xC1, 0xF8, 0x7E, 0x1F, 0xFF, 0x7F, 0xC2, 0x74, 0x1D, 0xFF,
0xFF, 0x87, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0xBC, 0xFF, 0xBF, 0xFF, 0x1F,
0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xC0, 0xFF, 0x8F, 0xFF, 0xFF,
0xFF, 0xC0, 0x1C, 0x71, 0xC0, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x1C,
0x71, 0xDF, 0x79, 0xC0, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0xEE, 0x39, 0xCE,
0x3B, 0x87, 0xF0, 0xFE, 0x1E, 0xE3, 0x9E, 0x71, 0xEE, 0x1E, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0xEF, 0x1C, 0x7F, 0xFF, 0xBF, 0xFF, 0xDC, 0x38, 0x7E,
0x1C, 0x3F, 0x0E, 0x1F, 0x87, 0x0F, 0xC3, 0x87, 0xE1, 0xC3, 0xF0, 0xE1,
0xC0, 0xEF, 0x3F, 0xEF, 0xFF, 0xC7, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1,
0xF8, 0x70, 0x1E, 0x1F, 0xEF, 0xFB, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF,
0x7F, 0x8F, 0xC0, 0xEF, 0x1F, 0xF3, 0xEF, 0x78, 0x7E, 0x0F, 0xC1, 0xF8,
0x3F, 0x8E, 0xFF, 0xDD, 0xF3, 0x80, 0x70, 0x0E, 0x00, 0x1D, 0xDF, 0xFF,
0xFF, 0x87, 0xC1, 0xF0, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0x1C, 0x07,
0x01, 0xC0, 0xEF, 0xFF, 0xFC, 0xE3, 0x8E, 0x38, 0xE3, 0x80, 0x1F, 0x3F,
0xDC, 0x4C, 0x07, 0xE1, 0xFC, 0x0E, 0x87, 0x7F, 0xBF, 0x80, 0x30, 0x30,
0xFE, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x3E, 0x1F, 0xE1, 0xF8,
0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0xCF, 0x7F, 0xCF, 0xF0, 0xE0,
0xFC, 0x19, 0xC7, 0x38, 0xE3, 0x38, 0x77, 0x0E, 0xC0, 0xF8, 0x1E, 0x01,
0xC0, 0xE1, 0xC3, 0xF0, 0xE1, 0x98, 0x70, 0xCE, 0x7C, 0xE3, 0x36, 0x61,
0xBB, 0xB0, 0xFD, 0xF8, 0x3C, 0x78, 0x1E, 0x3C, 0x0E, 0x1E, 0x00, 0xE1,
0xCE, 0x38, 0xEE, 0x0F, 0x81, 0xE0, 0x1C, 0x07, 0xC1, 0xDC, 0x73, 0xDC,
0x38, 0xE0, 0xFC, 0x19, 0xC7, 0x38, 0xE3, 0x38, 0x77, 0x06, 0xC0, 0xF8,
0x1E, 0x01, 0xC0, 0x38, 0x7E, 0x0F, 0x80, 0xE0, 0x00, 0xFF, 0xFF, 0x07,
0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xFF, 0xFF, 0x3C, 0xF7, 0x1C, 0x71, 0xC7,
0x3C, 0xF1, 0xC7, 0x1C, 0x71, 0xC7, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF3, 0xE3, 0x8E, 0x38, 0xE3, 0x8F, 0x3C, 0xE3, 0x8E, 0x38, 0xEF,
0xBC, 0x71, 0xFF, 0xF3, 0xC0 };
const GFXglyph Montserrat_Bold9pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' '
{ 1, 3, 13, 5, 1, -12 }, // 0x21 '!'
{ 6, 6, 6, 8, 1, -12 }, // 0x22 '"'
{ 11, 13, 13, 13, 0, -12 }, // 0x23 '#'
{ 33, 11, 17, 11, 0, -14 }, // 0x24 '$'
{ 57, 15, 13, 16, 0, -12 }, // 0x25 '%'
{ 82, 12, 13, 13, 1, -12 }, // 0x26 '&'
{ 102, 2, 6, 4, 1, -12 }, // 0x27 '''
{ 104, 5, 16, 6, 1, -12 }, // 0x28 '('
{ 114, 5, 16, 6, 0, -12 }, // 0x29 ')'
{ 124, 8, 7, 8, 0, -12 }, // 0x2A '*'
{ 131, 9, 8, 11, 1, -9 }, // 0x2B '+'
{ 140, 3, 6, 5, 1, -2 }, // 0x2C ','
{ 143, 5, 2, 7, 1, -5 }, // 0x2D '-'
{ 145, 3, 3, 5, 1, -2 }, // 0x2E '.'
{ 147, 9, 17, 7, -1, -14 }, // 0x2F '/'
{ 167, 11, 13, 12, 1, -12 }, // 0x30 '0'
{ 185, 6, 13, 7, 0, -12 }, // 0x31 '1'
{ 195, 10, 13, 11, 0, -12 }, // 0x32 '2'
{ 212, 10, 13, 11, 0, -12 }, // 0x33 '3'
{ 229, 11, 13, 12, 1, -12 }, // 0x34 '4'
{ 247, 10, 13, 11, 0, -12 }, // 0x35 '5'
{ 264, 10, 13, 11, 1, -12 }, // 0x36 '6'
{ 281, 11, 13, 11, 0, -12 }, // 0x37 '7'
{ 299, 10, 13, 12, 1, -12 }, // 0x38 '8'
{ 316, 11, 13, 11, 0, -12 }, // 0x39 '9'
{ 334, 3, 9, 5, 1, -8 }, // 0x3A ':'
{ 338, 3, 12, 5, 1, -8 }, // 0x3B ';'
{ 343, 9, 9, 11, 1, -10 }, // 0x3C '<'
{ 354, 9, 7, 11, 1, -9 }, // 0x3D '='
{ 362, 9, 9, 11, 1, -10 }, // 0x3E '>'
{ 373, 10, 13, 11, 0, -12 }, // 0x3F '?'
{ 390, 17, 17, 19, 1, -12 }, // 0x40 '@'
{ 427, 14, 13, 14, 0, -12 }, // 0x41 'A'
{ 450, 12, 13, 14, 1, -12 }, // 0x42 'B'
{ 470, 12, 13, 13, 1, -12 }, // 0x43 'C'
{ 490, 13, 13, 15, 1, -12 }, // 0x44 'D'
{ 512, 10, 13, 12, 1, -12 }, // 0x45 'E'
{ 529, 10, 13, 12, 1, -12 }, // 0x46 'F'
{ 546, 12, 13, 14, 1, -12 }, // 0x47 'G'
{ 566, 12, 13, 15, 1, -12 }, // 0x48 'H'
{ 586, 3, 13, 6, 1, -12 }, // 0x49 'I'
{ 591, 8, 13, 10, 0, -12 }, // 0x4A 'J'
{ 604, 13, 13, 13, 1, -12 }, // 0x4B 'K'
{ 626, 10, 13, 11, 1, -12 }, // 0x4C 'L'
{ 643, 15, 13, 17, 1, -12 }, // 0x4D 'M'
{ 668, 12, 13, 15, 1, -12 }, // 0x4E 'N'
{ 688, 13, 13, 15, 1, -12 }, // 0x4F 'O'
{ 710, 11, 13, 13, 1, -12 }, // 0x50 'P'
{ 728, 14, 16, 15, 1, -12 }, // 0x51 'Q'
{ 756, 12, 13, 13, 1, -12 }, // 0x52 'R'
{ 776, 11, 13, 11, 0, -12 }, // 0x53 'S'
{ 794, 11, 13, 11, 0, -12 }, // 0x54 'T'
{ 812, 12, 13, 14, 1, -12 }, // 0x55 'U'
{ 832, 14, 13, 13, 0, -12 }, // 0x56 'V'
{ 855, 21, 13, 21, 0, -12 }, // 0x57 'W'
{ 890, 13, 13, 13, 0, -12 }, // 0x58 'X'
{ 912, 12, 13, 12, 0, -12 }, // 0x59 'Y'
{ 932, 11, 13, 12, 1, -12 }, // 0x5A 'Z'
{ 950, 5, 16, 7, 1, -12 }, // 0x5B '['
{ 960, 9, 17, 7, -1, -14 }, // 0x5C '\'
{ 980, 5, 16, 7, 0, -12 }, // 0x5D ']'
{ 990, 9, 7, 11, 1, -9 }, // 0x5E '^'
{ 998, 9, 2, 9, 0, 1 }, // 0x5F '_'
{ 1001, 5, 3, 11, 2, -13 }, // 0x60 '`'
{ 1003, 9, 10, 11, 1, -9 }, // 0x61 'a'
{ 1015, 11, 13, 12, 1, -12 }, // 0x62 'b'
{ 1033, 9, 10, 11, 1, -9 }, // 0x63 'c'
{ 1045, 10, 13, 12, 1, -12 }, // 0x64 'd'
{ 1062, 10, 10, 11, 1, -9 }, // 0x65 'e'
{ 1075, 8, 14, 7, 0, -13 }, // 0x66 'f'
{ 1089, 10, 14, 13, 1, -9 }, // 0x67 'g'
{ 1107, 10, 13, 12, 1, -12 }, // 0x68 'h'
{ 1124, 3, 14, 5, 1, -13 }, // 0x69 'i'
{ 1130, 6, 18, 6, -2, -13 }, // 0x6A 'j'
{ 1144, 11, 13, 12, 1, -12 }, // 0x6B 'k'
{ 1162, 3, 13, 5, 1, -12 }, // 0x6C 'l'
{ 1167, 17, 10, 19, 1, -9 }, // 0x6D 'm'
{ 1189, 10, 10, 12, 1, -9 }, // 0x6E 'n'
{ 1202, 10, 10, 12, 1, -9 }, // 0x6F 'o'
{ 1215, 11, 13, 12, 1, -9 }, // 0x70 'p'
{ 1233, 10, 13, 12, 1, -9 }, // 0x71 'q'
{ 1250, 6, 10, 8, 1, -9 }, // 0x72 'r'
{ 1258, 9, 10, 10, 0, -9 }, // 0x73 's'
{ 1270, 8, 12, 8, 0, -11 }, // 0x74 't'
{ 1282, 10, 10, 12, 1, -9 }, // 0x75 'u'
{ 1295, 11, 10, 11, 0, -9 }, // 0x76 'v'
{ 1309, 17, 10, 17, 0, -9 }, // 0x77 'w'
{ 1331, 11, 10, 11, 0, -9 }, // 0x78 'x'
{ 1345, 11, 14, 11, 0, -9 }, // 0x79 'y'
{ 1365, 8, 10, 10, 1, -9 }, // 0x7A 'z'
{ 1375, 6, 16, 7, 1, -12 }, // 0x7B '{'
{ 1387, 3, 16, 6, 1, -12 }, // 0x7C '|'
{ 1393, 6, 16, 7, 0, -12 }, // 0x7D '}'
{ 1405, 9, 3, 11, 1, -7 } }; // 0x7E '~'
const GFXfont Montserrat_Bold9pt7b PROGMEM = {
(uint8_t *)Montserrat_Bold9pt7bBitmaps,
(GFXglyph *)Montserrat_Bold9pt7bGlyphs,
0x20, 0x7E, 21 };
// Approx. 2081 bytes
#endif // MONTSERRATBOLD9PT7B_H
@@ -0,0 +1,272 @@
#ifndef NOTOSANS12PT7B_H
#define NOTOSANS12PT7B_H
const uint8_t NotoSans_Regular12pt7bBitmaps[] PROGMEM = {
0x00, 0xDB, 0x6D, 0xB6, 0xDB, 0x60, 0x37, 0xC0, 0xCF, 0x3C, 0xF3, 0x8E,
0x30, 0x06, 0x30, 0x10, 0x80, 0xC6, 0x03, 0x18, 0x0C, 0x63, 0xFF, 0xFF,
0xFF, 0xC6, 0x30, 0x18, 0xC0, 0x63, 0x01, 0x8C, 0x3F, 0xFE, 0x31, 0x80,
0xC6, 0x03, 0x18, 0x0C, 0x60, 0x21, 0x00, 0x04, 0x00, 0x80, 0x7E, 0x1F,
0xF6, 0x45, 0xC8, 0x39, 0x03, 0x20, 0x7C, 0x03, 0xF0, 0x1F, 0x02, 0x70,
0x46, 0x08, 0xF1, 0x3F, 0xFE, 0x3F, 0x00, 0x80, 0x10, 0x00, 0x38, 0x0C,
0x36, 0x06, 0x31, 0x86, 0x18, 0xC3, 0x0C, 0x63, 0x06, 0x31, 0x03, 0x19,
0x81, 0x8D, 0x9E, 0x66, 0xD9, 0xBE, 0xC8, 0xC4, 0x6C, 0x20, 0x66, 0x10,
0x33, 0x08, 0x30, 0x84, 0x10, 0x46, 0x18, 0x33, 0x18, 0x0F, 0x00, 0x0F,
0x00, 0x3F, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x31, 0xC0, 0x1B,
0x80, 0x0F, 0x00, 0x1E, 0x00, 0x73, 0x06, 0x61, 0x8E, 0xE0, 0xEC, 0xC0,
0x7C, 0xE0, 0x38, 0x60, 0x7C, 0x7F, 0xEE, 0x3F, 0x87, 0xFF, 0xA0, 0x19,
0x8C, 0xC6, 0x33, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x8C, 0x63, 0x0C, 0x71,
0x80, 0xC3, 0x18, 0x63, 0x18, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x66, 0x31,
0x98, 0xCC, 0x00, 0x0E, 0x01, 0x80, 0x10, 0x42, 0x1F, 0x5F, 0xFF, 0xC3,
0x80, 0xD8, 0x3B, 0x8E, 0x30, 0x44, 0x00, 0x06, 0x00, 0xC0, 0x18, 0x03,
0x00, 0x61, 0xFF, 0xFF, 0xF8, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x00, 0x76,
0x66, 0xCC, 0xFF, 0xF0, 0xDF, 0x00, 0x03, 0x81, 0x80, 0xC0, 0xC0, 0x60,
0x30, 0x30, 0x18, 0x18, 0x0C, 0x06, 0x06, 0x03, 0x01, 0x81, 0x80, 0xC0,
0xC0, 0x00, 0x1F, 0x07, 0xF1, 0xC3, 0x30, 0x76, 0x07, 0x80, 0xF0, 0x1E,
0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x06, 0xC1, 0xD8, 0x31, 0xFE,
0x1F, 0x00, 0x0C, 0x73, 0xFB, 0x4C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
0x30, 0xC3, 0x0C, 0x1F, 0x0F, 0xF3, 0x83, 0x00, 0x60, 0x0E, 0x01, 0x80,
0x30, 0x0E, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18, 0x07,
0xFF, 0xFF, 0xE0, 0x3F, 0x1F, 0xF9, 0x03, 0x00, 0x70, 0x0E, 0x01, 0x80,
0x70, 0xFC, 0x1F, 0x00, 0x38, 0x03, 0x80, 0x30, 0x06, 0x00, 0xE0, 0x3F,
0xFE, 0x7F, 0x80, 0x00, 0xE0, 0x0F, 0x00, 0x58, 0x06, 0xC0, 0x66, 0x03,
0x30, 0x31, 0x83, 0x0C, 0x18, 0x61, 0x83, 0x18, 0x19, 0xFF, 0xFF, 0xFF,
0x80, 0x30, 0x01, 0x80, 0x0C, 0x00, 0x60, 0x7F, 0xCF, 0xF9, 0x80, 0x30,
0x06, 0x00, 0xC0, 0x18, 0x03, 0xFC, 0x77, 0xC0, 0x1C, 0x01, 0x80, 0x30,
0x06, 0x00, 0xE0, 0x37, 0xFE, 0x7F, 0x00, 0x07, 0xC3, 0xF8, 0xE0, 0x18,
0x06, 0x00, 0xC0, 0x18, 0x86, 0xFE, 0xF0, 0xFC, 0x0F, 0x81, 0xE0, 0x36,
0x06, 0xC0, 0xDC, 0x39, 0xFE, 0x1F, 0x80, 0xFF, 0xFF, 0xFC, 0x01, 0x80,
0x70, 0x0C, 0x03, 0x80, 0x60, 0x0C, 0x03, 0x00, 0x60, 0x18, 0x03, 0x00,
0xE0, 0x18, 0x07, 0x00, 0xC0, 0x38, 0x00, 0x1F, 0x07, 0xF9, 0x83, 0x30,
0x36, 0x06, 0xC1, 0x8C, 0x70, 0xFC, 0x1F, 0x07, 0x79, 0x83, 0xE0, 0x3C,
0x07, 0x80, 0xF8, 0x1B, 0xDE, 0x3F, 0x80, 0x1F, 0x07, 0xF1, 0x83, 0x70,
0x7C, 0x07, 0x80, 0xF0, 0x1F, 0x03, 0x60, 0xE7, 0xEC, 0x79, 0x80, 0x30,
0x0C, 0x01, 0x80, 0x63, 0x7C, 0x7E, 0x00, 0xDF, 0x00, 0x00, 0x03, 0x7C,
0x67, 0x60, 0x00, 0x00, 0x00, 0x66, 0x6C, 0xCC, 0x00, 0x20, 0x1C, 0x0E,
0x07, 0x03, 0x81, 0xC0, 0x3C, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0x80,
0xFF, 0xE0, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xC0, 0xC0, 0x1E, 0x00,
0xF0, 0x07, 0x80, 0x3C, 0x01, 0xC0, 0x78, 0x3C, 0x3E, 0x1E, 0x03, 0x00,
0x00, 0x3E, 0x3F, 0xE4, 0x18, 0x03, 0x00, 0xC0, 0x60, 0x18, 0x1C, 0x0E,
0x03, 0x01, 0x80, 0x60, 0x00, 0x00, 0x01, 0x80, 0x70, 0x1C, 0x00, 0x00,
0xF8, 0x00, 0xFF, 0xC0, 0x38, 0x0C, 0x0C, 0x00, 0xC3, 0x00, 0x0C, 0xC3,
0xF8, 0x98, 0xE3, 0x1A, 0x18, 0x63, 0xC6, 0x0C, 0x78, 0xC1, 0x0F, 0x18,
0x21, 0xE3, 0x0C, 0x24, 0x31, 0xCC, 0xC7, 0xCF, 0x18, 0x00, 0x01, 0x80,
0x00, 0x38, 0x00, 0x03, 0xF7, 0x80, 0x1F, 0xE0, 0x00, 0x03, 0x80, 0x07,
0x00, 0x0A, 0x00, 0x36, 0x00, 0x6C, 0x01, 0xCC, 0x03, 0x18, 0x06, 0x30,
0x18, 0x30, 0x30, 0x60, 0x7F, 0xC1, 0xFF, 0xC3, 0x01, 0x8E, 0x03, 0x98,
0x03, 0x30, 0x06, 0xC0, 0x06, 0xFF, 0x0F, 0xFC, 0xC0, 0xEC, 0x06, 0xC0,
0x6C, 0x06, 0xC0, 0x6F, 0xFC, 0xFF, 0x8C, 0x0E, 0xC0, 0x7C, 0x03, 0xC0,
0x3C, 0x07, 0xC0, 0x6F, 0xFE, 0xFF, 0x80, 0x07, 0xF0, 0xFF, 0xCF, 0x02,
0x60, 0x07, 0x00, 0x30, 0x01, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x18,
0x00, 0xC0, 0x06, 0x00, 0x38, 0x00, 0xE0, 0x03, 0xFE, 0x0F, 0xF0, 0xFF,
0x03, 0xFF, 0x0C, 0x0F, 0x30, 0x0C, 0xC0, 0x1B, 0x00, 0x6C, 0x01, 0xF0,
0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x06, 0xC0, 0x1B, 0x00, 0xCC,
0x0F, 0x3F, 0xF8, 0xFF, 0x00, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x30,
0x0C, 0x03, 0xFE, 0xFF, 0xB0, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03,
0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03,
0x00, 0xFF, 0xBF, 0xEC, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
0x00, 0x03, 0xF8, 0x3F, 0xF1, 0xC0, 0x4C, 0x00, 0x70, 0x01, 0x80, 0x06,
0x00, 0x38, 0x00, 0xE0, 0x7F, 0x81, 0xF6, 0x00, 0xD8, 0x03, 0x60, 0x0C,
0xC0, 0x33, 0x80, 0xC7, 0xFF, 0x07, 0xFC, 0xC0, 0x1E, 0x00, 0xF0, 0x07,
0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x7F, 0xFF, 0xFF, 0xFE, 0x00, 0xF0,
0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x18, 0xFF,
0xF3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x1E, 0xFC,
0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3,
0x0C, 0x30, 0xEF, 0xF8, 0xC0, 0x36, 0x03, 0x30, 0x31, 0x83, 0x0C, 0x30,
0x63, 0x83, 0x38, 0x1B, 0x80, 0xFC, 0x07, 0xF0, 0x31, 0xC1, 0x87, 0x0C,
0x18, 0x60, 0xE3, 0x03, 0x98, 0x0C, 0xC0, 0x38, 0xC0, 0x30, 0x0C, 0x03,
0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
0x30, 0x0C, 0x03, 0xFF, 0xFF, 0xC0, 0xF0, 0x03, 0xF8, 0x03, 0xFC, 0x01,
0xFB, 0x00, 0xFD, 0x80, 0xDE, 0xC0, 0x6F, 0x30, 0x27, 0x98, 0x33, 0xCE,
0x19, 0xE3, 0x18, 0xF1, 0x8C, 0x78, 0x66, 0x3C, 0x36, 0x1E, 0x1B, 0x0F,
0x07, 0x07, 0x83, 0x83, 0xC1, 0xC1, 0x80, 0xE0, 0x0F, 0xC0, 0x3F, 0x00,
0xFE, 0x03, 0xD8, 0x0F, 0x30, 0x3C, 0xE0, 0xF1, 0x83, 0xC3, 0x0F, 0x0E,
0x3C, 0x18, 0xF0, 0x33, 0xC0, 0xEF, 0x01, 0xBC, 0x07, 0xF0, 0x0F, 0xC0,
0x1C, 0x07, 0xE0, 0x1F, 0xF8, 0x38, 0x1C, 0x30, 0x0E, 0x60, 0x06, 0x60,
0x07, 0x60, 0x07, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0x60, 0x03, 0x60,
0x07, 0x60, 0x06, 0x70, 0x0E, 0x38, 0x1C, 0x1F, 0xF8, 0x0F, 0xF0, 0xFE,
0x1F, 0xFB, 0x07, 0x60, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x07, 0xC7, 0xDF,
0xF3, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x00, 0x07,
0xE0, 0x1F, 0xF8, 0x38, 0x1C, 0x30, 0x0E, 0x60, 0x06, 0x60, 0x07, 0x60,
0x07, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0x60, 0x03, 0x60, 0x07, 0x60,
0x06, 0x70, 0x0E, 0x38, 0x1C, 0x1F, 0xF8, 0x0F, 0xF0, 0x00, 0x70, 0x00,
0x38, 0x00, 0x1C, 0x00, 0x0E, 0xFF, 0x0F, 0xFC, 0xC1, 0xCC, 0x0E, 0xC0,
0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8F, 0xF0, 0xC3, 0x0C, 0x18, 0xC1,
0xCC, 0x0C, 0xC0, 0xEC, 0x06, 0xC0, 0x70, 0x1F, 0x8F, 0xF9, 0x81, 0x70,
0x0E, 0x00, 0xC0, 0x1C, 0x01, 0xE0, 0x1F, 0x00, 0xF8, 0x07, 0x00, 0x70,
0x06, 0x00, 0xE0, 0x37, 0xFE, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xC1, 0xC0,
0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01,
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0xC0,
0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03,
0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xF0, 0x1D, 0xC0, 0xC7,
0xFC, 0x1F, 0xC0, 0xC0, 0x0F, 0x80, 0x76, 0x01, 0x98, 0x06, 0x30, 0x38,
0xC0, 0xC3, 0x03, 0x06, 0x1C, 0x18, 0x60, 0x61, 0x80, 0xCC, 0x03, 0x30,
0x0C, 0xC0, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x03, 0x00, 0xE0, 0x30, 0x1D,
0x81, 0xC0, 0x66, 0x07, 0x81, 0x98, 0x1E, 0x0E, 0x70, 0xD8, 0x30, 0xC3,
0x30, 0xC3, 0x0C, 0xC3, 0x0C, 0x33, 0x1C, 0x39, 0x8C, 0x60, 0x66, 0x19,
0x81, 0x98, 0x66, 0x06, 0xC1, 0xB8, 0x0F, 0x03, 0xC0, 0x3C, 0x0F, 0x00,
0xF0, 0x3C, 0x03, 0x80, 0xE0, 0x06, 0x01, 0x80, 0xE0, 0x19, 0xC0, 0xC3,
0x03, 0x06, 0x18, 0x18, 0xE0, 0x33, 0x00, 0xF8, 0x01, 0xE0, 0x07, 0x00,
0x1E, 0x00, 0xDC, 0x03, 0x30, 0x18, 0x60, 0xE1, 0x83, 0x03, 0x18, 0x0E,
0xE0, 0x1C, 0xC0, 0x1B, 0x01, 0xDC, 0x0C, 0x60, 0xE3, 0x86, 0x0C, 0x60,
0x73, 0x01, 0xB0, 0x0F, 0x80, 0x38, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01,
0x80, 0x0C, 0x00, 0x60, 0x03, 0x00, 0xFF, 0xEF, 0xFE, 0x00, 0xE0, 0x0C,
0x01, 0xC0, 0x38, 0x03, 0x00, 0x70, 0x0E, 0x00, 0xC0, 0x1C, 0x03, 0x80,
0x30, 0x07, 0x00, 0xE0, 0x0F, 0xFF, 0xFF, 0xF0, 0xFF, 0xF1, 0x8C, 0x63,
0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0xFF, 0x80, 0xC0, 0x30,
0x18, 0x0C, 0x03, 0x01, 0x80, 0x60, 0x30, 0x18, 0x06, 0x03, 0x01, 0x80,
0x60, 0x30, 0x0C, 0x06, 0x03, 0x80, 0xFF, 0xC6, 0x31, 0x8C, 0x63, 0x18,
0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC7, 0xFF, 0x80, 0x04, 0x00, 0xE0, 0x0A,
0x01, 0xB0, 0x19, 0x03, 0x18, 0x30, 0x86, 0x0C, 0x60, 0x4C, 0x06, 0xC0,
0x30, 0xFF, 0xFF, 0xF0, 0xE3, 0x0C, 0x30, 0x1F, 0x1F, 0xE2, 0x0C, 0x03,
0x00, 0xC0, 0xF3, 0xFD, 0x83, 0xC0, 0xF0, 0x3C, 0x1D, 0xDF, 0x7E, 0x40,
0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x9E, 0x37, 0xE7, 0x06, 0xE0,
0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1F, 0x06, 0xFF, 0xDB,
0xF0, 0x0F, 0x4F, 0xE7, 0x09, 0x80, 0x60, 0x38, 0x0C, 0x03, 0x00, 0xE0,
0x18, 0x07, 0x00, 0xFE, 0x1F, 0x80, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x30,
0x06, 0x1C, 0xCF, 0xFB, 0x87, 0x60, 0x7C, 0x0F, 0x81, 0xE0, 0x3C, 0x07,
0xC0, 0xD8, 0x1B, 0x03, 0x3F, 0xA3, 0xE4, 0x0F, 0x07, 0xF1, 0xC3, 0x30,
0x36, 0x07, 0xFF, 0xFF, 0xFF, 0x00, 0xE0, 0x0C, 0x01, 0xC0, 0x1F, 0xE1,
0xFC, 0x0F, 0x8F, 0xC6, 0x03, 0x01, 0x81, 0xFB, 0xFC, 0x30, 0x18, 0x0C,
0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x0E, 0x27,
0xF5, 0xC3, 0xB0, 0x36, 0x07, 0xC0, 0xF0, 0x1E, 0x03, 0xE0, 0x6C, 0x0D,
0x81, 0x9F, 0xF1, 0xF6, 0x00, 0xC0, 0x18, 0x03, 0x60, 0xEF, 0xF8, 0x38,
0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x9E, 0x37, 0xF7, 0x06,
0xE0, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0,
0x78, 0x0C, 0xF0, 0xFF, 0xFF, 0xFF, 0xC0, 0x18, 0xC0, 0x01, 0x8C, 0x63,
0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x33, 0xFB, 0x00, 0xC0, 0x30,
0x0C, 0x03, 0x00, 0xC0, 0x30, 0x7C, 0x1B, 0x0C, 0xC6, 0x33, 0x0D, 0x83,
0xE0, 0xEC, 0x33, 0x8C, 0x73, 0x0C, 0xC1, 0xB0, 0x70, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0xCF, 0x0F, 0x37, 0xEF, 0xEE, 0x1E, 0x1F, 0x83, 0x83, 0xC0,
0xC0, 0xF0, 0x30, 0x3C, 0x0C, 0x0F, 0x03, 0x03, 0xC0, 0xC0, 0xF0, 0x30,
0x3C, 0x0C, 0x0F, 0x03, 0x03, 0xC0, 0xC0, 0xC0, 0xCF, 0x1B, 0xFB, 0x83,
0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0,
0x3C, 0x06, 0x0F, 0x03, 0xFC, 0x70, 0xE6, 0x06, 0x60, 0x3E, 0x03, 0xC0,
0x3C, 0x03, 0xE0, 0x36, 0x07, 0x70, 0x63, 0xFC, 0x1F, 0x80, 0xCF, 0x1B,
0xF3, 0x83, 0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F,
0x83, 0x7F, 0xED, 0xF9, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00,
0x00, 0x0E, 0x27, 0xF5, 0xC3, 0xB0, 0x3E, 0x07, 0xC0, 0xF0, 0x1E, 0x03,
0xE0, 0x6C, 0x0D, 0x81, 0x9F, 0xF1, 0xF6, 0x00, 0xC0, 0x18, 0x03, 0x00,
0x60, 0x0C, 0x01, 0x80, 0xCF, 0xBF, 0xC7, 0x0C, 0x18, 0x30, 0x60, 0xC1,
0x83, 0x06, 0x0C, 0x00, 0x1E, 0x3F, 0xF8, 0x38, 0x0E, 0x03, 0xC0, 0xF8,
0x0E, 0x01, 0x80, 0xC0, 0x7E, 0xFF, 0xE0, 0x10, 0x30, 0x7F, 0xFF, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x1D, 0x1F, 0xC0, 0xF8,
0x1F, 0x03, 0xE0, 0x7C, 0x0F, 0x81, 0xF0, 0x3E, 0x07, 0xC0, 0xF8, 0x1F,
0x03, 0xBF, 0xB7, 0xE6, 0xC0, 0x3E, 0x07, 0x60, 0x66, 0x06, 0x30, 0xC3,
0x0C, 0x30, 0xC1, 0x98, 0x19, 0x81, 0xB0, 0x0F, 0x00, 0xF0, 0x06, 0x00,
0xC0, 0xC0, 0xD8, 0x38, 0x36, 0x1E, 0x0D, 0x87, 0x86, 0x61, 0xB1, 0x8C,
0x4C, 0x63, 0x33, 0x38, 0xCC, 0x6C, 0x33, 0x1B, 0x07, 0x86, 0xC1, 0xE0,
0xA0, 0x78, 0x38, 0x0C, 0x0E, 0x00, 0x60, 0x77, 0x06, 0x30, 0xC1, 0x9C,
0x0D, 0x80, 0xF0, 0x06, 0x00, 0xF0, 0x0D, 0x81, 0x9C, 0x30, 0xC7, 0x06,
0xE0, 0x70, 0xC0, 0x3E, 0x07, 0x60, 0x66, 0x06, 0x30, 0xC3, 0x0C, 0x38,
0xC1, 0x98, 0x19, 0x80, 0xD8, 0x0F, 0x00, 0xF0, 0x06, 0x00, 0x60, 0x06,
0x00, 0xC0, 0x1C, 0x0F, 0x80, 0xE0, 0x00, 0xFF, 0xFF, 0xC0, 0xE0, 0x60,
0x60, 0x60, 0x30, 0x30, 0x30, 0x38, 0x18, 0x1F, 0xFF, 0xF8, 0x02, 0x3C,
0x60, 0xC1, 0x83, 0x06, 0x0C, 0x31, 0xE3, 0x03, 0x83, 0x03, 0x06, 0x0C,
0x18, 0x30, 0x60, 0xF0, 0x20, 0xFF, 0xFF, 0xFF, 0x81, 0xE0, 0xC1, 0x83,
0x06, 0x0C, 0x18, 0x38, 0x3C, 0x18, 0xE3, 0x86, 0x0C, 0x18, 0x30, 0x60,
0xC7, 0x08, 0x00, 0x78, 0x3F, 0xEE, 0x1F, 0x80 };
const GFXglyph NotoSans_Regular12pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 6, 0, 0 }, // 0x20 ' '
{ 1, 3, 17, 6, 2, -16 }, // 0x21 '!'
{ 8, 6, 6, 10, 2, -16 }, // 0x22 '"'
{ 13, 14, 17, 15, 1, -16 }, // 0x23 '#'
{ 43, 11, 19, 13, 1, -17 }, // 0x24 '$'
{ 70, 17, 17, 20, 1, -16 }, // 0x25 '%'
{ 107, 16, 17, 17, 1, -16 }, // 0x26 '&'
{ 141, 2, 6, 5, 2, -16 }, // 0x27 '''
{ 143, 5, 21, 7, 1, -16 }, // 0x28 '('
{ 157, 5, 21, 7, 1, -16 }, // 0x29 ')'
{ 171, 11, 11, 13, 1, -17 }, // 0x2A '*'
{ 187, 11, 11, 13, 1, -13 }, // 0x2B '+'
{ 203, 4, 6, 6, 1, -2 }, // 0x2C ','
{ 206, 6, 2, 8, 1, -6 }, // 0x2D '-'
{ 208, 3, 3, 6, 2, -2 }, // 0x2E '.'
{ 210, 9, 17, 9, 0, -16 }, // 0x2F '/'
{ 230, 11, 17, 13, 1, -16 }, // 0x30 '0'
{ 254, 6, 17, 13, 2, -16 }, // 0x31 '1'
{ 267, 11, 17, 13, 1, -16 }, // 0x32 '2'
{ 291, 11, 17, 13, 1, -16 }, // 0x33 '3'
{ 315, 13, 17, 13, 0, -16 }, // 0x34 '4'
{ 343, 11, 17, 13, 1, -16 }, // 0x35 '5'
{ 367, 11, 17, 13, 1, -16 }, // 0x36 '6'
{ 391, 11, 17, 13, 1, -16 }, // 0x37 '7'
{ 415, 11, 17, 13, 1, -16 }, // 0x38 '8'
{ 439, 11, 17, 13, 1, -16 }, // 0x39 '9'
{ 463, 3, 13, 6, 2, -12 }, // 0x3A ':'
{ 468, 4, 16, 6, 1, -12 }, // 0x3B ';'
{ 476, 11, 11, 13, 1, -13 }, // 0x3C '<'
{ 492, 11, 6, 13, 1, -10 }, // 0x3D '='
{ 501, 11, 11, 13, 1, -13 }, // 0x3E '>'
{ 517, 10, 17, 10, 0, -16 }, // 0x3F '?'
{ 539, 19, 19, 21, 1, -16 }, // 0x40 '@'
{ 585, 15, 17, 15, 0, -16 }, // 0x41 'A'
{ 617, 12, 17, 15, 2, -16 }, // 0x42 'B'
{ 643, 13, 17, 15, 1, -16 }, // 0x43 'C'
{ 671, 14, 17, 17, 2, -16 }, // 0x44 'D'
{ 701, 10, 17, 13, 2, -16 }, // 0x45 'E'
{ 723, 10, 17, 12, 2, -16 }, // 0x46 'F'
{ 745, 14, 17, 17, 1, -16 }, // 0x47 'G'
{ 775, 13, 17, 17, 2, -16 }, // 0x48 'H'
{ 803, 6, 17, 8, 1, -16 }, // 0x49 'I'
{ 816, 6, 21, 6, -2, -16 }, // 0x4A 'J'
{ 832, 13, 17, 15, 2, -16 }, // 0x4B 'K'
{ 860, 10, 17, 12, 2, -16 }, // 0x4C 'L'
{ 882, 17, 17, 21, 2, -16 }, // 0x4D 'M'
{ 919, 14, 17, 18, 2, -16 }, // 0x4E 'N'
{ 949, 16, 17, 18, 1, -16 }, // 0x4F 'O'
{ 983, 11, 17, 14, 2, -16 }, // 0x50 'P'
{ 1007, 16, 21, 18, 1, -16 }, // 0x51 'Q'
{ 1049, 12, 17, 15, 2, -16 }, // 0x52 'R'
{ 1075, 11, 17, 13, 1, -16 }, // 0x53 'S'
{ 1099, 13, 17, 13, 0, -16 }, // 0x54 'T'
{ 1127, 13, 17, 17, 2, -16 }, // 0x55 'U'
{ 1155, 14, 17, 14, 0, -16 }, // 0x56 'V'
{ 1185, 22, 17, 22, 0, -16 }, // 0x57 'W'
{ 1232, 14, 17, 14, 0, -16 }, // 0x58 'X'
{ 1262, 13, 17, 13, 0, -16 }, // 0x59 'Y'
{ 1290, 12, 17, 13, 1, -16 }, // 0x5A 'Z'
{ 1316, 5, 21, 8, 2, -16 }, // 0x5B '['
{ 1330, 9, 17, 9, 0, -16 }, // 0x5C '\'
{ 1350, 5, 21, 8, 1, -16 }, // 0x5D ']'
{ 1364, 12, 11, 13, 1, -16 }, // 0x5E '^'
{ 1381, 10, 2, 10, 0, 3 }, // 0x5F '_'
{ 1384, 5, 4, 7, 1, -17 }, // 0x60 '`'
{ 1387, 10, 13, 13, 1, -12 }, // 0x61 'a'
{ 1404, 11, 18, 14, 2, -17 }, // 0x62 'b'
{ 1429, 10, 13, 11, 1, -12 }, // 0x63 'c'
{ 1446, 11, 18, 14, 1, -17 }, // 0x64 'd'
{ 1471, 11, 13, 13, 1, -12 }, // 0x65 'e'
{ 1489, 9, 18, 8, 0, -17 }, // 0x66 'f'
{ 1510, 11, 19, 14, 1, -12 }, // 0x67 'g'
{ 1537, 11, 18, 15, 2, -17 }, // 0x68 'h'
{ 1562, 2, 17, 6, 2, -16 }, // 0x69 'i'
{ 1567, 5, 23, 6, -1, -16 }, // 0x6A 'j'
{ 1582, 10, 18, 13, 2, -17 }, // 0x6B 'k'
{ 1605, 2, 18, 6, 2, -17 }, // 0x6C 'l'
{ 1610, 18, 13, 22, 2, -12 }, // 0x6D 'm'
{ 1640, 11, 13, 15, 2, -12 }, // 0x6E 'n'
{ 1658, 12, 13, 14, 1, -12 }, // 0x6F 'o'
{ 1678, 11, 19, 14, 2, -12 }, // 0x70 'p'
{ 1705, 11, 19, 14, 1, -12 }, // 0x71 'q'
{ 1732, 7, 13, 10, 2, -12 }, // 0x72 'r'
{ 1744, 9, 13, 11, 1, -12 }, // 0x73 's'
{ 1759, 8, 15, 8, 0, -14 }, // 0x74 't'
{ 1774, 11, 13, 15, 2, -12 }, // 0x75 'u'
{ 1792, 12, 13, 12, 0, -12 }, // 0x76 'v'
{ 1812, 18, 13, 18, 0, -12 }, // 0x77 'w'
{ 1842, 12, 13, 12, 0, -12 }, // 0x78 'x'
{ 1862, 12, 19, 12, 0, -12 }, // 0x79 'y'
{ 1891, 9, 13, 11, 1, -12 }, // 0x7A 'z'
{ 1906, 7, 21, 9, 1, -16 }, // 0x7B '{'
{ 1925, 1, 24, 13, 6, -17 }, // 0x7C '|'
{ 1928, 7, 21, 9, 1, -16 }, // 0x7D '}'
{ 1947, 11, 3, 13, 1, -9 } }; // 0x7E '~'
const GFXfont NotoSans_Regular12pt7b PROGMEM = {
(uint8_t *)NotoSans_Regular12pt7bBitmaps,
(GFXglyph *)NotoSans_Regular12pt7bGlyphs,
0x20, 0x7E, 32 };
// Approx. 2624 bytes
#endif // NOTOSANS12PT7B_H
@@ -0,0 +1,464 @@
#ifndef NOTOSANS18PT7B_H
#define NOTOSANS18PT7B_H
const uint8_t NotoSans_Regular18pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFE, 0xEE, 0xEE, 0xEE, 0xEE, 0xE6, 0x66, 0x66, 0x00, 0x0E,
0xFF, 0xF4, 0xF1, 0xFC, 0x76, 0x1D, 0x87, 0x61, 0xD8, 0x76, 0x1D, 0x87,
0x61, 0x80, 0x00, 0xC1, 0xC0, 0x0E, 0x0C, 0x00, 0x70, 0x60, 0x03, 0x83,
0x00, 0x18, 0x38, 0x00, 0xC1, 0xC0, 0x0E, 0x0E, 0x0F, 0xFF, 0xFF, 0x7F,
0xFF, 0xFB, 0xFF, 0xFF, 0xC0, 0xC1, 0xC0, 0x06, 0x0E, 0x00, 0x70, 0x60,
0x03, 0x83, 0x00, 0x18, 0x38, 0x1F, 0xFF, 0xFE, 0xFF, 0xFF, 0xF7, 0xFF,
0xFF, 0x83, 0x83, 0x00, 0x1C, 0x38, 0x00, 0xC1, 0xC0, 0x06, 0x0E, 0x00,
0x70, 0x60, 0x03, 0x83, 0x00, 0x1C, 0x38, 0x00, 0x01, 0x80, 0x01, 0x80,
0x01, 0x80, 0x03, 0xE0, 0x1F, 0xFE, 0x3F, 0xFE, 0x79, 0x8E, 0xF1, 0x80,
0xE1, 0x80, 0xE1, 0x80, 0xF1, 0x80, 0x79, 0x80, 0x7F, 0x80, 0x3F, 0xE0,
0x0F, 0xF8, 0x01, 0xFE, 0x01, 0xBE, 0x01, 0x8F, 0x01, 0x87, 0x01, 0x87,
0x01, 0x87, 0x81, 0x8F, 0xFD, 0xFE, 0xFF, 0xFC, 0x7F, 0xF0, 0x01, 0x80,
0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x08, 0x00, 0x00, 0x0F, 0xC0, 0x0E,
0x07, 0xF8, 0x07, 0x03, 0x86, 0x01, 0xC0, 0xE1, 0xC0, 0xE0, 0x38, 0x70,
0x30, 0x0C, 0x1C, 0x1C, 0x03, 0x03, 0x06, 0x00, 0xC0, 0xC3, 0x80, 0x30,
0x31, 0xC0, 0x0C, 0x1C, 0x70, 0x03, 0x87, 0x39, 0xF8, 0xE1, 0xCE, 0xFF,
0x1C, 0xE7, 0x38, 0xE7, 0xF9, 0x8C, 0x38, 0xFC, 0xE7, 0x06, 0x00, 0x31,
0xC1, 0x80, 0x1C, 0x70, 0x70, 0x0E, 0x1C, 0x1C, 0x03, 0x87, 0x07, 0x01,
0xC1, 0xC1, 0x80, 0x70, 0x70, 0x60, 0x38, 0x0C, 0x38, 0x0C, 0x03, 0x8E,
0x07, 0x00, 0x7F, 0x03, 0x80, 0x0F, 0x80, 0x00, 0x80, 0x00, 0x0F, 0xF8,
0x00, 0x1F, 0xFC, 0x00, 0x1E, 0x3C, 0x00, 0x3C, 0x1E, 0x00, 0x38, 0x0E,
0x00, 0x38, 0x0E, 0x00, 0x3C, 0x1E, 0x00, 0x1C, 0x1C, 0x00, 0x1E, 0x3C,
0x00, 0x0F, 0xF0, 0x00, 0x07, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x1F, 0xE0,
0x1C, 0x3C, 0xF0, 0x1C, 0x78, 0x78, 0x3C, 0xF0, 0x3C, 0x38, 0xE0, 0x1E,
0x38, 0xE0, 0x0F, 0x70, 0xE0, 0x07, 0xF0, 0xE0, 0x03, 0xE0, 0xF0, 0x03,
0xE0, 0xF0, 0x07, 0xF0, 0x7E, 0x7F, 0x78, 0x3F, 0xFE, 0x3C, 0x1F, 0xF8,
0x1F, 0xFF, 0x66, 0x66, 0x66, 0x60, 0x07, 0x87, 0x03, 0x83, 0x81, 0xC1,
0xC0, 0xE0, 0xF0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x07, 0x83, 0xC1, 0xE0,
0xF0, 0x78, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xE0, 0x70, 0x38, 0x1E, 0x07,
0x03, 0xC0, 0xE0, 0x38, 0x0C, 0xF0, 0x70, 0x38, 0x38, 0x1C, 0x1C, 0x0E,
0x0E, 0x0E, 0x0F, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x0F, 0x0E, 0x0E, 0x0E, 0x1E, 0x1C, 0x3C, 0x38, 0x78, 0x70, 0xE0,
0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x02, 0x0E,
0x09, 0xF3, 0x7E, 0xFF, 0xFF, 0x9F, 0xFE, 0x01, 0xF0, 0x00, 0xDC, 0x00,
0xEE, 0x00, 0xE3, 0x80, 0xF1, 0xE0, 0x78, 0x78, 0x08, 0x30, 0x01, 0x80,
0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x3C, 0xE3, 0x8E, 0x71,
0xC7, 0x18, 0xE0, 0xFF, 0xFF, 0xFF, 0xE0, 0xEF, 0xFF, 0x40, 0x00, 0x78,
0x03, 0x80, 0x1C, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x07, 0x00, 0x38, 0x03,
0xC0, 0x1C, 0x00, 0xE0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x38, 0x01, 0xC0,
0x0E, 0x00, 0xE0, 0x07, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x01, 0xC0, 0x0E,
0x00, 0xF0, 0x00, 0x00, 0x80, 0x0F, 0xF0, 0x1F, 0xF8, 0x3C, 0x3C, 0x78,
0x1E, 0x70, 0x0E, 0x70, 0x0F, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0x70, 0x0F, 0x70, 0x0E, 0x38,
0x1E, 0x3E, 0x7C, 0x1F, 0xF8, 0x0F, 0xF0, 0x03, 0xC1, 0xF1, 0xFC, 0xF7,
0x79, 0xFC, 0xF6, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0,
0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C,
0x0F, 0x03, 0xC0, 0x01, 0x00, 0x1F, 0xF0, 0x7F, 0xFC, 0xF8, 0x3C, 0x60,
0x1E, 0x40, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00,
0x1E, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x00, 0xE0, 0x01,
0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x80, 0x3F, 0xF0, 0x7F,
0xFC, 0xF8, 0x3C, 0x40, 0x1E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00,
0x0E, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0xF8, 0x1F, 0xE0, 0x1F, 0xF8, 0x01,
0xFC, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00,
0x07, 0x00, 0x0F, 0x80, 0x1E, 0xF8, 0x7E, 0xFF, 0xFC, 0x7F, 0xF0, 0x00,
0x1E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x01, 0xF8, 0x00, 0xEE, 0x00, 0x73,
0x80, 0x1C, 0xE0, 0x0E, 0x38, 0x07, 0x0E, 0x01, 0xC3, 0x80, 0xE0, 0xE0,
0x70, 0x38, 0x1C, 0x0E, 0x0E, 0x03, 0x87, 0x00, 0xE1, 0x80, 0x38, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03,
0x80, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x3F, 0xFC, 0x3F, 0xFC,
0x3F, 0xFC, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00,
0x70, 0x00, 0x70, 0x00, 0x7F, 0xF0, 0x7F, 0xFC, 0x30, 0x7E, 0x00, 0x1E,
0x00, 0x0F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07,
0x00, 0x0E, 0x80, 0x1E, 0xF8, 0x7C, 0xFF, 0xF8, 0x7F, 0xF0, 0x00, 0x10,
0x01, 0xFF, 0x01, 0xFF, 0x83, 0xE0, 0x01, 0xC0, 0x01, 0xC0, 0x01, 0xE0,
0x00, 0xE0, 0x00, 0x70, 0x00, 0x78, 0x00, 0x38, 0x78, 0x1C, 0xFF, 0x8E,
0xFF, 0xE7, 0xC0, 0x73, 0xC0, 0x1D, 0xE0, 0x0E, 0xE0, 0x07, 0x70, 0x03,
0xF8, 0x01, 0xDC, 0x00, 0xE7, 0x00, 0x73, 0x80, 0x38, 0xE0, 0x38, 0x7C,
0x7C, 0x1F, 0xFC, 0x03, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x07, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x1C, 0x00, 0x3C,
0x00, 0x38, 0x00, 0x78, 0x00, 0x70, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xE0,
0x01, 0xC0, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0x80, 0x07, 0x80, 0x07, 0x00,
0x0F, 0x00, 0x0E, 0x00, 0x1E, 0x00, 0x1C, 0x00, 0x01, 0x80, 0x0F, 0xF8,
0x3F, 0xFC, 0x78, 0x1E, 0x70, 0x0E, 0x70, 0x0F, 0x70, 0x07, 0x70, 0x0F,
0x70, 0x0E, 0x78, 0x1E, 0x3C, 0x3C, 0x1F, 0xF8, 0x0F, 0xE0, 0x0F, 0xF0,
0x3E, 0xFC, 0x78, 0x1E, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07,
0xE0, 0x07, 0xE0, 0x07, 0xF0, 0x0F, 0x7C, 0x1E, 0x3F, 0xFC, 0x1F, 0xF8,
0x01, 0x00, 0x0F, 0xF0, 0x3F, 0xF8, 0x7C, 0x3C, 0x70, 0x1E, 0xF0, 0x0E,
0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07,
0xF0, 0x0F, 0x78, 0x3F, 0x3F, 0xF7, 0x1F, 0xE7, 0x07, 0x07, 0x00, 0x07,
0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x3C, 0x41, 0xF8,
0x3F, 0xF0, 0x3F, 0xC0, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E,
0xFF, 0xF4, 0x39, 0xF7, 0xCE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x0E, 0x39, 0xE7, 0x1C, 0x71, 0x8E, 0x30, 0x00, 0x03, 0x00, 0x0F,
0x00, 0x3F, 0x00, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x3F, 0x00, 0xF8, 0x00,
0xE0, 0x00, 0xF8, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0x7E,
0x00, 0x1F, 0x00, 0x07, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xC0, 0x00, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0,
0x00, 0x7C, 0x00, 0x1F, 0x00, 0x07, 0x00, 0x1F, 0x00, 0x7C, 0x03, 0xF0,
0x0F, 0xC0, 0x7F, 0x00, 0xF8, 0x00, 0xE0, 0x00, 0x80, 0x00, 0x01, 0x00,
0xFF, 0xCF, 0xFF, 0x9E, 0x1F, 0x40, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07,
0x00, 0x1C, 0x00, 0xF0, 0x03, 0x80, 0x3C, 0x01, 0xE0, 0x0F, 0x00, 0x38,
0x01, 0xC0, 0x07, 0x00, 0x1C, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x70, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0x20, 0x00, 0x00, 0x3F,
0xE0, 0x00, 0x0F, 0xFF, 0xC0, 0x03, 0xF0, 0x3E, 0x00, 0x78, 0x00, 0xF0,
0x0E, 0x00, 0x03, 0x81, 0xC0, 0x00, 0x1C, 0x38, 0x00, 0x00, 0xC3, 0x81,
0xFF, 0x0E, 0x70, 0x3F, 0xF0, 0x67, 0x07, 0x07, 0x06, 0x60, 0xE0, 0x70,
0x7E, 0x0C, 0x07, 0x07, 0xE1, 0xC0, 0x70, 0x7E, 0x1C, 0x07, 0x07, 0xE1,
0xC0, 0x70, 0x6E, 0x1C, 0x07, 0x06, 0xE1, 0xC0, 0xF0, 0xEE, 0x0C, 0x0F,
0x0E, 0xE0, 0xE1, 0xB1, 0xC6, 0x07, 0xFB, 0xF8, 0x70, 0x3F, 0x1F, 0x07,
0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x00, 0x1E, 0x00,
0x08, 0x00, 0xFC, 0x0F, 0x80, 0x03, 0xFF, 0xF8, 0x00, 0x0F, 0xFC, 0x00,
0x00, 0x38, 0x00, 0x01, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x3F, 0x00, 0x00,
0xEE, 0x00, 0x03, 0xB8, 0x00, 0x1C, 0xE0, 0x00, 0x71, 0xC0, 0x03, 0x87,
0x00, 0x0E, 0x1C, 0x00, 0x38, 0x38, 0x01, 0xC0, 0xE0, 0x07, 0x01, 0xC0,
0x3C, 0x07, 0x00, 0xFF, 0xFC, 0x03, 0xFF, 0xF8, 0x1F, 0xFF, 0xE0, 0x70,
0x03, 0xC1, 0xC0, 0x07, 0x0E, 0x00, 0x1C, 0x38, 0x00, 0x79, 0xE0, 0x00,
0xE7, 0x00, 0x03, 0xDC, 0x00, 0x07, 0xE0, 0x00, 0x1C, 0xFF, 0xF8, 0x3F,
0xFF, 0x8F, 0xFF, 0xF3, 0xC0, 0x3E, 0xF0, 0x07, 0xBC, 0x00, 0xEF, 0x00,
0x3B, 0xC0, 0x0E, 0xF0, 0x07, 0xBC, 0x01, 0xCF, 0x07, 0xE3, 0xFF, 0xE0,
0xFF, 0xFE, 0x3C, 0x07, 0xCF, 0x00, 0x7B, 0xC0, 0x0F, 0xF0, 0x03, 0xFC,
0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x0F, 0xF0, 0x03, 0xFC, 0x01, 0xEF, 0xFF,
0xF3, 0xFF, 0xF8, 0xFF, 0xF8, 0x00, 0x00, 0x18, 0x00, 0x3F, 0xF8, 0x1F,
0xFF, 0x87, 0xE1, 0xE1, 0xF0, 0x04, 0x78, 0x00, 0x0E, 0x00, 0x03, 0xC0,
0x00, 0x70, 0x00, 0x0E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0F, 0x00,
0x01, 0xE0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x00, 0xF0, 0x00, 0x0E, 0x00,
0x01, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0x80, 0x00, 0x78, 0x00, 0x07, 0xC0,
0x00, 0x7F, 0xBE, 0x07, 0xFF, 0xC0, 0x3F, 0xF8, 0xFF, 0xF8, 0x07, 0xFF,
0xF0, 0x3F, 0xFF, 0xE1, 0xE0, 0x0F, 0x8F, 0x00, 0x3E, 0x78, 0x00, 0xF3,
0xC0, 0x03, 0xDE, 0x00, 0x1E, 0xF0, 0x00, 0x77, 0x80, 0x03, 0xBC, 0x00,
0x1D, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xDE,
0x00, 0x0E, 0xF0, 0x00, 0x77, 0x80, 0x07, 0xBC, 0x00, 0x39, 0xE0, 0x03,
0xCF, 0x00, 0x3C, 0x78, 0x07, 0xC3, 0xFF, 0xFC, 0x1F, 0xFF, 0xC0, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0xF0, 0x03, 0xC0,
0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C,
0x00, 0xF0, 0x03, 0xC0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00,
0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0,
0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x00, 0x00, 0x04, 0x00, 0x0F, 0xFF, 0x81,
0xFF, 0xFE, 0x1F, 0xC3, 0xE1, 0xF0, 0x01, 0x1E, 0x00, 0x00, 0xF0, 0x00,
0x0F, 0x00, 0x00, 0x70, 0x00, 0x03, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xE0,
0x00, 0x0F, 0x00, 0x00, 0x70, 0x07, 0xFF, 0x80, 0x3F, 0xFE, 0x01, 0xFF,
0xF0, 0x00, 0x3B, 0x80, 0x01, 0xDC, 0x00, 0x0E, 0xF0, 0x00, 0x73, 0x80,
0x03, 0x9E, 0x00, 0x1C, 0x7C, 0x00, 0xE1, 0xFE, 0x3F, 0x07, 0xFF, 0xF8,
0x0F, 0xFF, 0x00, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00,
0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0,
0x00, 0xFF, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F,
0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00,
0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xF0, 0xFF, 0xFF, 0xF1, 0xE0, 0x78, 0x1E,
0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81,
0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE3, 0xFF,
0xFF, 0xC0, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03,
0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0,
0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x7F, 0xFB,
0xF8, 0xF0, 0xF0, 0x03, 0xDE, 0x00, 0xF3, 0xC0, 0x3C, 0x78, 0x0F, 0x0F,
0x01, 0xC1, 0xE0, 0x70, 0x3C, 0x1C, 0x07, 0x87, 0x00, 0xF1, 0xE0, 0x1E,
0x78, 0x03, 0xDE, 0x00, 0x7F, 0xC0, 0x0F, 0xFC, 0x01, 0xFB, 0x80, 0x3C,
0x78, 0x07, 0x87, 0x80, 0xF0, 0x78, 0x1E, 0x07, 0x03, 0xC0, 0xF0, 0x78,
0x0F, 0x0F, 0x00, 0xF1, 0xE0, 0x1E, 0x3C, 0x01, 0xE7, 0x80, 0x1E, 0xF0,
0x01, 0xE0, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80, 0x0F, 0x00, 0x1E,
0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03, 0xC0, 0x07, 0x80,
0x0F, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03,
0xC0, 0x07, 0x80, 0x0F, 0x00, 0x1E, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFE, 0xF8, 0x00, 0x07, 0xFF, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0xFF, 0xF0,
0x00, 0x77, 0xEE, 0x00, 0x1D, 0xFB, 0x80, 0x07, 0xFE, 0x70, 0x03, 0xBF,
0x9C, 0x00, 0xEF, 0xE7, 0x00, 0x33, 0xF8, 0xE0, 0x1C, 0xFE, 0x38, 0x07,
0x3F, 0x8E, 0x03, 0x8F, 0xE1, 0xC0, 0xE3, 0xF8, 0x70, 0x38, 0xFE, 0x0E,
0x1C, 0x3F, 0x83, 0x87, 0x0F, 0xE0, 0xE3, 0x83, 0xF8, 0x1C, 0xE0, 0xFE,
0x07, 0x38, 0x3F, 0x81, 0xFC, 0x0F, 0xE0, 0x3F, 0x03, 0xF8, 0x0F, 0x80,
0xFE, 0x01, 0xE0, 0x3F, 0x80, 0x78, 0x0F, 0xE0, 0x1C, 0x03, 0xC0, 0xF8,
0x00, 0x7F, 0x80, 0x07, 0xFC, 0x00, 0x7F, 0xC0, 0x07, 0xFE, 0x00, 0x7E,
0xF0, 0x07, 0xE7, 0x00, 0x7E, 0x78, 0x07, 0xE3, 0xC0, 0x7E, 0x1C, 0x07,
0xE1, 0xE0, 0x7E, 0x0F, 0x07, 0xE0, 0x70, 0x7E, 0x07, 0x87, 0xE0, 0x3C,
0x7E, 0x01, 0xC7, 0xE0, 0x1E, 0x7E, 0x00, 0xE7, 0xE0, 0x0F, 0x3E, 0x00,
0x7B, 0xE0, 0x03, 0xBE, 0x00, 0x3F, 0xE0, 0x01, 0xFE, 0x00, 0x0F, 0xE0,
0x00, 0xF0, 0x00, 0x10, 0x00, 0x07, 0xFF, 0x00, 0x1F, 0xFF, 0x80, 0xFC,
0x1F, 0x81, 0xE0, 0x07, 0x87, 0x80, 0x07, 0x1E, 0x00, 0x0F, 0x3C, 0x00,
0x0E, 0x70, 0x00, 0x1F, 0xE0, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0x80, 0x00,
0x7F, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07,
0xF0, 0x00, 0x0E, 0xE0, 0x00, 0x1D, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0xE3,
0x80, 0x03, 0xC7, 0x80, 0x0F, 0x07, 0x80, 0x3E, 0x07, 0xF3, 0xF8, 0x07,
0xFF, 0xE0, 0x03, 0xFF, 0x00, 0xFF, 0xF0, 0x7F, 0xFE, 0x3F, 0xFF, 0x9E,
0x03, 0xEF, 0x00, 0xF7, 0x80, 0x3B, 0xC0, 0x1D, 0xE0, 0x0F, 0xF0, 0x07,
0x78, 0x03, 0xBC, 0x03, 0xDE, 0x03, 0xCF, 0xFF, 0xE7, 0xFF, 0xC3, 0xFF,
0x81, 0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x0F,
0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x00, 0x00,
0x10, 0x00, 0x07, 0xFF, 0x00, 0x1F, 0xFF, 0x80, 0xFC, 0x1F, 0x81, 0xE0,
0x07, 0x87, 0x80, 0x07, 0x1E, 0x00, 0x0F, 0x3C, 0x00, 0x0E, 0x70, 0x00,
0x1F, 0xE0, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0x80, 0x00, 0x7F, 0x00, 0x00,
0xFE, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x0E,
0xE0, 0x00, 0x1D, 0xC0, 0x00, 0x7B, 0xC0, 0x00, 0xE3, 0x80, 0x03, 0xC7,
0x80, 0x0F, 0x07, 0x80, 0x3E, 0x07, 0xF3, 0xF8, 0x07, 0xFF, 0xE0, 0x03,
0xFF, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x00, 0x00,
0x3E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x3E, 0xFF, 0xF0, 0x3F, 0xFF, 0x0F,
0xFF, 0xE3, 0xC0, 0x3C, 0xF0, 0x07, 0x3C, 0x01, 0xCF, 0x00, 0x7B, 0xC0,
0x1E, 0xF0, 0x07, 0x3C, 0x01, 0xCF, 0x00, 0xF3, 0xC0, 0xF8, 0xFF, 0xFC,
0x3F, 0xFC, 0x0F, 0xFF, 0x03, 0xC1, 0xE0, 0xF0, 0x38, 0x3C, 0x0F, 0x0F,
0x01, 0xC3, 0xC0, 0x78, 0xF0, 0x0F, 0x3C, 0x01, 0xCF, 0x00, 0x7B, 0xC0,
0x0E, 0xF0, 0x03, 0xC0, 0x00, 0x80, 0x1F, 0xFC, 0x3F, 0xFE, 0x7E, 0x3E,
0x70, 0x04, 0xF0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0x70, 0x00,
0x78, 0x00, 0x3F, 0x00, 0x1F, 0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00, 0x7E,
0x00, 0x1E, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x0F, 0x00, 0x0E,
0x80, 0x1E, 0xFC, 0xFC, 0xFF, 0xF8, 0x7F, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x80, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38,
0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x70,
0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0,
0x00, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0,
0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xFE, 0x00,
0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xE0,
0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFE,
0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F,
0xE0, 0x00, 0xFE, 0x00, 0x0E, 0xF0, 0x00, 0xE7, 0x00, 0x0E, 0x78, 0x01,
0xE3, 0xC0, 0x3C, 0x3F, 0x9F, 0x81, 0xFF, 0xF0, 0x07, 0xFE, 0x00, 0xF0,
0x00, 0x3B, 0x80, 0x03, 0xDC, 0x00, 0x1C, 0xF0, 0x01, 0xE3, 0x80, 0x0F,
0x1C, 0x00, 0x70, 0xF0, 0x07, 0x83, 0x80, 0x38, 0x1C, 0x01, 0xC0, 0xF0,
0x1E, 0x03, 0x80, 0xE0, 0x1C, 0x07, 0x00, 0x70, 0x78, 0x03, 0x83, 0x80,
0x1C, 0x1C, 0x00, 0x71, 0xE0, 0x03, 0x8E, 0x00, 0x1E, 0x70, 0x00, 0x77,
0x80, 0x03, 0xB8, 0x00, 0x1D, 0xC0, 0x00, 0x7C, 0x00, 0x03, 0xE0, 0x00,
0x1F, 0x00, 0x00, 0x70, 0x00, 0xF0, 0x03, 0xC0, 0x07, 0x70, 0x03, 0xC0,
0x07, 0x70, 0x03, 0xE0, 0x0F, 0x78, 0x03, 0xE0, 0x0E, 0x38, 0x07, 0xE0,
0x0E, 0x38, 0x07, 0x70, 0x0E, 0x38, 0x07, 0x70, 0x1E, 0x3C, 0x0E, 0x70,
0x1C, 0x1C, 0x0E, 0x38, 0x1C, 0x1C, 0x0E, 0x38, 0x1C, 0x1C, 0x1E, 0x38,
0x3C, 0x0E, 0x1C, 0x38, 0x38, 0x0E, 0x1C, 0x1C, 0x38, 0x0E, 0x1C, 0x1C,
0x38, 0x0E, 0x38, 0x1C, 0x70, 0x07, 0x38, 0x0E, 0x70, 0x07, 0x38, 0x0E,
0x70, 0x07, 0x30, 0x0E, 0x70, 0x07, 0x70, 0x0E, 0xE0, 0x03, 0xF0, 0x07,
0xE0, 0x03, 0xF0, 0x07, 0xE0, 0x03, 0xE0, 0x07, 0xE0, 0x03, 0xE0, 0x03,
0xC0, 0x01, 0xE0, 0x03, 0xC0, 0x01, 0xC0, 0x03, 0xC0, 0x78, 0x00, 0xF1,
0xC0, 0x0F, 0x0F, 0x00, 0x70, 0x38, 0x07, 0x80, 0xE0, 0x38, 0x07, 0x83,
0x80, 0x1C, 0x3C, 0x00, 0x71, 0xC0, 0x03, 0xDC, 0x00, 0x0F, 0xE0, 0x00,
0x3E, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0xFC, 0x00, 0x07, 0xF0,
0x00, 0x73, 0x80, 0x03, 0x8E, 0x00, 0x38, 0x78, 0x03, 0xC1, 0xC0, 0x1C,
0x07, 0x01, 0xC0, 0x3C, 0x1E, 0x00, 0xE0, 0xE0, 0x07, 0x8E, 0x00, 0x1E,
0xF0, 0x00, 0x78, 0xF0, 0x00, 0xF7, 0x00, 0x0E, 0x78, 0x01, 0xE3, 0x80,
0x1C, 0x1C, 0x03, 0x81, 0xC0, 0x38, 0x0E, 0x07, 0x00, 0xE0, 0xF0, 0x07,
0x0E, 0x00, 0x79, 0xE0, 0x03, 0x9C, 0x00, 0x3F, 0xC0, 0x01, 0xF8, 0x00,
0x1F, 0x80, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00,
0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0,
0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x7F, 0xFF, 0x9F, 0xFF, 0xE7, 0xFF,
0xF8, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x03, 0x80, 0x01, 0xE0, 0x00, 0xF0,
0x00, 0x38, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x03, 0x80, 0x01, 0xE0, 0x00,
0xF0, 0x00, 0x38, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x03, 0x80, 0x01, 0xE0,
0x00, 0xF0, 0x00, 0x38, 0x00, 0x1E, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, 0xF0, 0x03,
0x80, 0x1C, 0x00, 0x70, 0x03, 0x80, 0x1E, 0x00, 0x70, 0x03, 0x80, 0x0E,
0x00, 0x70, 0x03, 0x80, 0x0E, 0x00, 0x70, 0x03, 0xC0, 0x0E, 0x00, 0x70,
0x01, 0xC0, 0x0E, 0x00, 0x70, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x01, 0xC0,
0x0E, 0x00, 0x38, 0xFF, 0xFF, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFF, 0xFF, 0xFF, 0x01, 0xC0,
0x00, 0x78, 0x00, 0x3E, 0x00, 0x0D, 0xC0, 0x03, 0x30, 0x01, 0xCE, 0x00,
0x61, 0x80, 0x38, 0x70, 0x0C, 0x0C, 0x07, 0x03, 0x81, 0x80, 0x60, 0xE0,
0x1C, 0x30, 0x03, 0x1C, 0x00, 0xE7, 0x00, 0x1B, 0x80, 0x07, 0xFF, 0xFF,
0xFF, 0xFF, 0xF0, 0x78, 0x3C, 0x1C, 0x0E, 0x07, 0x0F, 0xF0, 0x7F, 0xF0,
0xF9, 0xF1, 0x00, 0xF0, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x0F,
0xFE, 0x7F, 0xFD, 0xE0, 0x3F, 0x80, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x07,
0xF0, 0x1F, 0xF8, 0xFE, 0xFF, 0xDC, 0xFF, 0x18, 0xE0, 0x00, 0x70, 0x00,
0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0,
0x00, 0xE7, 0xF0, 0x77, 0xFE, 0x3F, 0x9F, 0x9F, 0x01, 0xCF, 0x00, 0xF7,
0x80, 0x3B, 0x80, 0x1D, 0xC0, 0x0F, 0xE0, 0x07, 0xF0, 0x01, 0xF8, 0x01,
0xFC, 0x00, 0xFE, 0x00, 0x7F, 0x80, 0x3B, 0xC0, 0x1D, 0xF0, 0x1E, 0xFE,
0x3E, 0x77, 0xFE, 0x31, 0xFE, 0x00, 0x07, 0xF8, 0x7F, 0xF3, 0xF7, 0x9E,
0x00, 0x70, 0x03, 0xC0, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E,
0x00, 0x38, 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x1E, 0x00, 0x3E, 0x38,
0x7F, 0xE0, 0xFF, 0x80, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00,
0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x0F, 0xE3, 0x8F,
0xFD, 0xCF, 0x9F, 0xEF, 0x01, 0xF7, 0x00, 0x7F, 0x80, 0x3F, 0xC0, 0x1F,
0xC0, 0x0F, 0xE0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xFC, 0x00, 0x7E, 0x00,
0x7F, 0x80, 0x3D, 0xC0, 0x1E, 0xF0, 0x1F, 0x3E, 0x3F, 0x8F, 0xFD, 0xC3,
0xF8, 0xE0, 0x07, 0xF0, 0x1F, 0xF8, 0x3E, 0x3C, 0x78, 0x1E, 0x70, 0x0E,
0x70, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0x70, 0x00, 0x78, 0x01, 0x3F, 0x1E,
0x1F, 0xFE, 0x07, 0xFC, 0x03, 0xF8, 0x3F, 0x83, 0xFC, 0x3C, 0x01, 0xC0,
0x0E, 0x00, 0x70, 0x03, 0x80, 0x7F, 0xE7, 0xFF, 0x3F, 0xF8, 0x38, 0x01,
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38,
0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00,
0x0F, 0xE3, 0x8F, 0xFD, 0xCF, 0x9F, 0xEF, 0x01, 0xF7, 0x00, 0x7F, 0x80,
0x3F, 0x80, 0x1F, 0xC0, 0x07, 0xE0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xFC,
0x00, 0x7E, 0x00, 0x7F, 0x80, 0x3D, 0xC0, 0x1E, 0xF0, 0x1F, 0x3E, 0x3F,
0x8F, 0xFD, 0xC3, 0xF8, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x3C, 0x00,
0x1C, 0x80, 0x1E, 0x78, 0x1E, 0x3F, 0xFF, 0x0F, 0xFE, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE3, 0xF8, 0xEF, 0xFC, 0xFE, 0x3E, 0xF8, 0x0E, 0xF0, 0x0F,
0xF0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07,
0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07,
0xE0, 0x07, 0xE0, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFC, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x0F, 0xFE, 0xFC,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x1E, 0xE0, 0x3C, 0xE0, 0x78, 0xE0, 0xF0,
0xE1, 0xE0, 0xE3, 0xC0, 0xE7, 0x80, 0xEF, 0x00, 0xEF, 0x00, 0xFF, 0x00,
0xFF, 0x80, 0xF3, 0xC0, 0xE1, 0xE0, 0xE0, 0xE0, 0xE0, 0xF0, 0xE0, 0x78,
0xE0, 0x3C, 0xE0, 0x1C, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE7, 0xF0, 0x7F, 0x1D, 0xFF, 0x9F, 0xFB,
0xF9, 0xF7, 0x9F, 0x7C, 0x0F, 0xC0, 0xFF, 0x00, 0xF0, 0x0F, 0xE0, 0x1C,
0x01, 0xF8, 0x03, 0x80, 0x3F, 0x00, 0x70, 0x07, 0xE0, 0x0E, 0x00, 0xFC,
0x01, 0xC0, 0x1F, 0x80, 0x38, 0x03, 0xF0, 0x07, 0x00, 0x7E, 0x00, 0xE0,
0x0F, 0xC0, 0x1C, 0x01, 0xF8, 0x03, 0x80, 0x3F, 0x00, 0x70, 0x07, 0xE0,
0x0E, 0x00, 0xFC, 0x01, 0xC0, 0x1F, 0x80, 0x38, 0x03, 0x80, 0xE3, 0xF8,
0xEF, 0xFC, 0xFF, 0x3E, 0xF8, 0x0E, 0xF0, 0x0F, 0xF0, 0x07, 0xE0, 0x07,
0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07,
0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07,
0x07, 0xF0, 0x0F, 0xFE, 0x0F, 0xCF, 0x8F, 0x01, 0xE7, 0x00, 0x77, 0x80,
0x1F, 0x80, 0x0F, 0xC0, 0x07, 0xE0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xFC,
0x00, 0x7E, 0x00, 0x3B, 0x80, 0x1D, 0xC0, 0x1C, 0xF0, 0x1E, 0x3E, 0x1E,
0x0F, 0xFE, 0x01, 0xFE, 0x00, 0xE3, 0xF0, 0x77, 0xFE, 0x3F, 0x9F, 0x9F,
0x01, 0xCF, 0x00, 0xF7, 0x80, 0x3B, 0x80, 0x1D, 0xC0, 0x0F, 0xE0, 0x07,
0xF0, 0x01, 0xF8, 0x01, 0xFC, 0x00, 0xFE, 0x00, 0x77, 0x80, 0x3B, 0xC0,
0x3D, 0xF0, 0x1C, 0xFC, 0x3E, 0x77, 0xFE, 0x39, 0xFE, 0x1C, 0x00, 0x0E,
0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00,
0x38, 0x00, 0x00, 0x0F, 0xE3, 0x8F, 0xFD, 0xCF, 0x9E, 0xEF, 0x01, 0xF7,
0x00, 0x7F, 0x80, 0x3F, 0xC0, 0x1F, 0xC0, 0x0F, 0xE0, 0x03, 0xF0, 0x01,
0xF8, 0x00, 0xFC, 0x00, 0x7E, 0x00, 0x7F, 0x80, 0x3D, 0xC0, 0x1E, 0xF0,
0x1F, 0x3E, 0x3F, 0x8F, 0xFD, 0xC3, 0xF8, 0xE0, 0x00, 0x70, 0x00, 0x38,
0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xC0, 0x00,
0xE0, 0xE3, 0xFC, 0xFF, 0xBF, 0xFE, 0x0F, 0x81, 0xE0, 0x38, 0x07, 0x00,
0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0,
0x1C, 0x03, 0x80, 0x00, 0x1F, 0xF3, 0xFF, 0xFE, 0x3D, 0xC0, 0x0E, 0x00,
0x70, 0x03, 0xC0, 0x0F, 0x80, 0x3F, 0x00, 0xFF, 0x00, 0xFC, 0x01, 0xF0,
0x03, 0x80, 0x1C, 0x00, 0xF0, 0x07, 0xE0, 0xFF, 0xFF, 0x9F, 0xF0, 0x18,
0x03, 0x00, 0x60, 0x1C, 0x07, 0xFF, 0xFF, 0xFF, 0xF9, 0xC0, 0x38, 0x07,
0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00,
0xE0, 0x1E, 0x01, 0xE2, 0x3F, 0xC3, 0xF8, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0,
0x0F, 0xF0, 0x1F, 0x78, 0x7F, 0x7F, 0xF7, 0x1F, 0xC7, 0xE0, 0x03, 0xDC,
0x00, 0xE7, 0x00, 0x39, 0xE0, 0x1E, 0x38, 0x07, 0x0E, 0x01, 0xC3, 0xC0,
0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x03, 0x87, 0x00, 0xE1, 0xC0, 0x38, 0xF0,
0x07, 0x38, 0x01, 0xCE, 0x00, 0x77, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00,
0x78, 0x00, 0x1E, 0x00, 0xF0, 0x0F, 0x00, 0xEE, 0x01, 0xE0, 0x1D, 0xC0,
0x7C, 0x07, 0xB8, 0x0F, 0xC0, 0xE3, 0x81, 0xF8, 0x1C, 0x70, 0x77, 0x03,
0x8E, 0x0E, 0x70, 0xF1, 0xE1, 0xCE, 0x1C, 0x1C, 0x31, 0xC3, 0x83, 0x8E,
0x18, 0x70, 0x71, 0xC3, 0x9C, 0x07, 0x30, 0x73, 0x80, 0xEE, 0x0E, 0x70,
0x1D, 0xC0, 0xEE, 0x03, 0xB8, 0x1F, 0x80, 0x36, 0x03, 0xF0, 0x07, 0xC0,
0x3E, 0x00, 0xF8, 0x07, 0x80, 0x1E, 0x00, 0xF0, 0x00, 0xF0, 0x07, 0xB8,
0x07, 0x8E, 0x03, 0x87, 0x83, 0x81, 0xE3, 0xC0, 0x73, 0xC0, 0x3D, 0xC0,
0x0F, 0xC0, 0x03, 0xE0, 0x01, 0xE0, 0x00, 0xF8, 0x00, 0xFE, 0x00, 0xF7,
0x00, 0x71, 0xC0, 0x70, 0xF0, 0x78, 0x3C, 0x78, 0x0E, 0x38, 0x07, 0xB8,
0x01, 0xE0, 0xF0, 0x03, 0xDC, 0x00, 0xE7, 0x00, 0x39, 0xE0, 0x1E, 0x38,
0x07, 0x0E, 0x01, 0xC1, 0xC0, 0xF0, 0x70, 0x38, 0x1E, 0x0E, 0x03, 0x87,
0x00, 0xE1, 0xC0, 0x1C, 0x70, 0x07, 0x38, 0x01, 0xCE, 0x00, 0x3B, 0x80,
0x0F, 0xC0, 0x01, 0xF0, 0x00, 0x78, 0x00, 0x1E, 0x00, 0x07, 0x80, 0x01,
0xC0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x3F, 0xC0,
0x0F, 0xC0, 0x00, 0x7F, 0xFD, 0xFF, 0xF7, 0xFF, 0xC0, 0x0E, 0x00, 0x78,
0x03, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0xC0,
0x1E, 0x00, 0x70, 0x03, 0x80, 0x1E, 0x00, 0x70, 0x03, 0xFF, 0xFF, 0xFF,
0xC0, 0x00, 0xE0, 0x7C, 0x1F, 0x83, 0x80, 0xF0, 0x1C, 0x03, 0x80, 0x70,
0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0x7C, 0x3E, 0x07, 0x80, 0xFC,
0x03, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01,
0xC0, 0x3C, 0x03, 0xC0, 0x7E, 0x03, 0xC0, 0x08, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0x1F,
0x81, 0xF0, 0x0F, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0,
0x38, 0x07, 0x00, 0xF0, 0x0F, 0x00, 0xF8, 0x0F, 0x07, 0xE1, 0xE0, 0x38,
0x07, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x1F,
0x0F, 0xC1, 0xF0, 0x30, 0x00, 0x1C, 0x01, 0xFF, 0x81, 0xFF, 0xFF, 0xC1,
0xFF, 0x80, 0x3C };
const GFXglyph NotoSans_Regular18pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 9, 0, 0 }, // 0x20 ' '
{ 1, 4, 26, 9, 3, -24 }, // 0x21 '!'
{ 14, 10, 9, 14, 2, -24 }, // 0x22 '"'
{ 26, 21, 25, 23, 1, -24 }, // 0x23 '#'
{ 92, 16, 29, 20, 2, -26 }, // 0x24 '$'
{ 150, 26, 26, 29, 2, -25 }, // 0x25 '%'
{ 235, 24, 26, 26, 2, -25 }, // 0x26 '&'
{ 313, 4, 9, 8, 2, -24 }, // 0x27 '''
{ 318, 9, 31, 11, 1, -24 }, // 0x28 '('
{ 353, 8, 31, 11, 1, -24 }, // 0x29 ')'
{ 384, 17, 16, 19, 1, -26 }, // 0x2A '*'
{ 418, 16, 17, 20, 2, -20 }, // 0x2B '+'
{ 452, 6, 9, 9, 1, -3 }, // 0x2C ','
{ 459, 9, 3, 11, 1, -10 }, // 0x2D '-'
{ 463, 4, 5, 9, 3, -3 }, // 0x2E '.'
{ 466, 13, 25, 13, 0, -24 }, // 0x2F '/'
{ 507, 16, 26, 20, 2, -25 }, // 0x30 '0'
{ 559, 10, 25, 20, 3, -24 }, // 0x31 '1'
{ 591, 16, 26, 20, 2, -25 }, // 0x32 '2'
{ 643, 16, 26, 20, 2, -25 }, // 0x33 '3'
{ 695, 18, 25, 20, 1, -24 }, // 0x34 '4'
{ 752, 16, 25, 20, 2, -24 }, // 0x35 '5'
{ 802, 17, 26, 20, 2, -25 }, // 0x36 '6'
{ 858, 16, 25, 20, 2, -24 }, // 0x37 '7'
{ 908, 16, 26, 20, 2, -25 }, // 0x38 '8'
{ 960, 16, 26, 20, 2, -25 }, // 0x39 '9'
{ 1012, 4, 20, 9, 3, -18 }, // 0x3A ':'
{ 1022, 6, 24, 9, 1, -18 }, // 0x3B ';'
{ 1040, 16, 17, 20, 2, -20 }, // 0x3C '<'
{ 1074, 16, 9, 20, 2, -16 }, // 0x3D '='
{ 1092, 16, 17, 20, 2, -20 }, // 0x3E '>'
{ 1126, 14, 27, 15, 0, -25 }, // 0x3F '?'
{ 1174, 28, 28, 32, 2, -24 }, // 0x40 '@'
{ 1272, 22, 25, 23, 0, -24 }, // 0x41 'A'
{ 1341, 18, 25, 23, 3, -24 }, // 0x42 'B'
{ 1398, 19, 26, 22, 2, -25 }, // 0x43 'C'
{ 1460, 21, 25, 26, 3, -24 }, // 0x44 'D'
{ 1526, 14, 25, 20, 3, -24 }, // 0x45 'E'
{ 1570, 14, 25, 18, 3, -24 }, // 0x46 'F'
{ 1614, 21, 26, 26, 2, -25 }, // 0x47 'G'
{ 1683, 20, 25, 26, 3, -24 }, // 0x48 'H'
{ 1746, 10, 25, 12, 1, -24 }, // 0x49 'I'
{ 1778, 9, 32, 10, -3, -24 }, // 0x4A 'J'
{ 1814, 19, 25, 22, 3, -24 }, // 0x4B 'K'
{ 1874, 15, 25, 18, 3, -24 }, // 0x4C 'L'
{ 1921, 26, 25, 32, 3, -24 }, // 0x4D 'M'
{ 2003, 20, 25, 27, 3, -24 }, // 0x4E 'N'
{ 2066, 23, 26, 28, 2, -25 }, // 0x4F 'O'
{ 2141, 17, 25, 21, 3, -24 }, // 0x50 'P'
{ 2195, 23, 32, 28, 2, -25 }, // 0x51 'Q'
{ 2287, 18, 25, 22, 3, -24 }, // 0x52 'R'
{ 2344, 16, 26, 19, 2, -25 }, // 0x53 'S'
{ 2396, 19, 25, 20, 0, -24 }, // 0x54 'T'
{ 2456, 20, 25, 26, 3, -24 }, // 0x55 'U'
{ 2519, 21, 25, 21, 0, -24 }, // 0x56 'V'
{ 2585, 32, 25, 33, 0, -24 }, // 0x57 'W'
{ 2685, 21, 25, 21, 0, -24 }, // 0x58 'X'
{ 2751, 20, 25, 20, 0, -24 }, // 0x59 'Y'
{ 2814, 18, 25, 20, 1, -24 }, // 0x5A 'Z'
{ 2871, 8, 31, 12, 3, -24 }, // 0x5B '['
{ 2902, 13, 25, 13, 0, -24 }, // 0x5C '\'
{ 2943, 8, 31, 12, 1, -24 }, // 0x5D ']'
{ 2974, 18, 16, 20, 1, -24 }, // 0x5E '^'
{ 3010, 16, 2, 16, 0, 4 }, // 0x5F '_'
{ 3014, 8, 6, 10, 1, -26 }, // 0x60 '`'
{ 3020, 15, 19, 20, 2, -18 }, // 0x61 'a'
{ 3056, 17, 27, 22, 3, -26 }, // 0x62 'b'
{ 3114, 14, 19, 17, 2, -18 }, // 0x63 'c'
{ 3148, 17, 27, 22, 2, -26 }, // 0x64 'd'
{ 3206, 16, 19, 20, 2, -18 }, // 0x65 'e'
{ 3244, 13, 27, 12, 1, -26 }, // 0x66 'f'
{ 3288, 17, 27, 22, 2, -18 }, // 0x67 'g'
{ 3346, 16, 27, 22, 3, -26 }, // 0x68 'h'
{ 3400, 3, 26, 9, 3, -25 }, // 0x69 'i'
{ 3410, 8, 34, 9, -2, -25 }, // 0x6A 'j'
{ 3444, 16, 27, 19, 3, -26 }, // 0x6B 'k'
{ 3498, 3, 27, 9, 3, -26 }, // 0x6C 'l'
{ 3509, 27, 19, 33, 3, -18 }, // 0x6D 'm'
{ 3574, 16, 19, 22, 3, -18 }, // 0x6E 'n'
{ 3612, 17, 19, 21, 2, -18 }, // 0x6F 'o'
{ 3653, 17, 27, 22, 3, -18 }, // 0x70 'p'
{ 3711, 17, 27, 22, 2, -18 }, // 0x71 'q'
{ 3769, 11, 19, 15, 3, -18 }, // 0x72 'r'
{ 3796, 13, 19, 17, 2, -18 }, // 0x73 's'
{ 3827, 11, 23, 13, 1, -22 }, // 0x74 't'
{ 3859, 16, 19, 22, 3, -18 }, // 0x75 'u'
{ 3897, 18, 19, 18, 0, -18 }, // 0x76 'v'
{ 3940, 27, 19, 28, 0, -18 }, // 0x77 'w'
{ 4005, 17, 19, 19, 1, -18 }, // 0x78 'x'
{ 4046, 18, 27, 18, 0, -18 }, // 0x79 'y'
{ 4107, 14, 19, 17, 1, -18 }, // 0x7A 'z'
{ 4141, 11, 31, 13, 1, -24 }, // 0x7B '{'
{ 4184, 3, 36, 19, 8, -26 }, // 0x7C '|'
{ 4198, 11, 31, 13, 1, -24 }, // 0x7D '}'
{ 4241, 16, 5, 20, 2, -14 } }; // 0x7E '~'
const GFXfont NotoSans_Regular18pt7b PROGMEM = {
(uint8_t *)NotoSans_Regular18pt7bBitmaps,
(GFXglyph *)NotoSans_Regular18pt7bGlyphs,
0x20, 0x7E, 48 };
// Approx. 4923 bytes
#endif // NOTOSANS18PT7B_H
@@ -0,0 +1,545 @@
#ifndef NOTOSANS20PT7B_H
#define NOTOSANS20PT7B_H
const uint8_t NotoSans_Regular20pt7bBitmaps[] PROGMEM = {
0x00, 0xF7, 0xBD, 0xEF, 0x7B, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73,
0x98, 0xC0, 0x00, 0x0C, 0xF7, 0xFF, 0xE2, 0x00, 0xE1, 0xF8, 0x7E, 0x1F,
0x87, 0xE1, 0xF8, 0x7E, 0x1F, 0x87, 0xE1, 0xF8, 0x70, 0x00, 0x70, 0x70,
0x01, 0xC0, 0xE0, 0x03, 0x81, 0x80, 0x07, 0x03, 0x00, 0x0E, 0x0E, 0x00,
0x1C, 0x1C, 0x00, 0x70, 0x38, 0x00, 0xE0, 0x60, 0x7F, 0xFF, 0xFE, 0xFF,
0xFF, 0xFD, 0xFF, 0xFF, 0xF8, 0x0C, 0x0E, 0x00, 0x38, 0x1C, 0x00, 0x70,
0x70, 0x00, 0xE0, 0xE0, 0x01, 0xC1, 0xC0, 0x03, 0x03, 0x81, 0xFF, 0xFF,
0xFB, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xE0, 0x70, 0x70, 0x00, 0xC0, 0xE0,
0x03, 0x81, 0xC0, 0x07, 0x03, 0x00, 0x0E, 0x0E, 0x00, 0x1C, 0x1C, 0x00,
0x30, 0x38, 0x00, 0xE0, 0x70, 0x00, 0x00, 0xC0, 0x00, 0x30, 0x00, 0x0C,
0x00, 0x03, 0x00, 0x0F, 0xFF, 0x07, 0xFF, 0xE3, 0xFF, 0xF9, 0xE3, 0x04,
0x70, 0xC0, 0x3C, 0x30, 0x0F, 0x0C, 0x01, 0xC3, 0x00, 0x78, 0xC0, 0x1F,
0xB0, 0x03, 0xFC, 0x00, 0x3F, 0xE0, 0x03, 0xFE, 0x00, 0x3F, 0xE0, 0x0C,
0xFC, 0x03, 0x0F, 0x00, 0xC1, 0xC0, 0x30, 0x70, 0x0C, 0x1E, 0x03, 0x0F,
0xF0, 0xCF, 0xBF, 0xFF, 0xEF, 0xFF, 0xE0, 0x7F, 0xE0, 0x00, 0xC0, 0x00,
0x30, 0x00, 0x0C, 0x00, 0x03, 0x00, 0x1F, 0x80, 0x0F, 0x01, 0xFE, 0x00,
0x70, 0x1C, 0x70, 0x07, 0x00, 0xE1, 0xC0, 0x38, 0x0E, 0x0E, 0x03, 0x80,
0x70, 0x70, 0x3C, 0x03, 0x81, 0x81, 0xC0, 0x1C, 0x0C, 0x1C, 0x00, 0xE0,
0x70, 0xE0, 0x07, 0x03, 0x0E, 0x00, 0x38, 0x18, 0x70, 0x01, 0xC1, 0xC7,
0x1F, 0x0E, 0x0E, 0x39, 0xFE, 0x38, 0x73, 0x9E, 0xF1, 0xEF, 0x3C, 0xE1,
0xC7, 0xF9, 0xCE, 0x0E, 0x1F, 0x1C, 0x70, 0x30, 0x00, 0xE3, 0x81, 0xC0,
0x0E, 0x1C, 0x0E, 0x00, 0x70, 0xE0, 0x70, 0x07, 0x07, 0x03, 0x80, 0x38,
0x38, 0x1C, 0x03, 0x81, 0xC0, 0xC0, 0x1C, 0x0E, 0x0E, 0x01, 0xC0, 0x38,
0x70, 0x1C, 0x01, 0xC7, 0x00, 0xE0, 0x07, 0xF8, 0x0E, 0x00, 0x1F, 0x80,
0x03, 0xFC, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x7E, 0xFC, 0x00, 0x0F, 0x07,
0x80, 0x01, 0xC0, 0x78, 0x00, 0x38, 0x0F, 0x00, 0x07, 0x01, 0xE0, 0x00,
0xE0, 0x38, 0x00, 0x1E, 0x0F, 0x00, 0x01, 0xE3, 0xC0, 0x00, 0x3E, 0xF0,
0x00, 0x03, 0xFC, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x07,
0xFE, 0x01, 0xE1, 0xF3, 0xE0, 0x38, 0x7C, 0x3E, 0x07, 0x0F, 0x03, 0xE1,
0xE3, 0xC0, 0x3E, 0x38, 0x78, 0x03, 0xEF, 0x0F, 0x00, 0x3F, 0xC1, 0xE0,
0x03, 0xF8, 0x3C, 0x00, 0x3E, 0x07, 0xC0, 0x0F, 0xE0, 0x7C, 0x07, 0xFE,
0x07, 0xFF, 0xFB, 0xE0, 0x7F, 0xFC, 0x3E, 0x07, 0xFE, 0x03, 0xF0, 0xFF,
0xFF, 0xFF, 0xFC, 0x07, 0x87, 0x87, 0x83, 0x83, 0xC1, 0xC1, 0xE0, 0xF0,
0x70, 0x78, 0x3C, 0x1E, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38,
0x1C, 0x0E, 0x07, 0x03, 0xC1, 0xE0, 0xF0, 0x38, 0x1E, 0x0F, 0x03, 0x81,
0xE0, 0x70, 0x3C, 0x0E, 0x03, 0xC0, 0xF0, 0x3C, 0x0E, 0x07, 0x81, 0xC0,
0xF0, 0x38, 0x1E, 0x0F, 0x03, 0x81, 0xC0, 0xF0, 0x78, 0x3C, 0x0E, 0x07,
0x03, 0x81, 0xC0, 0xE0, 0x70, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x07, 0x83,
0xC1, 0xC1, 0xE0, 0xF0, 0xF0, 0x70, 0x78, 0x78, 0x00, 0x01, 0xE0, 0x00,
0x70, 0x00, 0x1C, 0x00, 0x07, 0x00, 0x01, 0xC0, 0x00, 0x70, 0x0E, 0x1C,
0x3B, 0xFB, 0x7F, 0xFF, 0xFF, 0xC7, 0xFF, 0x80, 0x3E, 0x00, 0x1D, 0xC0,
0x07, 0x78, 0x03, 0xCE, 0x01, 0xE3, 0xC0, 0xF8, 0x78, 0x1C, 0x1C, 0x01,
0x02, 0x00, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x00,
0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFC, 0x03, 0x80, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00,
0x03, 0x80, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x3D, 0xE7, 0x9E,
0x71, 0xCF, 0x38, 0xE3, 0x00, 0xFF, 0xFF, 0xFF, 0xE0, 0x67, 0xBF, 0xFF,
0x10, 0x00, 0x1C, 0x00, 0xF0, 0x03, 0x80, 0x0E, 0x00, 0x78, 0x01, 0xC0,
0x0F, 0x00, 0x38, 0x00, 0xE0, 0x07, 0x80, 0x1C, 0x00, 0x70, 0x03, 0xC0,
0x0E, 0x00, 0x78, 0x01, 0xC0, 0x07, 0x00, 0x3C, 0x00, 0xE0, 0x03, 0x80,
0x1E, 0x00, 0x70, 0x03, 0xC0, 0x0E, 0x00, 0x38, 0x01, 0xE0, 0x07, 0x00,
0x3C, 0x00, 0x07, 0xF8, 0x03, 0xFF, 0x81, 0xFF, 0xF0, 0xF0, 0x3C, 0x78,
0x07, 0x9E, 0x00, 0xE7, 0x00, 0x3D, 0xC0, 0x0F, 0xF0, 0x01, 0xFC, 0x00,
0x7F, 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x1F,
0x80, 0x07, 0xE0, 0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x07, 0x70,
0x03, 0xDC, 0x00, 0xF7, 0x80, 0x38, 0xE0, 0x1E, 0x3C, 0x0F, 0x07, 0xFF,
0xC0, 0xFF, 0xE0, 0x1F, 0xE0, 0x01, 0xE0, 0x7C, 0x1F, 0x87, 0xF3, 0xEF,
0xF9, 0xDC, 0x39, 0x07, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01,
0xC0, 0x38, 0x07, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0,
0x38, 0x07, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0F, 0xF8, 0x0F, 0xFF,
0x87, 0xFF, 0xF3, 0xE0, 0x3C, 0x60, 0x07, 0x80, 0x01, 0xE0, 0x00, 0x38,
0x00, 0x0E, 0x00, 0x03, 0x80, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x1C, 0x00,
0x0F, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x78,
0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xC0, 0x01,
0xE0, 0x00, 0x70, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F,
0xF8, 0x1F, 0xFF, 0x8F, 0xFF, 0xF1, 0xC0, 0x3E, 0x40, 0x07, 0x80, 0x00,
0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x07, 0x80, 0x01, 0xE0, 0x00, 0xF0,
0x00, 0xF8, 0x0F, 0xFC, 0x03, 0xFC, 0x00, 0xFF, 0xE0, 0x00, 0x7C, 0x00,
0x07, 0x80, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x07, 0x00, 0x01, 0xC0, 0x00,
0xF0, 0x00, 0x3C, 0x00, 0x1F, 0xC0, 0x0F, 0xBF, 0xFF, 0xCF, 0xFF, 0xE1,
0xFF, 0xE0, 0x00, 0x07, 0x80, 0x00, 0x7C, 0x00, 0x07, 0xE0, 0x00, 0x7F,
0x00, 0x03, 0xF8, 0x00, 0x3B, 0xC0, 0x03, 0xDE, 0x00, 0x1C, 0xF0, 0x01,
0xC7, 0x80, 0x1E, 0x3C, 0x00, 0xE1, 0xE0, 0x0E, 0x0F, 0x00, 0xE0, 0x78,
0x0F, 0x03, 0xC0, 0x70, 0x1E, 0x07, 0x00, 0xF0, 0x78, 0x07, 0x83, 0x80,
0x3C, 0x38, 0x01, 0xE1, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x01,
0xE0, 0x00, 0x0F, 0x00, 0x3F, 0xFF, 0x0F, 0xFF, 0xC3, 0xFF, 0xF0, 0xE0,
0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x00, 0xE0, 0x00, 0x38, 0x00,
0x1E, 0x00, 0x07, 0x80, 0x01, 0xFF, 0xE0, 0x7F, 0xFE, 0x0F, 0xFF, 0xC0,
0x00, 0xF8, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x1C, 0x00,
0x07, 0x00, 0x01, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x1E, 0xC0, 0x0F,
0xBF, 0xFF, 0xCF, 0xFF, 0xE0, 0xFF, 0xE0, 0x00, 0xFF, 0x00, 0x7F, 0xE0,
0x3F, 0xEC, 0x07, 0x80, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x0E, 0x00, 0x03,
0xC0, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x80, 0x79, 0xFF, 0x0F,
0x7F, 0xF1, 0xFE, 0x1F, 0x3F, 0x00, 0xF7, 0xC0, 0x1E, 0xF0, 0x01, 0xDE,
0x00, 0x3B, 0xC0, 0x07, 0xF8, 0x00, 0xF7, 0x00, 0x1C, 0xE0, 0x03, 0x9E,
0x00, 0x71, 0xC0, 0x1E, 0x3C, 0x07, 0x83, 0xFF, 0xF0, 0x3F, 0xFC, 0x01,
0xFE, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x07, 0x00,
0x03, 0xC0, 0x00, 0xE0, 0x00, 0x78, 0x00, 0x1C, 0x00, 0x0F, 0x00, 0x03,
0x80, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0x80,
0x01, 0xE0, 0x00, 0x70, 0x00, 0x3C, 0x00, 0x0E, 0x00, 0x07, 0x80, 0x01,
0xE0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x07, 0x80, 0x03, 0xC0,
0x00, 0xF0, 0x00, 0x78, 0x00, 0x07, 0xFC, 0x07, 0xFF, 0x83, 0xFB, 0xF1,
0xF0, 0x1E, 0x78, 0x03, 0x9C, 0x00, 0xE7, 0x00, 0x3D, 0xC0, 0x0E, 0x78,
0x03, 0x8E, 0x01, 0xE3, 0xE0, 0xF0, 0x7E, 0xF8, 0x0F, 0xF8, 0x01, 0xFE,
0x00, 0xFF, 0xE0, 0xF8, 0xFC, 0x7C, 0x0F, 0x9E, 0x00, 0xFF, 0x00, 0x3F,
0x80, 0x07, 0xE0, 0x01, 0xF8, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x0F, 0x78,
0x07, 0xDF, 0xCF, 0xE3, 0xFF, 0xF0, 0x3F, 0xF0, 0x07, 0xF8, 0x07, 0xFF,
0x03, 0xFF, 0xE1, 0xF0, 0x3C, 0x78, 0x07, 0xBC, 0x00, 0xEF, 0x00, 0x3F,
0x80, 0x07, 0xE0, 0x01, 0xF8, 0x00, 0x7E, 0x00, 0x1F, 0xC0, 0x0F, 0xF0,
0x03, 0xDE, 0x01, 0xF7, 0xE1, 0xFC, 0xFF, 0xF7, 0x0F, 0xF1, 0xC0, 0x40,
0x70, 0x00, 0x3C, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x01, 0xE0, 0x00, 0x70,
0x00, 0x3C, 0x00, 0x3E, 0x0C, 0xFF, 0x03, 0xFF, 0x80, 0xFF, 0x80, 0x27,
0xBF, 0xFF, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3D, 0xFF,
0xF8, 0x80, 0x08, 0x78, 0xF9, 0xF3, 0xC3, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0xF1, 0xE3, 0x8F, 0x1E, 0x38, 0x70,
0xC3, 0x80, 0x00, 0x00, 0x40, 0x00, 0x30, 0x00, 0x3C, 0x00, 0x3F, 0x00,
0x3F, 0x00, 0x3F, 0x00, 0x3F, 0x00, 0x3E, 0x00, 0x3E, 0x00, 0x3E, 0x00,
0x0F, 0x00, 0x03, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xFC, 0x00, 0x1F, 0xC0,
0x01, 0xFC, 0x00, 0x0F, 0xC0, 0x00, 0xF0, 0x00, 0x0C, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x80, 0x00,
0x38, 0x00, 0x0F, 0x80, 0x03, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00,
0x1F, 0x80, 0x01, 0xF8, 0x00, 0x1F, 0x80, 0x01, 0xF0, 0x00, 0x3C, 0x00,
0x3F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7E, 0x00, 0xFE, 0x00, 0xFE, 0x00,
0x3C, 0x00, 0x0C, 0x00, 0x00, 0x1F, 0xF0, 0xFF, 0xFC, 0x7F, 0xFE, 0x70,
0x1E, 0x00, 0x0F, 0x00, 0x07, 0x00, 0x07, 0x00, 0x07, 0x00, 0x0F, 0x00,
0x0E, 0x00, 0x1E, 0x00, 0x3C, 0x00, 0x78, 0x00, 0xF0, 0x01, 0xE0, 0x03,
0xC0, 0x03, 0x80, 0x03, 0x00, 0x07, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x07, 0x80, 0x07, 0x80, 0x07,
0x80, 0x01, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x03,
0xFF, 0xFE, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x78, 0x00, 0x0F, 0x01, 0xE0,
0x00, 0x0E, 0x07, 0x80, 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x0E, 0x38, 0x07,
0xFC, 0x1C, 0x70, 0x3F, 0xF8, 0x39, 0xC0, 0xF0, 0x70, 0x3B, 0x83, 0xC0,
0xE0, 0x77, 0x07, 0x01, 0xC0, 0xEC, 0x1E, 0x03, 0x81, 0xF8, 0x38, 0x07,
0x03, 0xF0, 0x70, 0x0E, 0x07, 0xE0, 0xE0, 0x1C, 0x0F, 0xC1, 0xC0, 0x38,
0x1F, 0x83, 0x80, 0xF0, 0x77, 0x03, 0x81, 0xE0, 0xE6, 0x07, 0x87, 0xE3,
0x8E, 0x07, 0xFD, 0xFF, 0x1C, 0x0F, 0xF1, 0xFC, 0x38, 0x03, 0x80, 0xE0,
0x38, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
0x78, 0x00, 0x10, 0x00, 0x7E, 0x01, 0xE0, 0x00, 0x3F, 0xFF, 0xC0, 0x00,
0x1F, 0xFF, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x0F,
0x80, 0x00, 0x07, 0xE0, 0x00, 0x07, 0x70, 0x00, 0x03, 0xB8, 0x00, 0x03,
0xDE, 0x00, 0x01, 0xC7, 0x00, 0x00, 0xE3, 0x80, 0x00, 0xF1, 0xE0, 0x00,
0x70, 0x70, 0x00, 0x78, 0x3C, 0x00, 0x38, 0x0E, 0x00, 0x1C, 0x07, 0x00,
0x1E, 0x03, 0xC0, 0x0E, 0x00, 0xE0, 0x0F, 0xFF, 0xF8, 0x07, 0xFF, 0xFC,
0x03, 0xFF, 0xFE, 0x03, 0xC0, 0x07, 0x81, 0xC0, 0x03, 0xC0, 0xE0, 0x00,
0xE0, 0xF0, 0x00, 0x78, 0x70, 0x00, 0x1C, 0x78, 0x00, 0x0F, 0x3C, 0x00,
0x07, 0x9C, 0x00, 0x01, 0xDE, 0x00, 0x00, 0xF0, 0xFF, 0xF8, 0x1F, 0xFF,
0xE3, 0xFF, 0xFE, 0x70, 0x07, 0xEE, 0x00, 0x3D, 0xC0, 0x07, 0xB8, 0x00,
0x77, 0x00, 0x0E, 0xE0, 0x01, 0xDC, 0x00, 0x7B, 0x80, 0x0E, 0x70, 0x07,
0xCF, 0xFF, 0xE1, 0xFF, 0xF8, 0x3F, 0xFF, 0xE7, 0x00, 0x3E, 0xE0, 0x03,
0xFC, 0x00, 0x3F, 0x80, 0x07, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x03,
0xF8, 0x00, 0x7F, 0x00, 0x1F, 0xE0, 0x07, 0xDF, 0xFF, 0xF3, 0xFF, 0xFC,
0x7F, 0xFE, 0x00, 0x00, 0x7F, 0xF0, 0x0F, 0xFF, 0xF0, 0x7F, 0xFF, 0x83,
0xF0, 0x0E, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x03, 0xC0, 0x00, 0x1F, 0x00,
0x00, 0x78, 0x00, 0x01, 0xE0, 0x00, 0x07, 0x00, 0x00, 0x1C, 0x00, 0x00,
0xF0, 0x00, 0x03, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0x3C, 0x00, 0x00, 0xF0,
0x00, 0x01, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x1E, 0x00, 0x00, 0x78, 0x00,
0x00, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x10,
0x1F, 0xFF, 0xC0, 0x3F, 0xFF, 0x00, 0x3F, 0xFC, 0xFF, 0xF8, 0x03, 0xFF,
0xFC, 0x0F, 0xFF, 0xF8, 0x38, 0x03, 0xF0, 0xE0, 0x03, 0xE3, 0x80, 0x03,
0xCE, 0x00, 0x0F, 0xB8, 0x00, 0x1E, 0xE0, 0x00, 0x3B, 0x80, 0x00, 0xFE,
0x00, 0x03, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00,
0x03, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x03,
0xF8, 0x00, 0x1E, 0xE0, 0x00, 0x7B, 0x80, 0x03, 0xEE, 0x00, 0x1F, 0x38,
0x00, 0xF8, 0xE0, 0x1F, 0xC3, 0xFF, 0xFE, 0x0F, 0xFF, 0xE0, 0x3F, 0xFC,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x0E, 0x00, 0x1C, 0x00,
0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80,
0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0,
0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38,
0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x00, 0x00,
0x7F, 0xF8, 0x01, 0xFF, 0xFE, 0x07, 0xFF, 0xFE, 0x0F, 0xC0, 0x0C, 0x1F,
0x00, 0x00, 0x1E, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x78,
0x00, 0x00, 0x78, 0x00, 0x00, 0x70, 0x00, 0x00, 0x70, 0x00, 0x00, 0xF0,
0x00, 0x00, 0xF0, 0x03, 0xFF, 0xF0, 0x03, 0xFF, 0xF0, 0x03, 0xFF, 0x70,
0x00, 0x0F, 0x70, 0x00, 0x0F, 0x78, 0x00, 0x0F, 0x78, 0x00, 0x0F, 0x78,
0x00, 0x0F, 0x3C, 0x00, 0x0F, 0x3E, 0x00, 0x0F, 0x1F, 0x00, 0x0F, 0x0F,
0xC0, 0x0F, 0x07, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0x00, 0xFF, 0xFC, 0xE0,
0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x03,
0xF0, 0x00, 0x1F, 0x80, 0x00, 0xFC, 0x00, 0x07, 0xE0, 0x00, 0x3F, 0x00,
0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFC, 0x00, 0x07, 0xE0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00,
0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x80, 0x00, 0xFC,
0x00, 0x07, 0xE0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00,
0x70, 0xFF, 0xFF, 0xF7, 0xF0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C,
0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01,
0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x0F, 0xCF, 0xFF, 0xFF,
0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0,
0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C,
0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01,
0xC0, 0xF0, 0x3C, 0x1E, 0xFF, 0xBF, 0xCF, 0xE0, 0xE0, 0x01, 0xFE, 0x00,
0x3C, 0xE0, 0x07, 0xCE, 0x00, 0x78, 0xE0, 0x0F, 0x0E, 0x01, 0xE0, 0xE0,
0x3C, 0x0E, 0x07, 0x80, 0xE0, 0xF0, 0x0E, 0x1E, 0x00, 0xE3, 0xC0, 0x0E,
0x78, 0x00, 0xEF, 0x80, 0x0E, 0xFC, 0x00, 0xFF, 0xC0, 0x0F, 0x9E, 0x00,
0xF0, 0xF0, 0x0E, 0x0F, 0x80, 0xE0, 0x78, 0x0E, 0x03, 0xC0, 0xE0, 0x1E,
0x0E, 0x01, 0xF0, 0xE0, 0x0F, 0x0E, 0x00, 0x78, 0xE0, 0x07, 0xCE, 0x00,
0x3C, 0xE0, 0x01, 0xEE, 0x00, 0x0F, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x3F, 0xFC, 0x00, 0x03,
0xFF, 0xC0, 0x00, 0x7F, 0xFE, 0x00, 0x07, 0xFE, 0xE0, 0x00, 0xFF, 0xEE,
0x00, 0x0E, 0xFE, 0xF0, 0x00, 0xEF, 0xE7, 0x00, 0x1C, 0xFE, 0x78, 0x01,
0xCF, 0xE3, 0x80, 0x1C, 0xFE, 0x38, 0x03, 0x8F, 0xE3, 0xC0, 0x38, 0xFE,
0x1C, 0x07, 0x8F, 0xE1, 0xC0, 0x70, 0xFE, 0x1E, 0x07, 0x0F, 0xE0, 0xE0,
0xE0, 0xFE, 0x0F, 0x0E, 0x0F, 0xE0, 0x71, 0xE0, 0xFE, 0x07, 0x1C, 0x0F,
0xE0, 0x79, 0xC0, 0xFE, 0x03, 0xBC, 0x0F, 0xE0, 0x3B, 0x80, 0xFE, 0x03,
0xF8, 0x0F, 0xE0, 0x1F, 0x00, 0xFE, 0x01, 0xF0, 0x0F, 0xE0, 0x0F, 0x00,
0xFE, 0x00, 0xE0, 0x0F, 0xF0, 0x00, 0x1F, 0xE0, 0x00, 0x7F, 0x80, 0x01,
0xFF, 0x00, 0x07, 0xFE, 0x00, 0x1F, 0xF8, 0x00, 0x7E, 0xF0, 0x01, 0xF9,
0xE0, 0x07, 0xE7, 0x80, 0x1F, 0x8F, 0x00, 0x7E, 0x1E, 0x01, 0xF8, 0x78,
0x07, 0xE0, 0xF0, 0x1F, 0x81, 0xE0, 0x7E, 0x07, 0x81, 0xF8, 0x0F, 0x07,
0xE0, 0x3C, 0x1F, 0x80, 0x78, 0x7E, 0x00, 0xF1, 0xF8, 0x03, 0xC7, 0xE0,
0x07, 0x9F, 0x80, 0x0F, 0x7E, 0x00, 0x3D, 0xF8, 0x00, 0x7F, 0xE0, 0x00,
0xFF, 0x80, 0x03, 0xFE, 0x00, 0x07, 0xF8, 0x00, 0x0F, 0x00, 0xFF, 0xE0,
0x00, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xC0, 0x3E, 0x00, 0xF8, 0x1F, 0x00,
0x1F, 0x0F, 0x80, 0x03, 0xC3, 0xC0, 0x00, 0x79, 0xE0, 0x00, 0x1E, 0x78,
0x00, 0x03, 0x9E, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x0F,
0xF0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3F, 0xC0, 0x00,
0x0F, 0x70, 0x00, 0x03, 0xDC, 0x00, 0x00, 0xF7, 0x80, 0x00, 0x3D, 0xE0,
0x00, 0x0E, 0x78, 0x00, 0x07, 0x8F, 0x00, 0x01, 0xE3, 0xC0, 0x00, 0xF0,
0x7C, 0x00, 0x7C, 0x0F, 0x80, 0x3E, 0x01, 0xFF, 0xFF, 0x00, 0x3F, 0xFF,
0x80, 0x03, 0xFF, 0x80, 0xFF, 0xF0, 0x3F, 0xFF, 0x0F, 0xFF, 0xF3, 0x80,
0xFC, 0xE0, 0x0F, 0xB8, 0x01, 0xEE, 0x00, 0x3F, 0x80, 0x0F, 0xE0, 0x03,
0xF8, 0x00, 0xFE, 0x00, 0x3B, 0x80, 0x1E, 0xE0, 0x0F, 0xB8, 0x07, 0xCF,
0xFF, 0xE3, 0xFF, 0xF0, 0xFF, 0xF0, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80,
0x00, 0xE0, 0x00, 0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x00, 0xE0, 0x00,
0x38, 0x00, 0x0E, 0x00, 0x03, 0x80, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0xFF,
0xFE, 0x00, 0x7F, 0xFF, 0xC0, 0x3E, 0x00, 0xF8, 0x1F, 0x00, 0x1F, 0x0F,
0x80, 0x03, 0xC3, 0xC0, 0x00, 0x79, 0xE0, 0x00, 0x1E, 0x78, 0x00, 0x03,
0x9E, 0x00, 0x00, 0xF7, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x0F, 0xF0, 0x00,
0x03, 0xFC, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x0F, 0x70,
0x00, 0x03, 0xDC, 0x00, 0x00, 0xF7, 0x80, 0x00, 0x3D, 0xE0, 0x00, 0x0E,
0x78, 0x00, 0x07, 0x8F, 0x00, 0x01, 0xE3, 0xC0, 0x00, 0xF0, 0x7C, 0x00,
0x7C, 0x0F, 0x80, 0x3E, 0x01, 0xFF, 0xFF, 0x00, 0x3F, 0xFF, 0x80, 0x03,
0xFF, 0x80, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0x80,
0x00, 0x01, 0xF0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x07, 0xC0, 0x00, 0x00,
0xF8, 0xFF, 0xF0, 0x0F, 0xFF, 0xC0, 0xFF, 0xFF, 0x0E, 0x01, 0xF8, 0xE0,
0x07, 0x8E, 0x00, 0x78, 0xE0, 0x03, 0xCE, 0x00, 0x3C, 0xE0, 0x03, 0xCE,
0x00, 0x3C, 0xE0, 0x03, 0x8E, 0x00, 0x78, 0xE0, 0x0F, 0x0F, 0xFF, 0xE0,
0xFF, 0xFC, 0x0F, 0xFF, 0x00, 0xE0, 0x78, 0x0E, 0x03, 0x80, 0xE0, 0x3C,
0x0E, 0x01, 0xE0, 0xE0, 0x1E, 0x0E, 0x00, 0xF0, 0xE0, 0x0F, 0x0E, 0x00,
0x78, 0xE0, 0x03, 0xCE, 0x00, 0x3C, 0xE0, 0x01, 0xEE, 0x00, 0x1F, 0x07,
0xFE, 0x07, 0xFF, 0xE3, 0xFF, 0xF9, 0xF0, 0x0C, 0x78, 0x00, 0x3C, 0x00,
0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x1E, 0x00, 0x07, 0xC0, 0x00,
0xFC, 0x00, 0x1F, 0xC0, 0x03, 0xFE, 0x00, 0x3F, 0xC0, 0x01, 0xFC, 0x00,
0x1F, 0x80, 0x01, 0xE0, 0x00, 0x38, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00,
0xF0, 0x00, 0x38, 0x00, 0x1E, 0xC0, 0x0F, 0xBF, 0xFF, 0xCF, 0xFF, 0xE1,
0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0xF0,
0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00,
0x78, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80,
0x00, 0x3C, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0x78, 0x00, 0x03,
0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00,
0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x1E,
0x00, 0x00, 0xF0, 0x00, 0xE0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F,
0xC0, 0x00, 0x7E, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x80, 0x00, 0xFC, 0x00,
0x07, 0xE0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x7E,
0x00, 0x03, 0xF0, 0x00, 0x1F, 0x80, 0x00, 0xFC, 0x00, 0x07, 0xE0, 0x00,
0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0xFE, 0x00, 0x07, 0xF8,
0x00, 0x3F, 0xC0, 0x03, 0xCF, 0x00, 0x1E, 0x7C, 0x03, 0xE1, 0xFF, 0xFE,
0x07, 0xFF, 0xE0, 0x0F, 0xFC, 0x00, 0xF0, 0x00, 0x0F, 0x70, 0x00, 0x1E,
0x78, 0x00, 0x1E, 0x78, 0x00, 0x1C, 0x38, 0x00, 0x3C, 0x3C, 0x00, 0x3C,
0x3C, 0x00, 0x78, 0x1C, 0x00, 0x78, 0x1E, 0x00, 0x70, 0x1E, 0x00, 0xF0,
0x0E, 0x00, 0xF0, 0x0F, 0x00, 0xE0, 0x0F, 0x01, 0xE0, 0x07, 0x01, 0xE0,
0x07, 0x81, 0xC0, 0x03, 0x83, 0xC0, 0x03, 0x83, 0xC0, 0x03, 0xC3, 0x80,
0x01, 0xC7, 0x80, 0x01, 0xE7, 0x80, 0x01, 0xE7, 0x00, 0x00, 0xEF, 0x00,
0x00, 0xEE, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x7C, 0x00, 0x00, 0x3C, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF7, 0x80,
0x0F, 0x00, 0x0F, 0x78, 0x00, 0xF8, 0x00, 0xE7, 0x80, 0x1F, 0x80, 0x1E,
0x38, 0x01, 0xF8, 0x01, 0xE3, 0xC0, 0x1F, 0xC0, 0x1C, 0x3C, 0x03, 0xDC,
0x01, 0xC3, 0xC0, 0x39, 0xC0, 0x3C, 0x1C, 0x03, 0x9C, 0x03, 0xC1, 0xE0,
0x79, 0xE0, 0x38, 0x1E, 0x07, 0x8E, 0x03, 0x80, 0xE0, 0x70, 0xE0, 0x78,
0x0E, 0x07, 0x0F, 0x07, 0x80, 0xF0, 0xF0, 0x70, 0x70, 0x0F, 0x0E, 0x07,
0x07, 0x00, 0x70, 0xE0, 0x78, 0xF0, 0x07, 0x1E, 0x03, 0x8F, 0x00, 0x79,
0xE0, 0x38, 0xE0, 0x07, 0x9C, 0x03, 0x8E, 0x00, 0x39, 0xC0, 0x3D, 0xE0,
0x03, 0xBC, 0x01, 0xDC, 0x00, 0x3B, 0x80, 0x1D, 0xC0, 0x03, 0xF8, 0x01,
0xDC, 0x00, 0x1F, 0x80, 0x0F, 0xC0, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x1F,
0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x0F, 0x00, 0x07, 0x80,
0x78, 0x00, 0x3C, 0x78, 0x00, 0xF0, 0xF0, 0x01, 0xE0, 0xF0, 0x07, 0x80,
0xE0, 0x0E, 0x01, 0xE0, 0x3C, 0x01, 0xE0, 0xF0, 0x01, 0xC1, 0xC0, 0x03,
0xC7, 0x80, 0x03, 0xDE, 0x00, 0x03, 0xB8, 0x00, 0x07, 0xF0, 0x00, 0x07,
0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x7F, 0x00, 0x01, 0xEE,
0x00, 0x03, 0x9E, 0x00, 0x0F, 0x1E, 0x00, 0x1C, 0x1C, 0x00, 0x78, 0x3C,
0x01, 0xE0, 0x3C, 0x03, 0x80, 0x78, 0x0F, 0x00, 0x78, 0x3C, 0x00, 0x78,
0x70, 0x00, 0xF1, 0xE0, 0x00, 0xF7, 0x80, 0x01, 0xF0, 0xF0, 0x00, 0x3D,
0xE0, 0x00, 0xE7, 0x80, 0x07, 0x8F, 0x00, 0x1C, 0x3C, 0x00, 0xF0, 0x78,
0x07, 0x81, 0xE0, 0x1E, 0x03, 0xC0, 0xF0, 0x07, 0x03, 0xC0, 0x1E, 0x1E,
0x00, 0x38, 0x70, 0x00, 0xF3, 0xC0, 0x01, 0xCE, 0x00, 0x07, 0xF8, 0x00,
0x0F, 0xC0, 0x00, 0x3F, 0x00, 0x00, 0x78, 0x00, 0x01, 0xE0, 0x00, 0x07,
0x80, 0x00, 0x1E, 0x00, 0x00, 0x78, 0x00, 0x01, 0xE0, 0x00, 0x07, 0x80,
0x00, 0x1E, 0x00, 0x00, 0x78, 0x00, 0x01, 0xE0, 0x00, 0x07, 0x80, 0x00,
0x1E, 0x00, 0x7F, 0xFF, 0xE7, 0xFF, 0xFE, 0x7F, 0xFF, 0xE0, 0x00, 0x1E,
0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x00, 0xF0, 0x00, 0x0F,
0x00, 0x01, 0xE0, 0x00, 0x3C, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0F,
0x00, 0x00, 0xF0, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x07,
0x80, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x01, 0xE0, 0x00, 0x3C, 0x00, 0x03,
0xC0, 0x00, 0x78, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C,
0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07,
0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xFF,
0xFF, 0xFF, 0xC0, 0xF0, 0x01, 0xC0, 0x07, 0x80, 0x0E, 0x00, 0x38, 0x00,
0xF0, 0x01, 0xC0, 0x07, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xF0, 0x01, 0xC0,
0x07, 0x00, 0x1E, 0x00, 0x38, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x00, 0x1E,
0x00, 0x38, 0x00, 0xE0, 0x03, 0xC0, 0x07, 0x00, 0x1E, 0x00, 0x38, 0x00,
0xE0, 0x03, 0xC0, 0x07, 0xFF, 0xFF, 0xFF, 0xE0, 0xF0, 0x78, 0x3C, 0x1E,
0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0,
0x78, 0x3C, 0x1F, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xE0, 0x00, 0x0F, 0x00,
0x00, 0xF0, 0x00, 0x1F, 0x80, 0x01, 0xB8, 0x00, 0x39, 0xC0, 0x03, 0x1C,
0x00, 0x70, 0xE0, 0x07, 0x0E, 0x00, 0xE0, 0x70, 0x0E, 0x07, 0x01, 0xC0,
0x38, 0x1C, 0x03, 0x83, 0x80, 0x1C, 0x38, 0x01, 0xC7, 0x00, 0x0E, 0x70,
0x00, 0xEF, 0x00, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xF1, 0xE1, 0xE1,
0xE1, 0xC1, 0xC0, 0x0F, 0xFC, 0x1F, 0xFF, 0x07, 0xEF, 0xC2, 0x01, 0xE0,
0x00, 0x78, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x7F, 0x87, 0xFF,
0xCF, 0xFF, 0xEF, 0x80, 0xFF, 0x00, 0x7F, 0x80, 0x3F, 0x80, 0x1F, 0xC0,
0x0F, 0xF0, 0x0F, 0xF8, 0x0F, 0xDF, 0x3E, 0xEF, 0xFE, 0x71, 0xFE, 0x38,
0xF0, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0F, 0x00, 0x01,
0xE0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x00, 0xF0, 0x00, 0x1E, 0x7F, 0x83,
0xDF, 0xFC, 0x7F, 0xFF, 0xCF, 0xC0, 0x79, 0xF0, 0x07, 0xBE, 0x00, 0x77,
0x80, 0x0F, 0xF0, 0x01, 0xFE, 0x00, 0x3F, 0xC0, 0x07, 0xF8, 0x00, 0xFF,
0x00, 0x1F, 0xE0, 0x03, 0xFC, 0x00, 0x7F, 0x80, 0x0F, 0xF8, 0x03, 0xDF,
0x00, 0x7B, 0xF0, 0x1E, 0x77, 0xDF, 0xCE, 0x7F, 0xF1, 0xC7, 0xF8, 0x00,
0x07, 0xFF, 0x0F, 0xFE, 0x1F, 0xFE, 0x3C, 0x02, 0x78, 0x00, 0x78, 0x00,
0x70, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF0, 0x00,
0xF0, 0x00, 0xF0, 0x00, 0x70, 0x00, 0x78, 0x00, 0x78, 0x00, 0x3C, 0x02,
0x1F, 0xFE, 0x0F, 0xFE, 0x07, 0xFE, 0x00, 0x01, 0xE0, 0x00, 0x3C, 0x00,
0x07, 0x80, 0x00, 0xF0, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00,
0x0F, 0x00, 0x01, 0xE0, 0xFF, 0x3C, 0x7F, 0xF7, 0x9F, 0xDF, 0x73, 0xC0,
0x7E, 0xF0, 0x07, 0xDE, 0x00, 0x7B, 0x80, 0x0F, 0xF0, 0x01, 0xFE, 0x00,
0x3F, 0xC0, 0x07, 0xF8, 0x00, 0xFF, 0x00, 0x1F, 0xE0, 0x03, 0xFC, 0x00,
0x7B, 0x80, 0x0F, 0x78, 0x01, 0xEF, 0x00, 0x7C, 0xF0, 0x1F, 0x9F, 0xDF,
0x71, 0xFF, 0xCE, 0x0F, 0xF1, 0xC0, 0x07, 0xFC, 0x03, 0xFF, 0x81, 0xFB,
0xF0, 0xF0, 0x1E, 0x78, 0x07, 0x9E, 0x00, 0xF7, 0x00, 0x3F, 0xC0, 0x0F,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0xF0, 0x00, 0x3C,
0x00, 0x07, 0x00, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x0F, 0x80, 0x21, 0xFF,
0xF8, 0x3F, 0xFE, 0x03, 0xFF, 0x00, 0x01, 0xF8, 0x1F, 0xF0, 0xFF, 0xC3,
0xC0, 0x0E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x01, 0xFF, 0xCF,
0xFF, 0x3F, 0xFC, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00,
0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80,
0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x00, 0x07,
0xF8, 0xE3, 0xFF, 0x9C, 0xFF, 0xFB, 0x9E, 0x03, 0xF7, 0x80, 0x3E, 0xF0,
0x03, 0xDC, 0x00, 0x7F, 0x80, 0x0F, 0xF0, 0x01, 0xFE, 0x00, 0x3F, 0xC0,
0x07, 0xF8, 0x00, 0xFF, 0x00, 0x1F, 0xE0, 0x03, 0xDC, 0x00, 0x7B, 0xC0,
0x0F, 0x78, 0x03, 0xE7, 0x80, 0xFC, 0xFE, 0xFF, 0x8F, 0xFE, 0xF0, 0x7F,
0x9E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0F, 0x00, 0x01, 0xC0, 0x00,
0x78, 0x80, 0x1F, 0x1F, 0xDF, 0xC3, 0xFF, 0xF0, 0x3F, 0xF8, 0x00, 0xF0,
0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00,
0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x7F, 0x8F, 0x7F, 0xF3,
0xFF, 0xFE, 0xFC, 0x07, 0xBE, 0x00, 0xFF, 0x80, 0x3F, 0xC0, 0x07, 0xF0,
0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00,
0x7F, 0x00, 0x1F, 0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F,
0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00, 0x70, 0x6F, 0xFF, 0x20, 0x00, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0x03,
0xC1, 0xE0, 0xF0, 0x10, 0x00, 0x00, 0x00, 0x07, 0x83, 0xC1, 0xE0, 0xF0,
0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E,
0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
0xC1, 0xDB, 0xEF, 0xF7, 0xE0, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03,
0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0,
0x00, 0x3C, 0x03, 0xEF, 0x00, 0xF3, 0xC0, 0x78, 0xF0, 0x3C, 0x3C, 0x1E,
0x0F, 0x0F, 0x03, 0xC7, 0x80, 0xF3, 0xC0, 0x3D, 0xE0, 0x0F, 0xF8, 0x03,
0xFF, 0x00, 0xFF, 0xC0, 0x3E, 0x78, 0x0F, 0x0F, 0x03, 0xC1, 0xE0, 0xF0,
0x78, 0x3C, 0x0F, 0x0F, 0x01, 0xE3, 0xC0, 0x3C, 0xF0, 0x0F, 0x3C, 0x01,
0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xFC, 0x1F, 0xE3, 0x9F, 0xF8, 0xFF, 0xEF,
0xFF, 0xF7, 0xFF, 0xBF, 0x03, 0xF8, 0x0F, 0xF8, 0x07, 0xC0, 0x3F, 0xC0,
0x1F, 0x00, 0x7F, 0x00, 0x38, 0x01, 0xFC, 0x00, 0xE0, 0x07, 0xF0, 0x03,
0x80, 0x1F, 0xC0, 0x0E, 0x00, 0x7F, 0x00, 0x38, 0x01, 0xFC, 0x00, 0xE0,
0x07, 0xF0, 0x03, 0x80, 0x1F, 0xC0, 0x0E, 0x00, 0x7F, 0x00, 0x38, 0x01,
0xFC, 0x00, 0xE0, 0x07, 0xF0, 0x03, 0x80, 0x1F, 0xC0, 0x0E, 0x00, 0x7F,
0x00, 0x38, 0x01, 0xFC, 0x00, 0xE0, 0x07, 0xF0, 0x03, 0x80, 0x1C, 0xE3,
0xFE, 0x39, 0xFF, 0xCF, 0xFF, 0xFB, 0xF0, 0x1E, 0xF8, 0x03, 0xFE, 0x00,
0xFF, 0x00, 0x1F, 0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F,
0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x07, 0xF0,
0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x07, 0xF0, 0x01, 0xC0, 0x07,
0xFC, 0x00, 0xFF, 0xF0, 0x1F, 0xFF, 0x83, 0xC0, 0x7C, 0x78, 0x03, 0xC7,
0x80, 0x1E, 0x70, 0x01, 0xEF, 0x00, 0x0E, 0xF0, 0x00, 0xEF, 0x00, 0x0F,
0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xEF, 0x00, 0x0E, 0x70, 0x01,
0xE7, 0x80, 0x1E, 0x78, 0x03, 0xC3, 0xC0, 0x7C, 0x1F, 0xFF, 0x80, 0xFF,
0xF0, 0x03, 0xFC, 0x00, 0xE3, 0xFC, 0x1C, 0xFF, 0xE3, 0xFF, 0xFE, 0x7E,
0x03, 0xCF, 0x80, 0x3D, 0xE0, 0x07, 0xBC, 0x00, 0x7F, 0x80, 0x0F, 0xF0,
0x01, 0xFE, 0x00, 0x3F, 0xC0, 0x07, 0xF8, 0x00, 0xFF, 0x00, 0x1F, 0xE0,
0x03, 0xFC, 0x00, 0x7F, 0xC0, 0x1E, 0xF8, 0x03, 0xDF, 0x80, 0xF3, 0xFE,
0xFE, 0x7B, 0xFF, 0x8F, 0x3F, 0xC1, 0xE0, 0x00, 0x3C, 0x00, 0x07, 0x80,
0x00, 0xF0, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0F, 0x00,
0x01, 0xE0, 0x00, 0x00, 0x07, 0xF8, 0xE3, 0xFF, 0x9C, 0xFE, 0xFB, 0x9E,
0x03, 0xF7, 0x80, 0x3E, 0xF0, 0x03, 0xDC, 0x00, 0x7F, 0x80, 0x0F, 0xF0,
0x01, 0xFE, 0x00, 0x3F, 0xC0, 0x07, 0xF8, 0x00, 0xFF, 0x00, 0x1F, 0xE0,
0x03, 0xDC, 0x00, 0x7B, 0xC0, 0x0F, 0x78, 0x03, 0xE7, 0x80, 0xFC, 0xFE,
0xFF, 0x8F, 0xFE, 0xF0, 0x7F, 0x9E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00,
0x0F, 0x00, 0x01, 0xE0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x00, 0xF0, 0x00,
0x1E, 0x00, 0x03, 0xC0, 0xE1, 0xFF, 0x1F, 0xB9, 0xFD, 0xFC, 0x0F, 0xC0,
0x7C, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0, 0x0F,
0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xE0,
0x0F, 0x00, 0x00, 0x1F, 0xF8, 0x7F, 0xFD, 0xFB, 0xF7, 0x80, 0x2E, 0x00,
0x1C, 0x00, 0x3C, 0x00, 0x7C, 0x00, 0x7F, 0x00, 0x7F, 0x80, 0x3F, 0xC0,
0x0F, 0xC0, 0x07, 0xC0, 0x03, 0xC0, 0x07, 0x80, 0x07, 0x00, 0x1F, 0x00,
0x3F, 0xE3, 0xF7, 0xFF, 0xC7, 0xFE, 0x00, 0x0C, 0x00, 0xC0, 0x1C, 0x01,
0xC0, 0x1C, 0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0x1C, 0x01, 0xC0, 0x1C, 0x01,
0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01, 0xC0, 0x1C, 0x01,
0xC0, 0x1C, 0x01, 0xC0, 0x1E, 0x01, 0xFB, 0x0F, 0xF0, 0x7F, 0xF0, 0x03,
0xFC, 0x00, 0xFF, 0x00, 0x3F, 0xC0, 0x0F, 0xF0, 0x03, 0xFC, 0x00, 0xFF,
0x00, 0x3F, 0xC0, 0x0F, 0xF0, 0x03, 0xFC, 0x00, 0xFF, 0x00, 0x3F, 0xC0,
0x0F, 0xF0, 0x03, 0xFC, 0x00, 0xFF, 0x00, 0x3F, 0xC0, 0x0F, 0xF0, 0x07,
0xDE, 0x03, 0xF7, 0xF7, 0xDC, 0xFF, 0xE7, 0x1F, 0xF1, 0xC0, 0xF0, 0x00,
0xF7, 0x00, 0x0E, 0x78, 0x01, 0xE7, 0x80, 0x1E, 0x38, 0x01, 0xC3, 0xC0,
0x3C, 0x3C, 0x03, 0x81, 0xC0, 0x78, 0x1E, 0x07, 0x80, 0xE0, 0x70, 0x0E,
0x0F, 0x00, 0xF0, 0xF0, 0x07, 0x0E, 0x00, 0x79, 0xE0, 0x07, 0x9C, 0x00,
0x39, 0xC0, 0x03, 0xBC, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00, 0x1F, 0x00,
0x00, 0xF0, 0x00, 0xF0, 0x07, 0x80, 0x1D, 0xC0, 0x1F, 0x00, 0xF7, 0x80,
0x7C, 0x03, 0xDE, 0x03, 0xF0, 0x0E, 0x38, 0x0E, 0xE0, 0x38, 0xE0, 0x3B,
0x81, 0xE3, 0xC1, 0xEE, 0x07, 0x8F, 0x07, 0x3C, 0x1C, 0x1C, 0x1C, 0x70,
0x70, 0x70, 0x71, 0xC3, 0xC1, 0xE3, 0x87, 0x8E, 0x03, 0x8E, 0x0E, 0x38,
0x0E, 0x38, 0x38, 0xE0, 0x39, 0xC0, 0xE7, 0x80, 0xF7, 0x01, 0xDC, 0x01,
0xDC, 0x07, 0x70, 0x07, 0x70, 0x1D, 0xC0, 0x1F, 0x80, 0x7F, 0x00, 0x3E,
0x00, 0xF8, 0x00, 0xF8, 0x03, 0xE0, 0x03, 0xC0, 0x0F, 0x80, 0xF0, 0x03,
0xEF, 0x00, 0x78, 0xF0, 0x1E, 0x0E, 0x07, 0x81, 0xE0, 0xE0, 0x1E, 0x3C,
0x01, 0xCF, 0x00, 0x3D, 0xC0, 0x03, 0xF8, 0x00, 0x3E, 0x00, 0x07, 0xC0,
0x01, 0xF8, 0x00, 0x3F, 0x80, 0x0F, 0x78, 0x03, 0xC7, 0x00, 0x70, 0xF0,
0x1E, 0x0F, 0x07, 0x80, 0xF1, 0xE0, 0x1E, 0x3C, 0x01, 0xEF, 0x00, 0x1E,
0xF0, 0x00, 0xF7, 0x00, 0x0E, 0x78, 0x01, 0xE7, 0x80, 0x1E, 0x38, 0x01,
0xC3, 0xC0, 0x3C, 0x1C, 0x03, 0xC1, 0xE0, 0x38, 0x1E, 0x07, 0x80, 0xE0,
0x70, 0x0F, 0x0F, 0x00, 0x70, 0xF0, 0x07, 0x0E, 0x00, 0x79, 0xE0, 0x03,
0x9E, 0x00, 0x39, 0xC0, 0x01, 0xFC, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00,
0x0F, 0x80, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00,
0x01, 0xE0, 0x00, 0x1C, 0x00, 0x03, 0xC0, 0x0D, 0xF8, 0x00, 0xFF, 0x00,
0x0F, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x01, 0xE0, 0x03,
0x80, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x01, 0xC0, 0x07, 0x80, 0x1E, 0x00,
0x38, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0x00, 0x1E, 0x00, 0x78, 0x01, 0xE0,
0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x78, 0x0F, 0xC0, 0xFE,
0x0F, 0x80, 0x78, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01,
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x3C, 0x0F, 0xC0, 0xFC, 0x07, 0xC0,
0x3F, 0x80, 0x1E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00,
0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0xC0, 0x1E, 0x00, 0x7F, 0x01,
0xF8, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0xF0, 0x07, 0xE0, 0x3F, 0x80, 0x3C,
0x00, 0xF0, 0x07, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0,
0x0E, 0x00, 0x70, 0x03, 0x80, 0x1E, 0x00, 0x7E, 0x01, 0xF8, 0x07, 0xC0,
0xFE, 0x0F, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38,
0x01, 0xC0, 0x0E, 0x00, 0x70, 0x07, 0x80, 0x7C, 0x1F, 0xC0, 0xFC, 0x07,
0x80, 0x00, 0x7F, 0x80, 0x7F, 0xF8, 0x3F, 0x7F, 0xFF, 0x03, 0xFE, 0x80,
0x1E, 0x00 };
const GFXglyph NotoSans_Regular20pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 10, 0, 0 }, // 0x20 ' '
{ 1, 5, 29, 11, 3, -27 }, // 0x21 '!'
{ 20, 10, 10, 16, 3, -27 }, // 0x22 '"'
{ 33, 23, 28, 25, 1, -27 }, // 0x23 '#'
{ 114, 18, 32, 22, 2, -29 }, // 0x24 '$'
{ 186, 29, 28, 33, 2, -27 }, // 0x25 '%'
{ 288, 27, 28, 29, 2, -27 }, // 0x26 '&'
{ 383, 3, 10, 9, 3, -27 }, // 0x27 '''
{ 387, 9, 34, 12, 2, -27 }, // 0x28 '('
{ 426, 9, 34, 12, 1, -27 }, // 0x29 ')'
{ 465, 18, 18, 22, 2, -29 }, // 0x2A '*'
{ 506, 18, 19, 22, 2, -22 }, // 0x2B '+'
{ 549, 6, 10, 11, 2, -4 }, // 0x2C ','
{ 557, 9, 3, 13, 2, -11 }, // 0x2D '-'
{ 561, 5, 6, 11, 3, -4 }, // 0x2E '.'
{ 565, 14, 28, 15, 0, -27 }, // 0x2F '/'
{ 614, 18, 28, 22, 2, -27 }, // 0x30 '0'
{ 677, 11, 28, 22, 3, -27 }, // 0x31 '1'
{ 716, 18, 28, 22, 2, -27 }, // 0x32 '2'
{ 779, 18, 28, 22, 2, -27 }, // 0x33 '3'
{ 842, 21, 28, 22, 1, -27 }, // 0x34 '4'
{ 916, 18, 28, 22, 2, -27 }, // 0x35 '5'
{ 979, 19, 28, 22, 2, -27 }, // 0x36 '6'
{ 1046, 18, 28, 22, 2, -27 }, // 0x37 '7'
{ 1109, 18, 28, 22, 2, -27 }, // 0x38 '8'
{ 1172, 18, 28, 22, 2, -27 }, // 0x39 '9'
{ 1235, 5, 23, 11, 3, -21 }, // 0x3A ':'
{ 1250, 7, 27, 11, 1, -21 }, // 0x3B ';'
{ 1274, 18, 19, 22, 2, -23 }, // 0x3C '<'
{ 1317, 18, 11, 22, 2, -18 }, // 0x3D '='
{ 1342, 18, 19, 22, 2, -23 }, // 0x3E '>'
{ 1385, 16, 29, 17, 0, -27 }, // 0x3F '?'
{ 1443, 31, 31, 35, 2, -27 }, // 0x40 '@'
{ 1564, 25, 28, 25, 0, -27 }, // 0x41 'A'
{ 1652, 19, 28, 25, 4, -27 }, // 0x42 'B'
{ 1719, 22, 28, 25, 2, -27 }, // 0x43 'C'
{ 1796, 22, 28, 29, 4, -27 }, // 0x44 'D'
{ 1873, 15, 28, 22, 4, -27 }, // 0x45 'E'
{ 1926, 15, 28, 20, 4, -27 }, // 0x46 'F'
{ 1979, 24, 28, 29, 2, -27 }, // 0x47 'G'
{ 2063, 21, 28, 29, 4, -27 }, // 0x48 'H'
{ 2137, 10, 28, 13, 2, -27 }, // 0x49 'I'
{ 2172, 10, 35, 11, -3, -27 }, // 0x4A 'J'
{ 2216, 20, 28, 24, 4, -27 }, // 0x4B 'K'
{ 2286, 16, 28, 21, 4, -27 }, // 0x4C 'L'
{ 2342, 28, 28, 36, 4, -27 }, // 0x4D 'M'
{ 2440, 22, 28, 30, 4, -27 }, // 0x4E 'N'
{ 2517, 26, 28, 31, 2, -27 }, // 0x4F 'O'
{ 2608, 18, 28, 24, 4, -27 }, // 0x50 'P'
{ 2671, 26, 35, 31, 2, -27 }, // 0x51 'Q'
{ 2785, 20, 28, 24, 4, -27 }, // 0x52 'R'
{ 2855, 18, 28, 22, 2, -27 }, // 0x53 'S'
{ 2918, 21, 28, 22, 0, -27 }, // 0x54 'T'
{ 2992, 21, 28, 29, 4, -27 }, // 0x55 'U'
{ 3066, 24, 28, 24, 0, -27 }, // 0x56 'V'
{ 3150, 36, 28, 36, 0, -27 }, // 0x57 'W'
{ 3276, 23, 28, 23, 0, -27 }, // 0x58 'X'
{ 3357, 22, 28, 22, 0, -27 }, // 0x59 'Y'
{ 3434, 20, 28, 22, 1, -27 }, // 0x5A 'Z'
{ 3504, 9, 34, 13, 3, -27 }, // 0x5B '['
{ 3543, 14, 28, 15, 0, -27 }, // 0x5C '\'
{ 3592, 9, 34, 13, 1, -27 }, // 0x5D ']'
{ 3631, 20, 18, 22, 1, -27 }, // 0x5E '^'
{ 3676, 17, 2, 17, 0, 5 }, // 0x5F '_'
{ 3681, 7, 6, 11, 2, -29 }, // 0x60 '`'
{ 3687, 17, 21, 22, 2, -20 }, // 0x61 'a'
{ 3732, 19, 30, 24, 3, -29 }, // 0x62 'b'
{ 3804, 16, 21, 19, 2, -20 }, // 0x63 'c'
{ 3846, 19, 30, 24, 2, -29 }, // 0x64 'd'
{ 3918, 18, 21, 22, 2, -20 }, // 0x65 'e'
{ 3966, 14, 30, 13, 1, -29 }, // 0x66 'f'
{ 4019, 19, 30, 24, 2, -20 }, // 0x67 'g'
{ 4091, 18, 30, 24, 3, -29 }, // 0x68 'h'
{ 4159, 4, 29, 10, 3, -28 }, // 0x69 'i'
{ 4174, 9, 38, 10, -2, -28 }, // 0x6A 'j'
{ 4217, 18, 30, 21, 3, -29 }, // 0x6B 'k'
{ 4285, 4, 30, 10, 3, -29 }, // 0x6C 'l'
{ 4300, 30, 21, 37, 3, -20 }, // 0x6D 'm'
{ 4379, 18, 21, 24, 3, -20 }, // 0x6E 'n'
{ 4427, 20, 21, 24, 2, -20 }, // 0x6F 'o'
{ 4480, 19, 30, 24, 3, -20 }, // 0x70 'p'
{ 4552, 19, 30, 24, 2, -20 }, // 0x71 'q'
{ 4624, 13, 21, 16, 3, -20 }, // 0x72 'r'
{ 4659, 15, 21, 19, 2, -20 }, // 0x73 's'
{ 4699, 12, 26, 14, 1, -25 }, // 0x74 't'
{ 4738, 18, 21, 24, 3, -20 }, // 0x75 'u'
{ 4786, 20, 21, 20, 0, -20 }, // 0x76 'v'
{ 4839, 30, 21, 31, 0, -20 }, // 0x77 'w'
{ 4918, 19, 21, 21, 1, -20 }, // 0x78 'x'
{ 4968, 20, 30, 20, 0, -20 }, // 0x79 'y'
{ 5043, 15, 21, 18, 2, -20 }, // 0x7A 'z'
{ 5083, 13, 34, 15, 1, -27 }, // 0x7B '{'
{ 5139, 3, 39, 22, 9, -29 }, // 0x7C '|'
{ 5154, 13, 34, 15, 1, -27 }, // 0x7D '}'
{ 5210, 18, 5, 22, 2, -15 } }; // 0x7E '~'
const GFXfont NotoSans_Regular20pt7b PROGMEM = {
(uint8_t *)NotoSans_Regular20pt7bBitmaps,
(GFXglyph *)NotoSans_Regular20pt7bGlyphs,
0x20, 0x7E, 53 };
// Approx. 5894 bytes
#endif // NOTOSANS20PT7B_H
@@ -0,0 +1,639 @@
#ifndef NOTOSANS22PT7B_H
#define NOTOSANS22PT7B_H
const uint8_t NotoSans_Regular22pt7bBitmaps[] PROGMEM = {
0x00, 0xFB, 0xDE, 0xF7, 0xBD, 0xEF, 0x7B, 0xDE, 0xF7, 0xB9, 0xCE, 0x73,
0x9C, 0xE7, 0x18, 0x00, 0x00, 0x1F, 0xFF, 0xFD, 0xE4, 0xF0, 0xFF, 0x0F,
0xF0, 0xFF, 0x0F, 0xF0, 0xEF, 0x0E, 0xE0, 0xEE, 0x0E, 0xE0, 0xE6, 0x0E,
0x60, 0xE0, 0x00, 0x38, 0x1C, 0x00, 0x1E, 0x07, 0x00, 0x07, 0x01, 0xC0,
0x01, 0xC0, 0xE0, 0x00, 0x70, 0x38, 0x00, 0x1C, 0x0E, 0x00, 0x0F, 0x03,
0x80, 0x03, 0x80, 0xE0, 0x00, 0xE0, 0x70, 0x0F, 0xFF, 0xFF, 0xF3, 0xFF,
0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0x01, 0xC0, 0x70, 0x00, 0x70, 0x38, 0x00,
0x1C, 0x0E, 0x00, 0x07, 0x03, 0x80, 0x01, 0xC0, 0xE0, 0x00, 0xE0, 0x38,
0x00, 0x38, 0x1C, 0x03, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF,
0xFF, 0xC0, 0x70, 0x1C, 0x00, 0x1C, 0x0F, 0x00, 0x07, 0x03, 0x80, 0x01,
0xC0, 0xE0, 0x00, 0x70, 0x38, 0x00, 0x3C, 0x0E, 0x00, 0x0E, 0x07, 0x80,
0x03, 0x81, 0xC0, 0x00, 0xE0, 0x70, 0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00,
0x03, 0x80, 0x00, 0x70, 0x00, 0x7F, 0xE0, 0x3F, 0xFF, 0x8F, 0xFF, 0xF3,
0xF7, 0x7E, 0xF0, 0xE0, 0x9E, 0x1C, 0x03, 0x83, 0x80, 0x70, 0x70, 0x0F,
0x0E, 0x01, 0xE1, 0xC0, 0x3F, 0x38, 0x03, 0xFF, 0x00, 0x3F, 0xF0, 0x01,
0xFF, 0xC0, 0x07, 0xFE, 0x00, 0x7F, 0xE0, 0x0E, 0x7E, 0x01, 0xC3, 0xC0,
0x38, 0x78, 0x07, 0x07, 0x00, 0xE1, 0xE0, 0x1C, 0x3F, 0x03, 0x8F, 0xFF,
0x7F, 0xEF, 0xFF, 0xF9, 0xFF, 0xFC, 0x07, 0xFC, 0x00, 0x07, 0x00, 0x00,
0xE0, 0x00, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x1F, 0x80, 0x01,
0xC0, 0x3F, 0xE0, 0x03, 0x80, 0x3F, 0xE0, 0x07, 0x80, 0x70, 0xF0, 0x07,
0x00, 0x70, 0x70, 0x0F, 0x00, 0xF0, 0x70, 0x0E, 0x00, 0xE0, 0x38, 0x1E,
0x00, 0xE0, 0x38, 0x1C, 0x00, 0xE0, 0x38, 0x3C, 0x00, 0xE0, 0x38, 0x38,
0x00, 0xE0, 0x38, 0x70, 0x00, 0xE0, 0x38, 0x70, 0x00, 0xE0, 0x78, 0xE1,
0xE0, 0x70, 0x71, 0xE7, 0xF8, 0x70, 0x71, 0xC7, 0xFC, 0x78, 0xF3, 0xCF,
0x1E, 0x3F, 0xE3, 0x8E, 0x0E, 0x3F, 0xE7, 0x9E, 0x0E, 0x0F, 0x87, 0x1C,
0x0E, 0x00, 0x0E, 0x1C, 0x0F, 0x00, 0x0E, 0x1C, 0x0F, 0x00, 0x1C, 0x1C,
0x07, 0x00, 0x3C, 0x1C, 0x07, 0x00, 0x38, 0x1C, 0x0F, 0x00, 0x78, 0x1C,
0x0F, 0x00, 0x70, 0x1C, 0x0E, 0x00, 0xF0, 0x1E, 0x0E, 0x00, 0xE0, 0x0E,
0x1E, 0x01, 0xC0, 0x0F, 0xBC, 0x01, 0xC0, 0x07, 0xFC, 0x03, 0x80, 0x03,
0xF8, 0x01, 0xFE, 0x00, 0x00, 0x3F, 0xFC, 0x00, 0x03, 0xFF, 0xE0, 0x00,
0x1F, 0x0F, 0x80, 0x01, 0xE0, 0x3C, 0x00, 0x0F, 0x00, 0xE0, 0x00, 0x78,
0x07, 0x80, 0x03, 0xC0, 0x38, 0x00, 0x1E, 0x03, 0xC0, 0x00, 0x78, 0x1E,
0x00, 0x03, 0xE1, 0xE0, 0x00, 0x0F, 0x3E, 0x00, 0x00, 0x3F, 0xE0, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x0F, 0xC0, 0x00, 0x01, 0xFF, 0x00, 0x02, 0x1F,
0xFE, 0x01, 0xE1, 0xF1, 0xF8, 0x0F, 0x1F, 0x07, 0xE0, 0x78, 0xF0, 0x1F,
0x87, 0x87, 0x80, 0x7E, 0x3C, 0x78, 0x00, 0xFB, 0xC3, 0xC0, 0x03, 0xFE,
0x1E, 0x00, 0x0F, 0xE0, 0xF0, 0x00, 0x3E, 0x03, 0xC0, 0x01, 0xF8, 0x1F,
0x00, 0x3F, 0xE0, 0xFC, 0x07, 0xEF, 0x83, 0xFF, 0xFE, 0x3E, 0x0F, 0xFF,
0xE0, 0xF8, 0x1F, 0xF8, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xEE, 0xE6, 0x60,
0x03, 0xC1, 0xE0, 0xF0, 0x38, 0x1E, 0x07, 0x03, 0xC0, 0xF0, 0x78, 0x1E,
0x07, 0x81, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x01, 0xE0, 0x78,
0x1E, 0x03, 0xC0, 0xF0, 0x1C, 0x07, 0x80, 0xE0, 0x3C, 0x07, 0x80, 0xF0,
0xF0, 0x1E, 0x03, 0xC0, 0xF0, 0x1E, 0x07, 0x80, 0xF0, 0x3C, 0x07, 0x01,
0xE0, 0x78, 0x1E, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C,
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x78, 0x1E, 0x07,
0x81, 0xE0, 0xF0, 0x3C, 0x1E, 0x07, 0x83, 0xC0, 0xF0, 0x78, 0x3C, 0x00,
0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xE0,
0x00, 0x0E, 0x00, 0x80, 0xE0, 0x2F, 0x8E, 0x1E, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x0F, 0xFF, 0x00, 0x1F, 0x00, 0x03, 0xF8, 0x00, 0x3B, 0xC0, 0x07,
0x9E, 0x00, 0xF1, 0xE0, 0x1F, 0x0F, 0x01, 0xE0, 0xF8, 0x0E, 0x06, 0x00,
0x20, 0x40, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x07, 0x00,
0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x70,
0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x70, 0x00, 0x07,
0x00, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x07, 0x00, 0x00,
0x70, 0x00, 0x07, 0x00, 0x00, 0x70, 0x00, 0x3C, 0xF7, 0xDE, 0x79, 0xE7,
0x3C, 0xE3, 0x8E, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0x7F, 0xFF, 0xF7, 0x98,
0x00, 0x0F, 0x00, 0x1E, 0x00, 0x1E, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0x3C,
0x00, 0x38, 0x00, 0x78, 0x00, 0x78, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0xE0,
0x01, 0xE0, 0x01, 0xE0, 0x01, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x07, 0x80,
0x07, 0x80, 0x07, 0x00, 0x0F, 0x00, 0x0F, 0x00, 0x0E, 0x00, 0x1E, 0x00,
0x1E, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x38, 0x00, 0x78, 0x00, 0x78, 0x00,
0xF0, 0x00, 0x03, 0xFC, 0x00, 0x3F, 0xF8, 0x07, 0xFF, 0xE0, 0x3E, 0x0F,
0x83, 0xC0, 0x3C, 0x1E, 0x00, 0xF1, 0xE0, 0x07, 0x8F, 0x00, 0x1E, 0x78,
0x00, 0xF3, 0x80, 0x07, 0xBC, 0x00, 0x3D, 0xE0, 0x00, 0xEF, 0x00, 0x07,
0x78, 0x00, 0x3B, 0xC0, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x80,
0x03, 0xBC, 0x00, 0x1D, 0xE0, 0x00, 0xEF, 0x00, 0x0F, 0x38, 0x00, 0x79,
0xE0, 0x03, 0xCF, 0x00, 0x1E, 0x78, 0x01, 0xE1, 0xE0, 0x0F, 0x0F, 0x00,
0xF8, 0x3C, 0x0F, 0x81, 0xFF, 0xF8, 0x07, 0xFF, 0x80, 0x0F, 0xF8, 0x00,
0x00, 0xE0, 0x3C, 0x1F, 0x87, 0xF1, 0xEE, 0xF9, 0xFE, 0x3F, 0x87, 0x60,
0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0,
0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0x1C,
0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x03, 0xFC, 0x01, 0xFF, 0xF0,
0x3F, 0xFF, 0x8F, 0xE0, 0xFC, 0x78, 0x03, 0xC2, 0x00, 0x1E, 0x00, 0x01,
0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00,
0x1E, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x07, 0x80, 0x00, 0xF0, 0x00,
0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0, 0x00,
0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00,
0x7C, 0x00, 0x0F, 0x80, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x07, 0xFC, 0x01, 0xFF, 0xF0, 0x7F, 0xFF, 0x8F, 0xC0, 0x7C, 0x70,
0x03, 0xE2, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xE0,
0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x3C, 0x00, 0x0F, 0x80, 0x0F, 0xF0,
0x07, 0xFC, 0x00, 0x7F, 0xE0, 0x07, 0xFF, 0x80, 0x00, 0x7E, 0x00, 0x01,
0xE0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00,
0x0F, 0x00, 0x00, 0xF0, 0x00, 0x1F, 0x80, 0x01, 0xEE, 0x00, 0x7E, 0xFF,
0xFF, 0xCF, 0xFF, 0xF0, 0x3F, 0xFE, 0x00, 0x00, 0x03, 0xC0, 0x00, 0x0F,
0x80, 0x00, 0x1F, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xB8,
0x00, 0x0E, 0x70, 0x00, 0x3C, 0xE0, 0x00, 0xF1, 0xC0, 0x01, 0xC3, 0x80,
0x07, 0x87, 0x00, 0x1E, 0x0E, 0x00, 0x38, 0x1C, 0x00, 0xF0, 0x38, 0x03,
0xC0, 0x70, 0x07, 0x00, 0xE0, 0x1E, 0x01, 0xC0, 0x78, 0x03, 0x81, 0xE0,
0x07, 0x03, 0x80, 0x0E, 0x0F, 0x00, 0x1C, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0xC0, 0x00, 0x03, 0x80, 0x00, 0x07,
0x00, 0x00, 0x0E, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70,
0x00, 0x3F, 0xFF, 0x8F, 0xFF, 0xF1, 0xFF, 0xFE, 0x3F, 0xFF, 0xC7, 0x80,
0x00, 0xF0, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x70, 0x00, 0x0E, 0x00,
0x01, 0xC0, 0x00, 0x38, 0x00, 0x07, 0x7F, 0x00, 0xFF, 0xFC, 0x3F, 0xFF,
0xC1, 0xC3, 0xFC, 0x00, 0x07, 0xC0, 0x00, 0x7C, 0x00, 0x07, 0x80, 0x00,
0xF0, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0F, 0x00, 0x01,
0xE0, 0x00, 0x7A, 0x00, 0x1F, 0x70, 0x07, 0xCF, 0xFF, 0xF1, 0xFF, 0xFC,
0x1F, 0xFE, 0x00, 0x00, 0x7F, 0xC0, 0x0F, 0xFE, 0x00, 0xFF, 0xF0, 0x0F,
0xC0, 0x00, 0xF8, 0x00, 0x0F, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00,
0x38, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x0F,
0xF0, 0x39, 0xFF, 0xC3, 0xDF, 0xFF, 0x1F, 0xE0, 0x7C, 0xFC, 0x01, 0xF7,
0xC0, 0x07, 0xBE, 0x00, 0x1D, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xB8, 0x00,
0x3D, 0xC0, 0x01, 0xEF, 0x00, 0x0E, 0x78, 0x00, 0xF1, 0xE0, 0x07, 0x8F,
0x80, 0x78, 0x3E, 0x07, 0xC0, 0xFF, 0xFC, 0x03, 0xFF, 0xC0, 0x07, 0xF8,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
0x00, 0x0F, 0x00, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x03,
0xC0, 0x00, 0x1E, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00,
0x07, 0x80, 0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x01, 0xE0,
0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x03,
0xC0, 0x00, 0x3C, 0x00, 0x01, 0xE0, 0x00, 0x1F, 0x00, 0x00, 0xF0, 0x00,
0x0F, 0x80, 0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x00, 0x03,
0xFE, 0x00, 0xFF, 0xF8, 0x1F, 0xFF, 0xC3, 0xE0, 0x7E, 0x3C, 0x01, 0xE7,
0x80, 0x1E, 0x78, 0x00, 0xE7, 0x80, 0x0F, 0x78, 0x00, 0xE7, 0x80, 0x1E,
0x3C, 0x01, 0xE3, 0xE0, 0x3C, 0x1F, 0x8F, 0x80, 0xFF, 0xF0, 0x03, 0xFC,
0x00, 0x7F, 0xE0, 0x0F, 0xFF, 0x81, 0xF0, 0xFC, 0x3C, 0x03, 0xE7, 0x80,
0x1F, 0x70, 0x00, 0xFF, 0x00, 0x07, 0xF0, 0x00, 0x7F, 0x00, 0x07, 0xF0,
0x00, 0x7F, 0x00, 0x0F, 0x78, 0x00, 0xF7, 0xC0, 0x3E, 0x3F, 0xFF, 0xC1,
0xFF, 0xF8, 0x07, 0xFE, 0x00, 0x03, 0xFC, 0x00, 0xFF, 0xF0, 0x1F, 0xFF,
0x83, 0xE0, 0xFC, 0x7C, 0x03, 0xC7, 0x80, 0x1E, 0x78, 0x01, 0xEF, 0x00,
0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x00, 0x0F, 0xF0,
0x00, 0xF7, 0x80, 0x0F, 0x78, 0x01, 0xF7, 0xC0, 0x3F, 0x3F, 0xFF, 0x71,
0xFF, 0xEF, 0x0F, 0xF8, 0xF0, 0x08, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0E,
0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x07,
0x80, 0x01, 0xF0, 0x3F, 0xFE, 0x03, 0xFF, 0xC0, 0x3F, 0xF0, 0x00, 0x37,
0xFF, 0xFF, 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
0xFF, 0xEF, 0x30, 0x0C, 0x7C, 0xF9, 0xF3, 0xE3, 0xC0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xF3, 0xE7, 0x8F, 0x1E,
0x78, 0xF1, 0xC3, 0x87, 0x1C, 0x00, 0x00, 0x00, 0x10, 0x00, 0x07, 0x00,
0x01, 0xF0, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x07, 0xF0, 0x01, 0xF8, 0x00,
0x7E, 0x00, 0x1F, 0x80, 0x07, 0xE0, 0x00, 0xF8, 0x00, 0x0F, 0xC0, 0x00,
0x7F, 0x00, 0x01, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x3F,
0xC0, 0x00, 0xFF, 0x00, 0x01, 0xF0, 0x00, 0x07, 0x00, 0x00, 0x10, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x0F, 0x00, 0x00, 0xFC, 0x00,
0x07, 0xF0, 0x00, 0x1F, 0xC0, 0x00, 0x7F, 0x00, 0x01, 0xFC, 0x00, 0x07,
0xF0, 0x00, 0x1F, 0xC0, 0x00, 0x7F, 0x00, 0x00, 0xF0, 0x00, 0x1F, 0x00,
0x0F, 0xE0, 0x03, 0xF8, 0x00, 0xFE, 0x00, 0x7F, 0x80, 0x1F, 0xC0, 0x0F,
0xF0, 0x00, 0xFC, 0x00, 0x0F, 0x00, 0x00, 0x80, 0x00, 0x00, 0x1F, 0xF0,
0x7F, 0xFE, 0x3F, 0xFF, 0x9F, 0x07, 0xE4, 0x00, 0xF0, 0x00, 0x38, 0x00,
0x1E, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x03, 0x80, 0x03, 0xC0, 0x03, 0xC0,
0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xE0, 0x03, 0xC0, 0x01, 0xC0,
0x01, 0xE0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00,
0x7C, 0x00, 0x3E, 0x00, 0x06, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x07,
0xFF, 0xE0, 0x00, 0x07, 0xFF, 0xFE, 0x00, 0x03, 0xF8, 0x0F, 0xE0, 0x03,
0xF0, 0x00, 0x7C, 0x01, 0xF0, 0x00, 0x07, 0x80, 0x78, 0x00, 0x00, 0xF0,
0x3C, 0x00, 0x00, 0x1C, 0x1E, 0x00, 0x00, 0x07, 0x87, 0x00, 0xFF, 0xC0,
0xE3, 0x80, 0xFF, 0xF8, 0x3C, 0xE0, 0x7E, 0x3E, 0x07, 0x78, 0x1E, 0x07,
0x81, 0xDC, 0x0F, 0x01, 0xE0, 0x77, 0x03, 0x80, 0x78, 0x1D, 0xC1, 0xE0,
0x1E, 0x07, 0x70, 0x78, 0x07, 0x81, 0xDC, 0x1E, 0x01, 0xC0, 0x7F, 0x07,
0x00, 0x70, 0x1F, 0xC1, 0xE0, 0x1C, 0x07, 0x70, 0x78, 0x07, 0x03, 0x9C,
0x0E, 0x03, 0xC0, 0xE7, 0x03, 0xC1, 0xF8, 0x79, 0xC0, 0xFD, 0xE7, 0x3C,
0x70, 0x1F, 0xF9, 0xFE, 0x0E, 0x01, 0xF8, 0x3F, 0x03, 0x80, 0x00, 0x00,
0x00, 0xF0, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x03, 0xC0, 0x00,
0x00, 0x00, 0x7C, 0x00, 0x04, 0x00, 0x0F, 0xC0, 0x1F, 0x00, 0x01, 0xFF,
0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00,
0x0F, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x0F, 0xC0,
0x00, 0x03, 0xF8, 0x00, 0x00, 0x77, 0x80, 0x00, 0x0E, 0xF0, 0x00, 0x03,
0xCE, 0x00, 0x00, 0x71, 0xE0, 0x00, 0x1E, 0x3C, 0x00, 0x03, 0xC3, 0xC0,
0x00, 0x70, 0x78, 0x00, 0x1E, 0x07, 0x00, 0x03, 0xC0, 0xF0, 0x00, 0xF0,
0x1E, 0x00, 0x1E, 0x01, 0xC0, 0x03, 0x80, 0x3C, 0x00, 0xF0, 0x07, 0x80,
0x1F, 0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xE0, 0x1E, 0x00,
0x1E, 0x07, 0x80, 0x03, 0xC0, 0xF0, 0x00, 0x3C, 0x1C, 0x00, 0x07, 0x87,
0x80, 0x00, 0xF0, 0xF0, 0x00, 0x0F, 0x3C, 0x00, 0x01, 0xE7, 0x80, 0x00,
0x3E, 0xF0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x78, 0xFF, 0xF0, 0x03, 0xFF,
0xFE, 0x0F, 0xFF, 0xFE, 0x3F, 0xFF, 0xF8, 0xF0, 0x03, 0xF3, 0xC0, 0x03,
0xCF, 0x00, 0x0F, 0xBC, 0x00, 0x1E, 0xF0, 0x00, 0x7B, 0xC0, 0x01, 0xCF,
0x00, 0x0F, 0x3C, 0x00, 0x3C, 0xF0, 0x01, 0xE3, 0xFF, 0xFF, 0x0F, 0xFF,
0xE0, 0x3F, 0xFF, 0xE0, 0xFF, 0xFF, 0xE3, 0xC0, 0x07, 0xCF, 0x00, 0x0F,
0xBC, 0x00, 0x1E, 0xF0, 0x00, 0x7F, 0xC0, 0x00, 0xFF, 0x00, 0x03, 0xFC,
0x00, 0x1F, 0xF0, 0x00, 0x7B, 0xC0, 0x03, 0xEF, 0x00, 0x1F, 0xBC, 0x03,
0xFC, 0xFF, 0xFF, 0xE3, 0xFF, 0xFF, 0x0F, 0xFF, 0xE0, 0x00, 0x00, 0x7F,
0xF0, 0x03, 0xFF, 0xFC, 0x1F, 0xFF, 0xF0, 0x7F, 0x83, 0xE1, 0xF8, 0x00,
0xC7, 0xE0, 0x00, 0x0F, 0x80, 0x00, 0x3E, 0x00, 0x00, 0x78, 0x00, 0x01,
0xF0, 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, 0x1F, 0x00,
0x00, 0x1E, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7C, 0x00,
0x00, 0x7C, 0x00, 0x00, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF,
0x80, 0x3F, 0xFE, 0x00, 0xFF, 0xF0, 0x00, 0x7F, 0xFF, 0xC0, 0x3F, 0xFF,
0xF8, 0x1F, 0xFF, 0xFE, 0x0F, 0x00, 0x1F, 0x87, 0x80, 0x03, 0xE3, 0xC0,
0x00, 0xF9, 0xE0, 0x00, 0x3C, 0xF0, 0x00, 0x1F, 0x78, 0x00, 0x07, 0xBC,
0x00, 0x03, 0xDE, 0x00, 0x01, 0xEF, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x3F,
0xC0, 0x00, 0x1F, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x07, 0xF8, 0x00, 0x03,
0xFC, 0x00, 0x03, 0xFE, 0x00, 0x01, 0xEF, 0x00, 0x00, 0xF7, 0x80, 0x00,
0x7B, 0xC0, 0x00, 0x7D, 0xE0, 0x00, 0x3C, 0xF0, 0x00, 0x3E, 0x78, 0x00,
0x3E, 0x3C, 0x00, 0x7E, 0x1E, 0x03, 0xFE, 0x0F, 0xFF, 0xFE, 0x07, 0xFF,
0xFC, 0x03, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00,
0x78, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x07, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x0F,
0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00,
0x3C, 0x00, 0x1E, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x07, 0x80, 0x03,
0xC0, 0x01, 0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x3C, 0x00, 0x1E, 0x00,
0x0F, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFC, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01,
0xE0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x0F, 0x00,
0x07, 0x80, 0x03, 0xC0, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x7F, 0xFF, 0xC0,
0xFF, 0xFF, 0xC1, 0xFF, 0x07, 0xE1, 0xF8, 0x00, 0x30, 0xF8, 0x00, 0x00,
0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x78, 0x00, 0x00, 0x3C, 0x00, 0x00,
0x3C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x07, 0x80, 0x00,
0x03, 0xC0, 0x00, 0x01, 0xE0, 0x03, 0xFF, 0xF0, 0x01, 0xFF, 0xF8, 0x00,
0xFF, 0xFC, 0x00, 0x01, 0xFE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0xC0,
0x00, 0x3D, 0xE0, 0x00, 0x1E, 0xF8, 0x00, 0x0F, 0x3C, 0x00, 0x07, 0x9F,
0x00, 0x03, 0xC7, 0xE0, 0x01, 0xE1, 0xFC, 0x00, 0xF0, 0x7F, 0xFF, 0xF8,
0x1F, 0xFF, 0xFC, 0x03, 0xFF, 0xF8, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F,
0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F,
0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F,
0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x0F,
0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F,
0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F,
0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F,
0xF0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0x01, 0xE0, 0x3C, 0x07,
0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80,
0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0,
0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x07, 0xFD, 0xFF, 0xFF, 0xF8, 0x01, 0xE0,
0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C,
0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07,
0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80,
0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x0F, 0x47, 0xEF,
0xF9, 0xFE, 0x3F, 0x00, 0xF0, 0x00, 0x7D, 0xE0, 0x00, 0xF3, 0xC0, 0x03,
0xC7, 0x80, 0x0F, 0x0F, 0x00, 0x3C, 0x1E, 0x00, 0xF0, 0x3C, 0x03, 0xE0,
0x78, 0x0F, 0x80, 0xF0, 0x3E, 0x01, 0xE0, 0xF8, 0x03, 0xC3, 0xE0, 0x07,
0x87, 0x80, 0x0F, 0x1E, 0x00, 0x1E, 0x78, 0x00, 0x3D, 0xF8, 0x00, 0x7F,
0xF0, 0x00, 0xFF, 0xF0, 0x01, 0xF9, 0xF0, 0x03, 0xE1, 0xF0, 0x07, 0x81,
0xE0, 0x0F, 0x03, 0xE0, 0x1E, 0x03, 0xE0, 0x3C, 0x03, 0xC0, 0x78, 0x03,
0xC0, 0xF0, 0x07, 0xC1, 0xE0, 0x07, 0xC3, 0xC0, 0x07, 0x87, 0x80, 0x0F,
0x8F, 0x00, 0x0F, 0x9E, 0x00, 0x0F, 0xBC, 0x00, 0x0F, 0x80, 0xF0, 0x00,
0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F,
0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0,
0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00,
0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F,
0x00, 0x03, 0xC0, 0x00, 0xF0, 0x00, 0x3C, 0x00, 0x0F, 0x00, 0x03, 0xC0,
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFC, 0x00, 0x00, 0x7F,
0xF8, 0x00, 0x00, 0xFF, 0xF8, 0x00, 0x03, 0xFF, 0xF0, 0x00, 0x07, 0xFE,
0xF0, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0x3F, 0xFD, 0xC0, 0x00, 0x77, 0xFB,
0xC0, 0x01, 0xEF, 0xF7, 0x80, 0x03, 0xDF, 0xE7, 0x00, 0x07, 0x3F, 0xCF,
0x00, 0x1E, 0x7F, 0x9E, 0x00, 0x38, 0xFF, 0x1E, 0x00, 0xF1, 0xFE, 0x3C,
0x01, 0xE3, 0xFC, 0x38, 0x03, 0x87, 0xF8, 0x78, 0x0F, 0x0F, 0xF0, 0xF0,
0x1C, 0x1F, 0xE0, 0xE0, 0x38, 0x3F, 0xC1, 0xE0, 0xF0, 0x7F, 0x83, 0xC1,
0xC0, 0xFF, 0x03, 0xC7, 0x81, 0xFE, 0x07, 0x8F, 0x03, 0xFC, 0x07, 0x1C,
0x07, 0xF8, 0x0F, 0x78, 0x0F, 0xF0, 0x1E, 0xE0, 0x1F, 0xE0, 0x1F, 0xC0,
0x3F, 0xC0, 0x3F, 0x80, 0x7F, 0x80, 0x7E, 0x00, 0xFF, 0x00, 0x7C, 0x01,
0xFE, 0x00, 0xF8, 0x03, 0xFC, 0x00, 0xE0, 0x07, 0x80, 0xF8, 0x00, 0x07,
0xFC, 0x00, 0x03, 0xFF, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0xFF, 0xE0, 0x00,
0x7F, 0x78, 0x00, 0x3F, 0xBE, 0x00, 0x1F, 0xEF, 0x00, 0x0F, 0xF3, 0xC0,
0x07, 0xF9, 0xF0, 0x03, 0xFC, 0x78, 0x01, 0xFE, 0x3E, 0x00, 0xFF, 0x0F,
0x80, 0x7F, 0x83, 0xC0, 0x3F, 0xC1, 0xF0, 0x1F, 0xE0, 0x7C, 0x0F, 0xF0,
0x1E, 0x07, 0xF8, 0x0F, 0x83, 0xFC, 0x03, 0xC1, 0xFE, 0x00, 0xF0, 0xFF,
0x00, 0x7C, 0x7F, 0x80, 0x1E, 0x3F, 0xC0, 0x07, 0x9F, 0xE0, 0x03, 0xEF,
0xF0, 0x00, 0xF7, 0xF8, 0x00, 0x7F, 0xFC, 0x00, 0x1F, 0xFE, 0x00, 0x07,
0xFF, 0x00, 0x03, 0xFF, 0x80, 0x00, 0xFF, 0xC0, 0x00, 0x3E, 0x00, 0x7F,
0xE0, 0x00, 0x3F, 0xFF, 0x80, 0x07, 0xFF, 0xFE, 0x00, 0xFE, 0x07, 0xF0,
0x1F, 0x00, 0x1F, 0x83, 0xE0, 0x00, 0x78, 0x3C, 0x00, 0x03, 0xC7, 0x80,
0x00, 0x3C, 0x78, 0x00, 0x01, 0xEF, 0x80, 0x00, 0x1E, 0xF0, 0x00, 0x01,
0xEF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0,
0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x01, 0xFF,
0x80, 0x00, 0x1E, 0x78, 0x00, 0x01, 0xE7, 0x80, 0x00, 0x3E, 0x7C, 0x00,
0x03, 0xC3, 0xE0, 0x00, 0x7C, 0x1F, 0x00, 0x0F, 0x81, 0xFC, 0x03, 0xF0,
0x07, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xC0, 0x00, 0xFF, 0xF0, 0x00, 0xFF,
0xF0, 0x0F, 0xFF, 0xE0, 0xFF, 0xFF, 0x8F, 0xFF, 0xFC, 0xF0, 0x07, 0xEF,
0x00, 0x3E, 0xF0, 0x01, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F,
0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x01, 0xEF, 0x00, 0x1E, 0xF0, 0x07,
0xCF, 0x03, 0xFC, 0xFF, 0xFF, 0x8F, 0xFF, 0xE0, 0xFF, 0xF8, 0x0F, 0x00,
0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0,
0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F,
0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x7F, 0xE0, 0x00, 0x3F, 0xFF, 0x80,
0x07, 0xFF, 0xFE, 0x00, 0xFE, 0x07, 0xF0, 0x1F, 0x00, 0x1F, 0x83, 0xE0,
0x00, 0x78, 0x3C, 0x00, 0x03, 0xC7, 0x80, 0x00, 0x3C, 0x78, 0x00, 0x01,
0xEF, 0x80, 0x00, 0x1E, 0xF0, 0x00, 0x01, 0xEF, 0x00, 0x00, 0x0F, 0xF0,
0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00,
0x0F, 0xF0, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0xFF,
0x00, 0x00, 0x0F, 0xF0, 0x00, 0x01, 0xFF, 0x80, 0x00, 0x1E, 0x78, 0x00,
0x01, 0xE7, 0x80, 0x00, 0x3E, 0x7C, 0x00, 0x03, 0xC3, 0xE0, 0x00, 0x7C,
0x1F, 0x00, 0x0F, 0x81, 0xFC, 0x03, 0xF0, 0x07, 0xFF, 0xFE, 0x00, 0x3F,
0xFF, 0xC0, 0x00, 0xFF, 0xE0, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0xF8,
0x00, 0x00, 0x07, 0xC0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x03, 0xF0, 0x00,
0x00, 0x1F, 0x80, 0x00, 0x00, 0xFC, 0xFF, 0xF0, 0x03, 0xFF, 0xFC, 0x0F,
0xFF, 0xF8, 0x3F, 0xFF, 0xF0, 0xF0, 0x07, 0xE3, 0xC0, 0x07, 0x8F, 0x00,
0x1F, 0x3C, 0x00, 0x3C, 0xF0, 0x00, 0xF3, 0xC0, 0x03, 0xCF, 0x00, 0x0F,
0x3C, 0x00, 0x7C, 0xF0, 0x01, 0xE3, 0xC0, 0x0F, 0x8F, 0x00, 0xFC, 0x3F,
0xFF, 0xE0, 0xFF, 0xFE, 0x03, 0xFF, 0xF0, 0x0F, 0x03, 0xC0, 0x3C, 0x07,
0x80, 0xF0, 0x1F, 0x03, 0xC0, 0x3C, 0x0F, 0x00, 0x78, 0x3C, 0x01, 0xF0,
0xF0, 0x03, 0xC3, 0xC0, 0x0F, 0x8F, 0x00, 0x1E, 0x3C, 0x00, 0x3C, 0xF0,
0x00, 0xFB, 0xC0, 0x01, 0xEF, 0x00, 0x07, 0xC0, 0x03, 0xFF, 0x00, 0xFF,
0xFE, 0x1F, 0xFF, 0xE3, 0xF0, 0x7C, 0x7C, 0x00, 0x47, 0x80, 0x00, 0x78,
0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07,
0xC0, 0x00, 0x3F, 0x00, 0x01, 0xFC, 0x00, 0x0F, 0xF8, 0x00, 0x3F, 0xE0,
0x00, 0xFF, 0x80, 0x03, 0xFC, 0x00, 0x07, 0xC0, 0x00, 0x3E, 0x00, 0x01,
0xE0, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00, 0xE0, 0x00,
0x1E, 0x80, 0x03, 0xEF, 0x00, 0x7C, 0xFF, 0xFF, 0x8F, 0xFF, 0xF0, 0x7F,
0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 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, 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, 0x80, 0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0xF0,
0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0,
0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0,
0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0,
0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0,
0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0,
0x00, 0x0E, 0xF0, 0x00, 0x1E, 0xF0, 0x00, 0x1E, 0x78, 0x00, 0x1E, 0x78,
0x00, 0x3C, 0x7C, 0x00, 0x7C, 0x3F, 0x01, 0xF8, 0x1F, 0xFF, 0xF0, 0x0F,
0xFF, 0xE0, 0x03, 0xFF, 0x80, 0xF0, 0x00, 0x03, 0xFC, 0x00, 0x01, 0xE7,
0x80, 0x00, 0x79, 0xE0, 0x00, 0x1E, 0x3C, 0x00, 0x0F, 0x0F, 0x00, 0x03,
0xC3, 0xC0, 0x00, 0xF0, 0x78, 0x00, 0x78, 0x1E, 0x00, 0x1E, 0x07, 0x80,
0x0F, 0x80, 0xF0, 0x03, 0xC0, 0x3C, 0x00, 0xF0, 0x0F, 0x00, 0x78, 0x01,
0xE0, 0x1E, 0x00, 0x78, 0x07, 0x80, 0x1E, 0x03, 0xC0, 0x03, 0xC0, 0xF0,
0x00, 0xF0, 0x3C, 0x00, 0x1C, 0x1E, 0x00, 0x07, 0x87, 0x80, 0x01, 0xE1,
0xE0, 0x00, 0x3C, 0xF0, 0x00, 0x0F, 0x3C, 0x00, 0x03, 0xCF, 0x00, 0x00,
0x77, 0x80, 0x00, 0x1F, 0xE0, 0x00, 0x07, 0xF0, 0x00, 0x00, 0xFC, 0x00,
0x00, 0x3F, 0x00, 0x00, 0x0F, 0x80, 0x00, 0x01, 0xE0, 0x00, 0xF0, 0x00,
0x78, 0x00, 0x3F, 0xE0, 0x01, 0xF0, 0x00, 0x7B, 0xC0, 0x03, 0xF0, 0x00,
0xF7, 0x80, 0x07, 0xE0, 0x01, 0xE7, 0x80, 0x0F, 0xC0, 0x07, 0x8F, 0x00,
0x3F, 0x80, 0x0F, 0x1E, 0x00, 0x7F, 0x80, 0x1E, 0x3C, 0x00, 0xEF, 0x00,
0x3C, 0x3C, 0x03, 0xCE, 0x00, 0xF0, 0x78, 0x07, 0x9E, 0x01, 0xE0, 0xF0,
0x0F, 0x3C, 0x03, 0xC0, 0xE0, 0x1C, 0x38, 0x07, 0x81, 0xE0, 0x78, 0x78,
0x1E, 0x03, 0xC0, 0xF0, 0xF0, 0x3C, 0x07, 0x81, 0xC1, 0xE0, 0x78, 0x07,
0x07, 0x81, 0xE0, 0xE0, 0x0F, 0x0F, 0x03, 0xC3, 0xC0, 0x1E, 0x1E, 0x07,
0x87, 0x80, 0x3C, 0x38, 0x07, 0x0F, 0x00, 0x38, 0xF0, 0x0F, 0x1C, 0x00,
0x79, 0xE0, 0x1E, 0x78, 0x00, 0xF3, 0x80, 0x1C, 0xF0, 0x01, 0xEF, 0x00,
0x39, 0xE0, 0x01, 0xDE, 0x00, 0x7B, 0x80, 0x03, 0xF8, 0x00, 0xFF, 0x00,
0x07, 0xF0, 0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x01, 0xFC, 0x00, 0x0F, 0xC0,
0x03, 0xF0, 0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x3E, 0x00, 0x07, 0xC0,
0x00, 0x3C, 0x00, 0x0F, 0x00, 0x00, 0x78, 0x00, 0x0F, 0x1E, 0x00, 0x0F,
0x8F, 0x80, 0x07, 0x83, 0xC0, 0x07, 0x80, 0xF0, 0x03, 0xC0, 0x78, 0x03,
0xC0, 0x1E, 0x03, 0xC0, 0x07, 0x81, 0xE0, 0x03, 0xC1, 0xE0, 0x00, 0xF1,
0xE0, 0x00, 0x7C, 0xF0, 0x00, 0x1E, 0xF0, 0x00, 0x07, 0xF0, 0x00, 0x03,
0xF8, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x7F, 0x00, 0x00,
0x3F, 0x80, 0x00, 0x3D, 0xE0, 0x00, 0x3C, 0x78, 0x00, 0x1E, 0x3C, 0x00,
0x1E, 0x0F, 0x00, 0x0F, 0x03, 0xC0, 0x0F, 0x01, 0xE0, 0x0F, 0x00, 0x78,
0x07, 0x80, 0x3E, 0x07, 0x80, 0x0F, 0x07, 0x80, 0x03, 0xC3, 0xC0, 0x01,
0xE3, 0xC0, 0x00, 0x7B, 0xE0, 0x00, 0x3E, 0xF0, 0x00, 0x0F, 0x78, 0x00,
0x0F, 0x78, 0x00, 0x1E, 0x3C, 0x00, 0x3E, 0x3C, 0x00, 0x3C, 0x1E, 0x00,
0x7C, 0x1F, 0x00, 0x78, 0x0F, 0x00, 0xF0, 0x0F, 0x80, 0xF0, 0x07, 0x81,
0xE0, 0x03, 0xC1, 0xE0, 0x03, 0xC3, 0xC0, 0x01, 0xE3, 0xC0, 0x01, 0xE7,
0x80, 0x00, 0xF7, 0x80, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7E,
0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C,
0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C,
0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x3C,
0x00, 0x00, 0x3C, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xE0, 0x00, 0x1F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x00, 0x00,
0xF8, 0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0xC0, 0x00, 0x3C, 0x00,
0x03, 0xC0, 0x00, 0x3E, 0x00, 0x01, 0xE0, 0x00, 0x1E, 0x00, 0x01, 0xF0,
0x00, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x80, 0x00, 0x78, 0x00, 0x07,
0x80, 0x00, 0x7C, 0x00, 0x03, 0xC0, 0x00, 0x3C, 0x00, 0x03, 0xE0, 0x00,
0x1E, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0,
0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C,
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xFF, 0xFF,
0xFF, 0xF0, 0xF0, 0x00, 0x78, 0x00, 0x78, 0x00, 0x38, 0x00, 0x3C, 0x00,
0x3C, 0x00, 0x1C, 0x00, 0x1E, 0x00, 0x0E, 0x00, 0x0F, 0x00, 0x0F, 0x00,
0x07, 0x00, 0x07, 0x80, 0x07, 0x80, 0x03, 0x80, 0x03, 0xC0, 0x03, 0xC0,
0x01, 0xE0, 0x01, 0xE0, 0x00, 0xE0, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x70,
0x00, 0x78, 0x00, 0x78, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x1C, 0x00, 0x1E,
0x00, 0x1E, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFC, 0x0F, 0x03, 0xC0, 0xF0,
0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F,
0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0,
0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3F,
0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x60, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00,
0x03, 0xF0, 0x00, 0x1F, 0x80, 0x01, 0xCE, 0x00, 0x0E, 0x70, 0x00, 0xE1,
0xC0, 0x07, 0x0E, 0x00, 0x70, 0x38, 0x03, 0x81, 0xC0, 0x3C, 0x07, 0x01,
0xC0, 0x38, 0x1E, 0x00, 0xE0, 0xE0, 0x07, 0x0F, 0x00, 0x1C, 0x70, 0x00,
0xE3, 0x80, 0x03, 0xB8, 0x00, 0x1D, 0xC0, 0x00, 0x70, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xF0, 0xF8, 0x7C, 0x3C, 0x1E, 0x0F, 0x07,
0x07, 0xFE, 0x03, 0xFF, 0xF0, 0x7F, 0xFF, 0x0E, 0x03, 0xE0, 0x00, 0x3C,
0x00, 0x03, 0xC0, 0x00, 0x78, 0x00, 0x0F, 0x00, 0x01, 0xE0, 0x1F, 0xFC,
0x3F, 0xFF, 0x9F, 0xFF, 0xF7, 0xE0, 0x1E, 0xF0, 0x03, 0xFC, 0x00, 0x7F,
0x80, 0x0F, 0xF0, 0x03, 0xFE, 0x00, 0x7F, 0xC0, 0x1F, 0xFC, 0x07, 0xF7,
0xFF, 0xDE, 0x7F, 0xF1, 0xC7, 0xFC, 0x38, 0xE0, 0x00, 0x0E, 0x00, 0x00,
0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00,
0x0E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE3, 0xFE, 0x0E, 0x7F,
0xF0, 0xEF, 0xFF, 0xCF, 0xC0, 0x7C, 0xF8, 0x03, 0xEF, 0x00, 0x1E, 0xF0,
0x01, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xE0, 0x00, 0xFE,
0x00, 0x0F, 0xE0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F,
0xF0, 0x01, 0xFF, 0x80, 0x1E, 0xF8, 0x03, 0xEF, 0xC0, 0x7C, 0xEF, 0xFF,
0x8E, 0x7F, 0xF0, 0xE3, 0xFE, 0x00, 0x00, 0x10, 0x01, 0xFF, 0xC3, 0xFF,
0xE3, 0xFF, 0xF3, 0xF0, 0x11, 0xE0, 0x01, 0xF0, 0x00, 0xF0, 0x00, 0x78,
0x00, 0x3C, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x03,
0xC0, 0x00, 0xF0, 0x00, 0x78, 0x00, 0x3C, 0x00, 0x1F, 0x00, 0x07, 0x80,
0x03, 0xF0, 0x18, 0xFF, 0xFC, 0x3F, 0xFE, 0x07, 0xFE, 0x00, 0x00, 0x78,
0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x07, 0x80, 0x00,
0x3C, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00, 0x00, 0x78, 0x03, 0x03, 0xC1,
0xFF, 0x1E, 0x1F, 0xFE, 0xF1, 0xFF, 0xFF, 0x9F, 0x01, 0xFC, 0xF0, 0x07,
0xEF, 0x80, 0x1F, 0x78, 0x00, 0xFB, 0xC0, 0x03, 0xDE, 0x00, 0x1F, 0xE0,
0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xC0, 0x01, 0xFE, 0x00, 0x0F,
0x78, 0x00, 0x7B, 0xC0, 0x03, 0xDE, 0x00, 0x3E, 0xF8, 0x01, 0xF3, 0xC0,
0x1F, 0x9F, 0x01, 0xFC, 0x7F, 0xFF, 0xE1, 0xFF, 0xEF, 0x03, 0xFC, 0x38,
0x00, 0x20, 0x00, 0x3F, 0xE0, 0x0F, 0xFF, 0x81, 0xFF, 0xFC, 0x1E, 0x03,
0xC3, 0xC0, 0x1E, 0x78, 0x01, 0xE7, 0x80, 0x0F, 0x78, 0x00, 0xF7, 0x00,
0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xF0,
0x00, 0x07, 0x80, 0x00, 0x78, 0x00, 0x07, 0x80, 0x00, 0x7C, 0x00, 0x03,
0xE0, 0x00, 0x1F, 0x00, 0x61, 0xFF, 0xFE, 0x07, 0xFF, 0xE0, 0x3F, 0xFC,
0x00, 0xFE, 0x03, 0xFF, 0x07, 0xFE, 0x07, 0xC2, 0x0F, 0x00, 0x0F, 0x00,
0x0F, 0x00, 0x0F, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x7F, 0xF8, 0xFF, 0xF8,
0xFF, 0xF8, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00,
0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00,
0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00,
0x0E, 0x00, 0x0E, 0x00, 0x0E, 0x00, 0x00, 0x60, 0x00, 0x3F, 0xE1, 0xC3,
0xFF, 0xCE, 0x3F, 0xFF, 0xF3, 0xE0, 0x3F, 0x9E, 0x00, 0xFD, 0xF0, 0x03,
0xEF, 0x00, 0x1F, 0x78, 0x00, 0x7B, 0xC0, 0x03, 0xFC, 0x00, 0x1F, 0xE0,
0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F, 0xE0, 0x01, 0xEF, 0x00, 0x0F,
0x78, 0x00, 0x7B, 0xC0, 0x03, 0xDF, 0x00, 0x3E, 0x78, 0x03, 0xF3, 0xE0,
0x3F, 0x8F, 0xFF, 0xFC, 0x3F, 0xFD, 0xE0, 0x7F, 0x8F, 0x00, 0x00, 0x78,
0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x0F, 0x10, 0x00,
0xF8, 0xE0, 0x0F, 0x87, 0xFF, 0xFC, 0x3F, 0xFF, 0xC0, 0x7F, 0xF8, 0x00,
0xE0, 0x00, 0x1C, 0x00, 0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01,
0xC0, 0x00, 0x38, 0x00, 0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x03,
0x8F, 0xFC, 0x73, 0xFF, 0xCE, 0xFF, 0xFD, 0xF8, 0x0F, 0xBE, 0x00, 0xFF,
0xC0, 0x0F, 0xF0, 0x01, 0xFE, 0x00, 0x3F, 0xC0, 0x07, 0xF8, 0x00, 0xFE,
0x00, 0x1F, 0xC0, 0x03, 0xF8, 0x00, 0x7F, 0x00, 0x0F, 0xE0, 0x01, 0xFC,
0x00, 0x3F, 0x80, 0x07, 0xF0, 0x00, 0xFE, 0x00, 0x1F, 0xC0, 0x03, 0xF8,
0x00, 0x7F, 0x00, 0x0F, 0xE0, 0x01, 0xE0, 0x33, 0xFF, 0xF7, 0x00, 0x00,
0x03, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C,
0xE7, 0x39, 0xCE, 0x01, 0x80, 0xF0, 0x7C, 0x1F, 0x03, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03,
0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0,
0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38, 0x0E,
0x03, 0x81, 0xE0, 0x7B, 0xFE, 0xFF, 0x3F, 0x80, 0xE0, 0x00, 0x1C, 0x00,
0x03, 0x80, 0x00, 0x70, 0x00, 0x0E, 0x00, 0x01, 0xC0, 0x00, 0x38, 0x00,
0x07, 0x00, 0x00, 0xE0, 0x00, 0x1C, 0x00, 0x03, 0x80, 0x1F, 0x70, 0x07,
0x8E, 0x01, 0xF1, 0xC0, 0x7C, 0x38, 0x1F, 0x07, 0x07, 0xC0, 0xE1, 0xF0,
0x1C, 0x7C, 0x03, 0x9F, 0x00, 0x73, 0xC0, 0x0E, 0xF8, 0x01, 0xFF, 0x80,
0x3F, 0xF8, 0x07, 0xCF, 0x00, 0xE0, 0xF0, 0x1C, 0x1F, 0x03, 0x81, 0xF0,
0x70, 0x1E, 0x0E, 0x01, 0xE1, 0xC0, 0x3E, 0x38, 0x03, 0xE7, 0x00, 0x3C,
0xE0, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x20, 0x00, 0xC0, 0x71, 0xFF, 0x03, 0xFE,
0x39, 0xFF, 0xC7, 0xFF, 0x9D, 0xFF, 0xF7, 0xFF, 0xEF, 0xC0, 0x7F, 0x81,
0xF7, 0xC0, 0x3F, 0x80, 0x7B, 0xC0, 0x0F, 0x80, 0x1F, 0xE0, 0x07, 0xC0,
0x0F, 0xF0, 0x03, 0xC0, 0x07, 0xF8, 0x01, 0xE0, 0x03, 0xFC, 0x00, 0xF0,
0x01, 0xFC, 0x00, 0x78, 0x00, 0xFE, 0x00, 0x3C, 0x00, 0x7F, 0x00, 0x1E,
0x00, 0x3F, 0x80, 0x0F, 0x00, 0x1F, 0xC0, 0x07, 0x80, 0x0F, 0xE0, 0x03,
0xC0, 0x07, 0xF0, 0x01, 0xE0, 0x03, 0xF8, 0x00, 0xF0, 0x01, 0xFC, 0x00,
0x78, 0x00, 0xFE, 0x00, 0x3C, 0x00, 0x7F, 0x00, 0x1E, 0x00, 0x3F, 0x80,
0x0F, 0x00, 0x1F, 0xC0, 0x07, 0x80, 0x0F, 0x00, 0x30, 0x1C, 0x7F, 0xE3,
0x9F, 0xFE, 0x77, 0xFF, 0xEF, 0xC0, 0x7D, 0xF0, 0x07, 0xFC, 0x00, 0x7F,
0x80, 0x0F, 0xF0, 0x01, 0xFE, 0x00, 0x3F, 0xC0, 0x07, 0xF0, 0x00, 0xFE,
0x00, 0x1F, 0xC0, 0x03, 0xF8, 0x00, 0x7F, 0x00, 0x0F, 0xE0, 0x01, 0xFC,
0x00, 0x3F, 0x80, 0x07, 0xF0, 0x00, 0xFE, 0x00, 0x1F, 0xC0, 0x03, 0xF8,
0x00, 0x7F, 0x00, 0x0F, 0x00, 0x10, 0x00, 0x0F, 0xFC, 0x00, 0xFF, 0xFC,
0x07, 0xFF, 0xF8, 0x3E, 0x03, 0xE0, 0xF0, 0x03, 0xC7, 0xC0, 0x0F, 0x9E,
0x00, 0x1E, 0x78, 0x00, 0x79, 0xE0, 0x00, 0xEF, 0x00, 0x03, 0xFC, 0x00,
0x0F, 0xF0, 0x00, 0x3F, 0xC0, 0x00, 0xFF, 0x00, 0x03, 0xDE, 0x00, 0x0E,
0x78, 0x00, 0x79, 0xE0, 0x01, 0xE3, 0xC0, 0x0F, 0x8F, 0x00, 0x3C, 0x1F,
0x03, 0xE0, 0x3F, 0xFF, 0x80, 0x7F, 0xFC, 0x00, 0xFF, 0xC0, 0x00, 0x20,
0x0E, 0x3F, 0xE0, 0xE7, 0xFF, 0x8E, 0xFF, 0xFC, 0xFC, 0x07, 0xCF, 0x80,
0x3E, 0xF0, 0x01, 0xEF, 0x00, 0x1F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0,
0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xF0, 0x00, 0xFF,
0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x1E, 0xF8, 0x01, 0xEF, 0x80, 0x3E,
0xFE, 0x07, 0xCE, 0xFF, 0xF8, 0xE7, 0xFF, 0x0E, 0x3F, 0xE0, 0xE0, 0x00,
0x0E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00,
0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0xE0, 0x00, 0x0E, 0x00, 0x00, 0x00,
0x60, 0x00, 0x1F, 0xE1, 0xC3, 0xFF, 0xCE, 0x3F, 0xFF, 0xF3, 0xE0, 0x3F,
0x9E, 0x00, 0xFD, 0xF0, 0x03, 0xEF, 0x00, 0x1F, 0x78, 0x00, 0x7B, 0xC0,
0x03, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00, 0x07, 0xF8, 0x00, 0x3F,
0xC0, 0x01, 0xEF, 0x00, 0x0F, 0x78, 0x00, 0x7B, 0xC0, 0x07, 0xDF, 0x00,
0x3E, 0x78, 0x03, 0xF3, 0xE0, 0x3F, 0x8F, 0xFF, 0xFC, 0x3F, 0xFD, 0xE0,
0x7F, 0x8F, 0x00, 0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x1E, 0x00, 0x00,
0xF0, 0x00, 0x07, 0x80, 0x00, 0x3C, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00,
0x00, 0x78, 0x00, 0x03, 0xC0, 0x00, 0x27, 0x0F, 0xF9, 0xFF, 0xDF, 0xFE,
0xF0, 0x7E, 0x03, 0xE0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C, 0x01, 0xC0,
0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01,
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0x00, 0xC0, 0x07, 0xFF,
0x0F, 0xFF, 0xCF, 0xFF, 0xE7, 0x80, 0x67, 0x80, 0x03, 0xC0, 0x01, 0xE0,
0x00, 0xF8, 0x00, 0x3F, 0x00, 0x0F, 0xE0, 0x03, 0xFE, 0x00, 0x7F, 0xC0,
0x0F, 0xF0, 0x00, 0xFC, 0x00, 0x1E, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x01,
0xE0, 0x00, 0xEE, 0x00, 0xF7, 0xFF, 0xF3, 0xFF, 0xF8, 0xFF, 0xF0, 0x0E,
0x00, 0x38, 0x00, 0xE0, 0x07, 0x80, 0x1E, 0x01, 0xFF, 0xEF, 0xFF, 0xBF,
0xFE, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x01,
0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00,
0x78, 0x01, 0xE0, 0x07, 0x80, 0x1F, 0x00, 0x3F, 0xF0, 0x7F, 0xC0, 0xFF,
0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00,
0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00,
0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x00, 0x0F, 0xF0,
0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0xF7, 0x80, 0x1F, 0x78, 0x03, 0xF7,
0xC0, 0x7F, 0x3F, 0xFF, 0xF1, 0xFF, 0xE7, 0x0F, 0xF8, 0x70, 0xF0, 0x00,
0x3D, 0xE0, 0x01, 0xE7, 0x80, 0x07, 0x9E, 0x00, 0x1E, 0x3C, 0x00, 0xF0,
0xF0, 0x03, 0xC1, 0xC0, 0x1E, 0x07, 0x80, 0x78, 0x1E, 0x01, 0xE0, 0x3C,
0x0F, 0x00, 0xF0, 0x3C, 0x03, 0xC0, 0xE0, 0x07, 0x87, 0x80, 0x1E, 0x1E,
0x00, 0x38, 0x70, 0x00, 0xF3, 0xC0, 0x03, 0xCF, 0x00, 0x07, 0x38, 0x00,
0x1F, 0xE0, 0x00, 0x7F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0, 0x00, 0x07,
0x80, 0x00, 0xF8, 0x01, 0xE0, 0x07, 0xBC, 0x01, 0xF8, 0x03, 0xDE, 0x00,
0xFC, 0x01, 0xEF, 0x00, 0x7E, 0x00, 0xE3, 0xC0, 0x7F, 0x00, 0xF1, 0xE0,
0x3B, 0xC0, 0x78, 0xF0, 0x1C, 0xE0, 0x3C, 0x38, 0x1E, 0x70, 0x1C, 0x1E,
0x0F, 0x3C, 0x1E, 0x0F, 0x07, 0x1E, 0x0F, 0x07, 0x83, 0x87, 0x07, 0x01,
0xC3, 0xC3, 0xC7, 0x80, 0xF1, 0xC1, 0xE3, 0xC0, 0x78, 0xE0, 0x71, 0xE0,
0x3C, 0xF0, 0x38, 0xE0, 0x0E, 0x70, 0x1E, 0xF0, 0x07, 0xB8, 0x07, 0x78,
0x03, 0xDC, 0x03, 0xBC, 0x00, 0xFE, 0x01, 0xDC, 0x00, 0x7E, 0x00, 0xFE,
0x00, 0x3F, 0x00, 0x3F, 0x00, 0x1F, 0x80, 0x1F, 0x00, 0x07, 0x80, 0x0F,
0x80, 0xF8, 0x00, 0xFB, 0xE0, 0x0F, 0x0F, 0x00, 0x78, 0x3C, 0x07, 0x81,
0xF0, 0x78, 0x07, 0x83, 0xC0, 0x1E, 0x3C, 0x00, 0x7B, 0xC0, 0x03, 0xFE,
0x00, 0x0F, 0xE0, 0x00, 0x3E, 0x00, 0x01, 0xF0, 0x00, 0x1F, 0xC0, 0x01,
0xFE, 0x00, 0x0F, 0x78, 0x00, 0xF1, 0xE0, 0x0F, 0x8F, 0x00, 0x78, 0x3C,
0x07, 0x80, 0xF0, 0x78, 0x07, 0xC3, 0xC0, 0x1E, 0x3C, 0x00, 0x7B, 0xC0,
0x03, 0xE0, 0xF0, 0x00, 0x3D, 0xE0, 0x01, 0xE7, 0x80, 0x07, 0x9E, 0x00,
0x1E, 0x3C, 0x00, 0xF0, 0xF0, 0x03, 0xC1, 0xE0, 0x1E, 0x07, 0x80, 0x78,
0x1E, 0x01, 0xE0, 0x3C, 0x0F, 0x00, 0xF0, 0x3C, 0x01, 0xC0, 0xF0, 0x07,
0x87, 0x80, 0x0E, 0x1E, 0x00, 0x3C, 0x70, 0x00, 0xF3, 0xC0, 0x01, 0xCF,
0x00, 0x07, 0xB8, 0x00, 0x1F, 0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFC, 0x00,
0x01, 0xF0, 0x00, 0x07, 0x80, 0x00, 0x1E, 0x00, 0x00, 0x78, 0x00, 0x03,
0xC0, 0x00, 0x0F, 0x00, 0x00, 0x78, 0x00, 0x01, 0xE0, 0x00, 0x0F, 0x00,
0x0F, 0xFC, 0x00, 0x3F, 0xE0, 0x00, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0x7F,
0xFF, 0xBF, 0xFF, 0xC0, 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xE0, 0x00, 0xF0,
0x00, 0xF0, 0x00, 0xF0, 0x00, 0xF8, 0x00, 0x78, 0x00, 0x78, 0x00, 0x78,
0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x3E, 0x00, 0x1E, 0x00, 0x1E,
0x00, 0x1E, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x1C,
0x01, 0xF0, 0x1F, 0xC0, 0xFE, 0x03, 0xC0, 0x0F, 0x00, 0x78, 0x01, 0xE0,
0x07, 0x80, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78,
0x01, 0xE0, 0x0F, 0x83, 0xFC, 0x0F, 0xC0, 0x3F, 0x00, 0xFF, 0x00, 0x3E,
0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07,
0x80, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x03, 0xC0, 0x0F, 0x00, 0x3F, 0x80,
0x7F, 0x00, 0xFC, 0x00, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0xE0, 0x03,
0xF0, 0x0F, 0xE0, 0x1F, 0xC0, 0x0F, 0x00, 0x1E, 0x00, 0x78, 0x01, 0xE0,
0x07, 0x80, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78,
0x01, 0xE0, 0x03, 0xC0, 0x07, 0xF0, 0x0F, 0xC0, 0x1F, 0x01, 0xFC, 0x0F,
0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07,
0x80, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x3C, 0x07, 0xF0, 0x3F,
0x80, 0xFC, 0x03, 0x80, 0x00, 0x1F, 0x80, 0x17, 0xFE, 0x01, 0xFF, 0xFE,
0xFE, 0x0F, 0xFF, 0xC0, 0x3F, 0xE8, 0x00, 0x78 };
const GFXglyph NotoSans_Regular22pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 11, 0, 0 }, // 0x20 ' '
{ 1, 5, 32, 12, 3, -30 }, // 0x21 '!'
{ 21, 12, 11, 18, 3, -30 }, // 0x22 '"'
{ 38, 26, 31, 28, 1, -30 }, // 0x23 '#'
{ 139, 19, 36, 25, 3, -32 }, // 0x24 '$'
{ 225, 32, 31, 36, 2, -30 }, // 0x25 '%'
{ 349, 29, 31, 32, 2, -30 }, // 0x26 '&'
{ 462, 4, 11, 10, 3, -30 }, // 0x27 '''
{ 468, 10, 38, 13, 2, -30 }, // 0x28 '('
{ 516, 10, 38, 13, 1, -30 }, // 0x29 ')'
{ 564, 20, 20, 24, 2, -32 }, // 0x2A '*'
{ 614, 20, 21, 25, 2, -25 }, // 0x2B '+'
{ 667, 6, 11, 12, 2, -4 }, // 0x2C ','
{ 676, 10, 3, 14, 2, -12 }, // 0x2D '-'
{ 680, 5, 6, 12, 3, -4 }, // 0x2E '.'
{ 684, 16, 31, 16, 0, -30 }, // 0x2F '/'
{ 746, 21, 31, 25, 2, -30 }, // 0x30 '0'
{ 828, 11, 31, 25, 4, -30 }, // 0x31 '1'
{ 871, 20, 31, 25, 2, -30 }, // 0x32 '2'
{ 949, 20, 31, 25, 2, -30 }, // 0x33 '3'
{ 1027, 23, 31, 25, 1, -30 }, // 0x34 '4'
{ 1117, 19, 31, 25, 3, -30 }, // 0x35 '5'
{ 1191, 21, 31, 25, 2, -30 }, // 0x36 '6'
{ 1273, 21, 31, 25, 2, -30 }, // 0x37 '7'
{ 1355, 20, 31, 25, 2, -30 }, // 0x38 '8'
{ 1433, 20, 31, 25, 2, -30 }, // 0x39 '9'
{ 1511, 5, 25, 12, 3, -23 }, // 0x3A ':'
{ 1527, 7, 30, 12, 1, -23 }, // 0x3B ';'
{ 1554, 20, 21, 25, 2, -25 }, // 0x3C '<'
{ 1607, 20, 12, 25, 2, -20 }, // 0x3D '='
{ 1637, 20, 21, 25, 2, -25 }, // 0x3E '>'
{ 1690, 17, 32, 19, 1, -30 }, // 0x3F '?'
{ 1758, 34, 35, 39, 2, -30 }, // 0x40 '@'
{ 1907, 27, 31, 28, 0, -30 }, // 0x41 'A'
{ 2012, 22, 31, 28, 4, -30 }, // 0x42 'B'
{ 2098, 23, 31, 27, 3, -30 }, // 0x43 'C'
{ 2188, 25, 31, 31, 4, -30 }, // 0x44 'D'
{ 2285, 17, 31, 24, 4, -30 }, // 0x45 'E'
{ 2351, 17, 31, 22, 4, -30 }, // 0x46 'F'
{ 2417, 25, 31, 31, 3, -30 }, // 0x47 'G'
{ 2514, 24, 31, 32, 4, -30 }, // 0x48 'H'
{ 2607, 11, 31, 15, 2, -30 }, // 0x49 'I'
{ 2650, 11, 39, 12, -3, -30 }, // 0x4A 'J'
{ 2704, 23, 31, 27, 4, -30 }, // 0x4B 'K'
{ 2794, 18, 31, 23, 4, -30 }, // 0x4C 'L'
{ 2864, 31, 31, 39, 4, -30 }, // 0x4D 'M'
{ 2985, 25, 31, 33, 4, -30 }, // 0x4E 'N'
{ 3082, 28, 31, 34, 3, -30 }, // 0x4F 'O'
{ 3191, 20, 31, 26, 4, -30 }, // 0x50 'P'
{ 3269, 28, 38, 34, 3, -30 }, // 0x51 'Q'
{ 3402, 22, 31, 27, 4, -30 }, // 0x52 'R'
{ 3488, 20, 31, 24, 2, -30 }, // 0x53 'S'
{ 3566, 23, 31, 24, 0, -30 }, // 0x54 'T'
{ 3656, 24, 31, 31, 4, -30 }, // 0x55 'U'
{ 3749, 26, 31, 26, 0, -30 }, // 0x56 'V'
{ 3850, 39, 31, 40, 1, -30 }, // 0x57 'W'
{ 4002, 25, 31, 25, 0, -30 }, // 0x58 'X'
{ 4099, 24, 31, 24, 0, -30 }, // 0x59 'Y'
{ 4192, 21, 31, 25, 2, -30 }, // 0x5A 'Z'
{ 4274, 10, 38, 14, 3, -30 }, // 0x5B '['
{ 4322, 16, 31, 16, 0, -30 }, // 0x5C '\'
{ 4384, 10, 38, 14, 1, -30 }, // 0x5D ']'
{ 4432, 21, 20, 25, 2, -30 }, // 0x5E '^'
{ 4485, 19, 3, 19, 0, 5 }, // 0x5F '_'
{ 4493, 8, 7, 12, 2, -32 }, // 0x60 '`'
{ 4500, 19, 23, 24, 2, -22 }, // 0x61 'a'
{ 4555, 20, 33, 27, 4, -32 }, // 0x62 'b'
{ 4638, 17, 24, 21, 2, -23 }, // 0x63 'c'
{ 4689, 21, 33, 27, 2, -32 }, // 0x64 'd'
{ 4776, 20, 24, 24, 2, -23 }, // 0x65 'e'
{ 4836, 16, 33, 15, 1, -32 }, // 0x66 'f'
{ 4902, 21, 34, 27, 2, -23 }, // 0x67 'g'
{ 4992, 19, 33, 27, 4, -32 }, // 0x68 'h'
{ 5071, 5, 32, 11, 3, -31 }, // 0x69 'i'
{ 5091, 10, 42, 11, -2, -31 }, // 0x6A 'j'
{ 5144, 19, 33, 23, 4, -32 }, // 0x6B 'k'
{ 5223, 3, 33, 11, 4, -32 }, // 0x6C 'l'
{ 5236, 33, 24, 40, 4, -23 }, // 0x6D 'm'
{ 5335, 19, 24, 27, 4, -23 }, // 0x6E 'n'
{ 5392, 22, 24, 26, 2, -23 }, // 0x6F 'o'
{ 5458, 20, 34, 27, 4, -23 }, // 0x70 'p'
{ 5543, 21, 34, 27, 2, -23 }, // 0x71 'q'
{ 5633, 13, 24, 18, 4, -23 }, // 0x72 'r'
{ 5672, 17, 24, 21, 2, -23 }, // 0x73 's'
{ 5723, 14, 28, 16, 1, -27 }, // 0x74 't'
{ 5772, 20, 23, 27, 3, -22 }, // 0x75 'u'
{ 5830, 22, 23, 22, 0, -22 }, // 0x76 'v'
{ 5894, 33, 23, 34, 0, -22 }, // 0x77 'w'
{ 5989, 21, 23, 23, 1, -22 }, // 0x78 'x'
{ 6050, 22, 33, 22, 0, -22 }, // 0x79 'y'
{ 6141, 17, 23, 20, 2, -22 }, // 0x7A 'z'
{ 6190, 14, 38, 16, 1, -30 }, // 0x7B '{'
{ 6257, 3, 43, 24, 10, -32 }, // 0x7C '|'
{ 6274, 14, 38, 16, 1, -30 }, // 0x7D '}'
{ 6341, 20, 6, 25, 2, -17 } }; // 0x7E '~'
const GFXfont NotoSans_Regular22pt7b PROGMEM = {
(uint8_t *)NotoSans_Regular22pt7bBitmaps,
(GFXglyph *)NotoSans_Regular22pt7bGlyphs,
0x20, 0x7E, 59 };
// Approx. 7028 bytes
#endif // NOTOSANS22PT7B_H
@@ -0,0 +1,166 @@
#ifndef NOTOSANS7PT7B_H
#define NOTOSANS7PT7B_H
const uint8_t NotoSans_Regular7pt7bBitmaps[] PROGMEM = {
0x00, 0xFA, 0xA8, 0xB0, 0xBB, 0x99, 0x12, 0x09, 0x04, 0x8F, 0xF1, 0x41,
0x23, 0xFC, 0x48, 0x24, 0x16, 0x00, 0x21, 0xFA, 0x28, 0xE0, 0xE2, 0x49,
0xF8, 0x82, 0x00, 0xE1, 0x2C, 0x89, 0x22, 0x50, 0x97, 0xBA, 0xB1, 0x24,
0x49, 0x22, 0x58, 0xE0, 0x78, 0x24, 0x13, 0x09, 0x03, 0x02, 0x8A, 0x25,
0x0C, 0x86, 0x3C, 0xC0, 0xF0, 0x6A, 0x49, 0x24, 0x93, 0x30, 0xC4, 0x22,
0x23, 0x32, 0x22, 0x6C, 0x22, 0x9F, 0xCC, 0x5B, 0x20, 0x20, 0x82, 0x3F,
0x20, 0x80, 0xEA, 0xE0, 0xB0, 0x08, 0x84, 0x22, 0x11, 0x88, 0x44, 0x00,
0x7B, 0x28, 0x61, 0x86, 0x18, 0x61, 0xCD, 0xE0, 0x37, 0xD1, 0x11, 0x11,
0x11, 0x7A, 0x20, 0xC3, 0x08, 0x43, 0x18, 0xC3, 0xF0, 0x7A, 0x30, 0x43,
0x78, 0x60, 0x41, 0x8F, 0xE0, 0x04, 0x0C, 0x14, 0x14, 0x24, 0x44, 0xC4,
0xFF, 0x04, 0x04, 0xFA, 0x08, 0x20, 0xF8, 0x30, 0x41, 0x8F, 0xE0, 0x39,
0x0C, 0x20, 0xFA, 0x18, 0x61, 0xC5, 0xE0, 0xFC, 0x10, 0xC2, 0x18, 0x43,
0x08, 0x21, 0x00, 0x7B, 0x38, 0x73, 0x79, 0x68, 0x61, 0x85, 0xE0, 0x73,
0x28, 0x61, 0x87, 0xF0, 0x43, 0x0B, 0xC0, 0xB0, 0x0B, 0x4C, 0x00, 0x1A,
0x50, 0x0C, 0xEC, 0x30, 0x30, 0x30, 0xFC, 0x00, 0x3F, 0x81, 0x81, 0x83,
0x33, 0x00, 0x7A, 0x20, 0xC2, 0x18, 0xC2, 0x00, 0x20, 0x80, 0x0E, 0x06,
0x31, 0x01, 0x47, 0xA9, 0x23, 0x24, 0x64, 0x94, 0xBA, 0x88, 0x88, 0x00,
0xFC, 0x00, 0x08, 0x0C, 0x05, 0x02, 0x82, 0x61, 0x11, 0xF8, 0x82, 0x41,
0x40, 0xC0, 0xF9, 0x8F, 0x0E, 0x3F, 0xD9, 0xB0, 0xE1, 0xC7, 0xF8, 0x3E,
0xC7, 0x04, 0x08, 0x10, 0x20, 0x60, 0x60, 0x7C, 0xF8, 0xC6, 0xC3, 0xC1,
0xC1, 0xC1, 0xC1, 0xC3, 0xC6, 0xFC, 0xFF, 0x0C, 0x30, 0xFF, 0x0C, 0x30,
0xC3, 0xF0, 0xFF, 0x0C, 0x30, 0xC3, 0xFC, 0x30, 0xC3, 0x00, 0x1E, 0x61,
0xC0, 0x80, 0x80, 0x87, 0x81, 0xC1, 0x61, 0x3F, 0xC1, 0xC1, 0xC1, 0xC1,
0xFF, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xE9, 0x24, 0x92, 0x5C, 0x33, 0x33,
0x33, 0x33, 0x33, 0x2E, 0xC0, 0xC3, 0x8B, 0x26, 0x8E, 0x1A, 0x36, 0x66,
0xC5, 0x84, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0xF0, 0xC0, 0xF8,
0x3A, 0x1E, 0x85, 0x91, 0x64, 0x99, 0xA6, 0x29, 0x8C, 0x63, 0x10, 0xC1,
0xE1, 0xA1, 0xB1, 0x99, 0x89, 0x8D, 0x85, 0x83, 0x83, 0x3E, 0x31, 0xB0,
0x50, 0x38, 0x0C, 0x06, 0x07, 0x82, 0x43, 0x1F, 0x00, 0xF9, 0x9B, 0x1E,
0x3C, 0x5F, 0x30, 0x60, 0xC1, 0x80, 0x3E, 0x31, 0xB0, 0x50, 0x38, 0x0C,
0x06, 0x07, 0x82, 0x43, 0x1F, 0x01, 0x80, 0x60, 0xF9, 0x9B, 0x1E, 0x3C,
0x5F, 0x32, 0x66, 0xC5, 0x84, 0x7B, 0x18, 0x20, 0x60, 0xE0, 0xC1, 0x8F,
0xE0, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, 0x20, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0xC3, 0x42, 0x3C, 0x81, 0xC3, 0x42, 0x42,
0x26, 0x24, 0x34, 0x1C, 0x18, 0x18, 0xC2, 0x1A, 0x30, 0x91, 0x44, 0x8A,
0x66, 0xD2, 0x14, 0xD0, 0xA2, 0x85, 0x1C, 0x30, 0xC0, 0x82, 0x00, 0xC3,
0x42, 0x24, 0x3C, 0x18, 0x18, 0x3C, 0x24, 0x42, 0xC3, 0x83, 0x42, 0x66,
0x24, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFC, 0x10, 0x86, 0x10, 0x86,
0x10, 0x83, 0xF0, 0xF2, 0x49, 0x24, 0x92, 0x70, 0x82, 0x10, 0xC2, 0x10,
0xC2, 0x10, 0x40, 0xE4, 0x92, 0x49, 0x24, 0xF0, 0x20, 0xC5, 0x12, 0x8A,
0x10, 0xFC, 0xB4, 0xF8, 0x30, 0xFF, 0x8E, 0x3F, 0x40, 0x81, 0x02, 0x07,
0xEC, 0x50, 0xE1, 0xC3, 0xC5, 0x78, 0x7C, 0x21, 0x08, 0x61, 0xE0, 0x04,
0x10, 0x5F, 0x86, 0x18, 0x61, 0xC5, 0xF0, 0x7A, 0x18, 0x7F, 0x83, 0x07,
0xC0, 0x39, 0x19, 0xF6, 0x31, 0x8C, 0x63, 0x00, 0x7E, 0x18, 0x61, 0x87,
0x17, 0xC1, 0x07, 0xE0, 0x82, 0x08, 0x2F, 0xC6, 0x18, 0x61, 0x86, 0x10,
0x9F, 0xC0, 0x20, 0x12, 0x49, 0x24, 0x9E, 0x82, 0x08, 0x62, 0x92, 0x8F,
0x24, 0x8A, 0x30, 0xFF, 0xC0, 0xFF, 0xD8, 0x8E, 0x10, 0xC2, 0x18, 0x43,
0x08, 0x61, 0x08, 0xFF, 0x18, 0x61, 0x86, 0x18, 0x40, 0x7D, 0x0A, 0x14,
0x38, 0x58, 0x9E, 0x00, 0xFD, 0x8A, 0x1C, 0x38, 0x78, 0xAF, 0x40, 0x81,
0x00, 0x7E, 0x18, 0x61, 0x87, 0x17, 0xC1, 0x04, 0x10, 0xBC, 0x88, 0x88,
0x80, 0xFC, 0x30, 0x60, 0x87, 0xC0, 0x22, 0x3E, 0x84, 0x21, 0x0C, 0x38,
0x86, 0x18, 0x61, 0x87, 0x17, 0xC0, 0xC6, 0x89, 0x13, 0x62, 0x85, 0x04,
0x00, 0xCC, 0x69, 0x49, 0x29, 0x25, 0x67, 0x38, 0x63, 0x0C, 0x60, 0xC6,
0x58, 0xE0, 0xC2, 0x8C, 0xB1, 0x80, 0xC6, 0x89, 0x11, 0x62, 0x85, 0x04,
0x08, 0x31, 0xC0, 0xF8, 0x88, 0xC4, 0x43, 0xE0, 0x19, 0x88, 0x42, 0x33,
0x84, 0x21, 0x08, 0x30, 0xFF, 0xF8, 0xC1, 0x08, 0x42, 0x18, 0x64, 0x21,
0x09, 0xC0, 0xE6, 0xF0 };
const GFXglyph NotoSans_Regular7pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 4, 0, 0 }, // 0x20 ' '
{ 1, 2, 10, 4, 1, -9 }, // 0x21 '!'
{ 4, 4, 4, 6, 1, -9 }, // 0x22 '"'
{ 6, 9, 10, 9, 0, -9 }, // 0x23 '#'
{ 18, 6, 11, 8, 1, -9 }, // 0x24 '$'
{ 27, 10, 10, 11, 1, -9 }, // 0x25 '%'
{ 40, 9, 10, 10, 1, -9 }, // 0x26 '&'
{ 52, 1, 4, 3, 1, -9 }, // 0x27 '''
{ 53, 3, 12, 4, 1, -9 }, // 0x28 '('
{ 58, 4, 12, 4, 0, -9 }, // 0x29 ')'
{ 64, 6, 6, 8, 1, -9 }, // 0x2A '*'
{ 69, 6, 6, 8, 1, -7 }, // 0x2B '+'
{ 74, 2, 4, 4, 1, -1 }, // 0x2C ','
{ 75, 3, 1, 4, 1, -3 }, // 0x2D '-'
{ 76, 2, 2, 4, 1, -1 }, // 0x2E '.'
{ 77, 5, 10, 5, 0, -9 }, // 0x2F '/'
{ 84, 6, 10, 8, 1, -9 }, // 0x30 '0'
{ 92, 4, 10, 8, 1, -9 }, // 0x31 '1'
{ 97, 6, 10, 8, 1, -9 }, // 0x32 '2'
{ 105, 6, 10, 8, 1, -9 }, // 0x33 '3'
{ 113, 8, 10, 8, 0, -9 }, // 0x34 '4'
{ 123, 6, 10, 8, 1, -9 }, // 0x35 '5'
{ 131, 6, 10, 8, 1, -9 }, // 0x36 '6'
{ 139, 6, 10, 8, 1, -9 }, // 0x37 '7'
{ 147, 6, 10, 8, 1, -9 }, // 0x38 '8'
{ 155, 6, 10, 8, 1, -9 }, // 0x39 '9'
{ 163, 2, 8, 4, 1, -7 }, // 0x3A ':'
{ 165, 3, 10, 4, 0, -7 }, // 0x3B ';'
{ 169, 6, 6, 8, 1, -7 }, // 0x3C '<'
{ 174, 6, 4, 8, 1, -6 }, // 0x3D '='
{ 177, 6, 6, 8, 1, -7 }, // 0x3E '>'
{ 182, 6, 10, 6, 0, -9 }, // 0x3F '?'
{ 190, 11, 11, 12, 1, -9 }, // 0x40 '@'
{ 206, 9, 10, 9, 0, -9 }, // 0x41 'A'
{ 218, 7, 10, 9, 1, -9 }, // 0x42 'B'
{ 227, 7, 10, 9, 1, -9 }, // 0x43 'C'
{ 236, 8, 10, 10, 1, -9 }, // 0x44 'D'
{ 246, 6, 10, 8, 1, -9 }, // 0x45 'E'
{ 254, 6, 10, 7, 1, -9 }, // 0x46 'F'
{ 262, 8, 10, 10, 1, -9 }, // 0x47 'G'
{ 272, 8, 10, 10, 1, -9 }, // 0x48 'H'
{ 282, 3, 10, 5, 1, -9 }, // 0x49 'I'
{ 286, 4, 13, 4, -1, -9 }, // 0x4A 'J'
{ 293, 7, 10, 8, 1, -9 }, // 0x4B 'K'
{ 302, 6, 10, 7, 1, -9 }, // 0x4C 'L'
{ 310, 10, 10, 12, 1, -9 }, // 0x4D 'M'
{ 323, 8, 10, 10, 1, -9 }, // 0x4E 'N'
{ 333, 9, 10, 11, 1, -9 }, // 0x4F 'O'
{ 345, 7, 10, 8, 1, -9 }, // 0x50 'P'
{ 354, 9, 12, 11, 1, -9 }, // 0x51 'Q'
{ 368, 7, 10, 9, 1, -9 }, // 0x52 'R'
{ 377, 6, 10, 8, 1, -9 }, // 0x53 'S'
{ 385, 7, 10, 8, 0, -9 }, // 0x54 'T'
{ 394, 8, 10, 10, 1, -9 }, // 0x55 'U'
{ 404, 8, 10, 8, 0, -9 }, // 0x56 'V'
{ 414, 13, 10, 13, 0, -9 }, // 0x57 'W'
{ 431, 8, 10, 8, 0, -9 }, // 0x58 'X'
{ 441, 8, 10, 8, 0, -9 }, // 0x59 'Y'
{ 451, 6, 10, 8, 1, -9 }, // 0x5A 'Z'
{ 459, 3, 12, 5, 1, -9 }, // 0x5B '['
{ 464, 5, 10, 5, 0, -9 }, // 0x5C '\'
{ 471, 3, 12, 5, 0, -9 }, // 0x5D ']'
{ 476, 6, 6, 8, 1, -9 }, // 0x5E '^'
{ 481, 6, 1, 6, 0, 2 }, // 0x5F '_'
{ 482, 2, 3, 4, 1, -10 }, // 0x60 '`'
{ 483, 6, 7, 8, 1, -6 }, // 0x61 'a'
{ 489, 7, 10, 8, 1, -9 }, // 0x62 'b'
{ 498, 5, 7, 7, 1, -6 }, // 0x63 'c'
{ 503, 6, 10, 8, 1, -9 }, // 0x64 'd'
{ 511, 6, 7, 8, 1, -6 }, // 0x65 'e'
{ 517, 5, 10, 5, 0, -9 }, // 0x66 'f'
{ 524, 6, 10, 8, 1, -6 }, // 0x67 'g'
{ 532, 6, 10, 8, 1, -9 }, // 0x68 'h'
{ 540, 1, 10, 4, 1, -9 }, // 0x69 'i'
{ 542, 3, 13, 4, -1, -9 }, // 0x6A 'j'
{ 547, 6, 10, 7, 1, -9 }, // 0x6B 'k'
{ 555, 1, 10, 4, 1, -9 }, // 0x6C 'l'
{ 557, 11, 7, 13, 1, -6 }, // 0x6D 'm'
{ 567, 6, 7, 8, 1, -6 }, // 0x6E 'n'
{ 573, 7, 7, 8, 1, -6 }, // 0x6F 'o'
{ 580, 7, 10, 8, 1, -6 }, // 0x70 'p'
{ 589, 6, 10, 8, 1, -6 }, // 0x71 'q'
{ 597, 4, 7, 6, 1, -6 }, // 0x72 'r'
{ 601, 5, 7, 7, 1, -6 }, // 0x73 's'
{ 606, 5, 9, 5, 0, -8 }, // 0x74 't'
{ 612, 6, 7, 8, 1, -6 }, // 0x75 'u'
{ 618, 7, 7, 7, 0, -6 }, // 0x76 'v'
{ 625, 11, 7, 11, 0, -6 }, // 0x77 'w'
{ 635, 7, 7, 7, 0, -6 }, // 0x78 'x'
{ 642, 7, 10, 7, 0, -6 }, // 0x79 'y'
{ 651, 5, 7, 6, 1, -6 }, // 0x7A 'z'
{ 656, 5, 12, 5, 0, -9 }, // 0x7B '{'
{ 664, 1, 13, 8, 3, -9 }, // 0x7C '|'
{ 666, 5, 12, 5, 0, -9 }, // 0x7D '}'
{ 674, 6, 2, 8, 1, -5 } }; // 0x7E '~'
const GFXfont NotoSans_Regular7pt7b PROGMEM = {
(uint8_t *)NotoSans_Regular7pt7bBitmaps,
(GFXglyph *)NotoSans_Regular7pt7bGlyphs,
0x20, 0x7E, 19 };
// Approx. 1348 bytes
#endif // NOTOSANS7PT7B_H
@@ -0,0 +1,201 @@
#ifndef NOTOSANS9PT7B_H
#define NOTOSANS9PT7B_H
const uint8_t NotoSans_Regular9pt7bBitmaps[] PROGMEM = {
0x00, 0xF5, 0x55, 0x43, 0xC0, 0xDE, 0xF3, 0x9C, 0x80, 0x0C, 0x81, 0x10,
0x22, 0x04, 0x47, 0xFE, 0x32, 0x04, 0x40, 0x88, 0xFF, 0xC2, 0x60, 0xC8,
0x11, 0x02, 0x20, 0x18, 0x3E, 0x7F, 0xD8, 0xD8, 0xF8, 0x3C, 0x1F, 0x1B,
0x19, 0x9B, 0xFE, 0x18, 0x18, 0x70, 0x46, 0xC2, 0x22, 0x21, 0x13, 0x08,
0x90, 0x45, 0xB3, 0x6B, 0x4E, 0xD3, 0x04, 0x98, 0x44, 0xC2, 0x26, 0x21,
0x23, 0x07, 0x00, 0x1C, 0x07, 0x60, 0x62, 0x06, 0x20, 0x26, 0x03, 0xC0,
0x38, 0x06, 0xC6, 0xC6, 0x6C, 0x3C, 0xC1, 0x8E, 0x3C, 0x7E, 0x70, 0xFF,
0xC0, 0x32, 0x64, 0xCC, 0x88, 0x88, 0x8C, 0xC4, 0x63, 0x8C, 0x46, 0x22,
0x23, 0x33, 0x22, 0x64, 0xC8, 0x18, 0x10, 0xD3, 0xFF, 0x18, 0x2C, 0x66,
0x24, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x7E, 0xF0, 0xF0,
0x04, 0x30, 0xC2, 0x18, 0x41, 0x0C, 0x21, 0x86, 0x10, 0xC0, 0x3C, 0x7E,
0x42, 0xC3, 0xC1, 0x81, 0x81, 0x81, 0xC1, 0xC3, 0xC3, 0x66, 0x3C, 0x13,
0xD9, 0x11, 0x11, 0x11, 0x11, 0x10, 0x3C, 0xFE, 0x83, 0x03, 0x03, 0x02,
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0xFF, 0x3C, 0xFE, 0x83, 0x03, 0x03,
0x06, 0x38, 0x06, 0x03, 0x03, 0x03, 0x86, 0xFC, 0x03, 0x01, 0xC0, 0x70,
0x3C, 0x1B, 0x04, 0xC2, 0x31, 0x8C, 0x43, 0x3F, 0xF0, 0x30, 0x0C, 0x03,
0x00, 0x7E, 0x7E, 0x40, 0x40, 0x40, 0xFC, 0x7E, 0x03, 0x03, 0x03, 0x03,
0x86, 0xFC, 0x0E, 0x3E, 0x60, 0x40, 0xC0, 0xDC, 0xE7, 0xC3, 0xC1, 0xC1,
0xC3, 0x63, 0x3E, 0xFF, 0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x0C, 0x18,
0x18, 0x10, 0x30, 0x60, 0x3C, 0x7E, 0xC3, 0xC3, 0x43, 0x76, 0x3C, 0x66,
0xC3, 0x81, 0x81, 0xC3, 0x7E, 0x38, 0x7E, 0xC3, 0xC3, 0x81, 0xC3, 0xC3,
0x7D, 0x03, 0x03, 0x02, 0x0E, 0x78, 0x74, 0x00, 0xF0, 0x74, 0x00, 0xFA,
0x01, 0x03, 0x0C, 0x30, 0xC0, 0xE0, 0x1C, 0x07, 0x01, 0xFF, 0xFF, 0x00,
0x00, 0xFF, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x07, 0x38, 0xE0, 0x80, 0x39,
0xFC, 0x08, 0x10, 0x60, 0x86, 0x08, 0x30, 0x00, 0x01, 0x83, 0x00, 0x03,
0x80, 0x7F, 0x83, 0x01, 0x18, 0x02, 0x47, 0xCF, 0x31, 0x38, 0x84, 0x62,
0x31, 0x88, 0xCE, 0x23, 0x2C, 0x77, 0x10, 0x00, 0x60, 0x00, 0x7F, 0x00,
0x30, 0x00, 0x04, 0x01, 0xC0, 0x28, 0x05, 0x81, 0xB0, 0x22, 0x04, 0x61,
0x84, 0x3F, 0xCC, 0x19, 0x81, 0x20, 0x3C, 0x06, 0xF8, 0x7F, 0x20, 0xD0,
0x68, 0x34, 0x33, 0xF1, 0x06, 0x81, 0x40, 0xE0, 0x50, 0xEF, 0xE0, 0x0F,
0x0F, 0xF6, 0x01, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x06,
0x00, 0xC2, 0x1F, 0x80, 0xF8, 0x3F, 0xC8, 0x3A, 0x06, 0x80, 0xE0, 0x38,
0x0E, 0x03, 0x80, 0xE0, 0x68, 0x1A, 0x1C, 0xFC, 0x00, 0xFF, 0xFE, 0x04,
0x08, 0x10, 0x3F, 0x40, 0x81, 0x02, 0x04, 0x0F, 0xE0, 0xFF, 0xFE, 0x04,
0x08, 0x10, 0x3F, 0x7E, 0x81, 0x02, 0x04, 0x08, 0x00, 0x0F, 0x87, 0xF9,
0xC0, 0x30, 0x0C, 0x01, 0x80, 0x30, 0xFE, 0x1F, 0xC0, 0x68, 0x0D, 0x81,
0x98, 0x31, 0xFE, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFF, 0x01,
0x80, 0xC0, 0x60, 0x30, 0x18, 0x08, 0xFF, 0x66, 0x66, 0x66, 0x66, 0x66,
0xF0, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x3E, 0x81, 0xC1, 0xA1,
0x91, 0x89, 0x85, 0x83, 0xC1, 0xB0, 0x8C, 0x46, 0x21, 0x90, 0x68, 0x18,
0x81, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x81, 0x02, 0x04, 0x0F, 0xE0,
0xC0, 0x3C, 0x03, 0xE0, 0x7A, 0x05, 0xB0, 0xDB, 0x09, 0x90, 0x99, 0x99,
0x89, 0x18, 0xB1, 0x8F, 0x18, 0x61, 0x86, 0x10, 0xC0, 0xF0, 0x3E, 0x0E,
0xC3, 0xB0, 0xE6, 0x38, 0x8E, 0x33, 0x86, 0xE0, 0xB8, 0x3E, 0x07, 0x80,
0xC0, 0x0F, 0x03, 0xFC, 0x60, 0x64, 0x06, 0xC0, 0x2C, 0x03, 0xC0, 0x3C,
0x03, 0xC0, 0x3C, 0x02, 0x60, 0x63, 0x0C, 0x1F, 0x80, 0xF0, 0xFE, 0x82,
0x83, 0x83, 0x83, 0x86, 0xFC, 0x80, 0x80, 0x80, 0x80, 0x80, 0x0F, 0x03,
0xFC, 0x60, 0x64, 0x06, 0xC0, 0x2C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3C,
0x02, 0x60, 0x63, 0x0C, 0x1F, 0x80, 0x18, 0x01, 0xC0, 0x0E, 0xF0, 0x7F,
0x20, 0xD0, 0x68, 0x34, 0x13, 0xF9, 0xF0, 0x8C, 0x43, 0x21, 0x90, 0x68,
0x18, 0x3D, 0x7E, 0xC0, 0xC0, 0xC0, 0x60, 0x3C, 0x0E, 0x03, 0x03, 0x03,
0x86, 0xFC, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30,
0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18,
0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x70, 0x7C, 0x63, 0xE0, 0xC0, 0x78,
0x09, 0x03, 0x30, 0x46, 0x18, 0x43, 0x0C, 0x40, 0x98, 0x1B, 0x03, 0x40,
0x38, 0x07, 0x00, 0xC0, 0xC1, 0x83, 0x41, 0x83, 0x41, 0xC3, 0x63, 0xC2,
0x63, 0x46, 0x22, 0x46, 0x22, 0x66, 0x36, 0x24, 0x34, 0x2C, 0x14, 0x3C,
0x14, 0x38, 0x1C, 0x18, 0x18, 0x18, 0xC0, 0xD8, 0x22, 0x18, 0xCC, 0x1A,
0x03, 0x80, 0xC0, 0x38, 0x1A, 0x0C, 0xC2, 0x19, 0x82, 0xC0, 0xC0, 0xC0,
0xD0, 0x26, 0x18, 0x84, 0x33, 0x04, 0x81, 0xE0, 0x30, 0x0C, 0x03, 0x00,
0xC0, 0x30, 0x0C, 0x00, 0xFF, 0xFF, 0x03, 0x06, 0x04, 0x0C, 0x18, 0x10,
0x30, 0x60, 0x40, 0xC0, 0xFF, 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
0xCF, 0xC1, 0x04, 0x18, 0x20, 0xC3, 0x04, 0x18, 0x20, 0x83, 0x04, 0xFF,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x1F, 0x10, 0x18, 0x38, 0x24, 0x64,
0x42, 0x42, 0x81, 0xFF, 0xD9, 0x80, 0x18, 0xFC, 0x08, 0x11, 0xEE, 0x70,
0xC1, 0xC6, 0xF4, 0xC0, 0x60, 0x30, 0x19, 0x8F, 0xF7, 0x0B, 0x07, 0x83,
0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, 0x1C, 0xFD, 0x06, 0x0C, 0x18, 0x30,
0x60, 0x62, 0x7C, 0x01, 0x01, 0x01, 0x19, 0x7F, 0xC3, 0xC1, 0xC1, 0xC1,
0xC1, 0xC1, 0x63, 0x3D, 0x18, 0x7E, 0x43, 0xC3, 0xFF, 0xFF, 0xC0, 0xC0,
0x61, 0x3F, 0x1E, 0x60, 0x81, 0x0F, 0xC4, 0x08, 0x10, 0x20, 0x40, 0x81,
0x02, 0x00, 0x18, 0x7F, 0x43, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x3D,
0x01, 0x01, 0x43, 0x7E, 0xC0, 0xC0, 0xC0, 0xCC, 0xFF, 0xE1, 0xC1, 0xC1,
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xF0, 0xFF, 0xFF, 0xC0, 0x33, 0x00, 0x33,
0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC6, 0xCC,
0xD8, 0xD0, 0xF8, 0xCC, 0xC4, 0xC6, 0xC3, 0xFF, 0xFF, 0xFF, 0xC0, 0x0C,
0x33, 0xFB, 0xFE, 0x38, 0xF0, 0xC3, 0xC1, 0x07, 0x04, 0x1C, 0x10, 0x70,
0x41, 0xC1, 0x07, 0x04, 0x10, 0x0C, 0xFF, 0xE1, 0xC1, 0xC1, 0xC1, 0xC1,
0xC1, 0xC1, 0xC1, 0x18, 0x3F, 0x10, 0xD8, 0x3C, 0x1E, 0x0F, 0x07, 0x82,
0x63, 0x1F, 0x00, 0x0C, 0x7F, 0xB8, 0x58, 0x3C, 0x1E, 0x0F, 0x07, 0x83,
0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x18, 0x7F, 0xC3, 0xC1, 0xC1,
0xC1, 0xC1, 0xC1, 0x63, 0x3D, 0x01, 0x01, 0x01, 0x01, 0x0F, 0x7E, 0x30,
0xC3, 0x0C, 0x30, 0xC3, 0x00, 0x39, 0xFA, 0x06, 0x07, 0x07, 0x81, 0x83,
0x85, 0xF8, 0x20, 0x86, 0x3F, 0x20, 0x82, 0x08, 0x20, 0x83, 0x0F, 0xC1,
0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x63, 0x7D, 0xC1, 0xA0, 0x98, 0xCC,
0x42, 0x21, 0xB0, 0x50, 0x28, 0x1C, 0x00, 0xC3, 0x0D, 0x1C, 0x26, 0x79,
0x99, 0x26, 0x24, 0x90, 0xB3, 0x43, 0x8F, 0x0E, 0x18, 0x18, 0x60, 0xE3,
0x99, 0x05, 0x83, 0x80, 0xC0, 0xB0, 0xC8, 0xC6, 0xC1, 0x80, 0xC1, 0xA0,
0x98, 0xC4, 0x43, 0x21, 0xB0, 0x50, 0x38, 0x0C, 0x04, 0x06, 0x02, 0x0F,
0x00, 0xFC, 0x18, 0x20, 0xC3, 0x0C, 0x10, 0x60, 0xFE, 0x04, 0x71, 0x04,
0x10, 0x41, 0x3C, 0xE0, 0xC1, 0x04, 0x10, 0x41, 0xC3, 0xFF, 0xFF, 0xFF,
0xFF, 0xC0, 0x87, 0x18, 0x42, 0x10, 0x87, 0x39, 0x08, 0x42, 0x33, 0x90,
0xF9, 0x8F };
const GFXglyph NotoSans_Regular9pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' '
{ 1, 2, 13, 5, 1, -12 }, // 0x21 '!'
{ 5, 5, 5, 7, 1, -12 }, // 0x22 '"'
{ 9, 11, 13, 11, 0, -12 }, // 0x23 '#'
{ 27, 8, 14, 10, 1, -12 }, // 0x24 '$'
{ 41, 13, 13, 15, 1, -12 }, // 0x25 '%'
{ 63, 12, 13, 13, 1, -12 }, // 0x26 '&'
{ 83, 2, 5, 4, 1, -12 }, // 0x27 '''
{ 85, 4, 16, 5, 1, -12 }, // 0x28 '('
{ 93, 4, 16, 5, 1, -12 }, // 0x29 ')'
{ 101, 8, 8, 10, 1, -12 }, // 0x2A '*'
{ 109, 8, 8, 10, 1, -9 }, // 0x2B '+'
{ 117, 2, 4, 5, 1, -1 }, // 0x2C ','
{ 118, 4, 1, 6, 1, -4 }, // 0x2D '-'
{ 119, 2, 2, 5, 1, -1 }, // 0x2E '.'
{ 120, 6, 13, 7, 0, -12 }, // 0x2F '/'
{ 130, 8, 13, 10, 1, -12 }, // 0x30 '0'
{ 143, 4, 13, 10, 2, -12 }, // 0x31 '1'
{ 150, 8, 13, 10, 1, -12 }, // 0x32 '2'
{ 163, 8, 13, 10, 1, -12 }, // 0x33 '3'
{ 176, 10, 13, 10, 0, -12 }, // 0x34 '4'
{ 193, 8, 13, 10, 1, -12 }, // 0x35 '5'
{ 206, 8, 13, 10, 1, -12 }, // 0x36 '6'
{ 219, 8, 13, 10, 1, -12 }, // 0x37 '7'
{ 232, 8, 13, 10, 1, -12 }, // 0x38 '8'
{ 245, 8, 13, 10, 1, -12 }, // 0x39 '9'
{ 258, 2, 10, 5, 1, -9 }, // 0x3A ':'
{ 261, 2, 12, 5, 1, -9 }, // 0x3B ';'
{ 264, 8, 9, 10, 1, -10 }, // 0x3C '<'
{ 273, 8, 5, 10, 1, -8 }, // 0x3D '='
{ 278, 8, 9, 10, 1, -10 }, // 0x3E '>'
{ 287, 7, 13, 8, 0, -12 }, // 0x3F '?'
{ 299, 14, 15, 16, 1, -12 }, // 0x40 '@'
{ 326, 11, 13, 11, 0, -12 }, // 0x41 'A'
{ 344, 9, 13, 11, 2, -12 }, // 0x42 'B'
{ 359, 10, 13, 11, 1, -12 }, // 0x43 'C'
{ 376, 10, 13, 13, 2, -12 }, // 0x44 'D'
{ 393, 7, 13, 10, 2, -12 }, // 0x45 'E'
{ 405, 7, 13, 9, 2, -12 }, // 0x46 'F'
{ 417, 11, 13, 13, 1, -12 }, // 0x47 'G'
{ 435, 9, 13, 13, 2, -12 }, // 0x48 'H'
{ 450, 4, 13, 6, 1, -12 }, // 0x49 'I'
{ 457, 4, 16, 5, -1, -12 }, // 0x4A 'J'
{ 465, 9, 13, 11, 2, -12 }, // 0x4B 'K'
{ 480, 7, 13, 9, 2, -12 }, // 0x4C 'L'
{ 492, 12, 13, 16, 2, -12 }, // 0x4D 'M'
{ 512, 10, 13, 13, 2, -12 }, // 0x4E 'N'
{ 529, 12, 13, 14, 1, -12 }, // 0x4F 'O'
{ 549, 8, 13, 11, 2, -12 }, // 0x50 'P'
{ 562, 12, 16, 14, 1, -12 }, // 0x51 'Q'
{ 586, 9, 13, 11, 2, -12 }, // 0x52 'R'
{ 601, 8, 13, 10, 1, -12 }, // 0x53 'S'
{ 614, 10, 13, 10, 0, -12 }, // 0x54 'T'
{ 631, 9, 13, 13, 2, -12 }, // 0x55 'U'
{ 646, 11, 13, 11, 0, -12 }, // 0x56 'V'
{ 664, 16, 13, 16, 0, -12 }, // 0x57 'W'
{ 690, 10, 13, 10, 0, -12 }, // 0x58 'X'
{ 707, 10, 13, 10, 0, -12 }, // 0x59 'Y'
{ 724, 8, 13, 10, 1, -12 }, // 0x5A 'Z'
{ 737, 4, 16, 6, 1, -12 }, // 0x5B '['
{ 745, 6, 13, 7, 0, -12 }, // 0x5C '\'
{ 755, 4, 16, 6, 0, -12 }, // 0x5D ']'
{ 763, 8, 8, 10, 1, -12 }, // 0x5E '^'
{ 771, 8, 1, 8, 0, 3 }, // 0x5F '_'
{ 772, 3, 3, 5, 1, -13 }, // 0x60 '`'
{ 774, 7, 10, 10, 1, -9 }, // 0x61 'a'
{ 783, 9, 13, 11, 1, -12 }, // 0x62 'b'
{ 798, 7, 10, 8, 1, -9 }, // 0x63 'c'
{ 807, 8, 13, 11, 1, -12 }, // 0x64 'd'
{ 820, 8, 10, 10, 1, -9 }, // 0x65 'e'
{ 830, 7, 13, 6, 0, -12 }, // 0x66 'f'
{ 842, 8, 14, 11, 1, -9 }, // 0x67 'g'
{ 856, 8, 13, 11, 1, -12 }, // 0x68 'h'
{ 869, 2, 13, 5, 1, -12 }, // 0x69 'i'
{ 873, 4, 17, 5, -1, -12 }, // 0x6A 'j'
{ 882, 8, 13, 9, 1, -12 }, // 0x6B 'k'
{ 895, 2, 13, 5, 1, -12 }, // 0x6C 'l'
{ 899, 14, 10, 16, 1, -9 }, // 0x6D 'm'
{ 917, 8, 10, 11, 1, -9 }, // 0x6E 'n'
{ 927, 9, 10, 11, 1, -9 }, // 0x6F 'o'
{ 939, 9, 14, 11, 1, -9 }, // 0x70 'p'
{ 955, 8, 14, 11, 1, -9 }, // 0x71 'q'
{ 969, 6, 10, 7, 1, -9 }, // 0x72 'r'
{ 977, 7, 10, 8, 1, -9 }, // 0x73 's'
{ 986, 6, 12, 6, 0, -11 }, // 0x74 't'
{ 995, 8, 9, 11, 1, -8 }, // 0x75 'u'
{ 1004, 9, 9, 9, 0, -8 }, // 0x76 'v'
{ 1015, 14, 9, 14, 0, -8 }, // 0x77 'w'
{ 1031, 9, 9, 9, 0, -8 }, // 0x78 'x'
{ 1042, 9, 13, 9, 0, -8 }, // 0x79 'y'
{ 1057, 7, 9, 8, 1, -8 }, // 0x7A 'z'
{ 1065, 6, 16, 7, 0, -12 }, // 0x7B '{'
{ 1077, 2, 17, 10, 4, -12 }, // 0x7C '|'
{ 1082, 5, 16, 7, 1, -12 }, // 0x7D '}'
{ 1092, 8, 2, 10, 1, -6 } }; // 0x7E '~'
const GFXfont NotoSans_Regular9pt7b PROGMEM = {
(uint8_t *)NotoSans_Regular9pt7bBitmaps,
(GFXglyph *)NotoSans_Regular9pt7bGlyphs,
0x20, 0x7E, 24 };
// Approx. 1766 bytes
#endif // NOTOSANS9PT7B_H
@@ -0,0 +1,285 @@
#ifndef NOTOSANSBOLD12PT7B_H
#define NOTOSANSBOLD12PT7B_H
const uint8_t NotoSans_Bold12pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0x77, 0x77, 0x77, 0x77, 0x06, 0xFF, 0x70, 0xF7, 0xB9,
0xDC, 0xEE, 0x77, 0x33, 0x18, 0x0E, 0x70, 0x39, 0xC0, 0xE6, 0x03, 0x18,
0x0C, 0x63, 0xFF, 0xFF, 0xFF, 0xC7, 0x30, 0x1C, 0xC0, 0x63, 0x0F, 0xFF,
0xBF, 0xFE, 0x39, 0x80, 0xE6, 0x03, 0x18, 0x0C, 0xE0, 0x73, 0x80, 0x06,
0x00, 0x60, 0x1F, 0xC7, 0xFE, 0xFF, 0xEF, 0x62, 0xF6, 0x0F, 0xE0, 0x7F,
0x03, 0xFC, 0x0F, 0xE0, 0x7E, 0x06, 0xF8, 0x6E, 0xFF, 0xEF, 0xFC, 0x7F,
0x80, 0x60, 0x06, 0x00, 0x3C, 0x07, 0x0F, 0xC1, 0xC3, 0xB8, 0x30, 0x73,
0x8E, 0x0E, 0x73, 0x81, 0x8E, 0x70, 0x39, 0xDC, 0x07, 0x33, 0xBE, 0xFE,
0xEF, 0xEF, 0x99, 0xDC, 0x47, 0x31, 0x80, 0xCE, 0x30, 0x38, 0xC6, 0x0E,
0x18, 0xC1, 0xC3, 0xB8, 0x70, 0x7F, 0x0E, 0x07, 0xC0, 0x0F, 0x80, 0x1F,
0xE0, 0x0F, 0xF8, 0x0F, 0x3C, 0x07, 0x8E, 0x01, 0xCF, 0x00, 0xFF, 0x00,
0x3F, 0x00, 0x3F, 0x0F, 0x3F, 0xC7, 0x3C, 0xF7, 0x9E, 0x3F, 0xCF, 0x0F,
0xC7, 0x83, 0xC3, 0xFF, 0xF0, 0xFF, 0xFC, 0x3F, 0xCF, 0x80, 0xF7, 0x77,
0x76, 0x1C, 0xE3, 0x9C, 0x71, 0xCE, 0x38, 0xE3, 0x8E, 0x38, 0xE3, 0x8E,
0x1C, 0x71, 0xC3, 0x8E, 0x1C, 0xE1, 0xC7, 0x0E, 0x38, 0xE3, 0xC7, 0x1C,
0x71, 0xC7, 0x1C, 0x73, 0xCE, 0x38, 0xE7, 0x38, 0xE0, 0x0E, 0x01, 0xC0,
0x38, 0x47, 0x3F, 0xFF, 0xFF, 0xC7, 0x80, 0xF8, 0x3B, 0x8E, 0x78, 0xC4,
0x00, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x0F, 0xFF, 0xFF, 0xFF, 0xF8, 0x70,
0x0E, 0x01, 0xC0, 0x38, 0x00, 0x77, 0xFE, 0xEC, 0xFF, 0xFF, 0xC0, 0x6F,
0xF7, 0x03, 0xC0, 0xE0, 0x38, 0x1C, 0x07, 0x03, 0xC0, 0xE0, 0x38, 0x1E,
0x07, 0x01, 0xC0, 0xE0, 0x38, 0x1E, 0x07, 0x01, 0xC0, 0xF0, 0x00, 0x1F,
0x03, 0xFC, 0x7F, 0xC7, 0x1E, 0xF0, 0xEF, 0x0E, 0xE0, 0xEE, 0x0F, 0xE0,
0xFE, 0x0F, 0xE0, 0xFF, 0x0E, 0xF0, 0xE7, 0x1E, 0x7F, 0xE3, 0xFC, 0x1F,
0x80, 0x07, 0x87, 0xC7, 0xE7, 0xFF, 0xFB, 0xBC, 0x9E, 0x0F, 0x07, 0x83,
0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x80, 0x1F, 0x87, 0xFC,
0xFF, 0xE7, 0x1E, 0x40, 0xE0, 0x0E, 0x01, 0xE0, 0x1C, 0x03, 0xC0, 0x78,
0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F,
0x0F, 0xFC, 0xFF, 0xE6, 0x1E, 0x00, 0xE0, 0x1E, 0x01, 0xC3, 0xF8, 0x3F,
0x83, 0xFE, 0x01, 0xE0, 0x0E, 0x00, 0xF8, 0x1E, 0xFF, 0xEF, 0xFC, 0xFF,
0x80, 0x00, 0xE0, 0x0F, 0x00, 0xF8, 0x07, 0xC0, 0x7E, 0x07, 0x70, 0x73,
0x83, 0x9C, 0x38, 0xE3, 0x87, 0x1C, 0x39, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
0x03, 0x80, 0x1C, 0x00, 0xE0, 0x7F, 0xCF, 0xF9, 0xFF, 0x38, 0x07, 0x00,
0xE0, 0x1F, 0xC3, 0xFE, 0xFF, 0xE8, 0x7C, 0x03, 0x80, 0x70, 0x0F, 0x03,
0xFF, 0xFF, 0xFE, 0x7F, 0x00, 0x07, 0xC1, 0xFC, 0x3F, 0xC7, 0x80, 0x70,
0x0F, 0x00, 0xE7, 0x8E, 0xFC, 0xFF, 0xEF, 0x0E, 0xE0, 0xFE, 0x0F, 0xF0,
0xFF, 0x0E, 0x7F, 0xE3, 0xFC, 0x1F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
0x0E, 0x01, 0xE0, 0x1C, 0x03, 0xC0, 0x38, 0x07, 0x80, 0x78, 0x07, 0x00,
0xF0, 0x0E, 0x01, 0xE0, 0x1C, 0x03, 0xC0, 0x3C, 0x00, 0x1F, 0x07, 0xFC,
0x7F, 0xEF, 0x0E, 0xF0, 0xE7, 0x1E, 0x7B, 0xC3, 0xF8, 0x1F, 0x87, 0xFC,
0xF1, 0xEE, 0x0E, 0xE0, 0xFE, 0x0F, 0xF9, 0xE7, 0xFC, 0x3F, 0x80, 0x1F,
0x07, 0xF8, 0x7F, 0xCF, 0x1E, 0xE0, 0xEE, 0x0E, 0xE0, 0xFF, 0x1F, 0xFF,
0xF7, 0xFE, 0x3E, 0xE0, 0x0E, 0x01, 0xE0, 0x1C, 0x7F, 0xC7, 0xF8, 0x7E,
0x00, 0x7F, 0xF6, 0x00, 0x00, 0x06, 0xFF, 0x70, 0x7F, 0xF6, 0x00, 0x00,
0x00, 0x77, 0xFE, 0xEC, 0x00, 0x20, 0x0C, 0x07, 0x83, 0xE1, 0xF0, 0xF8,
0x3C, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0x80, 0x30, 0x02, 0xFF, 0xFF,
0xFF, 0xFF, 0x80, 0x00, 0x01, 0xFF, 0xFF, 0xF8, 0x80, 0x18, 0x03, 0xC0,
0x3E, 0x01, 0xF0, 0x0F, 0x80, 0x78, 0x1F, 0x1F, 0x8F, 0xC3, 0xE0, 0x70,
0x08, 0x00, 0x3F, 0x1F, 0xF9, 0xFF, 0x20, 0xF0, 0x1E, 0x03, 0xC0, 0xF0,
0x3C, 0x0F, 0x03, 0xC0, 0x70, 0x0E, 0x00, 0x00, 0x10, 0x07, 0x80, 0xF0,
0x1E, 0x00, 0x01, 0xF8, 0x00, 0xFF, 0xC0, 0x7C, 0x3E, 0x1E, 0x01, 0xE3,
0x83, 0x1C, 0xE3, 0xF9, 0xD8, 0xFF, 0x3F, 0x38, 0xE7, 0xE7, 0x1C, 0xFC,
0xC3, 0x9F, 0x98, 0x73, 0xF3, 0x8E, 0x6E, 0x7F, 0xFC, 0xC7, 0xCF, 0x1C,
0x00, 0x01, 0xC0, 0x00, 0x3E, 0x1E, 0x01, 0xFF, 0xC0, 0x0F, 0xE0, 0x00,
0x03, 0xC0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x0F, 0x70, 0x0E, 0x70,
0x0E, 0x78, 0x1E, 0x78, 0x1E, 0x38, 0x1C, 0x3C, 0x3F, 0xFC, 0x3F, 0xFC,
0x3F, 0xFE, 0x78, 0x1E, 0x78, 0x0E, 0x70, 0x0F, 0xF0, 0x0F, 0xFF, 0x8F,
0xFE, 0xFF, 0xFF, 0x0F, 0xF0, 0xFF, 0x0F, 0xF1, 0xEF, 0xFE, 0xFF, 0xCF,
0xFF, 0xF0, 0xFF, 0x07, 0xF0, 0x7F, 0x0F, 0xFF, 0xFF, 0xFE, 0xFF, 0x80,
0x07, 0xF0, 0xFF, 0xCF, 0xFE, 0x78, 0x27, 0x80, 0x3C, 0x03, 0xC0, 0x1E,
0x00, 0xF0, 0x07, 0x80, 0x3C, 0x00, 0xE0, 0x07, 0x80, 0x3E, 0x04, 0xFF,
0xE3, 0xFF, 0x0F, 0xF0, 0xFF, 0x03, 0xFF, 0x8F, 0xFF, 0x3C, 0x7E, 0xF0,
0x7B, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC,
0x0F, 0xF0, 0x7B, 0xC3, 0xEF, 0xFF, 0x3F, 0xF8, 0xFF, 0x80, 0xFF, 0xFF,
0xFF, 0xFF, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xFE, 0xFF, 0xBF, 0xEF, 0x03,
0xC0, 0xF0, 0x3C, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xFE, 0xFF, 0xBF, 0xEF, 0x03, 0xC0, 0xF0,
0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x00, 0x03, 0xF8, 0x3F, 0xF3, 0xFF, 0xCF,
0x82, 0x78, 0x01, 0xE0, 0x07, 0x00, 0x3C, 0x00, 0xF1, 0xFF, 0xC7, 0xFF,
0x1F, 0xDC, 0x07, 0x78, 0x1D, 0xF0, 0x73, 0xFF, 0xC7, 0xFF, 0x0F, 0xF8,
0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0,
0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3C, 0xFF, 0xFF, 0xF9, 0xC3, 0x87, 0x0E,
0x1C, 0x38, 0x70, 0xE1, 0xC3, 0x87, 0x1F, 0x7F, 0xFE, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x1E, 0xFE, 0xFC, 0xF8, 0xF0, 0x7F, 0xC1, 0xEF, 0x0F,
0x3C, 0x78, 0xF3, 0xC3, 0xDE, 0x0F, 0x78, 0x3F, 0xC0, 0xFF, 0x03, 0xFE,
0x0F, 0x3C, 0x3C, 0xF0, 0xF1, 0xE3, 0xC7, 0x8F, 0x0F, 0x3C, 0x1E, 0xF0,
0x7C, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0,
0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0xF8,
0x07, 0xFE, 0x01, 0xFF, 0xC0, 0xFF, 0xF0, 0x3F, 0xFC, 0x0F, 0xFB, 0x87,
0x7E, 0xE1, 0xDF, 0xB8, 0x77, 0xE7, 0x39, 0xF9, 0xCE, 0x7E, 0x73, 0x9F,
0x8D, 0xC7, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3E, 0x1F, 0x87, 0x87, 0xE1,
0xE1, 0xC0, 0xF8, 0x0F, 0xF0, 0x1F, 0xF0, 0x3F, 0xF0, 0x7F, 0xE0, 0xFD,
0xE1, 0xFB, 0xC3, 0xF3, 0xC7, 0xE3, 0x8F, 0xC7, 0x9F, 0x87, 0xBF, 0x0F,
0x7E, 0x0F, 0xFC, 0x1F, 0xF8, 0x1F, 0xF0, 0x1F, 0xE0, 0x3E, 0x07, 0xF0,
0x1F, 0xF8, 0x3F, 0xFE, 0x7C, 0x3E, 0x78, 0x0F, 0x78, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0x70, 0x0F, 0x78, 0x0F,
0x7C, 0x1E, 0x3F, 0xFE, 0x1F, 0xFC, 0x0F, 0xF0, 0xFF, 0x0F, 0xFC, 0xFF,
0xEF, 0x1E, 0xF0, 0xFF, 0x0F, 0xF0, 0xFF, 0x1E, 0xFF, 0xEF, 0xFC, 0xFF,
0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x0F, 0x00, 0xF0, 0x00, 0x07, 0xF0,
0x1F, 0xF8, 0x3F, 0xFE, 0x7C, 0x3E, 0x78, 0x0F, 0x78, 0x0F, 0xF0, 0x0F,
0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0x70, 0x0F, 0x78, 0x0F,
0x7C, 0x1E, 0x3F, 0xFE, 0x1F, 0xFC, 0x0F, 0xF0, 0x00, 0x78, 0x00, 0x3C,
0x00, 0x3E, 0x00, 0x1F, 0xFF, 0x07, 0xFE, 0x3F, 0xF9, 0xE3, 0xCF, 0x0F,
0x78, 0x7B, 0xC3, 0xDE, 0x3C, 0xFF, 0xC7, 0xFC, 0x3F, 0xE1, 0xE7, 0x8F,
0x1E, 0x78, 0xF3, 0xC3, 0xDE, 0x1E, 0xF0, 0x78, 0x1F, 0x87, 0xFD, 0xFF,
0x78, 0x2F, 0x01, 0xE0, 0x1E, 0x03, 0xF0, 0x3F, 0x81, 0xF8, 0x0F, 0x80,
0xF0, 0x0F, 0x83, 0xFF, 0xFF, 0xFE, 0x7F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFE, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80, 0x3C,
0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1E, 0x00, 0xF0, 0x07, 0x80,
0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03,
0xFC, 0x0F, 0xF0, 0x3F, 0xC0, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0xE1,
0xE7, 0xFF, 0x8F, 0xFC, 0x1F, 0xE0, 0xF0, 0x0F, 0xE0, 0x3D, 0xC0, 0x7B,
0xC0, 0xE7, 0x83, 0xC7, 0x07, 0x0F, 0x0E, 0x1E, 0x3C, 0x1C, 0x70, 0x3C,
0xE0, 0x7B, 0xC0, 0x77, 0x00, 0xEE, 0x01, 0xFC, 0x01, 0xF0, 0x03, 0xE0,
0x03, 0xC0, 0xF0, 0x38, 0x1F, 0xE0, 0xF0, 0x39, 0xC1, 0xF0, 0x73, 0x83,
0xE1, 0xE7, 0x87, 0xC3, 0xCF, 0x1D, 0x87, 0x0E, 0x3B, 0x8E, 0x1C, 0x77,
0x3C, 0x38, 0xEE, 0x78, 0x7B, 0x9C, 0xE0, 0x77, 0x1D, 0xC0, 0xEE, 0x3B,
0x81, 0xD8, 0x7F, 0x03, 0xF0, 0xFC, 0x03, 0xE0, 0xF8, 0x07, 0xC1, 0xF0,
0x0F, 0x03, 0xE0, 0xF8, 0x1E, 0x78, 0x3C, 0x3C, 0x3C, 0x1C, 0x78, 0x1E,
0x78, 0x0F, 0xF0, 0x0F, 0xE0, 0x07, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x0F,
0xE0, 0x0E, 0xF0, 0x1E, 0x78, 0x3C, 0x78, 0x3C, 0x3C, 0x78, 0x1E, 0xF0,
0x1F, 0xF0, 0x1E, 0xF0, 0x79, 0xE0, 0xE1, 0xE3, 0xC3, 0xC7, 0x03, 0xDE,
0x07, 0xB8, 0x07, 0xF0, 0x0F, 0xC0, 0x0F, 0x80, 0x1E, 0x00, 0x1C, 0x00,
0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0x1E, 0x01, 0xC0, 0x3C, 0x07, 0x80, 0x70, 0x0F, 0x01, 0xE0,
0x3C, 0x03, 0xC0, 0x78, 0x0F, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFF,
0xFF, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x3F, 0xFF,
0x80, 0xF0, 0x1C, 0x07, 0x01, 0xE0, 0x38, 0x0E, 0x03, 0xC0, 0x70, 0x1C,
0x03, 0x80, 0xE0, 0x3C, 0x07, 0x01, 0xC0, 0x78, 0x0E, 0x03, 0xC0, 0xFF,
0xFE, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xE7, 0x39, 0xFF, 0xFF,
0x80, 0x0C, 0x00, 0xE0, 0x1E, 0x01, 0xF0, 0x1B, 0x83, 0xB8, 0x31, 0xC7,
0x1C, 0x60, 0xEE, 0x0E, 0xC0, 0x70, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0x70,
0x70, 0x1F, 0x8F, 0xFC, 0xFF, 0x80, 0x70, 0x0E, 0x3F, 0xDF, 0xFF, 0xC7,
0xF0, 0xFE, 0x1F, 0xEF, 0xFF, 0xF7, 0xE6, 0xE0, 0x0E, 0x00, 0xE0, 0x0E,
0x00, 0xE0, 0x0E, 0x78, 0xFF, 0xCF, 0xFE, 0xF1, 0xEE, 0x0F, 0xE0, 0xFE,
0x0F, 0xE0, 0xFE, 0x0F, 0xF1, 0xEF, 0xFE, 0xFF, 0xCE, 0xF8, 0x0F, 0xCF,
0xF7, 0xFD, 0xE0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3E, 0x17, 0xFC,
0xFF, 0x1F, 0xC0, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x71, 0xE7,
0x3F, 0x77, 0xFF, 0xF8, 0xFF, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07,
0xF0, 0xF7, 0xFF, 0x7F, 0x73, 0xF7, 0x1F, 0x83, 0xFC, 0x7F, 0xE7, 0x0F,
0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0x00, 0xF0, 0x07, 0x00, 0x7C, 0xE3, 0xFE,
0x1F, 0xE0, 0x0F, 0xC7, 0xF1, 0xF8, 0xF0, 0x3C, 0x0F, 0xEF, 0xFB, 0xFE,
0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F,
0x00, 0x1E, 0x73, 0xF7, 0x7F, 0xF7, 0x8F, 0xF0, 0x7F, 0x07, 0xF0, 0x7F,
0x07, 0xF0, 0x7F, 0x0F, 0x7F, 0xF7, 0xF7, 0x3F, 0x70, 0x07, 0x00, 0xF6,
0x1F, 0x7F, 0xE7, 0xFC, 0x0F, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00,
0xE0, 0x0E, 0x7C, 0xFF, 0xEF, 0xFE, 0xF0, 0xFF, 0x0F, 0xE0, 0xFE, 0x0F,
0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F, 0xFF, 0xA1, 0xFF,
0xFF, 0xFF, 0xFF, 0xFC, 0x1C, 0x71, 0xC2, 0x00, 0x71, 0xC7, 0x1C, 0x71,
0xC7, 0x1C, 0x71, 0xC7, 0x1C, 0x71, 0xC7, 0x3F, 0xFF, 0x98, 0xE0, 0x07,
0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x7B, 0x87, 0x9C, 0x78, 0xE7,
0x87, 0x78, 0x3B, 0x81, 0xFE, 0x0F, 0xF0, 0x7B, 0xC3, 0x8F, 0x1C, 0x3C,
0xE1, 0xE7, 0x07, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xEF,
0x8F, 0x9F, 0xFF, 0xFB, 0xFF, 0xFF, 0xF8, 0xF8, 0xFF, 0x0F, 0x0F, 0xC1,
0xC1, 0xF8, 0x38, 0x3F, 0x07, 0x07, 0xE0, 0xE0, 0xFC, 0x1C, 0x1F, 0x83,
0x83, 0xF0, 0x70, 0x7E, 0x0E, 0x0E, 0xE7, 0xCF, 0xFE, 0xFF, 0xEF, 0x0F,
0xF0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F,
0xE0, 0xF0, 0x1F, 0x81, 0xFF, 0x1F, 0xF8, 0xE1, 0xEF, 0x07, 0x78, 0x3B,
0xC1, 0xFE, 0x0F, 0xF0, 0x73, 0x87, 0x9F, 0xFC, 0x7F, 0xC1, 0xFC, 0x00,
0xE7, 0x8F, 0xFC, 0xFF, 0xEF, 0x1E, 0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F,
0xE0, 0xFF, 0x1E, 0xFF, 0xEF, 0xFC, 0xEF, 0x8E, 0x00, 0xE0, 0x0E, 0x00,
0xE0, 0x0E, 0x00, 0xE0, 0x00, 0x1E, 0x73, 0xF7, 0x7F, 0xFF, 0x8F, 0xF0,
0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x0F, 0x7F, 0xF7, 0xF7, 0x3F,
0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0x07, 0x00, 0x70, 0xE7, 0xEF,
0xFF, 0xF8, 0xF0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x3F,
0x9F, 0xFF, 0xBB, 0xC0, 0xF8, 0x1F, 0x83, 0xF8, 0x3E, 0x03, 0xC0, 0xFF,
0x7F, 0xFE, 0xFF, 0x00, 0x38, 0x38, 0x38, 0x7F, 0xFF, 0xFF, 0x78, 0x78,
0x78, 0x78, 0x78, 0x78, 0x78, 0x7F, 0x3F, 0x1F, 0xE0, 0xFE, 0x0F, 0xE0,
0xFE, 0x0F, 0xE0, 0xFE, 0x0F, 0xE0, 0xFE, 0x0F, 0xE0, 0xFF, 0x1F, 0xFF,
0xFF, 0xFF, 0x7E, 0x70, 0xF0, 0x3B, 0x83, 0xDC, 0x1E, 0xF0, 0xE3, 0x8F,
0x1C, 0x70, 0xF3, 0x83, 0xBC, 0x1D, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x00,
0x78, 0x00, 0xF0, 0xF0, 0xF7, 0x0F, 0x0F, 0x70, 0xF8, 0xE7, 0x9F, 0x8E,
0x79, 0xF9, 0xE3, 0x99, 0x9C, 0x39, 0x9D, 0xC3, 0xF9, 0xDC, 0x1F, 0x9F,
0x81, 0xF0, 0xF8, 0x1F, 0x0F, 0x81, 0xF0, 0xF8, 0x0F, 0x0F, 0x00, 0xF8,
0x7B, 0xC7, 0x8F, 0x3C, 0x3B, 0xC1, 0xFC, 0x07, 0xE0, 0x3E, 0x01, 0xF8,
0x1F, 0xC1, 0xEF, 0x0F, 0x3C, 0xF0, 0xEF, 0x07, 0x80, 0xF0, 0x3B, 0x83,
0xDE, 0x1E, 0xF0, 0xE3, 0x8F, 0x1E, 0x70, 0x73, 0x83, 0xBC, 0x1D, 0xC0,
0x7E, 0x03, 0xF0, 0x0F, 0x00, 0x78, 0x03, 0x80, 0x3C, 0x03, 0xE0, 0x7E,
0x03, 0xE0, 0x1C, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0x1E, 0x0F, 0x03, 0x81,
0xE0, 0xF0, 0x78, 0x1C, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0x07, 0x0F, 0x1F,
0x1E, 0x1C, 0x1C, 0x1C, 0x1C, 0x1C, 0xFC, 0xF0, 0xFC, 0x1C, 0x1C, 0x1C,
0x1C, 0x1C, 0x1E, 0x1F, 0x0F, 0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xF8, 0xE0, 0xF0, 0xF8, 0x38, 0x38, 0x38, 0x38, 0x38, 0x3C,
0x1F, 0x07, 0x3F, 0x3C, 0x38, 0x38, 0x38, 0x38, 0x38, 0xF8, 0xF0, 0xC0,
0x7C, 0x3F, 0xFF, 0x3F, 0xC0, 0xC0 };
const GFXglyph NotoSans_Bold12pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 6, 0, 0 }, // 0x20 ' '
{ 1, 4, 17, 7, 1, -16 }, // 0x21 '!'
{ 10, 9, 6, 11, 1, -16 }, // 0x22 '"'
{ 17, 14, 17, 15, 1, -16 }, // 0x23 '#'
{ 47, 12, 19, 13, 1, -17 }, // 0x24 '$'
{ 76, 19, 17, 21, 1, -16 }, // 0x25 '%'
{ 117, 17, 17, 18, 1, -16 }, // 0x26 '&'
{ 154, 4, 6, 6, 1, -16 }, // 0x27 '''
{ 157, 6, 21, 8, 1, -16 }, // 0x28 '('
{ 173, 6, 21, 8, 1, -16 }, // 0x29 ')'
{ 189, 11, 11, 13, 1, -17 }, // 0x2A '*'
{ 205, 11, 11, 13, 1, -13 }, // 0x2B '+'
{ 221, 4, 6, 7, 1, -2 }, // 0x2C ','
{ 224, 6, 3, 8, 1, -7 }, // 0x2D '-'
{ 227, 4, 4, 7, 1, -3 }, // 0x2E '.'
{ 229, 10, 17, 10, 0, -16 }, // 0x2F '/'
{ 251, 12, 17, 13, 1, -16 }, // 0x30 '0'
{ 277, 9, 17, 13, 1, -16 }, // 0x31 '1'
{ 297, 12, 17, 13, 1, -16 }, // 0x32 '2'
{ 323, 12, 17, 13, 1, -16 }, // 0x33 '3'
{ 349, 13, 17, 13, 0, -16 }, // 0x34 '4'
{ 377, 11, 17, 13, 1, -16 }, // 0x35 '5'
{ 401, 12, 17, 13, 1, -16 }, // 0x36 '6'
{ 427, 12, 17, 13, 1, -16 }, // 0x37 '7'
{ 453, 12, 17, 13, 1, -16 }, // 0x38 '8'
{ 479, 12, 17, 13, 1, -16 }, // 0x39 '9'
{ 505, 4, 13, 7, 1, -12 }, // 0x3A ':'
{ 512, 4, 16, 7, 1, -12 }, // 0x3B ';'
{ 520, 11, 13, 13, 1, -14 }, // 0x3C '<'
{ 538, 11, 7, 13, 1, -11 }, // 0x3D '='
{ 548, 11, 13, 13, 1, -14 }, // 0x3E '>'
{ 566, 11, 17, 11, 0, -16 }, // 0x3F '?'
{ 590, 19, 19, 21, 1, -16 }, // 0x40 '@'
{ 636, 16, 17, 16, 0, -16 }, // 0x41 'A'
{ 670, 12, 17, 16, 2, -16 }, // 0x42 'B'
{ 696, 13, 17, 15, 1, -16 }, // 0x43 'C'
{ 724, 14, 17, 17, 2, -16 }, // 0x44 'D'
{ 754, 10, 17, 13, 2, -16 }, // 0x45 'E'
{ 776, 10, 17, 13, 2, -16 }, // 0x46 'F'
{ 798, 14, 17, 17, 1, -16 }, // 0x47 'G'
{ 828, 14, 17, 18, 2, -16 }, // 0x48 'H'
{ 858, 7, 17, 9, 1, -16 }, // 0x49 'I'
{ 873, 8, 22, 8, -2, -16 }, // 0x4A 'J'
{ 895, 14, 17, 16, 2, -16 }, // 0x4B 'K'
{ 925, 10, 17, 13, 2, -16 }, // 0x4C 'L'
{ 947, 18, 17, 22, 2, -16 }, // 0x4D 'M'
{ 986, 15, 17, 19, 2, -16 }, // 0x4E 'N'
{ 1018, 16, 17, 19, 1, -16 }, // 0x4F 'O'
{ 1052, 12, 17, 15, 2, -16 }, // 0x50 'P'
{ 1078, 16, 21, 19, 1, -16 }, // 0x51 'Q'
{ 1120, 13, 17, 15, 2, -16 }, // 0x52 'R'
{ 1148, 11, 17, 13, 1, -16 }, // 0x53 'S'
{ 1172, 13, 17, 14, 0, -16 }, // 0x54 'T'
{ 1200, 14, 17, 18, 2, -16 }, // 0x55 'U'
{ 1230, 15, 17, 15, 0, -16 }, // 0x56 'V'
{ 1262, 23, 17, 23, 0, -16 }, // 0x57 'W'
{ 1311, 16, 17, 16, 0, -16 }, // 0x58 'X'
{ 1345, 15, 17, 15, 0, -16 }, // 0x59 'Y'
{ 1377, 12, 17, 14, 1, -16 }, // 0x5A 'Z'
{ 1403, 5, 21, 8, 2, -16 }, // 0x5B '['
{ 1417, 10, 17, 10, 0, -16 }, // 0x5C '\'
{ 1439, 5, 21, 8, 1, -16 }, // 0x5D ']'
{ 1453, 12, 11, 13, 1, -16 }, // 0x5E '^'
{ 1470, 10, 2, 10, 0, 3 }, // 0x5F '_'
{ 1473, 7, 4, 9, 1, -17 }, // 0x60 '`'
{ 1477, 11, 13, 14, 1, -12 }, // 0x61 'a'
{ 1495, 12, 18, 15, 2, -17 }, // 0x62 'b'
{ 1522, 10, 13, 12, 1, -12 }, // 0x63 'c'
{ 1539, 12, 18, 15, 1, -17 }, // 0x64 'd'
{ 1566, 12, 13, 14, 1, -12 }, // 0x65 'e'
{ 1586, 10, 18, 9, 0, -17 }, // 0x66 'f'
{ 1609, 12, 19, 15, 1, -12 }, // 0x67 'g'
{ 1638, 12, 18, 15, 2, -17 }, // 0x68 'h'
{ 1665, 3, 18, 7, 2, -17 }, // 0x69 'i'
{ 1672, 6, 24, 7, -1, -17 }, // 0x6A 'j'
{ 1690, 13, 18, 15, 2, -17 }, // 0x6B 'k'
{ 1720, 3, 18, 7, 2, -17 }, // 0x6C 'l'
{ 1727, 19, 13, 23, 2, -12 }, // 0x6D 'm'
{ 1758, 12, 13, 15, 2, -12 }, // 0x6E 'n'
{ 1778, 13, 13, 15, 1, -12 }, // 0x6F 'o'
{ 1800, 12, 19, 15, 2, -12 }, // 0x70 'p'
{ 1829, 12, 19, 15, 1, -12 }, // 0x71 'q'
{ 1858, 8, 13, 11, 2, -12 }, // 0x72 'r'
{ 1871, 10, 13, 12, 1, -12 }, // 0x73 's'
{ 1888, 8, 16, 10, 1, -15 }, // 0x74 't'
{ 1904, 12, 13, 15, 2, -12 }, // 0x75 'u'
{ 1924, 13, 13, 13, 0, -12 }, // 0x76 'v'
{ 1946, 20, 13, 20, 0, -12 }, // 0x77 'w'
{ 1979, 13, 13, 14, 0, -12 }, // 0x78 'x'
{ 2001, 13, 19, 13, 0, -12 }, // 0x79 'y'
{ 2032, 10, 13, 12, 1, -12 }, // 0x7A 'z'
{ 2049, 8, 21, 9, 0, -16 }, // 0x7B '{'
{ 2070, 3, 23, 13, 5, -17 }, // 0x7C '|'
{ 2079, 8, 21, 9, 1, -16 }, // 0x7D '}'
{ 2100, 11, 4, 13, 1, -9 } }; // 0x7E '~'
const GFXfont NotoSans_Bold12pt7b PROGMEM = {
(uint8_t *)NotoSans_Bold12pt7bBitmaps,
(GFXglyph *)NotoSans_Bold12pt7bGlyphs,
0x20, 0x7E, 32 };
// Approx. 2778 bytes
#endif // NOTOSANSBOLD12PT7B_H
@@ -0,0 +1,498 @@
#ifndef NOTOSANSBOLD18PT7B_H
#define NOTOSANSBOLD18PT7B_H
const uint8_t NotoSans_Bold18pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE7, 0x9E, 0x79, 0xE7,
0x9E, 0x78, 0x00, 0x00, 0x7B, 0xFF, 0xFF, 0x78, 0xF8, 0xFF, 0xC7, 0xFE,
0x3F, 0xF1, 0xE7, 0x8F, 0x3C, 0x79, 0xE3, 0xCF, 0x1E, 0x78, 0xF0, 0x01,
0xE3, 0xC0, 0x0F, 0x1E, 0x00, 0x78, 0xF0, 0x03, 0x87, 0x80, 0x3C, 0x38,
0x01, 0xE3, 0xC0, 0x0F, 0x1E, 0x0F, 0xFF, 0xFF, 0x7F, 0xFF, 0xFB, 0xFF,
0xFF, 0xC1, 0xE3, 0xC0, 0x0F, 0x1E, 0x00, 0x78, 0xF0, 0x03, 0x87, 0x83,
0xFF, 0xFF, 0xDF, 0xFF, 0xFE, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0x83, 0xC7,
0x80, 0x1C, 0x38, 0x01, 0xE3, 0xC0, 0x0F, 0x1E, 0x00, 0x78, 0xF0, 0x03,
0xC7, 0x80, 0x1C, 0x38, 0x00, 0x01, 0x80, 0x00, 0xC0, 0x00, 0x60, 0x01,
0xFF, 0x83, 0xFF, 0xF3, 0xFF, 0xFB, 0xFF, 0xFD, 0xFB, 0x1C, 0xF9, 0x80,
0x7C, 0xC0, 0x3F, 0x60, 0x1F, 0xF0, 0x07, 0xFC, 0x01, 0xFF, 0xC0, 0x7F,
0xF0, 0x0F, 0xFC, 0x01, 0xFF, 0x00, 0xDF, 0xC0, 0x67, 0xE0, 0x31, 0xFC,
0x19, 0xFF, 0xFF, 0xFB, 0xFF, 0xFD, 0xFF, 0xFC, 0xFF, 0xF8, 0x01, 0xE0,
0x00, 0x60, 0x00, 0x30, 0x00, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7E,
0x00, 0x7C, 0x03, 0xFC, 0x01, 0xE0, 0x1F, 0xF8, 0x0F, 0x00, 0x79, 0xE0,
0x3C, 0x03, 0xE3, 0xC1, 0xE0, 0x0F, 0x0F, 0x07, 0x80, 0x3C, 0x3C, 0x3C,
0x00, 0xF0, 0xF1, 0xF0, 0x03, 0xC3, 0xC7, 0x80, 0x0F, 0x0F, 0x3E, 0x00,
0x3E, 0x7C, 0xF3, 0xF8, 0x79, 0xE7, 0x9F, 0xF1, 0xFF, 0x9E, 0x7F, 0xE3,
0xFC, 0xF3, 0xE7, 0x87, 0xE3, 0xCF, 0x1E, 0x00, 0x1E, 0x3C, 0x7C, 0x00,
0xF8, 0xF0, 0xF0, 0x03, 0xC3, 0xC3, 0xC0, 0x1F, 0x0F, 0x0F, 0x00, 0x78,
0x3C, 0x7C, 0x03, 0xC0, 0xF1, 0xE0, 0x0F, 0x03, 0xE7, 0x80, 0x78, 0x07,
0xFE, 0x01, 0xE0, 0x0F, 0xF0, 0x0F, 0x00, 0x1F, 0x80, 0x00, 0x60, 0x00,
0x03, 0xFE, 0x00, 0x03, 0xFF, 0xC0, 0x03, 0xFF, 0xE0, 0x01, 0xFF, 0xF8,
0x00, 0xF8, 0x7C, 0x00, 0x78, 0x3E, 0x00, 0x3E, 0x1F, 0x00, 0x1F, 0x1F,
0x00, 0x0F, 0xDF, 0x80, 0x03, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x00, 0xFF,
0x81, 0xF0, 0xFF, 0xC0, 0xF8, 0xFF, 0xF0, 0xFC, 0xFF, 0xFC, 0x7C, 0x7E,
0x7F, 0x7E, 0x3E, 0x1F, 0xFF, 0x3F, 0x07, 0xFF, 0x1F, 0x81, 0xFF, 0x07,
0xC0, 0x7F, 0x83, 0xF8, 0x7F, 0xC1, 0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xFC,
0x1F, 0xFF, 0x7F, 0x03, 0xFE, 0x1F, 0xC0, 0xFF, 0xFF, 0xF7, 0xBD, 0xEF,
0x78, 0x07, 0xC3, 0xE0, 0xF0, 0x7C, 0x1E, 0x0F, 0x83, 0xC1, 0xF0, 0x7C,
0x1F, 0x07, 0x81, 0xE0, 0x78, 0x3E, 0x0F, 0x83, 0xE0, 0xF8, 0x3E, 0x07,
0x81, 0xE0, 0x7C, 0x1F, 0x07, 0xC0, 0xF0, 0x3E, 0x0F, 0x81, 0xE0, 0x7C,
0x0F, 0x81, 0xE0, 0x3C, 0xF8, 0x1F, 0x03, 0xC0, 0xF8, 0x1E, 0x07, 0xC1,
0xF0, 0x3C, 0x0F, 0x83, 0xE0, 0x78, 0x1E, 0x07, 0x81, 0xE0, 0x7C, 0x1F,
0x07, 0xC1, 0xE0, 0x78, 0x1E, 0x0F, 0x83, 0xE0, 0xF8, 0x3C, 0x1F, 0x07,
0xC3, 0xE0, 0xF8, 0x7C, 0x1E, 0x0F, 0x00, 0x03, 0xE0, 0x01, 0xF0, 0x00,
0x78, 0x00, 0x38, 0x00, 0x1C, 0x03, 0x0E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x83, 0xF8, 0x01, 0xFC, 0x01, 0xEF, 0x00, 0xF7, 0x80, 0xF9,
0xE0, 0xF8, 0xF8, 0x1C, 0x30, 0x04, 0x10, 0x00, 0x03, 0xC0, 0x01, 0xE0,
0x00, 0xF0, 0x00, 0x78, 0x00, 0x3C, 0x00, 0x1E, 0x00, 0x0F, 0x01, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xF0, 0x00, 0x78, 0x00, 0x3C, 0x00,
0x1E, 0x00, 0x0F, 0x00, 0x07, 0x80, 0x03, 0xC0, 0x00, 0x3E, 0x7D, 0xF3,
0xE7, 0xCF, 0x1E, 0x78, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x7B,
0xFF, 0xFF, 0x78, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0x80, 0x3E, 0x00, 0xF8,
0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x03, 0xE0, 0x0F, 0x80, 0x3C, 0x01, 0xF0,
0x07, 0xC0, 0x1E, 0x00, 0xF8, 0x03, 0xE0, 0x1F, 0x00, 0x7C, 0x01, 0xF0,
0x0F, 0x80, 0x3E, 0x00, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0xF8, 0x00, 0x00,
0x40, 0x01, 0xFE, 0x01, 0xFF, 0xE0, 0xFF, 0xF8, 0x3F, 0xFF, 0x1F, 0x87,
0xE7, 0xC0, 0xF9, 0xF0, 0x3E, 0x7C, 0x0F, 0xBF, 0x03, 0xFF, 0xC0, 0xFF,
0xF0, 0x1F, 0xFC, 0x07, 0xFF, 0x01, 0xFF, 0xC0, 0x7F, 0xF0, 0x3F, 0xFC,
0x0F, 0xDF, 0x03, 0xF7, 0xC0, 0xF9, 0xF0, 0x3E, 0x7E, 0x0F, 0x8F, 0x87,
0xE3, 0xFF, 0xF0, 0x7F, 0xF8, 0x0F, 0xFE, 0x01, 0xFE, 0x00, 0x01, 0xF8,
0x1F, 0xC1, 0xFE, 0x1F, 0xF3, 0xFF, 0xBF, 0xFF, 0xF7, 0xEF, 0x3F, 0x31,
0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0, 0x3F,
0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07, 0xE0,
0x3F, 0x01, 0xF8, 0x00, 0x40, 0x03, 0xFF, 0x03, 0xFF, 0xE1, 0xFF, 0xFC,
0xFF, 0xFF, 0x8F, 0x07, 0xE3, 0x80, 0xF8, 0x40, 0x3E, 0x00, 0x0F, 0x80,
0x03, 0xE0, 0x01, 0xF8, 0x00, 0x7C, 0x00, 0x3F, 0x00, 0x1F, 0x80, 0x0F,
0xC0, 0x07, 0xE0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xFC, 0x00, 0x7E, 0x00,
0x3F, 0x00, 0x1F, 0x80, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xF0, 0x00, 0xC0, 0x07, 0xFF, 0x07, 0xFF, 0xE3, 0xFF, 0xFC, 0x7F,
0xFF, 0x8E, 0x07, 0xE2, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x07,
0xC0, 0x03, 0xF0, 0x3F, 0xF0, 0x0F, 0xF0, 0x03, 0xFF, 0x00, 0xFF, 0xF0,
0x00, 0xFE, 0x00, 0x0F, 0x80, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x80,
0x0F, 0xF8, 0x0F, 0xEF, 0xFF, 0xFB, 0xFF, 0xFC, 0xFF, 0xFE, 0x0F, 0xFE,
0x00, 0x00, 0x3F, 0x00, 0x0F, 0xE0, 0x01, 0xFC, 0x00, 0x7F, 0x80, 0x1F,
0xF0, 0x03, 0xFE, 0x00, 0xFF, 0xC0, 0x3F, 0xF8, 0x07, 0xBF, 0x01, 0xE7,
0xE0, 0x7C, 0xFC, 0x0F, 0x1F, 0x83, 0xC3, 0xF0, 0xF8, 0x7E, 0x1E, 0x0F,
0xC7, 0x81, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F,
0x00, 0x7F, 0xFE, 0x3F, 0xFF, 0x1F, 0xFF, 0x8F, 0xFF, 0xC7, 0xC0, 0x03,
0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x78, 0x00, 0x7F, 0xF8, 0x3F, 0xFF,
0x1F, 0xFF, 0xCF, 0xFF, 0xF1, 0x87, 0xF8, 0x00, 0xFC, 0x00, 0x3E, 0x00,
0x1F, 0x80, 0x0F, 0xC0, 0x07, 0xD0, 0x07, 0xEE, 0x07, 0xF7, 0xFF, 0xF3,
0xFF, 0xF9, 0xFF, 0xF0, 0x7F, 0xF0, 0x00, 0x01, 0xFF, 0x01, 0xFF, 0xC0,
0xFF, 0xF0, 0x7F, 0xFC, 0x3F, 0x80, 0x0F, 0x80, 0x07, 0xC0, 0x01, 0xF0,
0x00, 0x7C, 0x00, 0x1E, 0x7F, 0x8F, 0xBF, 0xF3, 0xFF, 0xFE, 0xFF, 0xFF,
0xBF, 0x83, 0xFF, 0xC0, 0xFF, 0xF0, 0x1F, 0xFC, 0x07, 0xFF, 0x01, 0xF7,
0xC0, 0x7D, 0xF0, 0x3F, 0x7E, 0x1F, 0x8F, 0xFF, 0xE1, 0xFF, 0xF0, 0x3F,
0xF8, 0x07, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x01, 0xF8, 0x00, 0x7C, 0x00, 0x3F,
0x00, 0x0F, 0x80, 0x03, 0xE0, 0x01, 0xF0, 0x00, 0x7C, 0x00, 0x3F, 0x00,
0x0F, 0x80, 0x07, 0xE0, 0x01, 0xF0, 0x00, 0xFC, 0x00, 0x3E, 0x00, 0x1F,
0x80, 0x07, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3E, 0x00, 0x1F, 0x80,
0x00, 0x0F, 0xFC, 0x07, 0xFF, 0x83, 0xFF, 0xF1, 0xFC, 0xFE, 0x7C, 0x0F,
0x9F, 0x03, 0xE7, 0xC0, 0xF9, 0xF0, 0x3E, 0x3E, 0x1F, 0x0F, 0xFF, 0xC1,
0xFF, 0xE0, 0x3F, 0xE0, 0x0F, 0xFC, 0x07, 0xFF, 0x83, 0xF3, 0xF1, 0xF8,
0x7E, 0x7C, 0x0F, 0xFE, 0x01, 0xFF, 0x80, 0x7F, 0xE0, 0x1F, 0xFC, 0x0F,
0xDF, 0xFF, 0xE7, 0xFF, 0xF8, 0xFF, 0xF8, 0x0F, 0xFC, 0x00, 0x0F, 0xF8,
0x07, 0xFF, 0x03, 0xFF, 0xE1, 0xFF, 0xFC, 0x7E, 0x1F, 0xBF, 0x03, 0xEF,
0x80, 0xFB, 0xE0, 0x3F, 0xF8, 0x07, 0xFE, 0x03, 0xFF, 0xC0, 0xFD, 0xF8,
0x7F, 0x7F, 0xFF, 0xCF, 0xFF, 0xF3, 0xFF, 0x7C, 0x3F, 0x9E, 0x00, 0x07,
0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x7F, 0x0F, 0xFF, 0x83,
0xFF, 0xC0, 0xFF, 0xE0, 0x3F, 0xE0, 0x00, 0x33, 0xFF, 0xFF, 0xFD, 0xE0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0xFF, 0xFF, 0xDE, 0x18, 0xFD,
0xFB, 0xF7, 0xE7, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x7D, 0xF3, 0xE7, 0xCF, 0x1E, 0x78, 0xF0, 0x00, 0x00, 0x80, 0x01,
0xC0, 0x03, 0xE0, 0x07, 0xF0, 0x0F, 0xF0, 0x1F, 0xE0, 0x3F, 0x80, 0x7F,
0x00, 0xFE, 0x00, 0x7C, 0x00, 0x3F, 0x80, 0x0F, 0xF8, 0x01, 0xFF, 0x00,
0x3F, 0xE0, 0x07, 0xFE, 0x00, 0x7F, 0x00, 0x0F, 0x80, 0x01, 0xC0, 0x00,
0x20, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xE0, 0x80, 0x00, 0x70, 0x00, 0x3E, 0x00, 0x1F, 0xC0, 0x0F, 0xF8, 0x00,
0xFF, 0x00, 0x1F, 0xE0, 0x03, 0xFC, 0x00, 0x7F, 0x80, 0x0F, 0xC0, 0x1F,
0xE0, 0x3F, 0xC0, 0xFF, 0x81, 0xFF, 0x03, 0xFE, 0x01, 0xF8, 0x00, 0xF0,
0x00, 0x60, 0x00, 0x20, 0x00, 0x00, 0x00, 0x80, 0x1F, 0xF8, 0xFF, 0xFC,
0x7F, 0xFE, 0x7F, 0xFF, 0x30, 0x3F, 0x00, 0x1F, 0x00, 0x1F, 0x00, 0x1F,
0x00, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x03, 0xF8, 0x03, 0xF0, 0x07, 0xC0,
0x07, 0xC0, 0x07, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x07, 0xC0, 0x00, 0x7F,
0xF0, 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0xFF, 0xFF, 0x00, 0xFE, 0x01, 0xF8,
0x1F, 0x80, 0x07, 0xC3, 0xE0, 0x00, 0x3C, 0x3C, 0x0F, 0xC1, 0xE7, 0x83,
0xFF, 0x9E, 0x78, 0x7F, 0xF8, 0xFF, 0x0F, 0xCF, 0x8F, 0xF1, 0xF0, 0x78,
0xFF, 0x1E, 0x07, 0x8F, 0xF1, 0xE0, 0xF0, 0xFF, 0x1E, 0x0F, 0x0F, 0xF1,
0xE0, 0xF0, 0xFF, 0x1E, 0x0F, 0x0F, 0xF1, 0xE0, 0xF1, 0xEF, 0x1F, 0x1F,
0x9E, 0xF0, 0xFF, 0xFF, 0xCF, 0x0F, 0xFB, 0xF8, 0x78, 0x3E, 0x1F, 0x07,
0xC0, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x03, 0xF0, 0x00, 0xC0, 0x1F, 0xFB,
0xFC, 0x00, 0x7F, 0xFF, 0xC0, 0x01, 0xFF, 0xF8, 0x00, 0x03, 0xF8, 0x00,
0x00, 0x7F, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x80,
0x01, 0xFF, 0x80, 0x01, 0xF7, 0xC0, 0x03, 0xE7, 0xC0, 0x03, 0xE7, 0xC0,
0x03, 0xE7, 0xE0, 0x07, 0xE3, 0xE0, 0x07, 0xC3, 0xE0, 0x07, 0xC3, 0xF0,
0x0F, 0xC1, 0xF0, 0x0F, 0x81, 0xF0, 0x0F, 0x81, 0xF8, 0x1F, 0xFF, 0xF8,
0x1F, 0xFF, 0xF8, 0x1F, 0xFF, 0xFC, 0x3F, 0xFF, 0xFC, 0x3F, 0x00, 0x7C,
0x3E, 0x00, 0x7E, 0x7E, 0x00, 0x7E, 0x7E, 0x00, 0x3F, 0x7C, 0x00, 0x3F,
0xFC, 0x00, 0x3F, 0xFF, 0xFC, 0x1F, 0xFF, 0xE3, 0xFF, 0xFE, 0x7F, 0xFF,
0xEF, 0x81, 0xFD, 0xF0, 0x1F, 0xBE, 0x03, 0xF7, 0xC0, 0x7E, 0xF8, 0x0F,
0xDF, 0x03, 0xF3, 0xFF, 0xFC, 0x7F, 0xFE, 0x0F, 0xFF, 0xF1, 0xFF, 0xFF,
0x3E, 0x07, 0xF7, 0xC0, 0x3E, 0xF8, 0x07, 0xFF, 0x00, 0xFF, 0xE0, 0x1F,
0xFC, 0x07, 0xEF, 0x81, 0xFD, 0xFF, 0xFF, 0xBF, 0xFF, 0xE7, 0xFF, 0xF8,
0xFF, 0xF8, 0x00, 0x00, 0x18, 0x00, 0x1F, 0xFC, 0x07, 0xFF, 0xF0, 0xFF,
0xFE, 0x1F, 0xFF, 0xE3, 0xF8, 0x1C, 0x7F, 0x00, 0x07, 0xE0, 0x00, 0x7C,
0x00, 0x0F, 0xC0, 0x00, 0xFC, 0x00, 0x0F, 0xC0, 0x00, 0xFC, 0x00, 0x0F,
0xC0, 0x00, 0xFC, 0x00, 0x0F, 0xC0, 0x00, 0xFC, 0x00, 0x0F, 0xC0, 0x00,
0x7C, 0x00, 0x07, 0xE0, 0x00, 0x7F, 0x00, 0x23, 0xFC, 0x1E, 0x3F, 0xFF,
0xE1, 0xFF, 0xFE, 0x07, 0xFF, 0xE0, 0x3F, 0xF8, 0xFF, 0xF8, 0x07, 0xFF,
0xF8, 0x3F, 0xFF, 0xE1, 0xFF, 0xFF, 0x8F, 0x83, 0xFE, 0x7C, 0x03, 0xF3,
0xE0, 0x0F, 0xDF, 0x00, 0x7E, 0xF8, 0x01, 0xFF, 0xC0, 0x0F, 0xFE, 0x00,
0x7F, 0xF0, 0x03, 0xFF, 0x80, 0x1F, 0xFC, 0x00, 0xFF, 0xE0, 0x07, 0xFF,
0x00, 0x3F, 0xF8, 0x01, 0xF7, 0xC0, 0x1F, 0xBE, 0x01, 0xFD, 0xF0, 0x1F,
0xCF, 0x87, 0xFC, 0x7F, 0xFF, 0xE3, 0xFF, 0xFC, 0x1F, 0xFF, 0xC0, 0xFF,
0xF0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F,
0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xFF, 0xF7, 0xFF,
0xEF, 0xFF, 0xDF, 0xFF, 0xBF, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03,
0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x1F, 0x00,
0x3E, 0x00, 0x7C, 0x00, 0xF8, 0x01, 0xF0, 0x03, 0xE0, 0x07, 0xFF, 0xEF,
0xFF, 0xDF, 0xFF, 0xBF, 0xFF, 0x7C, 0x00, 0xF8, 0x01, 0xF0, 0x03, 0xE0,
0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x00, 0x3E, 0x00, 0x7C, 0x00, 0xF8, 0x00,
0x00, 0x04, 0x00, 0x0F, 0xFF, 0x01, 0xFF, 0xFE, 0x1F, 0xFF, 0xE1, 0xFF,
0xFF, 0x1F, 0xE0, 0x30, 0xFC, 0x00, 0x0F, 0xC0, 0x00, 0x7E, 0x00, 0x07,
0xE0, 0x00, 0x3F, 0x00, 0x01, 0xF8, 0x00, 0x0F, 0xC1, 0xFF, 0xFE, 0x0F,
0xFF, 0xF0, 0x7F, 0xFF, 0x83, 0xFF, 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xDF,
0x00, 0x7E, 0xFC, 0x03, 0xF7, 0xF0, 0x1F, 0x9F, 0xE0, 0xFC, 0x7F, 0xFF,
0xE1, 0xFF, 0xFF, 0x07, 0xFF, 0xF8, 0x0F, 0xFF, 0x00, 0xFC, 0x01, 0xFF,
0xE0, 0x0F, 0xFF, 0x00, 0x7F, 0xF8, 0x03, 0xFF, 0xC0, 0x1F, 0xFE, 0x00,
0xFF, 0xF0, 0x07, 0xFF, 0x80, 0x3F, 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x07,
0xFF, 0x80, 0x3F, 0xFC, 0x01, 0xFF, 0xE0, 0x0F, 0xFF, 0x00, 0x7F, 0xF8,
0x03, 0xFF, 0xC0, 0x1F, 0xFE, 0x00, 0xFF, 0xF0, 0x07, 0xFF, 0x80, 0x3F,
0xFC, 0x01, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF, 0xF7, 0xFC, 0x1F, 0x81, 0xF8,
0x1F, 0x81, 0xF8, 0x1F, 0x81, 0xF8, 0x1F, 0x81, 0xF8, 0x1F, 0x81, 0xF8,
0x1F, 0x81, 0xF8, 0x1F, 0x81, 0xF8, 0x1F, 0x81, 0xF8, 0x1F, 0x87, 0xFE,
0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03,
0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03,
0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03,
0xF0, 0x3F, 0x03, 0xF0, 0x3F, 0x03, 0xE0, 0x3E, 0x03, 0xE0, 0x7E, 0xFF,
0xEF, 0xFC, 0xFF, 0x8F, 0xF0, 0xFC, 0x03, 0xFF, 0xC0, 0x7E, 0xFC, 0x0F,
0xCF, 0xC1, 0xF8, 0xFC, 0x1F, 0x8F, 0xC3, 0xF0, 0xFC, 0x7E, 0x0F, 0xCF,
0xC0, 0xFC, 0xFC, 0x0F, 0xDF, 0x80, 0xFF, 0xF0, 0x0F, 0xFF, 0x00, 0xFF,
0xF8, 0x0F, 0xFF, 0x80, 0xFF, 0xFC, 0x0F, 0xCF, 0xC0, 0xFC, 0x7E, 0x0F,
0xC3, 0xF0, 0xFC, 0x3F, 0x0F, 0xC1, 0xF8, 0xFC, 0x0F, 0xCF, 0xC0, 0xFC,
0xFC, 0x07, 0xEF, 0xC0, 0x7E, 0xFC, 0x03, 0xF0, 0xF8, 0x00, 0xF8, 0x00,
0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00,
0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00,
0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0xF8, 0x00,
0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
0x0F, 0xFF, 0xE0, 0x03, 0xFF, 0xFC, 0x00, 0x7F, 0xFF, 0xC0, 0x0F, 0xFF,
0xF8, 0x03, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xFE, 0x03,
0xDF, 0xFB, 0xC0, 0x7B, 0xFF, 0x78, 0x0F, 0x7F, 0xEF, 0x83, 0xEF, 0xFC,
0xF0, 0x79, 0xFF, 0x9E, 0x0F, 0x3F, 0xF3, 0xE3, 0xE7, 0xFE, 0x3C, 0x78,
0xFF, 0xC7, 0x8F, 0x1F, 0xF8, 0xFB, 0xE3, 0xFF, 0x0F, 0x78, 0x7F, 0xE1,
0xEF, 0x0F, 0xFC, 0x3F, 0xE1, 0xFF, 0x87, 0xF8, 0x3F, 0xF0, 0x7F, 0x07,
0xFE, 0x0F, 0xE0, 0xFF, 0xC1, 0xF8, 0x1F, 0xF8, 0x1F, 0x03, 0xE0, 0xFE,
0x00, 0x3F, 0xFC, 0x00, 0xFF, 0xF0, 0x03, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0,
0x3F, 0xFF, 0x00, 0xFF, 0xFE, 0x03, 0xFE, 0xF8, 0x0F, 0xFB, 0xF0, 0x3F,
0xE7, 0xE0, 0xFF, 0x9F, 0x83, 0xFE, 0x3F, 0x0F, 0xF8, 0x7C, 0x3F, 0xE1,
0xF8, 0xFF, 0x83, 0xE3, 0xFE, 0x0F, 0xCF, 0xF8, 0x1F, 0xBF, 0xE0, 0x7E,
0xFF, 0x80, 0xFF, 0xFE, 0x01, 0xFF, 0xF8, 0x07, 0xFF, 0xE0, 0x0F, 0xFF,
0x80, 0x3F, 0xFE, 0x00, 0x7F, 0xF8, 0x01, 0xFC, 0x00, 0x18, 0x00, 0x03,
0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x1F, 0xFF, 0xF8, 0x3F, 0xFF, 0xF8, 0x3F,
0x81, 0xFC, 0x7F, 0x00, 0xFE, 0x7E, 0x00, 0x7E, 0x7C, 0x00, 0x7E, 0xFC,
0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC,
0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC,
0x00, 0x3F, 0x7E, 0x00, 0x7E, 0x7E, 0x00, 0x7E, 0x7F, 0x00, 0xFC, 0x3F,
0xC3, 0xFC, 0x1F, 0xFF, 0xF8, 0x0F, 0xFF, 0xF0, 0x07, 0xFF, 0xE0, 0x01,
0xFF, 0x80, 0xFF, 0xF8, 0x7F, 0xFF, 0x3F, 0xFF, 0xDF, 0xFF, 0xEF, 0x83,
0xFF, 0xC0, 0xFF, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE,
0x07, 0xFF, 0x1F, 0xFF, 0xFF, 0xF7, 0xFF, 0xF3, 0xFF, 0xF1, 0xFF, 0xE0,
0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0,
0x03, 0xE0, 0x01, 0xF0, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x18, 0x00, 0x03,
0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x1F, 0xFF, 0xF8, 0x3F, 0xFF, 0xF8, 0x3F,
0x81, 0xFC, 0x7F, 0x00, 0xFE, 0x7E, 0x00, 0x7E, 0x7C, 0x00, 0x7E, 0xFC,
0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC,
0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC, 0x00, 0x3F, 0xFC,
0x00, 0x3F, 0x7E, 0x00, 0x7E, 0x7E, 0x00, 0x7E, 0x7F, 0x00, 0xFC, 0x3F,
0xC3, 0xFC, 0x1F, 0xFF, 0xF8, 0x0F, 0xFF, 0xF0, 0x07, 0xFF, 0xE0, 0x01,
0xFF, 0xC0, 0x00, 0x07, 0xE0, 0x00, 0x07, 0xF0, 0x00, 0x03, 0xF8, 0x00,
0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF,
0xE0, 0xFF, 0xFF, 0x0F, 0xFF, 0xF8, 0xF8, 0x3F, 0x8F, 0x80, 0xF8, 0xF8,
0x0F, 0xCF, 0x80, 0xFC, 0xF8, 0x0F, 0x8F, 0x80, 0xF8, 0xF8, 0x1F, 0x8F,
0xFF, 0xF0, 0xFF, 0xFE, 0x0F, 0xFF, 0xC0, 0xFF, 0xF8, 0x0F, 0x8F, 0xC0,
0xF8, 0x7E, 0x0F, 0x83, 0xE0, 0xF8, 0x3F, 0x0F, 0x81, 0xF8, 0xF8, 0x1F,
0x8F, 0x80, 0xFC, 0xF8, 0x07, 0xEF, 0x80, 0x7E, 0xF8, 0x03, 0xF0, 0x00,
0x80, 0x0F, 0xFC, 0x3F, 0xFF, 0x7F, 0xFE, 0x7F, 0xFE, 0xFC, 0x0E, 0xF8,
0x00, 0xF8, 0x00, 0xF8, 0x00, 0xFC, 0x00, 0xFF, 0x00, 0x7F, 0xC0, 0x3F,
0xF0, 0x1F, 0xF8, 0x07, 0xFC, 0x01, 0xFE, 0x00, 0x7F, 0x00, 0x3F, 0x00,
0x1F, 0x00, 0x1F, 0x80, 0x3F, 0xF0, 0x7F, 0xFF, 0xFE, 0xFF, 0xFC, 0xFF,
0xF8, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0,
0x00, 0x7E, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0,
0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xC0,
0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80,
0x03, 0xF0, 0x00, 0xF8, 0x01, 0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0x7F, 0xF0,
0x03, 0xFF, 0x80, 0x1F, 0xFC, 0x00, 0xFF, 0xE0, 0x07, 0xFF, 0x00, 0x3F,
0xF8, 0x01, 0xFF, 0xC0, 0x0F, 0xFE, 0x00, 0x7F, 0xF0, 0x03, 0xFF, 0x80,
0x1F, 0xFC, 0x00, 0xFF, 0xE0, 0x07, 0xFF, 0x00, 0x3F, 0xF8, 0x01, 0xFF,
0xE0, 0x0F, 0xFF, 0x00, 0x7C, 0xF8, 0x07, 0xE7, 0xF0, 0x7F, 0x1F, 0xFF,
0xF0, 0xFF, 0xFF, 0x03, 0xFF, 0xF0, 0x07, 0xFE, 0x00, 0xFC, 0x00, 0x7E,
0xF8, 0x00, 0xF9, 0xF0, 0x01, 0xF3, 0xF0, 0x07, 0xE3, 0xE0, 0x0F, 0x87,
0xC0, 0x1F, 0x0F, 0x80, 0x7E, 0x0F, 0x80, 0xF8, 0x1F, 0x01, 0xF0, 0x3E,
0x07, 0xE0, 0x3E, 0x0F, 0x80, 0x7C, 0x1F, 0x00, 0xF8, 0x7E, 0x00, 0xF8,
0xF8, 0x01, 0xF1, 0xF0, 0x03, 0xE3, 0xE0, 0x03, 0xEF, 0x80, 0x07, 0xDF,
0x00, 0x0F, 0xBE, 0x00, 0x0F, 0x78, 0x00, 0x1F, 0xF0, 0x00, 0x3F, 0xE0,
0x00, 0x3F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0xF8, 0x03, 0xF0,
0x07, 0xFF, 0x00, 0xFC, 0x03, 0xF7, 0xC0, 0x3F, 0x00, 0xF9, 0xF0, 0x0F,
0xE0, 0x3E, 0x7C, 0x07, 0xF8, 0x0F, 0x9F, 0x81, 0xFE, 0x07, 0xE3, 0xE0,
0x7F, 0x81, 0xF0, 0xF8, 0x1F, 0xF0, 0x7C, 0x3E, 0x0F, 0xFC, 0x1F, 0x0F,
0xC3, 0xCF, 0x07, 0xC1, 0xF0, 0xF3, 0xC3, 0xE0, 0x7C, 0x7C, 0xF8, 0xF8,
0x1F, 0x1F, 0x3E, 0x3E, 0x07, 0xC7, 0x87, 0x8F, 0x80, 0xF9, 0xE1, 0xE7,
0xC0, 0x3E, 0xF8, 0x7D, 0xF0, 0x0F, 0xBE, 0x1F, 0x7C, 0x01, 0xEF, 0x03,
0xDF, 0x00, 0x7B, 0xC0, 0xF7, 0x80, 0x1F, 0xF0, 0x3F, 0xE0, 0x07, 0xFC,
0x0F, 0xF8, 0x00, 0xFE, 0x01, 0xFE, 0x00, 0x3F, 0x80, 0x7F, 0x00, 0x0F,
0xE0, 0x1F, 0xC0, 0x03, 0xF8, 0x07, 0xF0, 0x00, 0x7E, 0x00, 0xFE, 0x7E,
0x01, 0xF8, 0xFC, 0x07, 0xE0, 0xFC, 0x0F, 0xC0, 0xF8, 0x3F, 0x01, 0xF8,
0xFC, 0x01, 0xF9, 0xF8, 0x01, 0xF7, 0xE0, 0x03, 0xFF, 0x80, 0x03, 0xFF,
0x00, 0x07, 0xFC, 0x00, 0x07, 0xF8, 0x00, 0x0F, 0xE0, 0x00, 0x3F, 0xE0,
0x00, 0x7F, 0xC0, 0x01, 0xFF, 0xC0, 0x03, 0xEF, 0xC0, 0x0F, 0xCF, 0x80,
0x3F, 0x1F, 0x80, 0x7E, 0x1F, 0x81, 0xF8, 0x3F, 0x07, 0xE0, 0x3F, 0x0F,
0xC0, 0x3F, 0x3F, 0x00, 0x7E, 0xFC, 0x00, 0x7E, 0xFC, 0x00, 0xFD, 0xF8,
0x07, 0xE7, 0xE0, 0x1F, 0x8F, 0xC0, 0xFC, 0x3F, 0x03, 0xF0, 0x7E, 0x1F,
0x80, 0xF8, 0x7C, 0x03, 0xF3, 0xF0, 0x07, 0xCF, 0x80, 0x1F, 0xFE, 0x00,
0x3F, 0xF0, 0x00, 0xFF, 0xC0, 0x01, 0xFE, 0x00, 0x07, 0xF8, 0x00, 0x0F,
0xC0, 0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0, 0x00, 0x0F, 0xC0,
0x00, 0x3F, 0x00, 0x00, 0xFC, 0x00, 0x03, 0xF0, 0x00, 0x0F, 0xC0, 0x00,
0x3F, 0x00, 0x00, 0xFC, 0x00, 0xFF, 0xFF, 0xDF, 0xFF, 0xFB, 0xFF, 0xFF,
0x7F, 0xFF, 0xE0, 0x00, 0xF8, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x01, 0xF0,
0x00, 0x7E, 0x00, 0x1F, 0x80, 0x03, 0xE0, 0x00, 0xFC, 0x00, 0x3F, 0x00,
0x0F, 0xC0, 0x01, 0xF0, 0x00, 0x7E, 0x00, 0x1F, 0x80, 0x03, 0xE0, 0x00,
0xFC, 0x00, 0x3F, 0x00, 0x07, 0xC0, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x87, 0xC3,
0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xF8,
0x7C, 0x3E, 0x1F, 0x0F, 0x87, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x1F,
0xFF, 0xFF, 0xFF, 0xFE, 0xF8, 0x01, 0xF0, 0x07, 0xC0, 0x0F, 0x00, 0x3E,
0x00, 0xF8, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x3E, 0x00, 0xF8, 0x01,
0xE0, 0x07, 0xC0, 0x1F, 0x00, 0x3C, 0x00, 0xF8, 0x03, 0xE0, 0x07, 0xC0,
0x1F, 0x00, 0x7C, 0x00, 0xF8, 0x03, 0xE0, 0x07, 0x80, 0x1F, 0x00, 0x7C,
0xFF, 0xFF, 0xFF, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x0F, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xC0, 0x00, 0x78, 0x00,
0x3E, 0x00, 0x0F, 0xC0, 0x07, 0xF0, 0x01, 0xDE, 0x00, 0xF7, 0x80, 0x3C,
0xF0, 0x1E, 0x3C, 0x07, 0x87, 0x83, 0xC1, 0xE0, 0xF0, 0x3C, 0x78, 0x0F,
0x9E, 0x01, 0xE7, 0x80, 0x7F, 0xC0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF8, 0xFE, 0x0F, 0x81, 0xF0, 0x3E, 0x07, 0xC0, 0x70, 0x00, 0x60, 0x03,
0xFF, 0x83, 0xFF, 0xF0, 0x7F, 0xFE, 0x1F, 0x1F, 0x82, 0x03, 0xE0, 0x00,
0xFC, 0x00, 0x3F, 0x03, 0xFF, 0xC7, 0xFF, 0xF3, 0xFF, 0xFD, 0xFC, 0x3F,
0x7C, 0x0F, 0xFF, 0x03, 0xFF, 0xC0, 0xFF, 0xF0, 0x7F, 0x7F, 0xFF, 0xDF,
0xFF, 0xF3, 0xFF, 0x7C, 0x7F, 0x0F, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80,
0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x80,
0xF9, 0xFC, 0x3F, 0xFF, 0x8F, 0xFF, 0xF3, 0xFF, 0xFE, 0xFC, 0x1F, 0xBE,
0x03, 0xEF, 0x80, 0xFB, 0xE0, 0x3E, 0xF8, 0x0F, 0xFE, 0x03, 0xFF, 0x80,
0xFF, 0xE0, 0x3E, 0xF8, 0x0F, 0xBF, 0x07, 0xEF, 0xE3, 0xFB, 0xFF, 0xFC,
0xFF, 0xFF, 0x3D, 0xFF, 0x8F, 0x1F, 0xC0, 0x00, 0xC0, 0x1F, 0xFC, 0x7F,
0xF9, 0xFF, 0xF7, 0xFF, 0xCF, 0xC0, 0xBF, 0x00, 0x7C, 0x00, 0xF8, 0x01,
0xF0, 0x03, 0xE0, 0x07, 0xC0, 0x0F, 0x80, 0x1F, 0x80, 0x3F, 0x00, 0x3F,
0x07, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF8, 0x3F, 0xE0, 0x00, 0x0F, 0xC0,
0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00,
0xFC, 0x0C, 0x3F, 0x1F, 0xEF, 0xCF, 0xFD, 0xF7, 0xFF, 0xFD, 0xFF, 0xFF,
0xFE, 0x1F, 0xFF, 0x03, 0xFF, 0x80, 0xFF, 0xE0, 0x1F, 0xF8, 0x07, 0xFE,
0x01, 0xFF, 0x80, 0x7F, 0xE0, 0x1F, 0xF8, 0x0F, 0xFF, 0x03, 0xFF, 0xE1,
0xFD, 0xFF, 0xFF, 0x7F, 0xFF, 0xCF, 0xFD, 0xF0, 0xFC, 0x7C, 0x00, 0xC0,
0x07, 0xFE, 0x07, 0xFF, 0x87, 0xFF, 0xE7, 0xE3, 0xF3, 0xE0, 0x7F, 0xF0,
0x3F, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x80, 0x07, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x02, 0x7F, 0xFF, 0x1F, 0xFF,
0x87, 0xFF, 0xC0, 0xFF, 0xC0, 0x03, 0xF8, 0x3F, 0xF1, 0xFF, 0xC7, 0xFE,
0x1F, 0x88, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x7F, 0xF3, 0xFF, 0xCF, 0xFF,
0x3F, 0xFC, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x7C,
0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x00, 0x7C, 0x01, 0xF0, 0x07, 0xC0, 0x1F,
0x00, 0x7C, 0x01, 0xF0, 0x00, 0x03, 0x00, 0x07, 0xF9, 0xF3, 0xFF, 0x7D,
0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x07, 0xFF, 0xC0, 0xFF, 0xE0, 0x3F, 0xF8,
0x07, 0xFE, 0x01, 0xFF, 0x80, 0x7F, 0xE0, 0x1F, 0xF8, 0x07, 0xFE, 0x03,
0xFF, 0xC0, 0xFF, 0xF8, 0x7F, 0x7F, 0xFF, 0xDF, 0xFF, 0xF3, 0xFF, 0xFC,
0x3F, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xF9, 0x80, 0x7E, 0x7F,
0xFF, 0x9F, 0xFF, 0xC7, 0xFF, 0xE1, 0xFF, 0xE0, 0xF8, 0x00, 0x7C, 0x00,
0x3E, 0x00, 0x1F, 0x00, 0x0F, 0x80, 0x07, 0xC0, 0x03, 0xE0, 0x01, 0xF0,
0x60, 0xF9, 0xFE, 0x7F, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC1, 0xFF,
0xE0, 0x7F, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03,
0xFF, 0x01, 0xFF, 0x80, 0xFF, 0xC0, 0x7F, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8,
0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xE0, 0x39, 0xFF, 0xFF, 0x7C, 0x00, 0x00,
0x7D, 0xF7, 0xDF, 0x7D, 0xF7, 0xDF, 0x7D, 0xF7, 0xDF, 0x7D, 0xF7, 0xDF,
0x7D, 0xF7, 0xC0, 0x03, 0x81, 0xF0, 0xFC, 0x3F, 0x07, 0xC0, 0x00, 0x00,
0x00, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07,
0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xF0,
0x7C, 0x1F, 0x07, 0xC3, 0xF0, 0xFF, 0xFF, 0xFF, 0xBF, 0xCF, 0xE0, 0xF8,
0x00, 0x1F, 0x00, 0x03, 0xE0, 0x00, 0x7C, 0x00, 0x0F, 0x80, 0x01, 0xF0,
0x00, 0x3E, 0x00, 0x07, 0xC0, 0x00, 0xF8, 0x0F, 0xDF, 0x03, 0xF3, 0xE0,
0xFC, 0x7C, 0x3F, 0x0F, 0x8F, 0xC1, 0xF3, 0xF0, 0x3E, 0xFC, 0x07, 0xDF,
0x00, 0xFF, 0xE0, 0x1F, 0xFE, 0x03, 0xFF, 0xE0, 0x7F, 0xFC, 0x0F, 0xCF,
0xC1, 0xF0, 0xFC, 0x3E, 0x0F, 0xC7, 0xC1, 0xF8, 0xF8, 0x1F, 0x9F, 0x01,
0xFB, 0xE0, 0x3F, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x00, 0x20, 0x06,
0x07, 0x9F, 0xF1, 0xFE, 0x3D, 0xFF, 0xDF, 0xFD, 0xFF, 0xFF, 0xFF, 0xEF,
0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xE0, 0xFF, 0xF0, 0x7F, 0x07, 0xFF, 0x03,
0xF0, 0x3F, 0xF8, 0x0F, 0x80, 0xFF, 0xC0, 0x7C, 0x07, 0xFE, 0x03, 0xE0,
0x3F, 0xF0, 0x1F, 0x01, 0xFF, 0x80, 0xF8, 0x0F, 0xFC, 0x07, 0xC0, 0x7F,
0xE0, 0x3E, 0x03, 0xFF, 0x01, 0xF0, 0x1F, 0xF8, 0x0F, 0x80, 0xFF, 0xC0,
0x7C, 0x07, 0xFE, 0x03, 0xE0, 0x3F, 0xF0, 0x1F, 0x01, 0xF0, 0x00, 0x20,
0x79, 0xFF, 0x3D, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFF, 0xF0,
0x3F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07, 0xFE, 0x03, 0xFF, 0x01, 0xFF,
0x80, 0xFF, 0xC0, 0x7F, 0xE0, 0x3F, 0xF0, 0x1F, 0xF8, 0x0F, 0xFC, 0x07,
0xFE, 0x03, 0xFF, 0x01, 0xF0, 0x00, 0xE0, 0x03, 0xFF, 0x01, 0xFF, 0xE0,
0xFF, 0xFC, 0x7F, 0xFF, 0x9F, 0x03, 0xEF, 0xC0, 0xFF, 0xE0, 0x1F, 0xF8,
0x07, 0xFE, 0x01, 0xFF, 0x80, 0x7F, 0xE0, 0x1F, 0xF8, 0x07, 0xFE, 0x01,
0xFF, 0xC0, 0xFD, 0xF8, 0x7E, 0x7F, 0xFF, 0x8F, 0xFF, 0xC1, 0xFF, 0xE0,
0x1F, 0xE0, 0x00, 0x30, 0x3C, 0x7F, 0x0F, 0x7F, 0xE3, 0xFF, 0xFC, 0xFF,
0xFF, 0xBF, 0x07, 0xEF, 0x80, 0xFB, 0xE0, 0x3E, 0xF8, 0x0F, 0xFE, 0x03,
0xFF, 0x80, 0xFF, 0xE0, 0x3F, 0xF8, 0x0F, 0xBE, 0x03, 0xEF, 0xC1, 0xFB,
0xF8, 0xFE, 0xFF, 0xFF, 0x3F, 0xFF, 0xCF, 0xFF, 0xE3, 0xE7, 0xF0, 0xF8,
0x00, 0x3E, 0x00, 0x0F, 0x80, 0x03, 0xE0, 0x00, 0xF8, 0x00, 0x3E, 0x00,
0x0F, 0x80, 0x03, 0xE0, 0x00, 0x03, 0x00, 0x07, 0xF9, 0xF3, 0xFF, 0x7D,
0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0x07, 0xFF, 0xC0, 0xFF, 0xE0, 0x3F, 0xF8,
0x07, 0xFE, 0x01, 0xFF, 0x80, 0x7F, 0xE0, 0x1F, 0xF8, 0x07, 0xFE, 0x03,
0xFF, 0xC0, 0xFF, 0xF8, 0x7F, 0x7F, 0xFF, 0xDF, 0xFF, 0xF3, 0xFF, 0xFC,
0x3F, 0x3F, 0x00, 0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00,
0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xFC, 0x00, 0x3F, 0x00, 0x3F, 0x1F, 0xF3,
0xFF, 0x7F, 0xFF, 0xFF, 0xF9, 0xFC, 0x0F, 0xC0, 0xF8, 0x0F, 0x80, 0xF8,
0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8, 0x0F, 0x80, 0xF8,
0x0F, 0x80, 0x03, 0x00, 0xFF, 0xE7, 0xFF, 0xFF, 0xFE, 0xF8, 0x3B, 0xE0,
0x2F, 0x80, 0x3F, 0x80, 0xFF, 0x81, 0xFF, 0x83, 0xFF, 0x83, 0xFF, 0x01,
0xFC, 0x03, 0xF0, 0x07, 0xE0, 0x1F, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xBF,
0xF8, 0x0F, 0x00, 0x78, 0x07, 0xC0, 0x3E, 0x07, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80,
0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x3F, 0xF1, 0xFF, 0x87,
0xFC, 0x1F, 0xE0, 0xFC, 0x07, 0xFF, 0x01, 0xFF, 0xC0, 0x7F, 0xF0, 0x1F,
0xFC, 0x07, 0xFF, 0x01, 0xFF, 0xC0, 0x7F, 0xF0, 0x1F, 0xFC, 0x07, 0xFF,
0x01, 0xFF, 0xC0, 0x7F, 0xF0, 0x1F, 0xFC, 0x07, 0xDF, 0x03, 0xF7, 0xE1,
0xFD, 0xFF, 0xFF, 0x7F, 0xFF, 0xCF, 0xFC, 0xF1, 0xFE, 0x3C, 0xFC, 0x03,
0xF7, 0xC0, 0x3E, 0x7C, 0x03, 0xE7, 0xE0, 0x7E, 0x3E, 0x07, 0xC3, 0xE0,
0x7C, 0x1F, 0x0F, 0xC1, 0xF0, 0xF8, 0x1F, 0x0F, 0x80, 0xF9, 0xF0, 0x0F,
0x9F, 0x00, 0xF9, 0xF0, 0x07, 0xFE, 0x00, 0x7F, 0xE0, 0x03, 0xFE, 0x00,
0x3F, 0xC0, 0x03, 0xFC, 0x00, 0x1F, 0x80, 0x01, 0xF8, 0x00, 0xFC, 0x0F,
0xC0, 0xFD, 0xF0, 0x3F, 0x03, 0xE7, 0xC0, 0xFE, 0x0F, 0x9F, 0x87, 0xF8,
0x3E, 0x3E, 0x1F, 0xE1, 0xF0, 0xF8, 0x7B, 0x87, 0xC3, 0xE3, 0xCF, 0x1F,
0x07, 0xCF, 0x3C, 0x7C, 0x1F, 0x3C, 0xF3, 0xE0, 0x7C, 0xF3, 0xCF, 0x81,
0xF3, 0x87, 0xBE, 0x03, 0xDE, 0x1E, 0xF0, 0x0F, 0xF8, 0x7B, 0xC0, 0x3F,
0xE1, 0xFF, 0x00, 0x7F, 0x83, 0xFC, 0x01, 0xFC, 0x0F, 0xE0, 0x07, 0xF0,
0x3F, 0x80, 0x1F, 0xC0, 0xFE, 0x00, 0x3F, 0x03, 0xF0, 0x00, 0xFE, 0x07,
0xF3, 0xF0, 0x7E, 0x3F, 0x0F, 0xC1, 0xF8, 0xF8, 0x0F, 0x9F, 0x80, 0xFF,
0xF0, 0x07, 0xFE, 0x00, 0x3F, 0xE0, 0x03, 0xFC, 0x00, 0x3F, 0xC0, 0x03,
0xFE, 0x00, 0x7F, 0xE0, 0x0F, 0xFF, 0x00, 0xFD, 0xF8, 0x1F, 0x9F, 0x83,
0xF0, 0xFC, 0x3F, 0x07, 0xE7, 0xE0, 0x7E, 0xFC, 0x03, 0xF0, 0xFC, 0x03,
0xF7, 0xC0, 0x3E, 0x7E, 0x03, 0xE7, 0xE0, 0x7E, 0x3E, 0x07, 0xC3, 0xF0,
0x7C, 0x1F, 0x0F, 0xC1, 0xF0, 0xF8, 0x1F, 0x0F, 0x80, 0xF9, 0xF0, 0x0F,
0x9F, 0x00, 0x79, 0xF0, 0x07, 0xDE, 0x00, 0x3F, 0xE0, 0x03, 0xFE, 0x00,
0x3F, 0xC0, 0x01, 0xFC, 0x00, 0x1F, 0x80, 0x00, 0xF8, 0x00, 0x1F, 0x80,
0x01, 0xF0, 0x00, 0x3F, 0x00, 0x07, 0xE0, 0x07, 0xFE, 0x00, 0x7F, 0xC0,
0x07, 0xF8, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0xFE, 0xFF, 0xFD, 0xFF, 0xFB,
0xFF, 0xF0, 0x0F, 0xC0, 0x1F, 0x00, 0x7E, 0x01, 0xF8, 0x07, 0xE0, 0x0F,
0x80, 0x3F, 0x00, 0xFC, 0x01, 0xF0, 0x07, 0xC0, 0x1F, 0x80, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x03, 0xE0, 0xFC, 0x3F, 0x87, 0xF0,
0xF8, 0x1F, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x81, 0xF1,
0xFE, 0x3F, 0x07, 0xC0, 0xFE, 0x0F, 0xE0, 0x7C, 0x07, 0x80, 0xF0, 0x1E,
0x03, 0xC0, 0x78, 0x0F, 0x01, 0xF0, 0x3F, 0x07, 0xF0, 0x7E, 0x07, 0xC0,
0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xFC, 0x0F, 0xE0, 0xFF, 0x0F,
0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01,
0xF0, 0x0F, 0x80, 0xFF, 0x07, 0xF0, 0x3F, 0x0F, 0xF0, 0xFE, 0x1F, 0x81,
0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x1F, 0x01, 0xF0, 0x3F, 0x0F,
0xF0, 0xFE, 0x0F, 0xC0, 0x80, 0x00, 0x7F, 0x00, 0xFF, 0xF1, 0xFF, 0xFF,
0xFD, 0xFF, 0xF8, 0x0F, 0xF4, 0x00, 0x00 };
const GFXglyph NotoSans_Bold18pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 9, 0, 0 }, // 0x20 ' '
{ 1, 6, 25, 10, 2, -24 }, // 0x21 '!'
{ 20, 13, 9, 17, 2, -24 }, // 0x22 '"'
{ 35, 21, 25, 23, 1, -24 }, // 0x23 '#'
{ 101, 17, 29, 20, 2, -26 }, // 0x24 '$'
{ 163, 30, 26, 32, 1, -25 }, // 0x25 '%'
{ 261, 25, 26, 26, 1, -25 }, // 0x26 '&'
{ 343, 5, 9, 9, 2, -24 }, // 0x27 '''
{ 349, 10, 31, 12, 1, -24 }, // 0x28 '('
{ 388, 10, 31, 12, 1, -24 }, // 0x29 ')'
{ 427, 17, 17, 19, 1, -26 }, // 0x2A '*'
{ 464, 17, 17, 20, 2, -20 }, // 0x2B '+'
{ 501, 7, 9, 10, 1, -3 }, // 0x2C ','
{ 509, 9, 5, 11, 1, -11 }, // 0x2D '-'
{ 515, 6, 5, 10, 2, -4 }, // 0x2E '.'
{ 519, 14, 25, 15, 0, -24 }, // 0x2F '/'
{ 563, 18, 26, 20, 1, -25 }, // 0x30 '0'
{ 622, 13, 25, 20, 2, -24 }, // 0x31 '1'
{ 663, 18, 26, 20, 1, -25 }, // 0x32 '2'
{ 722, 18, 26, 20, 1, -25 }, // 0x33 '3'
{ 781, 19, 25, 20, 1, -24 }, // 0x34 '4'
{ 841, 17, 25, 20, 2, -24 }, // 0x35 '5'
{ 895, 18, 25, 20, 1, -24 }, // 0x36 '6'
{ 952, 18, 25, 20, 1, -24 }, // 0x37 '7'
{ 1009, 18, 25, 20, 1, -24 }, // 0x38 '8'
{ 1066, 18, 25, 20, 1, -24 }, // 0x39 '9'
{ 1123, 6, 20, 10, 2, -19 }, // 0x3A ':'
{ 1138, 7, 25, 10, 1, -19 }, // 0x3B ';'
{ 1160, 17, 19, 20, 2, -21 }, // 0x3C '<'
{ 1201, 17, 11, 20, 2, -17 }, // 0x3D '='
{ 1225, 17, 19, 20, 2, -21 }, // 0x3E '>'
{ 1266, 16, 26, 17, 0, -25 }, // 0x3F '?'
{ 1318, 28, 28, 32, 2, -24 }, // 0x40 '@'
{ 1416, 24, 25, 24, 0, -24 }, // 0x41 'A'
{ 1491, 19, 25, 23, 3, -24 }, // 0x42 'B'
{ 1551, 20, 26, 23, 2, -25 }, // 0x43 'C'
{ 1616, 21, 25, 26, 3, -24 }, // 0x44 'D'
{ 1682, 15, 25, 20, 3, -24 }, // 0x45 'E'
{ 1729, 15, 25, 19, 3, -24 }, // 0x46 'F'
{ 1776, 21, 26, 26, 2, -25 }, // 0x47 'G'
{ 1845, 21, 25, 27, 3, -24 }, // 0x48 'H'
{ 1911, 12, 25, 14, 1, -24 }, // 0x49 'I'
{ 1949, 12, 32, 12, -3, -24 }, // 0x4A 'J'
{ 1997, 20, 25, 23, 3, -24 }, // 0x4B 'K'
{ 2060, 16, 25, 20, 3, -24 }, // 0x4C 'L'
{ 2110, 27, 25, 33, 3, -24 }, // 0x4D 'M'
{ 2195, 22, 25, 29, 3, -24 }, // 0x4E 'N'
{ 2264, 24, 26, 28, 2, -25 }, // 0x4F 'O'
{ 2342, 17, 25, 22, 3, -24 }, // 0x50 'P'
{ 2396, 24, 32, 28, 2, -25 }, // 0x51 'Q'
{ 2492, 20, 25, 23, 3, -24 }, // 0x52 'R'
{ 2555, 16, 26, 19, 2, -25 }, // 0x53 'S'
{ 2607, 19, 25, 20, 1, -24 }, // 0x54 'T'
{ 2667, 21, 25, 27, 3, -24 }, // 0x55 'U'
{ 2733, 23, 25, 23, 0, -24 }, // 0x56 'V'
{ 2805, 34, 25, 34, 0, -24 }, // 0x57 'W'
{ 2912, 23, 25, 24, 0, -24 }, // 0x58 'X'
{ 2984, 22, 25, 22, 0, -24 }, // 0x59 'Y'
{ 3053, 19, 25, 20, 1, -24 }, // 0x5A 'Z'
{ 3113, 9, 31, 12, 2, -24 }, // 0x5B '['
{ 3148, 14, 25, 15, 0, -24 }, // 0x5C '\'
{ 3192, 8, 31, 12, 1, -24 }, // 0x5D ']'
{ 3223, 18, 16, 20, 1, -24 }, // 0x5E '^'
{ 3259, 15, 3, 14, 0, 4 }, // 0x5F '_'
{ 3265, 10, 6, 13, 1, -26 }, // 0x60 '`'
{ 3273, 18, 20, 21, 1, -19 }, // 0x61 'a'
{ 3318, 18, 27, 22, 3, -26 }, // 0x62 'b'
{ 3379, 15, 20, 18, 2, -19 }, // 0x63 'c'
{ 3417, 18, 27, 22, 2, -26 }, // 0x64 'd'
{ 3478, 17, 20, 21, 2, -19 }, // 0x65 'e'
{ 3521, 14, 27, 14, 1, -26 }, // 0x66 'f'
{ 3569, 18, 28, 22, 2, -19 }, // 0x67 'g'
{ 3632, 17, 27, 23, 3, -26 }, // 0x68 'h'
{ 3690, 6, 27, 11, 2, -26 }, // 0x69 'i'
{ 3711, 10, 35, 11, -2, -26 }, // 0x6A 'j'
{ 3755, 19, 27, 22, 3, -26 }, // 0x6B 'k'
{ 3820, 5, 27, 11, 3, -26 }, // 0x6C 'l'
{ 3837, 29, 20, 34, 3, -19 }, // 0x6D 'm'
{ 3910, 17, 20, 23, 3, -19 }, // 0x6E 'n'
{ 3953, 18, 20, 22, 2, -19 }, // 0x6F 'o'
{ 3998, 18, 28, 22, 3, -19 }, // 0x70 'p'
{ 4061, 18, 28, 22, 2, -19 }, // 0x71 'q'
{ 4124, 12, 20, 16, 3, -19 }, // 0x72 'r'
{ 4154, 14, 20, 18, 2, -19 }, // 0x73 's'
{ 4189, 13, 23, 15, 1, -22 }, // 0x74 't'
{ 4227, 18, 19, 23, 2, -18 }, // 0x75 'u'
{ 4270, 20, 19, 20, 0, -18 }, // 0x76 'v'
{ 4318, 30, 19, 30, 0, -18 }, // 0x77 'w'
{ 4390, 20, 19, 20, 0, -18 }, // 0x78 'x'
{ 4438, 20, 27, 20, 0, -18 }, // 0x79 'y'
{ 4506, 15, 19, 17, 1, -18 }, // 0x7A 'z'
{ 4542, 11, 31, 14, 1, -24 }, // 0x7B '{'
{ 4585, 4, 35, 19, 8, -26 }, // 0x7C '|'
{ 4603, 12, 31, 14, 1, -24 }, // 0x7D '}'
{ 4650, 17, 6, 20, 2, -14 } }; // 0x7E '~'
const GFXfont NotoSans_Bold18pt7b PROGMEM = {
(uint8_t *)NotoSans_Bold18pt7bBitmaps,
(GFXglyph *)NotoSans_Bold18pt7bGlyphs,
0x20, 0x7E, 48 };
// Approx. 5335 bytes
#endif // NOTOSANSBOLD18PT7B_H
@@ -0,0 +1,801 @@
#ifndef NOTOSANSBOLD24PT7B_H
#define NOTOSANSBOLD24PT7B_H
const uint8_t NotoSans_Bold24pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE,
0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E, 0x7E,
0x00, 0x00, 0x00, 0x00, 0x7C, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0x10,
0xFE, 0x3F, 0xFF, 0x1F, 0xFF, 0x0F, 0xDF, 0x87, 0xEF, 0xC3, 0xF7, 0xE1,
0xFB, 0xF0, 0xFD, 0xF8, 0x7E, 0xFC, 0x1F, 0x3E, 0x0F, 0x9F, 0x07, 0xCF,
0x83, 0xE7, 0xC1, 0xF0, 0x00, 0x3E, 0x0F, 0x80, 0x03, 0xE1, 0xF0, 0x00,
0x3E, 0x1F, 0x00, 0x03, 0xE1, 0xF0, 0x00, 0x7C, 0x1F, 0x00, 0x07, 0xC1,
0xF0, 0x00, 0x7C, 0x1E, 0x00, 0x07, 0xC3, 0xE0, 0x00, 0x7C, 0x3E, 0x00,
0x0F, 0x83, 0xE0, 0x3F, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF,
0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xF0, 0x1F, 0x07, 0xC0,
0x01, 0xF0, 0x7C, 0x00, 0x1F, 0x0F, 0x80, 0x01, 0xF0, 0xF8, 0x00, 0x3E,
0x0F, 0x80, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF,
0xEF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xE0, 0x7C, 0x1F, 0x00, 0x07,
0xC1, 0xF0, 0x00, 0x7C, 0x3E, 0x00, 0x07, 0xC3, 0xE0, 0x00, 0x7C, 0x3E,
0x00, 0x0F, 0x83, 0xE0, 0x00, 0xF8, 0x3E, 0x00, 0x0F, 0x87, 0xC0, 0x00,
0xF8, 0x7C, 0x00, 0x00, 0x38, 0x00, 0x00, 0x70, 0x00, 0x00, 0xE0, 0x00,
0x01, 0xC0, 0x00, 0x3F, 0xFE, 0x01, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF, 0x1F,
0xFF, 0xFE, 0x7F, 0xFF, 0xF9, 0xFF, 0xF7, 0xF3, 0xFC, 0xE0, 0xE7, 0xF1,
0xC0, 0x0F, 0xE3, 0x80, 0x1F, 0xE7, 0x00, 0x3F, 0xEE, 0x00, 0x3F, 0xFC,
0x00, 0x7F, 0xFC, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFF, 0x00, 0x3F, 0xFF,
0x80, 0x1F, 0xFF, 0x80, 0x07, 0xFF, 0x80, 0x0F, 0xFF, 0x00, 0x1D, 0xFF,
0x00, 0x38, 0xFE, 0x00, 0x71, 0xFE, 0x00, 0xE3, 0xFF, 0x81, 0xCF, 0xFF,
0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFE, 0x7F, 0xFF, 0xF8, 0x7F,
0xFF, 0xE0, 0x1F, 0xFE, 0x00, 0x00, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0x03,
0x80, 0x00, 0x07, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x1F,
0x00, 0x0F, 0xF8, 0x00, 0x3F, 0x00, 0x1F, 0xFC, 0x00, 0x7E, 0x00, 0x3F,
0xFE, 0x00, 0x7E, 0x00, 0x7F, 0xFE, 0x00, 0xFC, 0x00, 0x7E, 0x3F, 0x00,
0xF8, 0x00, 0x7C, 0x3F, 0x01, 0xF8, 0x00, 0x7C, 0x1F, 0x01, 0xF0, 0x00,
0xFC, 0x1F, 0x03, 0xF0, 0x00, 0xFC, 0x1F, 0x03, 0xE0, 0x00, 0xFC, 0x1F,
0x07, 0xE0, 0x00, 0xFC, 0x1F, 0x0F, 0xC0, 0x00, 0xFC, 0x1F, 0x0F, 0xC0,
0x00, 0x7C, 0x1F, 0x1F, 0x83, 0xC0, 0x7C, 0x3F, 0x1F, 0x0F, 0xF0, 0x7E,
0x3F, 0x3F, 0x3F, 0xF8, 0x7F, 0xFE, 0x3E, 0x3F, 0xFC, 0x3F, 0xFE, 0x7E,
0x7F, 0xFE, 0x1F, 0xFC, 0x7C, 0x7E, 0x7E, 0x0F, 0xF8, 0xFC, 0xFC, 0x3E,
0x07, 0xF0, 0xF8, 0xFC, 0x3F, 0x00, 0x01, 0xF8, 0xFC, 0x3F, 0x00, 0x03,
0xF0, 0xFC, 0x3F, 0x00, 0x03, 0xE0, 0xFC, 0x3F, 0x00, 0x07, 0xE0, 0xFC,
0x3F, 0x00, 0x07, 0xC0, 0xFC, 0x3F, 0x00, 0x0F, 0xC0, 0xFC, 0x3F, 0x00,
0x0F, 0x80, 0xFC, 0x3F, 0x00, 0x1F, 0x80, 0x7C, 0x3E, 0x00, 0x1F, 0x00,
0x7E, 0x7E, 0x00, 0x3F, 0x00, 0x7F, 0xFE, 0x00, 0x7E, 0x00, 0x3F, 0xFC,
0x00, 0x7C, 0x00, 0x1F, 0xF8, 0x00, 0xFC, 0x00, 0x0F, 0xF0, 0x00, 0x7F,
0x00, 0x00, 0x01, 0xFF, 0xF0, 0x00, 0x01, 0xFF, 0xFC, 0x00, 0x01, 0xFF,
0xFF, 0x00, 0x01, 0xFF, 0xFF, 0x80, 0x00, 0xFF, 0xBF, 0xE0, 0x00, 0x7F,
0x07, 0xF0, 0x00, 0x3F, 0x03, 0xF8, 0x00, 0x1F, 0x81, 0xFC, 0x00, 0x0F,
0xC0, 0xFE, 0x00, 0x07, 0xF0, 0xFE, 0x00, 0x03, 0xF8, 0xFF, 0x00, 0x00,
0xFE, 0xFF, 0x00, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x1F, 0xFF, 0x00, 0x00,
0x07, 0xFF, 0x00, 0x00, 0x0F, 0xFE, 0x00, 0xFF, 0x0F, 0xFF, 0x80, 0x7F,
0x0F, 0xFF, 0xE0, 0x3F, 0x8F, 0xFF, 0xF8, 0x3F, 0xC7, 0xF9, 0xFE, 0x1F,
0xC7, 0xF8, 0x7F, 0x8F, 0xE3, 0xFC, 0x1F, 0xEF, 0xE1, 0xFC, 0x07, 0xFF,
0xF0, 0xFE, 0x01, 0xFF, 0xF0, 0x7F, 0x00, 0x7F, 0xF8, 0x3F, 0xC0, 0x1F,
0xF8, 0x1F, 0xF0, 0x0F, 0xFC, 0x07, 0xFF, 0x7F, 0xFF, 0x03, 0xFF, 0xFF,
0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF,
0xF1, 0xFF, 0x01, 0xFF, 0xE0, 0x7F, 0xC0, 0xFF, 0xFF, 0xF7, 0xEF, 0xDF,
0xBF, 0x7E, 0xFC, 0xF9, 0xF3, 0xE7, 0xC0, 0x01, 0xF8, 0x1F, 0x81, 0xF8,
0x0F, 0xC0, 0xFC, 0x0F, 0xC0, 0x7E, 0x07, 0xF0, 0x3F, 0x01, 0xF8, 0x1F,
0xC0, 0xFC, 0x07, 0xE0, 0x3F, 0x03, 0xF8, 0x1F, 0x80, 0xFC, 0x07, 0xE0,
0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F, 0x80, 0xFC, 0x07,
0xE0, 0x3F, 0x01, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xE0, 0x3F,
0x01, 0xF8, 0x0F, 0xE0, 0x3F, 0x01, 0xFC, 0x07, 0xE0, 0x1F, 0x80, 0xFC,
0x03, 0xF0, 0xFC, 0x03, 0xF0, 0x0F, 0xC0, 0x7E, 0x01, 0xF8, 0x0F, 0xE0,
0x3F, 0x01, 0xF8, 0x07, 0xE0, 0x3F, 0x01, 0xFC, 0x07, 0xE0, 0x3F, 0x01,
0xF8, 0x0F, 0xC0, 0x7F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x03, 0xF0, 0x1F,
0x80, 0xFC, 0x07, 0xE0, 0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0x7E, 0x07, 0xE0,
0x3F, 0x01, 0xF8, 0x0F, 0xC0, 0xFE, 0x07, 0xE0, 0x3F, 0x03, 0xF0, 0x1F,
0x81, 0xF8, 0x0F, 0xC0, 0xFC, 0x07, 0xE0, 0xFE, 0x00, 0x00, 0x7E, 0x00,
0x00, 0xFC, 0x00, 0x01, 0xF8, 0x00, 0x03, 0xE0, 0x00, 0x07, 0xC0, 0x00,
0x0F, 0x80, 0x10, 0x1F, 0x00, 0xBC, 0x3E, 0x1E, 0x7F, 0xBD, 0xFE, 0xFF,
0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7F, 0xFE, 0x00, 0x1F,
0xE0, 0x00, 0x7F, 0xE0, 0x01, 0xF7, 0xC0, 0x07, 0xEF, 0xC0, 0x0F, 0xCF,
0xC0, 0x3F, 0x1F, 0xC0, 0xFE, 0x1F, 0x80, 0x78, 0x3E, 0x00, 0x30, 0x30,
0x00, 0x00, 0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0,
0x00, 0x07, 0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x3E, 0x00,
0x00, 0x7C, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0x00, 0x00, 0x3E, 0x00, 0x00,
0x7C, 0x00, 0x00, 0xF8, 0x00, 0x01, 0xF0, 0x00, 0x03, 0xE0, 0x00, 0x07,
0xC0, 0x00, 0x0F, 0x80, 0x00, 0x1F, 0x00, 0x00, 0x1F, 0xCF, 0xE3, 0xF8,
0xFC, 0x3F, 0x0F, 0xC7, 0xE1, 0xF8, 0x7E, 0x1F, 0x0F, 0xC0, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C, 0xFE, 0xFF, 0xFF,
0xFF, 0xFE, 0xFE, 0x10, 0x00, 0x07, 0xE0, 0x01, 0xFC, 0x00, 0x3F, 0x00,
0x07, 0xE0, 0x01, 0xFC, 0x00, 0x3F, 0x00, 0x0F, 0xE0, 0x01, 0xFC, 0x00,
0x3F, 0x00, 0x0F, 0xE0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x0F, 0xE0, 0x01,
0xF8, 0x00, 0x3F, 0x00, 0x0F, 0xE0, 0x01, 0xF8, 0x00, 0x7F, 0x00, 0x0F,
0xE0, 0x01, 0xF8, 0x00, 0x7F, 0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x7F,
0x00, 0x0F, 0xC0, 0x01, 0xF8, 0x00, 0x7F, 0x00, 0x0F, 0xC0, 0x03, 0xF8,
0x00, 0x7F, 0x00, 0x0F, 0xC0, 0x03, 0xF8, 0x00, 0x7E, 0x00, 0x1F, 0xC0,
0x00, 0x01, 0xFE, 0x00, 0x0F, 0xFF, 0x00, 0x3F, 0xFF, 0x80, 0xFF, 0xFF,
0x83, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0x1F, 0xE0, 0xFE, 0x3F, 0x80, 0xFE,
0x7F, 0x01, 0xFD, 0xFC, 0x03, 0xFB, 0xF8, 0x03, 0xFF, 0xF0, 0x07, 0xFF,
0xE0, 0x0F, 0xFF, 0xC0, 0x1F, 0xFF, 0x80, 0x3F, 0xFF, 0x00, 0x7F, 0xFE,
0x00, 0xFF, 0xFC, 0x01, 0xFF, 0xF8, 0x03, 0xFF, 0xF0, 0x07, 0xFF, 0xE0,
0x0F, 0xFF, 0xC0, 0x1F, 0xFF, 0x80, 0x3F, 0xFF, 0x00, 0x7F, 0xFE, 0x01,
0xFE, 0xFE, 0x03, 0xF9, 0xFC, 0x07, 0xF3, 0xFC, 0x1F, 0xE3, 0xFC, 0x7F,
0x87, 0xFF, 0xFF, 0x07, 0xFF, 0xFC, 0x07, 0xFF, 0xF0, 0x07, 0xFF, 0xC0,
0x07, 0xFE, 0x00, 0x00, 0x3F, 0x00, 0x7F, 0x00, 0xFF, 0x01, 0xFF, 0x07,
0xFF, 0x0F, 0xFF, 0x1F, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0x7E,
0x7F, 0x38, 0x7F, 0x10, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00,
0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00,
0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00,
0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x00, 0x7F, 0x01,
0xFF, 0x00, 0x1F, 0xFF, 0x80, 0x7F, 0xFF, 0x83, 0xFF, 0xFF, 0x8F, 0xFF,
0xFF, 0x9F, 0xFF, 0xFF, 0x9F, 0xC0, 0xFF, 0x1E, 0x00, 0xFE, 0x18, 0x01,
0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x1F,
0xC0, 0x00, 0x7F, 0x80, 0x00, 0xFE, 0x00, 0x03, 0xFC, 0x00, 0x0F, 0xF0,
0x00, 0x3F, 0xC0, 0x00, 0xFF, 0x00, 0x03, 0xFC, 0x00, 0x0F, 0xF0, 0x00,
0x3F, 0xC0, 0x00, 0xFF, 0x00, 0x03, 0xFC, 0x00, 0x0F, 0xF0, 0x00, 0x3F,
0xC0, 0x00, 0xFF, 0x00, 0x03, 0xFC, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFC, 0x03, 0xFE, 0x00, 0x3F, 0xFF, 0x81, 0xFF, 0xFF, 0xC7, 0xFF, 0xFF,
0xC7, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0x8F, 0x00, 0xFF, 0x08, 0x00, 0xFE,
0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xC0,
0x00, 0x3F, 0x80, 0x01, 0xFE, 0x01, 0xFF, 0xF8, 0x03, 0xFF, 0xC0, 0x07,
0xFE, 0x00, 0x0F, 0xFF, 0xC0, 0x1F, 0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x00,
0x3F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0x00, 0x00,
0xFE, 0x00, 0x03, 0xFC, 0x00, 0x07, 0xFE, 0x00, 0x1F, 0xEF, 0xC0, 0xFF,
0xDF, 0xFF, 0xFF, 0xBF, 0xFF, 0xFE, 0x7F, 0xFF, 0xF8, 0xFF, 0xFF, 0xC0,
0x7F, 0xFE, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x01, 0xFE,
0x00, 0x01, 0xFF, 0x00, 0x00, 0xFF, 0x80, 0x00, 0xFF, 0xC0, 0x00, 0xFF,
0xE0, 0x00, 0x7F, 0xF0, 0x00, 0x7F, 0xF8, 0x00, 0x7F, 0xFC, 0x00, 0x3E,
0xFE, 0x00, 0x3F, 0x7F, 0x00, 0x3F, 0x3F, 0x80, 0x1F, 0x1F, 0xC0, 0x1F,
0x8F, 0xE0, 0x1F, 0x87, 0xF0, 0x0F, 0x83, 0xF8, 0x0F, 0xC1, 0xFC, 0x0F,
0xC0, 0xFE, 0x07, 0xC0, 0x7F, 0x07, 0xE0, 0x3F, 0x87, 0xE0, 0x1F, 0xC3,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F,
0xC0, 0x00, 0x0F, 0xE0, 0x00, 0x07, 0xF0, 0x00, 0x03, 0xF8, 0x00, 0x01,
0xFC, 0x00, 0x3F, 0xFF, 0xF0, 0x7F, 0xFF, 0xE0, 0xFF, 0xFF, 0xC1, 0xFF,
0xFF, 0x83, 0xFF, 0xFF, 0x07, 0xFF, 0xFE, 0x0F, 0xC0, 0x00, 0x1F, 0x80,
0x00, 0x3F, 0x00, 0x00, 0x7E, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8, 0x00,
0x07, 0xF0, 0x00, 0x0F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF8, 0x3F, 0xFF, 0xF8,
0x7F, 0xFF, 0xF8, 0xFF, 0xFF, 0xF8, 0x78, 0x7F, 0xF0, 0x00, 0x1F, 0xE0,
0x00, 0x1F, 0xE0, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0x80, 0x00, 0x7F, 0x00,
0x01, 0xFE, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xF7, 0x00, 0x1F, 0xEF, 0xE1,
0xFF, 0xDF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFC, 0x7F, 0xFF, 0xF0, 0xFF, 0xFF,
0xC0, 0x7F, 0xFE, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0xFF, 0xF0, 0x07, 0xFF,
0xE0, 0x3F, 0xFF, 0xC0, 0xFF, 0xFF, 0x83, 0xFF, 0xFF, 0x07, 0xF8, 0x00,
0x1F, 0xE0, 0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x01, 0xF8, 0x00, 0x03,
0xF0, 0x00, 0x0F, 0xE1, 0xF8, 0x1F, 0x8F, 0xFC, 0x3F, 0x3F, 0xFC, 0x7E,
0xFF, 0xFC, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFB, 0xFE, 0x07, 0xFF, 0xF8,
0x07, 0xFF, 0xE0, 0x0F, 0xFF, 0xC0, 0x1F, 0xFF, 0x80, 0x3F, 0xFF, 0x00,
0x7F, 0xFE, 0x00, 0xFF, 0xFC, 0x01, 0xFD, 0xFC, 0x03, 0xFB, 0xFC, 0x0F,
0xF3, 0xFC, 0x7F, 0xC7, 0xFF, 0xFF, 0x87, 0xFF, 0xFE, 0x07, 0xFF, 0xF8,
0x07, 0xFF, 0xE0, 0x03, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFC,
0x00, 0x01, 0xFC, 0x00, 0x03, 0xF8, 0x00, 0x03, 0xF8, 0x00, 0x03, 0xF8,
0x00, 0x07, 0xF0, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xE0,
0x00, 0x1F, 0xC0, 0x00, 0x1F, 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x3F, 0x80,
0x00, 0x7F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00,
0x00, 0xFE, 0x00, 0x01, 0xFC, 0x00, 0x01, 0xFC, 0x00, 0x03, 0xFC, 0x00,
0x03, 0xF8, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xF0, 0x00,
0x00, 0xFE, 0x00, 0x0F, 0xFF, 0x80, 0x7F, 0xFF, 0xC1, 0xFF, 0xFF, 0xC3,
0xFF, 0xFF, 0x8F, 0xF8, 0xFF, 0x9F, 0xC0, 0x7F, 0x3F, 0x80, 0xFE, 0x7E,
0x01, 0xFC, 0xFC, 0x03, 0xF9, 0xFC, 0x07, 0xF3, 0xFC, 0x1F, 0xC3, 0xFC,
0x7F, 0x83, 0xFF, 0xFE, 0x03, 0xFF, 0xF8, 0x03, 0xFF, 0xE0, 0x03, 0xFF,
0x80, 0x1F, 0xFF, 0x80, 0x7F, 0xFF, 0xC1, 0xFF, 0xFF, 0xC7, 0xF8, 0x7F,
0xCF, 0xE0, 0x7F, 0xBF, 0x80, 0x3F, 0xFE, 0x00, 0x7F, 0xFC, 0x00, 0x7F,
0xF8, 0x00, 0xFF, 0xF0, 0x03, 0xFF, 0xF0, 0x07, 0xFF, 0xF0, 0x1F, 0xEF,
0xFF, 0xFF, 0x9F, 0xFF, 0xFE, 0x1F, 0xFF, 0xFC, 0x1F, 0xFF, 0xE0, 0x0F,
0xFF, 0x00, 0x00, 0xFE, 0x00, 0x03, 0xFF, 0xC0, 0x0F, 0xFF, 0xE0, 0x1F,
0xFF, 0xF0, 0x3F, 0xFF, 0xF8, 0x3F, 0xFF, 0xFC, 0x7F, 0x81, 0xFE, 0x7F,
0x00, 0xFE, 0x7F, 0x00, 0xFE, 0x7F, 0x00, 0x7F, 0x7F, 0x00, 0x7F, 0xFE,
0x00, 0x7F, 0x7E, 0x00, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x00, 0xFF, 0x7F,
0x80, 0xFF, 0x7F, 0xC3, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0xFF, 0xBF, 0x1F,
0xFF, 0xBF, 0x0F, 0xFF, 0x7F, 0x03, 0xFC, 0x7F, 0x00, 0x00, 0x7E, 0x00,
0x00, 0x7E, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xFC, 0x00, 0x01, 0xFC, 0x00,
0x03, 0xF8, 0x20, 0x1F, 0xF8, 0x1F, 0xFF, 0xF0, 0x1F, 0xFF, 0xE0, 0x1F,
0xFF, 0xC0, 0x1F, 0xFF, 0x00, 0x1F, 0xFC, 0x00, 0x7C, 0xFE, 0xFF, 0xFF,
0xFF, 0xFE, 0xFE, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7C, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0x10, 0x1F,
0x0F, 0xE3, 0xFC, 0xFF, 0x3F, 0xCF, 0xE1, 0xF8, 0x38, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x07, 0xF3, 0xF8, 0xFE, 0x3F, 0x0F, 0xC3, 0xF1, 0xF8, 0x7E, 0x1F,
0x87, 0xC3, 0xF0, 0x00, 0x00, 0x06, 0x00, 0x00, 0x3C, 0x00, 0x01, 0xF8,
0x00, 0x0F, 0xF0, 0x00, 0x7F, 0xE0, 0x03, 0xFF, 0x80, 0x1F, 0xFC, 0x00,
0xFF, 0xE0, 0x07, 0xFF, 0x00, 0x3F, 0xF0, 0x01, 0xFF, 0x80, 0x07, 0xFC,
0x00, 0x0F, 0xE0, 0x00, 0x1F, 0xF8, 0x00, 0x3F, 0xFC, 0x00, 0x0F, 0xFF,
0x00, 0x07, 0xFF, 0x80, 0x03, 0xFF, 0xE0, 0x00, 0xFF, 0xF0, 0x00, 0x7F,
0xF0, 0x00, 0x3F, 0xE0, 0x00, 0x1F, 0xC0, 0x00, 0x07, 0x80, 0x00, 0x03,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xC0, 0x00, 0x01, 0xE0, 0x00, 0x03, 0xF0,
0x00, 0x07, 0xF8, 0x00, 0x0F, 0xFC, 0x00, 0x0F, 0xFE, 0x00, 0x07, 0xFF,
0x00, 0x03, 0xFF, 0x80, 0x01, 0xFF, 0xC0, 0x00, 0xFF, 0xE0, 0x00, 0x3F,
0xF0, 0x00, 0x1F, 0xF0, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0xC0, 0x07, 0xFF,
0x00, 0x7F, 0xF8, 0x03, 0xFF, 0xC0, 0x3F, 0xFE, 0x01, 0xFF, 0xE0, 0x07,
0xFF, 0x00, 0x0F, 0xF8, 0x00, 0x1F, 0x80, 0x00, 0x3C, 0x00, 0x00, 0x60,
0x00, 0x00, 0x03, 0xFE, 0x00, 0xFF, 0xFE, 0x1F, 0xFF, 0xF9, 0xFF, 0xFF,
0xE7, 0xFF, 0xFF, 0x9F, 0xFF, 0xFC, 0xF0, 0x0F, 0xE6, 0x00, 0x7F, 0x00,
0x01, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0xFE, 0x00, 0x07, 0xF0, 0x00, 0x7F,
0x00, 0x07, 0xF8, 0x00, 0xFF, 0x80, 0x0F, 0xF8, 0x00, 0xFF, 0x80, 0x0F,
0xF0, 0x00, 0x7F, 0x00, 0x03, 0xF0, 0x00, 0x1F, 0x80, 0x00, 0xF8, 0x00,
0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x03, 0xE0, 0x00, 0x3F, 0x80, 0x01, 0xFE, 0x00, 0x0F, 0xF0, 0x00,
0x7F, 0x80, 0x03, 0xF8, 0x00, 0x0F, 0xC0, 0x00, 0x10, 0x00, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0xFF, 0xC0,
0x00, 0x1F, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0xFF, 0x80, 0x0F, 0xF0,
0x00, 0xFF, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x03, 0xF8, 0x00, 0x01, 0xF8,
0x0F, 0xC0, 0x00, 0x03, 0xF0, 0x7E, 0x03, 0xFF, 0x07, 0xE3, 0xF0, 0x3F,
0xFF, 0x0F, 0x8F, 0x81, 0xFF, 0xFC, 0x3E, 0x3E, 0x0F, 0xFF, 0xF0, 0xFD,
0xF8, 0x7F, 0x07, 0xC1, 0xF7, 0xC3, 0xF8, 0x1F, 0x07, 0xDF, 0x0F, 0xC0,
0x7C, 0x1F, 0xFC, 0x3E, 0x01, 0xF0, 0x7F, 0xF0, 0xF8, 0x07, 0xC1, 0xFF,
0x87, 0xE0, 0x1F, 0x07, 0xFE, 0x1F, 0x80, 0xFC, 0x1F, 0xF8, 0x7E, 0x03,
0xF0, 0x7F, 0xE0, 0xF8, 0x0F, 0xC3, 0xEF, 0x83, 0xE0, 0x3F, 0x0F, 0xBF,
0x0F, 0xC1, 0xFC, 0x7E, 0x7C, 0x3F, 0xDF, 0xFB, 0xF1, 0xF0, 0x7F, 0xFF,
0xFF, 0x87, 0xC0, 0xFF, 0xE7, 0xFE, 0x1F, 0x81, 0xFF, 0x0F, 0xF0, 0x3F,
0x01, 0xF0, 0x0E, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x01, 0xF8, 0x00, 0x00,
0x00, 0x03, 0xF8, 0x00, 0x01, 0x00, 0x0F, 0xF8, 0x00, 0x7C, 0x00, 0x1F,
0xFF, 0xFF, 0xF0, 0x00, 0x1F, 0xFF, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xFF,
0x00, 0x00, 0x1F, 0xFF, 0xE0, 0x00, 0x00, 0x07, 0xF8, 0x00, 0x00, 0x00,
0x0F, 0xF8, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x07, 0xFE, 0x00, 0x00,
0x03, 0xFF, 0x80, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x01, 0xFF, 0xE0, 0x00,
0x00, 0xFF, 0xF8, 0x00, 0x00, 0xFE, 0xFC, 0x00, 0x00, 0x7F, 0x7F, 0x00,
0x00, 0x3F, 0x3F, 0x80, 0x00, 0x3F, 0x8F, 0xC0, 0x00, 0x1F, 0xC7, 0xF0,
0x00, 0x0F, 0xE3, 0xF8, 0x00, 0x0F, 0xE1, 0xFC, 0x00, 0x07, 0xF0, 0x7F,
0x00, 0x07, 0xF8, 0x3F, 0x80, 0x03, 0xF8, 0x1F, 0xC0, 0x01, 0xFC, 0x07,
0xF0, 0x01, 0xFE, 0x03, 0xF8, 0x00, 0xFE, 0x01, 0xFC, 0x00, 0x7F, 0xFF,
0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0x80, 0x3F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF,
0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xFE, 0x07, 0xF0,
0x00, 0xFF, 0x07, 0xF8, 0x00, 0x3F, 0x83, 0xFC, 0x00, 0x1F, 0xE1, 0xFC,
0x00, 0x0F, 0xF1, 0xFE, 0x00, 0x03, 0xF8, 0xFF, 0x00, 0x01, 0xFE, 0x7F,
0x00, 0x00, 0xFF, 0x7F, 0x80, 0x00, 0x3F, 0xC0, 0xFF, 0xF0, 0x00, 0x7F,
0xFF, 0xF0, 0x3F, 0xFF, 0xFE, 0x1F, 0xFF, 0xFF, 0x8F, 0xFF, 0xFF, 0xE7,
0xFF, 0xFF, 0xF3, 0xF8, 0x0F, 0xFD, 0xFC, 0x01, 0xFE, 0xFE, 0x00, 0xFF,
0x7F, 0x00, 0x3F, 0xBF, 0x80, 0x1F, 0xDF, 0xC0, 0x1F, 0xEF, 0xE0, 0x0F,
0xE7, 0xF0, 0x1F, 0xF3, 0xFF, 0xFF, 0xF1, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF,
0xE0, 0x7F, 0xFF, 0xFC, 0x3F, 0xFF, 0xFF, 0x9F, 0xC0, 0x7F, 0xEF, 0xE0,
0x0F, 0xF7, 0xF0, 0x03, 0xFF, 0xF8, 0x01, 0xFF, 0xFC, 0x00, 0xFF, 0xFE,
0x00, 0x7F, 0xFF, 0x00, 0x3F, 0xFF, 0x80, 0x1F, 0xFF, 0xC0, 0x1F, 0xEF,
0xFF, 0xFF, 0xF7, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xF8,
0xFF, 0xFF, 0xF0, 0x7F, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xF8, 0x00, 0x3F,
0xFF, 0xC0, 0x3F, 0xFF, 0xFC, 0x1F, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0x87,
0xFF, 0xFF, 0xC3, 0xFF, 0x80, 0xF0, 0xFF, 0x80, 0x0C, 0x7F, 0xC0, 0x00,
0x1F, 0xE0, 0x00, 0x07, 0xF0, 0x00, 0x03, 0xFC, 0x00, 0x00, 0xFF, 0x00,
0x00, 0x3F, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xF8, 0x00, 0x00, 0xFE,
0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x03, 0xF8, 0x00, 0x00,
0xFE, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x0F, 0xF0, 0x00, 0x03, 0xFC, 0x00,
0x00, 0x7F, 0x80, 0x00, 0x1F, 0xE0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0xFF,
0xC0, 0x0C, 0x3F, 0xFF, 0xFF, 0x07, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xF0,
0x1F, 0xFF, 0xFC, 0x01, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0x00, 0xFF, 0xF0,
0x00, 0x0F, 0xFF, 0xFC, 0x00, 0xFF, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF, 0xC0,
0xFF, 0xFF, 0xFE, 0x0F, 0xFF, 0xFF, 0xF0, 0xFE, 0x07, 0xFF, 0x8F, 0xE0,
0x0F, 0xFC, 0xFE, 0x00, 0x3F, 0xCF, 0xE0, 0x03, 0xFE, 0xFE, 0x00, 0x1F,
0xEF, 0xE0, 0x01, 0xFE, 0xFE, 0x00, 0x0F, 0xEF, 0xE0, 0x00, 0xFF, 0xFE,
0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00,
0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF,
0xE0, 0x00, 0xFE, 0xFE, 0x00, 0x1F, 0xEF, 0xE0, 0x01, 0xFE, 0xFE, 0x00,
0x3F, 0xEF, 0xE0, 0x03, 0xFC, 0xFE, 0x00, 0xFF, 0xCF, 0xE0, 0x3F, 0xF8,
0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xE0, 0xFF, 0xFF, 0xFC, 0x0F, 0xFF,
0xFF, 0x80, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00,
0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFF, 0xFF, 0xEF, 0xFF,
0xFE, 0xFF, 0xFF, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF, 0xEF, 0xE0, 0x00, 0xFE,
0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFE, 0x00, 0x0F,
0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0x80, 0x07, 0xF0, 0x00, 0xFE, 0x00, 0x1F, 0xC0, 0x03, 0xF8, 0x00,
0x7F, 0x00, 0x0F, 0xE0, 0x01, 0xFC, 0x00, 0x3F, 0x80, 0x07, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFC, 0x00, 0x3F, 0x80, 0x07, 0xF0, 0x00, 0xFE, 0x00, 0x1F, 0xC0, 0x03,
0xF8, 0x00, 0x7F, 0x00, 0x0F, 0xE0, 0x01, 0xFC, 0x00, 0x3F, 0x80, 0x07,
0xF0, 0x00, 0xFE, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x0F,
0xFF, 0xF8, 0x07, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xF0, 0xFF, 0xFF, 0xFC,
0x3F, 0xFF, 0xFF, 0x87, 0xFF, 0x00, 0xE1, 0xFF, 0x80, 0x04, 0x3F, 0xC0,
0x00, 0x0F, 0xF0, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x7F, 0x80, 0x00, 0x0F,
0xF0, 0x00, 0x01, 0xFC, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x07, 0xF0, 0x1F,
0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0xC0, 0x7F, 0xFF, 0xF8, 0x0F, 0xFF, 0xFF,
0x01, 0xFF, 0xFF, 0xE0, 0x3F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xC0, 0x03,
0xFF, 0xF8, 0x00, 0x7F, 0x7F, 0x80, 0x0F, 0xEF, 0xF0, 0x01, 0xFD, 0xFF,
0x00, 0x3F, 0x9F, 0xF0, 0x07, 0xF1, 0xFF, 0xE7, 0xFE, 0x3F, 0xFF, 0xFF,
0xC3, 0xFF, 0xFF, 0xF8, 0x3F, 0xFF, 0xFF, 0x01, 0xFF, 0xFF, 0xE0, 0x0F,
0xFF, 0xE0, 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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
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, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x1F,
0xFC, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07,
0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07,
0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07,
0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x0F, 0xF8, 0x7F,
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xFC, 0x07,
0xF0, 0x1F, 0xC0, 0x7F, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x01,
0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0,
0x7F, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x01, 0xFC, 0x07, 0xF0,
0x1F, 0xC0, 0x7F, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x01, 0xFC,
0x07, 0xF0, 0x1F, 0xC0, 0x7F, 0x01, 0xFC, 0x07, 0xF0, 0x1F, 0xC0, 0x7F,
0x03, 0xFE, 0x1F, 0xFF, 0xFF, 0xBF, 0xFE, 0xFF, 0xF3, 0xFF, 0x8F, 0xFC,
0x3F, 0x80, 0xFE, 0x00, 0x1F, 0xFF, 0xC0, 0x07, 0xFB, 0xF8, 0x00, 0xFF,
0x7F, 0x00, 0x3F, 0xCF, 0xE0, 0x0F, 0xF1, 0xFC, 0x03, 0xFC, 0x3F, 0x80,
0xFF, 0x07, 0xF0, 0x1F, 0xE0, 0xFE, 0x07, 0xF8, 0x1F, 0xC1, 0xFE, 0x03,
0xF8, 0x7F, 0x80, 0x7F, 0x1F, 0xE0, 0x0F, 0xE3, 0xFC, 0x01, 0xFC, 0xFF,
0x00, 0x3F, 0xBF, 0xC0, 0x07, 0xF7, 0xF8, 0x00, 0xFF, 0xFF, 0x00, 0x1F,
0xFF, 0xF0, 0x03, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0xE0, 0x0F, 0xF9, 0xFE,
0x01, 0xFE, 0x3F, 0xC0, 0x3F, 0x83, 0xFC, 0x07, 0xF0, 0x3F, 0xC0, 0xFE,
0x07, 0xF8, 0x1F, 0xC0, 0x7F, 0x83, 0xF8, 0x0F, 0xF0, 0x7F, 0x00, 0xFF,
0x0F, 0xE0, 0x0F, 0xF1, 0xFC, 0x01, 0xFE, 0x3F, 0x80, 0x1F, 0xE7, 0xF0,
0x01, 0xFE, 0xFE, 0x00, 0x3F, 0xDF, 0xC0, 0x03, 0xFC, 0xFE, 0x00, 0x07,
0xF0, 0x00, 0x3F, 0x80, 0x01, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0x7F, 0x00,
0x03, 0xF8, 0x00, 0x1F, 0xC0, 0x00, 0xFE, 0x00, 0x07, 0xF0, 0x00, 0x3F,
0x80, 0x01, 0xFC, 0x00, 0x0F, 0xE0, 0x00, 0x7F, 0x00, 0x03, 0xF8, 0x00,
0x1F, 0xC0, 0x00, 0xFE, 0x00, 0x07, 0xF0, 0x00, 0x3F, 0x80, 0x01, 0xFC,
0x00, 0x0F, 0xE0, 0x00, 0x7F, 0x00, 0x03, 0xF8, 0x00, 0x1F, 0xC0, 0x00,
0xFE, 0x00, 0x07, 0xF0, 0x00, 0x3F, 0x80, 0x01, 0xFC, 0x00, 0x0F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xC0, 0xFF, 0xC0, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0x03, 0xFF,
0xFF, 0xE0, 0x00, 0x3F, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xE0, 0x00,
0x7F, 0xFF, 0xFE, 0x00, 0x07, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xFF,
0x00, 0x0F, 0xFF, 0xFD, 0xF0, 0x00, 0xFB, 0xFF, 0xDF, 0x80, 0x1F, 0xBF,
0xFD, 0xF8, 0x01, 0xFB, 0xFF, 0xCF, 0x80, 0x1F, 0x3F, 0xFC, 0xFC, 0x03,
0xF3, 0xFF, 0xCF, 0xC0, 0x3F, 0x3F, 0xFC, 0xFC, 0x03, 0xE3, 0xFF, 0xE7,
0xE0, 0x7E, 0x7F, 0xFE, 0x7E, 0x07, 0xE7, 0xFF, 0xE7, 0xE0, 0x7C, 0x7F,
0xFE, 0x3E, 0x0F, 0xC7, 0xFF, 0xE3, 0xF0, 0xFC, 0x7F, 0xFE, 0x3F, 0x0F,
0x87, 0xFF, 0xE1, 0xF1, 0xF8, 0x7F, 0xFE, 0x1F, 0x9F, 0x87, 0xFF, 0xE1,
0xF9, 0xF0, 0x7F, 0xFE, 0x1F, 0x9F, 0x07, 0xFF, 0xE0, 0xFF, 0xF0, 0x7F,
0xFE, 0x0F, 0xFE, 0x07, 0xFF, 0xE0, 0xFF, 0xE0, 0x7F, 0xFE, 0x07, 0xFE,
0x07, 0xFF, 0xE0, 0x7F, 0xC0, 0x7F, 0xFE, 0x07, 0xFC, 0x07, 0xFF, 0xE0,
0x3F, 0xC0, 0x7F, 0xFE, 0x03, 0xF8, 0x07, 0xFF, 0xE0, 0x3F, 0x80, 0x7F,
0xFF, 0x80, 0x00, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFC, 0x00, 0x0F, 0xFF,
0xF8, 0x00, 0x3F, 0xFF, 0xF0, 0x00, 0xFF, 0xFF, 0xC0, 0x03, 0xFF, 0xFF,
0x80, 0x0F, 0xFF, 0xFE, 0x00, 0x3F, 0xFF, 0xFC, 0x00, 0xFF, 0xF7, 0xF0,
0x03, 0xFF, 0xDF, 0xE0, 0x0F, 0xFF, 0x3F, 0xC0, 0x3F, 0xFC, 0x7F, 0x00,
0xFF, 0xF1, 0xFE, 0x03, 0xFF, 0xC3, 0xF8, 0x0F, 0xFF, 0x0F, 0xF0, 0x3F,
0xFE, 0x1F, 0xE0, 0xFF, 0xF8, 0x7F, 0x83, 0xFF, 0xE0, 0xFF, 0x0F, 0xFF,
0x81, 0xFC, 0x3F, 0xFE, 0x07, 0xF8, 0xFF, 0xF8, 0x0F, 0xE3, 0xFF, 0xE0,
0x3F, 0xCF, 0xFF, 0x80, 0x7F, 0xBF, 0xFE, 0x01, 0xFE, 0xFF, 0xF8, 0x03,
0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0x80, 0x1F, 0xFF, 0xFE, 0x00, 0x3F,
0xFF, 0xF8, 0x00, 0xFF, 0xFF, 0xE0, 0x01, 0xFF, 0xFF, 0x80, 0x03, 0xFF,
0xFE, 0x00, 0x0F, 0xFF, 0xF8, 0x00, 0x1F, 0xF0, 0x00, 0x3F, 0xF8, 0x00,
0x00, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xE0,
0x0F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0, 0x3F, 0xF0, 0x1F, 0xF8,
0x3F, 0xC0, 0x07, 0xFC, 0x7F, 0x80, 0x03, 0xFC, 0x7F, 0x80, 0x03, 0xFC,
0xFF, 0x00, 0x01, 0xFE, 0xFF, 0x00, 0x01, 0xFE, 0xFF, 0x00, 0x00, 0xFE,
0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE,
0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF,
0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x00, 0xFE,
0xFF, 0x00, 0x01, 0xFE, 0xFF, 0x00, 0x01, 0xFE, 0x7F, 0x80, 0x01, 0xFC,
0x7F, 0x80, 0x03, 0xFC, 0x7F, 0xC0, 0x07, 0xFC, 0x3F, 0xE0, 0x0F, 0xF8,
0x1F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xE0,
0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0x7F, 0xFC, 0x00,
0xFF, 0xF0, 0x01, 0xFF, 0xFF, 0x03, 0xFF, 0xFF, 0x87, 0xFF, 0xFF, 0x8F,
0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xBF, 0x83, 0xFF, 0x7F, 0x01, 0xFF, 0xFE,
0x01, 0xFF, 0xFC, 0x01, 0xFF, 0xF8, 0x03, 0xFF, 0xF0, 0x07, 0xFF, 0xE0,
0x0F, 0xFF, 0xC0, 0x3F, 0xFF, 0x80, 0x7F, 0xFF, 0x03, 0xFE, 0xFF, 0xFF,
0xFD, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF, 0x0F, 0xFF, 0xFC,
0x1F, 0xFF, 0xC0, 0x3F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x01,
0xFC, 0x00, 0x03, 0xF8, 0x00, 0x07, 0xF0, 0x00, 0x0F, 0xE0, 0x00, 0x1F,
0xC0, 0x00, 0x3F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFC,
0x00, 0x00, 0x00, 0x3F, 0xF8, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x03, 0xFF,
0xFF, 0x80, 0x07, 0xFF, 0xFF, 0xE0, 0x0F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF,
0xFF, 0xF0, 0x3F, 0xF0, 0x1F, 0xF8, 0x3F, 0xC0, 0x07, 0xFC, 0x7F, 0x80,
0x03, 0xFC, 0x7F, 0x80, 0x03, 0xFC, 0xFF, 0x00, 0x01, 0xFE, 0xFF, 0x00,
0x01, 0xFE, 0xFF, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00,
0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00,
0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0xFE, 0x00, 0x00, 0xFE, 0xFE, 0x00,
0x00, 0xFE, 0xFF, 0x00, 0x00, 0xFE, 0xFF, 0x00, 0x01, 0xFE, 0xFF, 0x00,
0x01, 0xFE, 0x7F, 0x80, 0x01, 0xFE, 0x7F, 0x80, 0x03, 0xFC, 0x7F, 0xC0,
0x07, 0xFC, 0x3F, 0xE0, 0x0F, 0xF8, 0x1F, 0xFF, 0xFF, 0xF8, 0x1F, 0xFF,
0xFF, 0xF0, 0x0F, 0xFF, 0xFF, 0xE0, 0x07, 0xFF, 0xFF, 0xC0, 0x01, 0xFF,
0xFF, 0x00, 0x00, 0x7F, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x00, 0x00,
0x7F, 0xC0, 0x00, 0x00, 0x3F, 0xE0, 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x00,
0x1F, 0xF0, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x07, 0xFC, 0x00, 0x00,
0x03, 0xFE, 0xFF, 0xE0, 0x00, 0x1F, 0xFF, 0xF8, 0x03, 0xFF, 0xFF, 0xC0,
0x7F, 0xFF, 0xFC, 0x0F, 0xFF, 0xFF, 0xC1, 0xFF, 0xFF, 0xF8, 0x3F, 0x81,
0xFF, 0x87, 0xF0, 0x0F, 0xF0, 0xFE, 0x00, 0xFE, 0x1F, 0xC0, 0x1F, 0xC3,
0xF8, 0x03, 0xF8, 0x7F, 0x00, 0x7F, 0x0F, 0xE0, 0x0F, 0xE1, 0xFC, 0x03,
0xFC, 0x3F, 0x80, 0xFF, 0x07, 0xF0, 0xFF, 0xE0, 0xFF, 0xFF, 0xF8, 0x1F,
0xFF, 0xFE, 0x03, 0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xE0, 0x0F, 0xFF, 0xFC,
0x01, 0xFC, 0x3F, 0xC0, 0x3F, 0x83, 0xF8, 0x07, 0xF0, 0x3F, 0x80, 0xFE,
0x07, 0xF8, 0x1F, 0xC0, 0x7F, 0x03, 0xF8, 0x0F, 0xF0, 0x7F, 0x00, 0xFF,
0x0F, 0xE0, 0x1F, 0xE1, 0xFC, 0x01, 0xFE, 0x3F, 0x80, 0x1F, 0xE7, 0xF0,
0x03, 0xFC, 0xFE, 0x00, 0x3F, 0xDF, 0xC0, 0x07, 0xFC, 0x00, 0xFF, 0x80,
0x1F, 0xFF, 0xC0, 0xFF, 0xFF, 0xC7, 0xFF, 0xFE, 0x3F, 0xFF, 0xF9, 0xFF,
0xFF, 0xE7, 0xF8, 0x0F, 0x1F, 0xC0, 0x04, 0x7F, 0x00, 0x01, 0xFC, 0x00,
0x07, 0xF0, 0x00, 0x1F, 0xC0, 0x00, 0x7F, 0xC0, 0x01, 0xFF, 0xC0, 0x03,
0xFF, 0xC0, 0x07, 0xFF, 0xC0, 0x0F, 0xFF, 0x80, 0x1F, 0xFF, 0x80, 0x1F,
0xFF, 0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xF8, 0x00, 0x3F, 0xF0, 0x00, 0x3F,
0xC0, 0x00, 0x7F, 0x00, 0x01, 0xFC, 0x00, 0x07, 0xFC, 0x00, 0x1F, 0xFC,
0x00, 0xFF, 0xFF, 0x9F, 0xFB, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0x3F, 0xFF,
0xF8, 0xFF, 0xFF, 0xC0, 0x7F, 0xFC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFC, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00, 0x00,
0x3F, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x0F, 0xE0, 0x00, 0x07, 0xF0, 0x00,
0x03, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x3F, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x0F, 0xE0, 0x00, 0x07, 0xF0,
0x00, 0x03, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F,
0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x0F, 0xE0, 0x00, 0x07,
0xF0, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x3F, 0x80, 0x00, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00,
0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF,
0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, 0x00,
0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF,
0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xE0,
0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x0F,
0xFF, 0xE0, 0x00, 0xFF, 0xFE, 0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFF, 0xFE,
0x00, 0x0F, 0xFF, 0xE0, 0x00, 0xFE, 0xFF, 0x00, 0x0F, 0xEF, 0xF0, 0x00,
0xFE, 0x7F, 0x80, 0x1F, 0xE7, 0xFC, 0x03, 0xFC, 0x7F, 0xFF, 0xFF, 0xC3,
0xFF, 0xFF, 0xF8, 0x1F, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0xE0, 0x07, 0xFF,
0xFC, 0x00, 0x1F, 0xFF, 0x00, 0xFE, 0x00, 0x01, 0xFF, 0xFE, 0x00, 0x03,
0xF9, 0xFC, 0x00, 0x07, 0xF3, 0xF8, 0x00, 0x1F, 0xE7, 0xF0, 0x00, 0x3F,
0x87, 0xF0, 0x00, 0x7F, 0x0F, 0xE0, 0x01, 0xFE, 0x1F, 0xC0, 0x03, 0xF8,
0x1F, 0xC0, 0x07, 0xF0, 0x3F, 0x80, 0x1F, 0xC0, 0x7F, 0x00, 0x3F, 0x80,
0x7F, 0x00, 0x7F, 0x00, 0xFE, 0x00, 0xFC, 0x01, 0xFC, 0x03, 0xF8, 0x01,
0xFC, 0x07, 0xF0, 0x03, 0xF8, 0x0F, 0xC0, 0x07, 0xF0, 0x3F, 0x80, 0x07,
0xF0, 0x7F, 0x00, 0x0F, 0xE0, 0xFC, 0x00, 0x1F, 0xC3, 0xF8, 0x00, 0x1F,
0xC7, 0xF0, 0x00, 0x3F, 0x8F, 0xC0, 0x00, 0x7F, 0x3F, 0x80, 0x00, 0x7E,
0x7F, 0x00, 0x00, 0xFE, 0xFC, 0x00, 0x01, 0xFD, 0xF8, 0x00, 0x01, 0xFF,
0xF0, 0x00, 0x03, 0xFF, 0xC0, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x07, 0xFF,
0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x0F, 0xF8, 0x00, 0x00, 0x1F, 0xF0,
0x00, 0x00, 0x3F, 0xC0, 0x00, 0xFE, 0x00, 0x1F, 0xC0, 0x03, 0xFF, 0xF0,
0x00, 0xFE, 0x00, 0x1F, 0xDF, 0x80, 0x07, 0xF8, 0x00, 0xFE, 0xFE, 0x00,
0x3F, 0xC0, 0x07, 0xF7, 0xF0, 0x03, 0xFE, 0x00, 0x7F, 0x3F, 0x80, 0x1F,
0xF0, 0x03, 0xF8, 0xFC, 0x00, 0xFF, 0xC0, 0x1F, 0xC7, 0xF0, 0x07, 0xFE,
0x00, 0xFE, 0x3F, 0x80, 0x7F, 0xF0, 0x07, 0xE1, 0xFC, 0x03, 0xFF, 0x80,
0x7F, 0x07, 0xE0, 0x1F, 0x7E, 0x03, 0xF8, 0x3F, 0x81, 0xFB, 0xF0, 0x1F,
0xC1, 0xFC, 0x0F, 0xDF, 0x80, 0xFC, 0x0F, 0xE0, 0x7E, 0x7C, 0x0F, 0xE0,
0x3F, 0x03, 0xF3, 0xF0, 0x7F, 0x01, 0xFC, 0x3F, 0x1F, 0x83, 0xF8, 0x0F,
0xE1, 0xF8, 0xFC, 0x1F, 0x80, 0x7F, 0x0F, 0xC3, 0xF1, 0xFC, 0x01, 0xF8,
0x7E, 0x1F, 0x8F, 0xE0, 0x0F, 0xC7, 0xE0, 0xFC, 0x7F, 0x00, 0x7F, 0x3F,
0x07, 0xE3, 0xF0, 0x03, 0xF9, 0xF8, 0x1F, 0x1F, 0x80, 0x0F, 0xCF, 0xC0,
0xFD, 0xFC, 0x00, 0x7E, 0x7C, 0x07, 0xEF, 0xE0, 0x03, 0xF7, 0xE0, 0x3F,
0x7E, 0x00, 0x1F, 0xFF, 0x00, 0xFB, 0xF0, 0x00, 0x7F, 0xF8, 0x07, 0xDF,
0x80, 0x03, 0xFF, 0x80, 0x3F, 0xFC, 0x00, 0x1F, 0xFC, 0x01, 0xFF, 0xC0,
0x00, 0xFF, 0xE0, 0x07, 0xFE, 0x00, 0x03, 0xFF, 0x00, 0x3F, 0xF0, 0x00,
0x1F, 0xF0, 0x01, 0xFF, 0x80, 0x00, 0xFF, 0x80, 0x0F, 0xF8, 0x00, 0x07,
0xFC, 0x00, 0x3F, 0xC0, 0x00, 0x7F, 0x80, 0x03, 0xFE, 0xFF, 0x00, 0x07,
0xF8, 0xFF, 0x00, 0x1F, 0xE0, 0xFF, 0x00, 0x3F, 0xC1, 0xFE, 0x00, 0xFF,
0x01, 0xFE, 0x03, 0xFC, 0x01, 0xFC, 0x07, 0xF8, 0x03, 0xFC, 0x1F, 0xE0,
0x03, 0xFC, 0x3F, 0x80, 0x03, 0xF8, 0xFF, 0x00, 0x07, 0xF9, 0xFC, 0x00,
0x07, 0xF7, 0xF8, 0x00, 0x07, 0xFF, 0xE0, 0x00, 0x0F, 0xFF, 0x80, 0x00,
0x0F, 0xFF, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00,
0x3F, 0xE0, 0x00, 0x00, 0xFF, 0xE0, 0x00, 0x03, 0xFF, 0xE0, 0x00, 0x07,
0xFF, 0xC0, 0x00, 0x1F, 0xFF, 0xC0, 0x00, 0x3F, 0xBF, 0xC0, 0x00, 0xFF,
0x3F, 0x80, 0x03, 0xFC, 0x7F, 0x80, 0x07, 0xF0, 0x7F, 0x80, 0x1F, 0xE0,
0xFF, 0x00, 0x7F, 0x80, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x03, 0xFC, 0x01,
0xFE, 0x0F, 0xF0, 0x01, 0xFE, 0x1F, 0xE0, 0x03, 0xFE, 0x7F, 0x80, 0x03,
0xFD, 0xFE, 0x00, 0x03, 0xFC, 0xFF, 0x00, 0x03, 0xFB, 0xF8, 0x00, 0x3F,
0xDF, 0xE0, 0x01, 0xFC, 0x7F, 0x00, 0x1F, 0xE3, 0xFC, 0x00, 0xFE, 0x0F,
0xE0, 0x0F, 0xF0, 0x7F, 0x80, 0x7F, 0x01, 0xFC, 0x07, 0xF8, 0x0F, 0xF0,
0x3F, 0x80, 0x3F, 0x83, 0xFC, 0x01, 0xFE, 0x1F, 0xC0, 0x07, 0xF1, 0xFC,
0x00, 0x3F, 0xCF, 0xE0, 0x00, 0xFE, 0xFE, 0x00, 0x03, 0xFF, 0xF0, 0x00,
0x1F, 0xFF, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x03, 0xFF, 0x80, 0x00, 0x0F,
0xFC, 0x00, 0x00, 0x7F, 0xC0, 0x00, 0x01, 0xFE, 0x00, 0x00, 0x0F, 0xE0,
0x00, 0x00, 0x7F, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x1F, 0xC0, 0x00,
0x00, 0xFE, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x01,
0xFC, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x03, 0xF8,
0x00, 0x00, 0x1F, 0xC0, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x7F, 0xFF, 0xFF,
0xBF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF,
0xFB, 0xFF, 0xFF, 0xF8, 0x00, 0x03, 0xFC, 0x00, 0x03, 0xFC, 0x00, 0x01,
0xFC, 0x00, 0x01, 0xFE, 0x00, 0x01, 0xFE, 0x00, 0x00, 0xFE, 0x00, 0x00,
0xFE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00,
0x7F, 0x80, 0x00, 0x7F, 0x80, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0xC0, 0x00,
0x3F, 0xC0, 0x00, 0x1F, 0xC0, 0x00, 0x1F, 0xE0, 0x00, 0x1F, 0xE0, 0x00,
0x0F, 0xE0, 0x00, 0x0F, 0xE0, 0x00, 0x0F, 0xF0, 0x00, 0x0F, 0xF0, 0x00,
0x07, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E,
0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F,
0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1,
0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xFE, 0x00, 0x0F, 0xC0, 0x01, 0xFC, 0x00,
0x3F, 0x80, 0x03, 0xF0, 0x00, 0x7F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00,
0x1F, 0xC0, 0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xF0, 0x00, 0x7E, 0x00,
0x0F, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0x80, 0x03, 0xF8, 0x00, 0x3F, 0x00,
0x07, 0xE0, 0x00, 0xFE, 0x00, 0x0F, 0xC0, 0x01, 0xFC, 0x00, 0x3F, 0x80,
0x03, 0xF0, 0x00, 0x7F, 0x00, 0x07, 0xE0, 0x00, 0xFC, 0x00, 0x1F, 0xC0,
0x01, 0xF8, 0x00, 0x3F, 0x00, 0x07, 0xF0, 0x00, 0x7E, 0x00, 0x0F, 0xE0,
0x01, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0x0F, 0xC1, 0xF8,
0x3F, 0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F,
0x07, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07,
0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F, 0x07, 0xE0,
0xFC, 0x1F, 0x83, 0xF0, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x00,
0x3C, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1F, 0x80, 0x00, 0x0F, 0xC0, 0x00,
0x0F, 0xF0, 0x00, 0x07, 0xF8, 0x00, 0x07, 0xFE, 0x00, 0x03, 0xFF, 0x00,
0x03, 0xE7, 0xC0, 0x01, 0xF3, 0xE0, 0x01, 0xF8, 0xF8, 0x00, 0xF8, 0x7C,
0x00, 0xFC, 0x1F, 0x00, 0x7C, 0x0F, 0x80, 0x3E, 0x03, 0xE0, 0x3E, 0x01,
0xF0, 0x1F, 0x00, 0x7C, 0x1F, 0x00, 0x3E, 0x0F, 0x80, 0x0F, 0x8F, 0xC0,
0x07, 0xC7, 0xC0, 0x01, 0xF7, 0xE0, 0x00, 0xF8, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x80, 0xFF, 0x03, 0xFC, 0x0F, 0xF0, 0x3F, 0x80, 0xFE,
0x01, 0xF8, 0x07, 0xE0, 0x1F, 0x01, 0xFF, 0x80, 0x1F, 0xFF, 0xC0, 0x7F,
0xFF, 0xE0, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xC1, 0xF0, 0x7F, 0x83, 0x00,
0x7F, 0x80, 0x00, 0x7F, 0x00, 0x00, 0xFE, 0x00, 0x01, 0xFC, 0x03, 0xFF,
0xF8, 0x7F, 0xFF, 0xF1, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xDF, 0xF8, 0x3F,
0xFF, 0x80, 0x7F, 0xFE, 0x00, 0xFF, 0xFC, 0x01, 0xFF, 0xF8, 0x07, 0xFF,
0xF0, 0x0F, 0xFF, 0xF0, 0x3F, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xBF,
0xFF, 0x3F, 0x3F, 0xFC, 0x7E, 0x1F, 0xF0, 0x7C, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
0x00, 0x00, 0xFE, 0x1F, 0xC0, 0xFE, 0x3F, 0xF0, 0xFE, 0xFF, 0xF8, 0xFE,
0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, 0xFF, 0x81, 0xFE, 0xFF,
0x00, 0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF,
0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF,
0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0xFF, 0xFF,
0x80, 0xFF, 0xFF, 0xE3, 0xFE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0xFE,
0xFF, 0xF8, 0xFE, 0x7F, 0xF0, 0xFC, 0x3F, 0xE0, 0x00, 0x7F, 0xC0, 0x1F,
0xFF, 0xC1, 0xFF, 0xFE, 0x3F, 0xFF, 0xE1, 0xFF, 0xFF, 0x1F, 0xFF, 0xF1,
0xFF, 0x00, 0x8F, 0xF0, 0x00, 0x7F, 0x00, 0x03, 0xF8, 0x00, 0x3F, 0xC0,
0x01, 0xFE, 0x00, 0x0F, 0xE0, 0x00, 0x7F, 0x00, 0x03, 0xF8, 0x00, 0x1F,
0xE0, 0x00, 0xFF, 0x00, 0x03, 0xF8, 0x00, 0x1F, 0xE0, 0x00, 0xFF, 0x00,
0x23, 0xFE, 0x1F, 0x1F, 0xFF, 0xF8, 0x7F, 0xFF, 0xC1, 0xFF, 0xFE, 0x07,
0xFF, 0xF0, 0x0F, 0xFE, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00,
0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x01,
0xFC, 0x7F, 0x07, 0xFE, 0x7F, 0x0F, 0xFF, 0x7F, 0x1F, 0xFF, 0xFF, 0x3F,
0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x7F, 0xC1, 0xFF, 0x7F, 0x80, 0xFF, 0x7F,
0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x3F, 0xFE,
0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xFF, 0x00, 0x3F, 0xFF,
0x00, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x80, 0xFF, 0x7F,
0xE3, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x1F, 0xFF, 0xBF, 0x0F,
0xFF, 0x3F, 0x03, 0xFC, 0x1F, 0x00, 0xFF, 0x80, 0x03, 0xFF, 0xE0, 0x0F,
0xFF, 0xF0, 0x1F, 0xFF, 0xF8, 0x1F, 0xFF, 0xFC, 0x3F, 0xC1, 0xFE, 0x7F,
0x80, 0xFE, 0x7F, 0x00, 0x7E, 0x7F, 0x00, 0x7F, 0x7F, 0x00, 0x7F, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFE, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F,
0x00, 0x00, 0x7F, 0x80, 0x02, 0x3F, 0xE0, 0x1C, 0x3F, 0xFF, 0xFC, 0x1F,
0xFF, 0xFC, 0x0F, 0xFF, 0xFC, 0x07, 0xFF, 0xFC, 0x01, 0xFF, 0xF0, 0x00,
0x7F, 0x80, 0x3F, 0xFC, 0x0F, 0xFF, 0x83, 0xFF, 0xE0, 0xFF, 0xFC, 0x1F,
0xFF, 0x83, 0xF8, 0x00, 0x7F, 0x00, 0x0F, 0xE0, 0x01, 0xFC, 0x00, 0x7F,
0xFE, 0x3F, 0xFF, 0xCF, 0xFF, 0xF9, 0xFF, 0xFF, 0x3F, 0xFF, 0xE7, 0xFF,
0xFC, 0x0F, 0xE0, 0x01, 0xFC, 0x00, 0x3F, 0x80, 0x07, 0xF0, 0x00, 0xFE,
0x00, 0x1F, 0xC0, 0x03, 0xF8, 0x00, 0x7F, 0x00, 0x0F, 0xE0, 0x01, 0xFC,
0x00, 0x3F, 0x80, 0x07, 0xF0, 0x00, 0xFE, 0x00, 0x1F, 0xC0, 0x03, 0xF8,
0x00, 0x7F, 0x00, 0x0F, 0xE0, 0x01, 0xFC, 0x00, 0x3F, 0x80, 0x07, 0xF0,
0x00, 0x01, 0xFC, 0x3F, 0x07, 0xFE, 0x3F, 0x0F, 0xFF, 0xBF, 0x1F, 0xFF,
0xBF, 0x3F, 0xFF, 0xFF, 0x3F, 0xF7, 0xFF, 0x7F, 0x80, 0xFF, 0x7F, 0x80,
0x7F, 0x7F, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00,
0x3F, 0xFE, 0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xFF, 0x00,
0x3F, 0xFF, 0x00, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x80,
0xFF, 0x7F, 0xC1, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0x1F, 0xFF,
0xFF, 0x0F, 0xFF, 0x7F, 0x03, 0xFC, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xFF, 0x30, 0x01, 0xFF, 0x3F, 0x07,
0xFE, 0x3F, 0xFF, 0xFE, 0x3F, 0xFF, 0xFC, 0x3F, 0xFF, 0xF8, 0x3F, 0xFF,
0xF0, 0x0F, 0xFF, 0x80, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFE, 0x1F,
0xE0, 0xFE, 0x7F, 0xF8, 0xFE, 0xFF, 0xFC, 0xFE, 0xFF, 0xFE, 0xFF, 0xFF,
0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x00,
0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00,
0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00,
0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00,
0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00,
0x7F, 0xFF, 0x00, 0x7F, 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0x7F, 0x7E, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0xE0, 0x1F, 0x81, 0xFE, 0x0F, 0xF0, 0x7F,
0x81, 0xFC, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x01, 0xFE, 0x0F, 0xF0,
0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE, 0x0F,
0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1, 0xFE,
0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF8, 0x3F, 0xC1,
0xFE, 0x0F, 0xF0, 0x7F, 0x83, 0xFC, 0x1F, 0xE0, 0xFF, 0x07, 0xF4, 0xFF,
0xBF, 0xFD, 0xFF, 0xCF, 0xFE, 0x7F, 0xE3, 0xFC, 0x00, 0xFE, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x1F, 0xC0, 0x00, 0x0F, 0xE0, 0x00,
0x07, 0xF0, 0x00, 0x03, 0xF8, 0x00, 0x01, 0xFC, 0x00, 0x00, 0xFE, 0x00,
0x00, 0x7F, 0x00, 0x00, 0x3F, 0x80, 0x3F, 0xFF, 0xC0, 0x1F, 0xCF, 0xE0,
0x1F, 0xE7, 0xF0, 0x1F, 0xE3, 0xF8, 0x1F, 0xE1, 0xFC, 0x1F, 0xE0, 0xFE,
0x1F, 0xE0, 0x7F, 0x1F, 0xE0, 0x3F, 0x9F, 0xE0, 0x1F, 0xDF, 0xE0, 0x0F,
0xCF, 0xE0, 0x07, 0xEF, 0xE0, 0x03, 0xFF, 0xF8, 0x01, 0xFF, 0xFE, 0x00,
0xFF, 0xFF, 0x80, 0x7F, 0xFF, 0xC0, 0x3F, 0xEF, 0xF0, 0x1F, 0xC3, 0xFC,
0x0F, 0xE0, 0xFF, 0x07, 0xF0, 0x7F, 0x83, 0xF8, 0x1F, 0xE1, 0xFC, 0x07,
0xF8, 0xFE, 0x01, 0xFE, 0x7F, 0x00, 0xFF, 0x3F, 0x80, 0x3F, 0xDF, 0xC0,
0x0F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFC, 0x1F, 0xE0, 0x1F, 0xE1, 0xF8, 0xFF, 0xF0, 0xFF, 0xF3,
0xFB, 0xFF, 0xF3, 0xFF, 0xF7, 0xFF, 0xFF, 0xEF, 0xFF, 0xEF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0x7F, 0xE0, 0x7F,
0xFF, 0xC0, 0x7F, 0xC0, 0x7F, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFE, 0x01,
0xFE, 0x01, 0xFF, 0xFC, 0x03, 0xFC, 0x03, 0xFF, 0xF8, 0x07, 0xF8, 0x07,
0xFF, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF, 0xE0, 0x1F, 0xE0, 0x1F, 0xFF, 0xC0,
0x3F, 0xC0, 0x3F, 0xFF, 0x80, 0x7F, 0x80, 0x7F, 0xFF, 0x00, 0xFF, 0x00,
0xFF, 0xFE, 0x01, 0xFE, 0x01, 0xFF, 0xFC, 0x03, 0xFC, 0x03, 0xFF, 0xF8,
0x07, 0xF8, 0x07, 0xFF, 0xF0, 0x0F, 0xF0, 0x0F, 0xFF, 0xE0, 0x1F, 0xE0,
0x1F, 0xFF, 0xC0, 0x3F, 0xC0, 0x3F, 0xFF, 0x80, 0x7F, 0x80, 0x7F, 0xFF,
0x00, 0xFF, 0x00, 0xFF, 0xFE, 0x01, 0xFE, 0x01, 0xFC, 0xFC, 0x1F, 0xE0,
0xFC, 0x7F, 0xF8, 0xFE, 0xFF, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE,
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0x80, 0xFF, 0xFF, 0x00, 0x7F,
0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F,
0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F,
0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F,
0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F,
0xFF, 0x00, 0x7F, 0x00, 0xFF, 0x80, 0x01, 0xFF, 0xF0, 0x03, 0xFF, 0xFE,
0x03, 0xFF, 0xFF, 0x81, 0xFF, 0xFF, 0xE1, 0xFF, 0x1F, 0xF1, 0xFE, 0x03,
0xFC, 0xFF, 0x00, 0xFE, 0x7F, 0x00, 0x7F, 0xBF, 0x80, 0x3F, 0xFF, 0xC0,
0x0F, 0xFF, 0xE0, 0x07, 0xFF, 0xE0, 0x03, 0xFF, 0xF0, 0x01, 0xFF, 0xF8,
0x00, 0xFF, 0xFE, 0x00, 0x7F, 0xFF, 0x00, 0x3F, 0xBF, 0x80, 0x3F, 0xDF,
0xC0, 0x1F, 0xCF, 0xF0, 0x1F, 0xE3, 0xFC, 0x1F, 0xF0, 0xFF, 0xFF, 0xF0,
0x7F, 0xFF, 0xF0, 0x1F, 0xFF, 0xF0, 0x03, 0xFF, 0xF0, 0x00, 0xFF, 0xE0,
0x00, 0xFC, 0x1F, 0xC0, 0xFE, 0x7F, 0xF0, 0xFE, 0xFF, 0xF8, 0xFE, 0xFF,
0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFE, 0xFF, 0x81, 0xFF, 0xFF, 0x80,
0xFF, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00,
0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00,
0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00, 0xFF, 0xFF, 0x81,
0xFF, 0xFF, 0xE3, 0xFE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFC, 0xFE, 0xFF,
0xF8, 0xFE, 0x7F, 0xF0, 0xFE, 0x3F, 0xE0, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00,
0x00, 0xFF, 0x00, 0x00, 0x01, 0xFC, 0x3F, 0x07, 0xFE, 0x3F, 0x0F, 0xFF,
0x3F, 0x1F, 0xFF, 0xBF, 0x3F, 0xFF, 0xFF, 0x3F, 0xE7, 0xFF, 0x7F, 0x80,
0xFF, 0x7F, 0x80, 0x7F, 0x7F, 0x00, 0x7F, 0xFF, 0x00, 0x7F, 0xFF, 0x00,
0x7F, 0xFF, 0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xFE, 0x00, 0x3F, 0xFE, 0x00,
0x3F, 0xFF, 0x00, 0x3F, 0xFF, 0x00, 0x7F, 0x7F, 0x00, 0x7F, 0x7F, 0x00,
0x7F, 0x7F, 0x80, 0xFF, 0x7F, 0xE1, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0xFF,
0xFF, 0x1F, 0xFF, 0xFF, 0x0F, 0xFF, 0x7F, 0x03, 0xFC, 0x7F, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00,
0x7F, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x7F, 0xFC, 0x0F, 0xFE, 0x1F, 0xFF,
0x1F, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80,
0xFF, 0x80, 0x7F, 0x80, 0x3F, 0xC0, 0x1F, 0xE0, 0x0F, 0xF0, 0x07, 0xF8,
0x03, 0xFC, 0x01, 0xFE, 0x00, 0xFF, 0x00, 0x7F, 0x80, 0x3F, 0xC0, 0x1F,
0xE0, 0x0F, 0xF0, 0x07, 0xF8, 0x03, 0xFC, 0x01, 0xFE, 0x00, 0xFF, 0x00,
0x7F, 0x80, 0x00, 0x03, 0xFE, 0x01, 0xFF, 0xFE, 0x3F, 0xFF, 0xE7, 0xFF,
0xFE, 0x7F, 0xFF, 0xCF, 0xF0, 0x3C, 0xFE, 0x00, 0x4F, 0xE0, 0x00, 0xFF,
0x00, 0x0F, 0xFC, 0x00, 0x7F, 0xF8, 0x03, 0xFF, 0xE0, 0x3F, 0xFF, 0x80,
0xFF, 0xFC, 0x03, 0xFF, 0xE0, 0x0F, 0xFE, 0x00, 0x1F, 0xE0, 0x00, 0xFF,
0x00, 0x07, 0xF8, 0x00, 0x7F, 0xF0, 0x0F, 0xEF, 0xFF, 0xFE, 0xFF, 0xFF,
0xEF, 0xFF, 0xFC, 0xFF, 0xFF, 0x83, 0xFF, 0xE0, 0x03, 0xC0, 0x01, 0xF0,
0x00, 0x7C, 0x00, 0x1F, 0x00, 0x0F, 0xC0, 0x03, 0xFF, 0xF3, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x7F, 0x00, 0x1F,
0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x07, 0xF0,
0x01, 0xFC, 0x00, 0x7F, 0x00, 0x1F, 0xC0, 0x07, 0xF0, 0x01, 0xFC, 0x00,
0x7F, 0x00, 0x1F, 0xE0, 0x03, 0xFC, 0x30, 0xFF, 0xFC, 0x3F, 0xFF, 0x07,
0xFF, 0xC0, 0xFF, 0xF0, 0x1F, 0xF8, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F,
0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F,
0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F,
0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F,
0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFE, 0x00, 0x7F, 0xFF, 0x00, 0xFF,
0xFF, 0x00, 0xFF, 0xFF, 0x01, 0xFF, 0x7F, 0xC7, 0xFF, 0x7F, 0xFF, 0xFF,
0x7F, 0xFF, 0xFF, 0x3F, 0xFF, 0xBF, 0x1F, 0xFF, 0x3F, 0x07, 0xFC, 0x3F,
0xFE, 0x00, 0x1F, 0xFF, 0xE0, 0x03, 0xF9, 0xFC, 0x00, 0x7F, 0x3F, 0x80,
0x1F, 0xE3, 0xF8, 0x03, 0xF8, 0x7F, 0x00, 0x7F, 0x0F, 0xE0, 0x1F, 0xE0,
0xFE, 0x03, 0xF8, 0x1F, 0xC0, 0x7F, 0x03, 0xF8, 0x1F, 0xC0, 0x3F, 0x83,
0xF8, 0x07, 0xF0, 0x7F, 0x00, 0x7E, 0x1F, 0xC0, 0x0F, 0xE3, 0xF8, 0x01,
0xFC, 0x7E, 0x00, 0x1F, 0x8F, 0xC0, 0x03, 0xFB, 0xF8, 0x00, 0x3F, 0x7E,
0x00, 0x07, 0xEF, 0xC0, 0x00, 0xFF, 0xF8, 0x00, 0x0F, 0xFE, 0x00, 0x01,
0xFF, 0xC0, 0x00, 0x3F, 0xF0, 0x00, 0x03, 0xFE, 0x00, 0x00, 0x7F, 0xC0,
0x00, 0x07, 0xF0, 0x00, 0xFE, 0x00, 0xFF, 0x00, 0x7F, 0x7F, 0x00, 0xFF,
0x00, 0x7E, 0x7F, 0x00, 0xFF, 0x80, 0xFE, 0x7F, 0x01, 0xFF, 0x80, 0xFE,
0x3F, 0x81, 0xFF, 0x80, 0xFE, 0x3F, 0x81, 0xFF, 0x80, 0xFC, 0x3F, 0x81,
0xFF, 0xC1, 0xFC, 0x1F, 0x83, 0xF7, 0xC1, 0xFC, 0x1F, 0xC3, 0xE7, 0xC1,
0xF8, 0x1F, 0xC3, 0xE7, 0xC3, 0xF8, 0x1F, 0xC3, 0xE7, 0xC3, 0xF8, 0x0F,
0xC7, 0xE3, 0xE3, 0xF8, 0x0F, 0xE7, 0xC3, 0xE3, 0xF0, 0x0F, 0xE7, 0xC3,
0xE7, 0xF0, 0x0F, 0xE7, 0xC3, 0xE7, 0xF0, 0x07, 0xE7, 0xC3, 0xF7, 0xE0,
0x07, 0xEF, 0x81, 0xF7, 0xE0, 0x07, 0xEF, 0x81, 0xF7, 0xE0, 0x03, 0xFF,
0x81, 0xF7, 0xE0, 0x03, 0xFF, 0x81, 0xFF, 0xC0, 0x03, 0xFF, 0x80, 0xFF,
0xC0, 0x03, 0xFF, 0x00, 0xFF, 0xC0, 0x01, 0xFF, 0x00, 0xFF, 0x80, 0x01,
0xFF, 0x00, 0xFF, 0x80, 0x01, 0xFF, 0x00, 0xFF, 0x80, 0x00, 0xFE, 0x00,
0x7F, 0x80, 0x7F, 0x80, 0x1F, 0xEF, 0xF0, 0x07, 0xF8, 0xFF, 0x01, 0xFE,
0x0F, 0xF0, 0x3F, 0x81, 0xFE, 0x0F, 0xF0, 0x1F, 0xE3, 0xFC, 0x01, 0xFC,
0x7F, 0x00, 0x3F, 0xDF, 0xE0, 0x03, 0xFF, 0xF8, 0x00, 0x3F, 0xFE, 0x00,
0x07, 0xFF, 0xC0, 0x00, 0x7F, 0xF0, 0x00, 0x07, 0xFC, 0x00, 0x00, 0xFF,
0xC0, 0x00, 0x3F, 0xF8, 0x00, 0x0F, 0xFF, 0x80, 0x01, 0xFF, 0xF8, 0x00,
0x7F, 0x7F, 0x00, 0x1F, 0xEF, 0xF0, 0x03, 0xF8, 0xFF, 0x00, 0xFF, 0x0F,
0xE0, 0x3F, 0xC1, 0xFE, 0x07, 0xF0, 0x1F, 0xE1, 0xFE, 0x03, 0xFC, 0x7F,
0x80, 0x3F, 0xDF, 0xE0, 0x03, 0xFC, 0xFF, 0x00, 0x1F, 0xFF, 0xE0, 0x03,
0xF9, 0xFC, 0x00, 0x7F, 0x3F, 0xC0, 0x1F, 0xE3, 0xF8, 0x03, 0xF8, 0x7F,
0x00, 0x7F, 0x0F, 0xE0, 0x1F, 0xE0, 0xFE, 0x03, 0xF8, 0x1F, 0xC0, 0x7F,
0x01, 0xFC, 0x0F, 0xC0, 0x3F, 0x83, 0xF8, 0x07, 0xF0, 0x7F, 0x00, 0x7E,
0x0F, 0xC0, 0x0F, 0xE3, 0xF8, 0x00, 0xFC, 0x7F, 0x00, 0x1F, 0x8F, 0xC0,
0x03, 0xFB, 0xF8, 0x00, 0x3F, 0x7E, 0x00, 0x07, 0xEF, 0xC0, 0x00, 0x7F,
0xF8, 0x00, 0x0F, 0xFE, 0x00, 0x01, 0xFF, 0xC0, 0x00, 0x1F, 0xF8, 0x00,
0x03, 0xFE, 0x00, 0x00, 0x3F, 0xC0, 0x00, 0x07, 0xF0, 0x00, 0x00, 0xFE,
0x00, 0x00, 0x1F, 0xC0, 0x00, 0x07, 0xF0, 0x00, 0x01, 0xFE, 0x00, 0x00,
0x3F, 0x80, 0x01, 0x3F, 0xF0, 0x00, 0x3F, 0xFC, 0x00, 0x07, 0xFF, 0x80,
0x00, 0xFF, 0xE0, 0x00, 0x1F, 0xF8, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x7F,
0xFF, 0xF3, 0xFF, 0xFF, 0x9F, 0xFF, 0xFC, 0xFF, 0xFF, 0xE7, 0xFF, 0xFF,
0x3F, 0xFF, 0xF8, 0x00, 0x3F, 0x80, 0x03, 0xF8, 0x00, 0x3F, 0xC0, 0x03,
0xFC, 0x00, 0x1F, 0xC0, 0x01, 0xFC, 0x00, 0x1F, 0xE0, 0x00, 0xFE, 0x00,
0x0F, 0xE0, 0x00, 0xFF, 0x00, 0x0F, 0xF0, 0x00, 0x7F, 0x00, 0x07, 0xF0,
0x00, 0x7F, 0x80, 0x07, 0xF8, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x03, 0x00, 0xFF,
0x01, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xFF, 0x03, 0xF0, 0x03, 0xF0,
0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF0,
0x03, 0xF0, 0x07, 0xF0, 0x07, 0xF0, 0x0F, 0xE0, 0xFF, 0xE0, 0xFF, 0xC0,
0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xC0, 0xFF, 0xE0, 0x0F, 0xE0, 0x07, 0xF0,
0x07, 0xF0, 0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF0,
0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF0, 0x03, 0xF8, 0x03, 0xFF, 0x03, 0xFF,
0x03, 0xFF, 0x01, 0xFF, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
0x80, 0x00, 0xFE, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xC0,
0x1F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0,
0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xE0, 0x0F, 0xF0,
0x07, 0xFF, 0x03, 0xFF, 0x00, 0xFF, 0x01, 0xFF, 0x07, 0xFF, 0x07, 0xFF,
0x0F, 0xF0, 0x0F, 0xE0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0,
0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x0F, 0xC0, 0x1F, 0xC0,
0xFF, 0xC0, 0xFF, 0xC0, 0xFF, 0x80, 0xFF, 0x00, 0xFE, 0x00, 0x3F, 0xE0,
0x02, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF8, 0x07, 0xFF, 0xA0, 0x03, 0xFE, 0x00 };
const GFXglyph NotoSans_Bold24pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 12, 0, 0 }, // 0x20 ' '
{ 1, 8, 35, 13, 3, -33 }, // 0x21 '!'
{ 36, 17, 13, 23, 3, -33 }, // 0x22 '"'
{ 64, 28, 34, 30, 1, -33 }, // 0x23 '#'
{ 183, 23, 39, 27, 2, -35 }, // 0x24 '$'
{ 296, 40, 34, 42, 1, -33 }, // 0x25 '%'
{ 466, 33, 34, 35, 2, -33 }, // 0x26 '&'
{ 607, 7, 13, 13, 3, -33 }, // 0x27 '''
{ 619, 13, 41, 16, 2, -33 }, // 0x28 '('
{ 686, 13, 41, 16, 1, -33 }, // 0x29 ')'
{ 753, 23, 22, 25, 1, -35 }, // 0x2A '*'
{ 817, 23, 23, 27, 2, -27 }, // 0x2B '+'
{ 884, 10, 11, 13, 1, -4 }, // 0x2C ','
{ 898, 13, 6, 15, 1, -15 }, // 0x2D '-'
{ 908, 8, 8, 13, 3, -6 }, // 0x2E '.'
{ 916, 19, 34, 20, 0, -33 }, // 0x2F '/'
{ 997, 23, 34, 27, 2, -33 }, // 0x30 '0'
{ 1095, 16, 34, 27, 3, -33 }, // 0x31 '1'
{ 1163, 23, 34, 27, 2, -33 }, // 0x32 '2'
{ 1261, 23, 34, 27, 2, -33 }, // 0x33 '3'
{ 1359, 25, 34, 27, 1, -33 }, // 0x34 '4'
{ 1466, 23, 34, 27, 2, -33 }, // 0x35 '5'
{ 1564, 23, 34, 27, 2, -33 }, // 0x36 '6'
{ 1662, 24, 34, 27, 1, -33 }, // 0x37 '7'
{ 1764, 23, 34, 27, 2, -33 }, // 0x38 '8'
{ 1862, 24, 34, 27, 1, -33 }, // 0x39 '9'
{ 1964, 8, 27, 13, 3, -25 }, // 0x3A ':'
{ 1991, 10, 32, 13, 1, -25 }, // 0x3B ';'
{ 2031, 23, 24, 27, 2, -28 }, // 0x3C '<'
{ 2100, 23, 14, 27, 2, -23 }, // 0x3D '='
{ 2141, 23, 24, 27, 2, -28 }, // 0x3E '>'
{ 2210, 21, 35, 22, 0, -33 }, // 0x3F '?'
{ 2302, 38, 38, 42, 2, -33 }, // 0x40 '@'
{ 2483, 33, 34, 33, 0, -33 }, // 0x41 'A'
{ 2624, 25, 34, 31, 4, -33 }, // 0x42 'B'
{ 2731, 26, 34, 30, 3, -33 }, // 0x43 'C'
{ 2842, 28, 34, 34, 4, -33 }, // 0x44 'D'
{ 2961, 20, 34, 26, 4, -33 }, // 0x45 'E'
{ 3046, 19, 34, 26, 4, -33 }, // 0x46 'F'
{ 3127, 27, 34, 34, 3, -33 }, // 0x47 'G'
{ 3242, 28, 34, 36, 4, -33 }, // 0x48 'H'
{ 3361, 16, 34, 18, 1, -33 }, // 0x49 'I'
{ 3429, 14, 44, 16, -3, -33 }, // 0x4A 'J'
{ 3506, 27, 34, 31, 4, -33 }, // 0x4B 'K'
{ 3621, 21, 34, 26, 4, -33 }, // 0x4C 'L'
{ 3711, 36, 34, 44, 4, -33 }, // 0x4D 'M'
{ 3864, 30, 34, 38, 4, -33 }, // 0x4E 'N'
{ 3992, 32, 34, 37, 3, -33 }, // 0x4F 'O'
{ 4128, 23, 34, 29, 4, -33 }, // 0x50 'P'
{ 4226, 32, 42, 37, 3, -33 }, // 0x51 'Q'
{ 4394, 27, 34, 31, 4, -33 }, // 0x52 'R'
{ 4509, 22, 34, 26, 2, -33 }, // 0x53 'S'
{ 4603, 25, 34, 27, 1, -33 }, // 0x54 'T'
{ 4710, 28, 34, 36, 4, -33 }, // 0x55 'U'
{ 4829, 31, 34, 31, 0, -33 }, // 0x56 'V'
{ 4961, 45, 34, 45, 0, -33 }, // 0x57 'W'
{ 5153, 31, 34, 31, 0, -33 }, // 0x58 'X'
{ 5285, 29, 34, 29, 0, -33 }, // 0x59 'Y'
{ 5409, 25, 34, 27, 1, -33 }, // 0x5A 'Z'
{ 5516, 11, 41, 16, 3, -33 }, // 0x5B '['
{ 5573, 19, 34, 20, 0, -33 }, // 0x5C '\'
{ 5654, 11, 41, 16, 1, -33 }, // 0x5D ']'
{ 5711, 25, 22, 27, 1, -33 }, // 0x5E '^'
{ 5780, 19, 3, 19, 0, 5 }, // 0x5F '_'
{ 5788, 13, 8, 17, 2, -35 }, // 0x60 '`'
{ 5801, 23, 26, 28, 2, -25 }, // 0x61 'a'
{ 5876, 24, 36, 30, 3, -35 }, // 0x62 'b'
{ 5984, 21, 26, 24, 2, -25 }, // 0x63 'c'
{ 6053, 24, 36, 30, 2, -35 }, // 0x64 'd'
{ 6161, 24, 26, 28, 2, -25 }, // 0x65 'e'
{ 6239, 19, 36, 18, 1, -35 }, // 0x66 'f'
{ 6325, 24, 37, 30, 2, -25 }, // 0x67 'g'
{ 6436, 24, 36, 31, 3, -35 }, // 0x68 'h'
{ 6544, 8, 36, 14, 3, -35 }, // 0x69 'i'
{ 6580, 13, 47, 14, -2, -35 }, // 0x6A 'j'
{ 6657, 25, 36, 29, 4, -35 }, // 0x6B 'k'
{ 6770, 8, 36, 14, 3, -35 }, // 0x6C 'l'
{ 6806, 39, 26, 46, 3, -25 }, // 0x6D 'm'
{ 6933, 24, 26, 31, 3, -25 }, // 0x6E 'n'
{ 7011, 25, 26, 29, 2, -25 }, // 0x6F 'o'
{ 7093, 24, 37, 30, 3, -25 }, // 0x70 'p'
{ 7204, 24, 37, 30, 2, -25 }, // 0x71 'q'
{ 7315, 17, 26, 21, 3, -25 }, // 0x72 'r'
{ 7371, 20, 26, 24, 2, -25 }, // 0x73 's'
{ 7436, 18, 31, 20, 1, -30 }, // 0x74 't'
{ 7506, 24, 26, 31, 3, -25 }, // 0x75 'u'
{ 7584, 27, 26, 27, 0, -25 }, // 0x76 'v'
{ 7672, 40, 26, 40, 0, -25 }, // 0x77 'w'
{ 7802, 27, 26, 27, 0, -25 }, // 0x78 'x'
{ 7890, 27, 37, 27, 0, -25 }, // 0x79 'y'
{ 8015, 21, 26, 23, 1, -25 }, // 0x7A 'z'
{ 8084, 16, 41, 19, 1, -33 }, // 0x7B '{'
{ 8166, 5, 47, 26, 10, -35 }, // 0x7C '|'
{ 8196, 16, 41, 19, 2, -33 }, // 0x7D '}'
{ 8278, 23, 7, 27, 2, -19 } }; // 0x7E '~'
const GFXfont NotoSans_Bold24pt7b PROGMEM = {
(uint8_t *)NotoSans_Bold24pt7bBitmaps,
(GFXglyph *)NotoSans_Bold24pt7bGlyphs,
0x20, 0x7E, 64 };
// Approx. 8971 bytes
#endif // NOTOSANSBOLD24PT7B_H
@@ -0,0 +1,171 @@
#ifndef NOTOSANSBOLD7PT7B_H
#define NOTOSANSBOLD7PT7B_H
const uint8_t NotoSans_Bold7pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFC, 0xF0, 0xDE, 0xF7, 0xA0, 0x1A, 0x09, 0x04, 0x8F, 0xF3,
0x61, 0xA3, 0xFC, 0x48, 0x2C, 0x36, 0x00, 0x23, 0xFE, 0x78, 0xF0, 0xF2,
0xEB, 0xFC, 0x82, 0x00, 0x70, 0xC5, 0x98, 0xD9, 0x0D, 0xB0, 0x5A, 0xE7,
0x6B, 0x05, 0xB0, 0xDB, 0x19, 0xB1, 0x8E, 0x78, 0x3E, 0x33, 0x0F, 0x87,
0x87, 0xCF, 0x7D, 0x9E, 0xFF, 0x3F, 0xC0, 0xFF, 0x6B, 0x69, 0x24, 0xDB,
0x30, 0xC6, 0x23, 0x33, 0x33, 0x33, 0x6E, 0x19, 0x27, 0xF9, 0xC2, 0xCD,
0x80, 0x30, 0xCF, 0xFF, 0x30, 0xC0, 0x6D, 0x60, 0xFF, 0xF0, 0x0C, 0x61,
0x84, 0x30, 0xC6, 0x18, 0x63, 0x00, 0x3C, 0xFD, 0x9B, 0x36, 0x7C, 0xD9,
0xB3, 0x7E, 0x78, 0x1B, 0xFF, 0x31, 0x8C, 0x63, 0x18, 0xC0, 0x7B, 0xF8,
0xC3, 0x1C, 0x63, 0x18, 0xFF, 0xF0, 0x7B, 0xF0, 0xC3, 0x79, 0xF0, 0xC3,
0xFF, 0xE0, 0x0C, 0x0C, 0x1C, 0x3C, 0x2C, 0x6C, 0xFF, 0xFF, 0x0C, 0x0C,
0xFF, 0xFC, 0x30, 0xFA, 0x70, 0xC3, 0xFF, 0xE0, 0x1E, 0x7D, 0x83, 0x05,
0xFC, 0xD9, 0xB3, 0x7E, 0x78, 0xFF, 0xFC, 0x18, 0x70, 0xC1, 0x86, 0x0C,
0x30, 0x60, 0x3C, 0xFD, 0x9B, 0x33, 0xCF, 0x99, 0xE3, 0x66, 0xF8, 0x38,
0xFD, 0x9E, 0x36, 0x6F, 0xCD, 0x83, 0x5C, 0xF0, 0xFC, 0x0F, 0x6D, 0x80,
0x1B, 0x58, 0x04, 0x33, 0xB8, 0xC1, 0xE0, 0xC1, 0xFF, 0xF0, 0x3F, 0x83,
0x07, 0x07, 0x1D, 0xCC, 0x20, 0x7B, 0xF0, 0xC3, 0x18, 0xC3, 0x00, 0x30,
0xC0, 0x1F, 0x06, 0x31, 0x03, 0x6F, 0xA9, 0x37, 0x66, 0xEC, 0xD4, 0xFE,
0xC0, 0x0C, 0x20, 0xFC, 0x00, 0x1C, 0x0E, 0x07, 0x86, 0xC3, 0x31, 0x99,
0xFC, 0xFF, 0x61, 0xE0, 0xC0, 0xFD, 0xFF, 0x1E, 0x3F, 0xDF, 0xF1, 0xE3,
0xFF, 0xF8, 0x3E, 0xFF, 0x86, 0x0C, 0x18, 0x30, 0x70, 0x7E, 0x7C, 0xF8,
0xFE, 0xC7, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0xFE, 0xFC, 0xFF, 0xFC, 0x30,
0xFF, 0xFC, 0x30, 0xFF, 0xF0, 0xFF, 0xFC, 0x30, 0xFF, 0xFC, 0x30, 0xC3,
0x00, 0x1E, 0x7F, 0xE0, 0xC0, 0xCF, 0xCF, 0xC3, 0xE3, 0x7F, 0x3F, 0xC3,
0xC3, 0xC3, 0xC3, 0xFF, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0xFB, 0xCC, 0x63,
0x18, 0xC6, 0x77, 0xC0, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3F, 0xE0, 0xC3,
0xC6, 0xCC, 0xD8, 0xF8, 0xF8, 0xCC, 0xCE, 0xC6, 0xC7, 0xC3, 0x0C, 0x30,
0xC3, 0x0C, 0x30, 0xFF, 0xF0, 0xE0, 0xFC, 0x3F, 0xC7, 0xF8, 0xBD, 0x37,
0xB6, 0xF6, 0x9E, 0x73, 0xCE, 0x79, 0x8C, 0xE1, 0xF8, 0xFC, 0x7B, 0x3D,
0x9E, 0x6F, 0x37, 0x8F, 0xC7, 0xE1, 0xC0, 0x3E, 0x3F, 0xB8, 0xF8, 0x3C,
0x1E, 0x0F, 0x07, 0xC7, 0x7F, 0x1F, 0x00, 0xF9, 0xFB, 0x1E, 0x3C, 0xFF,
0xBC, 0x60, 0xC1, 0x80, 0x3E, 0x3F, 0xB8, 0xF8, 0x3C, 0x1E, 0x0F, 0x07,
0xC7, 0x7F, 0x1F, 0x01, 0x80, 0x70, 0xF8, 0xFE, 0xC6, 0xC6, 0xCE, 0xFC,
0xCC, 0xCC, 0xC6, 0xC7, 0x7B, 0xFC, 0x30, 0xF0, 0xE1, 0xC3, 0xFF, 0xE0,
0xFF, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xC3, 0xC3,
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x7F, 0x3E, 0xC1, 0xE1, 0x98, 0xCC,
0x66, 0x61, 0xB0, 0xD8, 0x68, 0x1C, 0x0E, 0x00, 0xC3, 0x1E, 0x38, 0xD9,
0xC6, 0xCA, 0x66, 0x5B, 0x36, 0xD8, 0xB2, 0xC7, 0x14, 0x38, 0xE1, 0xC7,
0x00, 0xE3, 0xB1, 0x8D, 0x87, 0xC1, 0xC0, 0xE0, 0xF8, 0x6C, 0x63, 0x71,
0xC0, 0xC3, 0xB1, 0x99, 0x86, 0xC3, 0xC0, 0xE0, 0x60, 0x30, 0x18, 0x0C,
0x00, 0xFE, 0xFE, 0x06, 0x0C, 0x18, 0x18, 0x30, 0x60, 0xFF, 0xFF, 0xFF,
0x6D, 0xB6, 0xDB, 0x70, 0xC1, 0x06, 0x18, 0x30, 0xC3, 0x06, 0x18, 0x30,
0xFF, 0x33, 0x33, 0x33, 0x33, 0x3F, 0x10, 0x18, 0x38, 0x2C, 0x64, 0x46,
0xC3, 0xFC, 0xCC, 0x80, 0x33, 0xF0, 0xCF, 0xFF, 0x3D, 0xFD, 0xC1, 0x83,
0x67, 0xEC, 0x78, 0xF1, 0xE3, 0xFF, 0xF8, 0x39, 0xFC, 0x30, 0xC3, 0x0F,
0x9E, 0x06, 0x0C, 0x9F, 0xFC, 0xF8, 0xF1, 0xE3, 0xFE, 0xEC, 0x30, 0xFB,
0x37, 0xFF, 0xF8, 0x39, 0x3E, 0x3D, 0xC6, 0x3E, 0x61, 0x86, 0x18, 0x61,
0x80, 0x21, 0xFF, 0x3E, 0x3C, 0x78, 0xFF, 0xBB, 0x07, 0x1B, 0xF0, 0xC1,
0x83, 0x67, 0xFE, 0x78, 0xF1, 0xE3, 0xC7, 0x8C, 0xD3, 0xFF, 0xF0, 0x31,
0x03, 0x33, 0x33, 0x33, 0x3B, 0xF0, 0xC0, 0xC0, 0xC2, 0xCC, 0xDC, 0xF8,
0xF8, 0xDC, 0xCC, 0xC7, 0xFF, 0xFF, 0xF0, 0x18, 0xDF, 0xFF, 0x39, 0xE3,
0x3C, 0x67, 0x8C, 0xF1, 0x9E, 0x33, 0x19, 0xFF, 0x9E, 0x3C, 0x78, 0xF1,
0xE3, 0x31, 0xFB, 0x3E, 0x3C, 0x78, 0xFB, 0x3C, 0x19, 0xFB, 0x1E, 0x3C,
0x78, 0xFF, 0xFE, 0xC1, 0x83, 0x00, 0x21, 0xFF, 0x3E, 0x3C, 0x78, 0xFF,
0xBB, 0x06, 0x0C, 0x18, 0x1F, 0xF9, 0x8C, 0x63, 0x18, 0x77, 0xF1, 0xC7,
0x8E, 0x7F, 0x21, 0x8F, 0x98, 0x61, 0x86, 0x1F, 0x3C, 0xC7, 0x8F, 0x1E,
0x3C, 0x7F, 0xDF, 0x80, 0xC7, 0x66, 0x66, 0x2C, 0x3C, 0x3C, 0x18, 0xC6,
0x76, 0xE6, 0x6F, 0x66, 0xB4, 0x29, 0xC3, 0x9C, 0x39, 0xC0, 0xE7, 0x3C,
0x3C, 0x3C, 0x3C, 0x66, 0xE7, 0xC7, 0x66, 0x66, 0x2C, 0x3C, 0x3C, 0x18,
0x18, 0x30, 0xF0, 0x7C, 0x31, 0x8C, 0x71, 0xFF, 0xC0, 0x19, 0xCC, 0x63,
0x73, 0x86, 0x31, 0x8C, 0x70, 0xFF, 0xFF, 0xFF, 0xC0, 0xCC, 0x44, 0x67,
0x76, 0x44, 0xCC, 0xE7, 0xF0 };
const GFXglyph NotoSans_Bold7pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 4, 0, 0 }, // 0x20 ' '
{ 1, 2, 10, 4, 1, -9 }, // 0x21 '!'
{ 4, 5, 4, 7, 1, -9 }, // 0x22 '"'
{ 7, 9, 10, 9, 0, -9 }, // 0x23 '#'
{ 19, 6, 11, 8, 1, -9 }, // 0x24 '$'
{ 28, 12, 10, 12, 0, -9 }, // 0x25 '%'
{ 43, 9, 10, 10, 1, -9 }, // 0x26 '&'
{ 55, 2, 4, 4, 1, -9 }, // 0x27 '''
{ 56, 3, 12, 5, 1, -9 }, // 0x28 '('
{ 61, 4, 12, 5, 0, -9 }, // 0x29 ')'
{ 67, 7, 6, 7, 0, -9 }, // 0x2A '*'
{ 73, 6, 6, 8, 1, -7 }, // 0x2B '+'
{ 78, 3, 4, 4, 0, -1 }, // 0x2C ','
{ 80, 4, 2, 4, 0, -4 }, // 0x2D '-'
{ 81, 2, 2, 4, 1, -1 }, // 0x2E '.'
{ 82, 6, 10, 6, 0, -9 }, // 0x2F '/'
{ 90, 7, 10, 8, 0, -9 }, // 0x30 '0'
{ 99, 5, 10, 8, 1, -9 }, // 0x31 '1'
{ 106, 6, 10, 8, 1, -9 }, // 0x32 '2'
{ 114, 6, 10, 8, 1, -9 }, // 0x33 '3'
{ 122, 8, 10, 8, 0, -9 }, // 0x34 '4'
{ 132, 6, 10, 8, 1, -9 }, // 0x35 '5'
{ 140, 7, 10, 8, 0, -9 }, // 0x36 '6'
{ 149, 7, 10, 8, 0, -9 }, // 0x37 '7'
{ 158, 7, 10, 8, 0, -9 }, // 0x38 '8'
{ 167, 7, 10, 8, 0, -9 }, // 0x39 '9'
{ 176, 2, 8, 4, 1, -7 }, // 0x3A ':'
{ 178, 3, 10, 4, 0, -7 }, // 0x3B ';'
{ 182, 6, 8, 8, 1, -8 }, // 0x3C '<'
{ 188, 6, 4, 8, 1, -6 }, // 0x3D '='
{ 191, 6, 8, 8, 1, -8 }, // 0x3E '>'
{ 197, 6, 10, 7, 0, -9 }, // 0x3F '?'
{ 205, 11, 11, 12, 1, -9 }, // 0x40 '@'
{ 221, 9, 10, 9, 0, -9 }, // 0x41 'A'
{ 233, 7, 10, 9, 1, -9 }, // 0x42 'B'
{ 242, 7, 10, 9, 1, -9 }, // 0x43 'C'
{ 251, 8, 10, 10, 1, -9 }, // 0x44 'D'
{ 261, 6, 10, 8, 1, -9 }, // 0x45 'E'
{ 269, 6, 10, 8, 1, -9 }, // 0x46 'F'
{ 277, 8, 10, 10, 1, -9 }, // 0x47 'G'
{ 287, 8, 10, 10, 1, -9 }, // 0x48 'H'
{ 297, 5, 10, 5, 0, -9 }, // 0x49 'I'
{ 304, 4, 13, 5, -1, -9 }, // 0x4A 'J'
{ 311, 8, 10, 9, 1, -9 }, // 0x4B 'K'
{ 321, 6, 10, 8, 1, -9 }, // 0x4C 'L'
{ 329, 11, 10, 13, 1, -9 }, // 0x4D 'M'
{ 343, 9, 10, 11, 1, -9 }, // 0x4E 'N'
{ 355, 9, 10, 11, 1, -9 }, // 0x4F 'O'
{ 367, 7, 10, 9, 1, -9 }, // 0x50 'P'
{ 376, 9, 12, 11, 1, -9 }, // 0x51 'Q'
{ 390, 8, 10, 9, 1, -9 }, // 0x52 'R'
{ 400, 6, 10, 8, 1, -9 }, // 0x53 'S'
{ 408, 8, 10, 8, 0, -9 }, // 0x54 'T'
{ 418, 8, 10, 10, 1, -9 }, // 0x55 'U'
{ 428, 9, 10, 9, 0, -9 }, // 0x56 'V'
{ 440, 13, 10, 13, 0, -9 }, // 0x57 'W'
{ 457, 9, 10, 9, 0, -9 }, // 0x58 'X'
{ 469, 9, 10, 9, 0, -9 }, // 0x59 'Y'
{ 481, 8, 10, 8, 0, -9 }, // 0x5A 'Z'
{ 491, 3, 12, 5, 1, -9 }, // 0x5B '['
{ 496, 6, 10, 6, 0, -9 }, // 0x5C '\'
{ 504, 4, 12, 5, 0, -9 }, // 0x5D ']'
{ 510, 8, 7, 8, 0, -9 }, // 0x5E '^'
{ 517, 6, 1, 6, 0, 2 }, // 0x5F '_'
{ 518, 3, 3, 5, 1, -10 }, // 0x60 '`'
{ 520, 6, 8, 8, 1, -7 }, // 0x61 'a'
{ 526, 7, 10, 9, 1, -9 }, // 0x62 'b'
{ 535, 6, 8, 7, 1, -7 }, // 0x63 'c'
{ 541, 7, 10, 9, 1, -9 }, // 0x64 'd'
{ 550, 7, 8, 8, 1, -7 }, // 0x65 'e'
{ 557, 6, 10, 5, 0, -9 }, // 0x66 'f'
{ 565, 7, 11, 9, 1, -7 }, // 0x67 'g'
{ 575, 7, 10, 9, 1, -9 }, // 0x68 'h'
{ 584, 2, 10, 4, 1, -9 }, // 0x69 'i'
{ 587, 4, 13, 4, -1, -9 }, // 0x6A 'j'
{ 594, 8, 10, 9, 1, -9 }, // 0x6B 'k'
{ 604, 2, 10, 4, 1, -9 }, // 0x6C 'l'
{ 607, 11, 8, 13, 1, -7 }, // 0x6D 'm'
{ 618, 7, 8, 9, 1, -7 }, // 0x6E 'n'
{ 625, 7, 8, 9, 1, -7 }, // 0x6F 'o'
{ 632, 7, 11, 9, 1, -7 }, // 0x70 'p'
{ 642, 7, 11, 9, 1, -7 }, // 0x71 'q'
{ 652, 5, 8, 6, 1, -7 }, // 0x72 'r'
{ 657, 5, 8, 7, 1, -7 }, // 0x73 's'
{ 662, 6, 9, 6, 0, -8 }, // 0x74 't'
{ 669, 7, 7, 9, 1, -6 }, // 0x75 'u'
{ 676, 8, 7, 8, 0, -6 }, // 0x76 'v'
{ 683, 12, 7, 12, 0, -6 }, // 0x77 'w'
{ 694, 8, 7, 8, 0, -6 }, // 0x78 'x'
{ 701, 8, 10, 8, 0, -6 }, // 0x79 'y'
{ 711, 6, 7, 7, 0, -6 }, // 0x7A 'z'
{ 717, 5, 12, 5, 0, -9 }, // 0x7B '{'
{ 725, 2, 13, 8, 3, -9 }, // 0x7C '|'
{ 729, 4, 12, 5, 1, -9 }, // 0x7D '}'
{ 735, 6, 2, 8, 1, -5 } }; // 0x7E '~'
const GFXfont NotoSans_Bold7pt7b PROGMEM = {
(uint8_t *)NotoSans_Bold7pt7bBitmaps,
(GFXglyph *)NotoSans_Bold7pt7bGlyphs,
0x20, 0x7E, 19 };
// Approx. 1409 bytes
#endif // NOTOSANSBOLD7PT7B_H
@@ -0,0 +1,210 @@
#ifndef NOTOSANSBOLD9PT7B_H
#define NOTOSANSBOLD9PT7B_H
const uint8_t NotoSans_Bold9pt7bBitmaps[] PROGMEM = {
0x00, 0xFF, 0xFF, 0xFF, 0xE1, 0x7E, 0xEF, 0xBC, 0xF3, 0xCC, 0x0C, 0xC1,
0x90, 0x36, 0x04, 0xC7, 0xFE, 0xFF, 0xC6, 0x40, 0xD8, 0xFF, 0xDF, 0xF8,
0xCC, 0x19, 0x03, 0x60, 0x18, 0x7F, 0xFF, 0xF9, 0xF8, 0xF8, 0x7E, 0x1F,
0x1F, 0x9B, 0xFF, 0xFE, 0x18, 0x18, 0x70, 0x63, 0xE1, 0x8D, 0x8C, 0x36,
0x30, 0xDD, 0x83, 0x66, 0xEF, 0xB7, 0xDD, 0xDB, 0x06, 0xCC, 0x33, 0x30,
0xCE, 0xC6, 0x1F, 0x38, 0x38, 0x1C, 0x07, 0xF0, 0x77, 0x06, 0x30, 0x77,
0x03, 0xE0, 0x7C, 0x7F, 0xE6, 0xEF, 0xEC, 0x7C, 0xE3, 0xCF, 0xFE, 0x7E,
0xF0, 0xFF, 0x6C, 0x33, 0x66, 0xCC, 0xCC, 0xCC, 0xCC, 0xE6, 0x73, 0xCC,
0x66, 0x73, 0x33, 0x33, 0x33, 0x76, 0xEC, 0x18, 0x18, 0xDB, 0xFF, 0x38,
0x3C, 0x6E, 0x24, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xFF, 0x18, 0x18, 0x18,
0xFF, 0x60, 0xFF, 0xC0, 0x5F, 0x80, 0x06, 0x1C, 0x30, 0x61, 0xC3, 0x06,
0x1C, 0x30, 0xE1, 0x83, 0x0E, 0x00, 0x3C, 0x7E, 0xE7, 0xE7, 0xC3, 0xC3,
0xC3, 0xC3, 0xC3, 0xE3, 0xE7, 0x7E, 0x3C, 0x0C, 0x77, 0xFB, 0x4C, 0x30,
0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x3C, 0x7F, 0x3B, 0xC8, 0xE0, 0x70, 0x38,
0x38, 0x38, 0x38, 0x38, 0x38, 0x1F, 0xFF, 0xF8, 0x3C, 0xFE, 0xEF, 0x07,
0x07, 0x1E, 0x3C, 0x3F, 0x07, 0x03, 0x87, 0xFF, 0xFE, 0x03, 0x01, 0xC0,
0xF0, 0x3C, 0x1B, 0x0E, 0xC3, 0x31, 0x8C, 0xFF, 0xFF, 0xF0, 0x30, 0x0C,
0x03, 0x00, 0x7E, 0x7E, 0xFE, 0xE0, 0xE0, 0xFE, 0xFF, 0x07, 0x03, 0x03,
0x87, 0xFE, 0xFC, 0x0F, 0x1F, 0x9E, 0x5C, 0x0C, 0x06, 0xF3, 0xFD, 0xC6,
0xC3, 0xE1, 0xB9, 0xCF, 0xE3, 0xE0, 0xFF, 0xFF, 0xFF, 0xF8, 0x0E, 0x03,
0x01, 0xC0, 0x70, 0x38, 0x0E, 0x03, 0x01, 0xC0, 0x60, 0x38, 0x00, 0x3C,
0x7E, 0xE7, 0xE3, 0xE7, 0x7E, 0x3C, 0x7E, 0xE7, 0xC3, 0xC3, 0xFF, 0x7E,
0x38, 0x7E, 0xEF, 0xC3, 0xC3, 0xC3, 0xEF, 0xFF, 0x33, 0x07, 0x06, 0xFE,
0xF8, 0xFF, 0x80, 0x02, 0xFC, 0xFF, 0x80, 0x00, 0xFF, 0x60, 0x01, 0x07,
0x1E, 0x78, 0xE0, 0xF0, 0x3E, 0x0F, 0x01, 0xFF, 0xFF, 0x00, 0x00, 0xFF,
0x80, 0xE0, 0x78, 0x1E, 0x07, 0x0F, 0x7C, 0xF0, 0x80, 0x3C, 0xFE, 0x67,
0x03, 0x07, 0x0E, 0x1C, 0x18, 0x38, 0x00, 0x18, 0x38, 0x38, 0x03, 0x80,
0x7F, 0xC3, 0x83, 0x98, 0x06, 0x67, 0xCF, 0x33, 0x3D, 0x8C, 0xF6, 0x33,
0xD8, 0xCF, 0x3F, 0xEC, 0xF7, 0x18, 0x00, 0x78, 0x60, 0x7F, 0x80, 0x0F,
0x00, 0xF0, 0x0F, 0x01, 0xF8, 0x1D, 0x81, 0x9C, 0x39, 0xC3, 0x8C, 0x3F,
0xE7, 0xFE, 0x70, 0xE6, 0x07, 0xE0, 0x70, 0xFC, 0x3F, 0xEF, 0xFB, 0x87,
0xE1, 0xBF, 0xEF, 0xF3, 0x9E, 0xE1, 0xF8, 0x7E, 0x3F, 0xFE, 0xFF, 0x00,
0x0F, 0x0F, 0xF7, 0xF9, 0xC0, 0xE0, 0x38, 0x0E, 0x03, 0x80, 0xE0, 0x38,
0x07, 0x09, 0xFE, 0x1F, 0x80, 0xFC, 0x1F, 0xF3, 0xFF, 0x70, 0xEE, 0x0F,
0xC1, 0xF8, 0x3F, 0x07, 0xE0, 0xFC, 0x3B, 0x8F, 0x7F, 0xCF, 0xE0, 0xFF,
0xFF, 0xFE, 0x0C, 0x1F, 0xFF, 0xFF, 0xC1, 0x83, 0x07, 0xFF, 0xE0, 0xFF,
0xFF, 0xFE, 0x0C, 0x18, 0x3F, 0x7E, 0xC1, 0x83, 0x06, 0x0C, 0x00, 0x0F,
0x8F, 0xF7, 0xDD, 0xC0, 0xE0, 0x38, 0x0E, 0x7F, 0x9F, 0xE0, 0xF8, 0x37,
0x0C, 0xFF, 0x1F, 0xC0, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xFF, 0xFF,
0xFF, 0xFF, 0xC1, 0xF0, 0x7C, 0x1F, 0x07, 0xC1, 0xC0, 0xFF, 0xDC, 0xE7,
0x39, 0xCE, 0x73, 0x9D, 0xFF, 0x80, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18,
0xC6, 0x31, 0x9F, 0xFE, 0xE0, 0xC1, 0xF0, 0xEC, 0x73, 0x38, 0xDC, 0x37,
0x0F, 0xC3, 0xF0, 0xCE, 0x33, 0x8C, 0x73, 0x0E, 0xC3, 0xC0, 0xE0, 0xE0,
0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xE0,
0x7F, 0x83, 0xFC, 0x1F, 0xE1, 0xBF, 0x0D, 0xEC, 0x6F, 0x67, 0x7B, 0x33,
0xCD, 0x9E, 0x7C, 0xF3, 0xC7, 0x9E, 0x3C, 0x71, 0x80, 0xE0, 0xFE, 0x1F,
0xC3, 0xFC, 0x7F, 0x8F, 0xB9, 0xF3, 0x3E, 0x77, 0xC7, 0xF8, 0xFF, 0x0F,
0xE1, 0xFC, 0x1E, 0x0F, 0x03, 0xFC, 0x79, 0xE7, 0x0E, 0xE0, 0x7E, 0x07,
0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0x70, 0xE3, 0xFC, 0x1F, 0x80, 0xFC,
0x7F, 0xBF, 0xFC, 0x7E, 0x3F, 0x1F, 0xFF, 0xFE, 0xF8, 0x70, 0x38, 0x1C,
0x0E, 0x00, 0x0F, 0x03, 0xFC, 0x79, 0xE7, 0x0E, 0xE0, 0x7E, 0x07, 0xE0,
0x7E, 0x07, 0xE0, 0x7E, 0x07, 0x70, 0xE3, 0xFC, 0x1F, 0x80, 0x3C, 0x01,
0xE0, 0x0F, 0xFC, 0x1F, 0xE3, 0xFE, 0x71, 0xCE, 0x19, 0xC7, 0x3F, 0xC7,
0xF0, 0xE7, 0x1C, 0xE3, 0x8E, 0x70, 0xEE, 0x1E, 0x3C, 0x7F, 0xF6, 0xE0,
0xE0, 0xF0, 0x7C, 0x1E, 0x07, 0x07, 0x87, 0xFE, 0xFC, 0xFF, 0xFF, 0xFF,
0xFC, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30,
0x0C, 0x00, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x0F, 0xC1, 0xF8, 0x3F,
0x07, 0xE0, 0xEC, 0x1D, 0xC7, 0x3F, 0xE1, 0xF8, 0xE0, 0x7C, 0x1D, 0x83,
0xB8, 0x67, 0x1C, 0x63, 0x8E, 0x61, 0xCC, 0x1B, 0x83, 0x60, 0x7C, 0x07,
0x80, 0xE0, 0xE1, 0xC3, 0xF0, 0xE1, 0xD8, 0x70, 0xEC, 0x7C, 0x67, 0x36,
0x73, 0x9B, 0x38, 0xCD, 0x98, 0x6E, 0xEC, 0x36, 0x36, 0x1F, 0x1F, 0x07,
0x8F, 0x03, 0xC7, 0x81, 0xC1, 0xC0, 0xE0, 0xE7, 0x0E, 0x39, 0xC3, 0x98,
0x1F, 0x80, 0xF0, 0x0F, 0x00, 0xF0, 0x1F, 0x83, 0xB8, 0x39, 0xC7, 0x0E,
0xE0, 0xF0, 0xE0, 0xEC, 0x19, 0xC7, 0x18, 0xC3, 0xB8, 0x36, 0x07, 0xC0,
0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00, 0xE0, 0x7F, 0xDF, 0xF7, 0xF8,
0x0E, 0x07, 0x03, 0x80, 0xE0, 0x70, 0x38, 0x0C, 0x07, 0x03, 0xFF, 0xFF,
0xC0, 0xFF, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xFF, 0xE0, 0xC1, 0x83,
0x83, 0x06, 0x0E, 0x0C, 0x1C, 0x38, 0x30, 0x70, 0x60, 0xFF, 0xCE, 0x73,
0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9F, 0xFF, 0x08, 0x03, 0x01, 0xE0, 0x78,
0x33, 0x0C, 0xC6, 0x19, 0x86, 0xC0, 0xC0, 0xFE, 0xE3, 0x0E, 0x3C, 0x7F,
0x47, 0x03, 0x3F, 0xFF, 0xE3, 0xC7, 0xFF, 0x7B, 0xE0, 0x70, 0x38, 0x1D,
0xCF, 0xF7, 0x9F, 0x8F, 0xC3, 0xE1, 0xF1, 0xF8, 0xFF, 0xFE, 0xF0, 0x1F,
0x7E, 0xF2, 0xE0, 0xE0, 0xE0, 0xE0, 0xE1, 0x7E, 0x3E, 0x03, 0x81, 0xC0,
0xE7, 0x77, 0xFF, 0xBF, 0x8F, 0xC7, 0xE3, 0xF1, 0xF8, 0xEF, 0xF7, 0xD8,
0x1C, 0x3F, 0xB8, 0xDC, 0x7F, 0xFF, 0xFF, 0x81, 0xC1, 0x7F, 0x1F, 0x80,
0x3F, 0x3E, 0x30, 0x3E, 0xFE, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x39, 0xBF, 0xFD, 0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0x7F, 0xBF,
0xC0, 0xF0, 0x7F, 0xF7, 0xF0, 0xE0, 0x70, 0x38, 0x1D, 0xCF, 0xFF, 0x9F,
0x8F, 0xC3, 0xE1, 0xF0, 0xF8, 0x7C, 0x3E, 0x18, 0xFC, 0x7F, 0xFF, 0xFF,
0xFE, 0x39, 0xC0, 0x73, 0x9C, 0xE7, 0x39, 0xCE, 0x73, 0x9C, 0xFF, 0xF0,
0xE0, 0x38, 0x0E, 0x03, 0x87, 0xE3, 0xB9, 0xCE, 0xE3, 0xF0, 0xFE, 0x3F,
0x8E, 0x73, 0x8E, 0xE1, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xCE, 0x39,
0xFF, 0xFB, 0xCF, 0x3F, 0x1C, 0x7E, 0x38, 0xFC, 0x71, 0xF8, 0xE3, 0xF1,
0xC7, 0xE3, 0x8F, 0xC7, 0x1C, 0xCE, 0x7F, 0xFC, 0xFC, 0x7E, 0x1F, 0x0F,
0x87, 0xC3, 0xE1, 0xF0, 0xC0, 0x1C, 0x3F, 0xB8, 0xFC, 0x7E, 0x3F, 0x1F,
0x8F, 0xC7, 0x7F, 0x1F, 0x00, 0xCE, 0x7F, 0xBC, 0xFC, 0x7E, 0x1F, 0x0F,
0x8F, 0xC7, 0xFF, 0xFF, 0xB8, 0x1C, 0x0E, 0x07, 0x00, 0x39, 0xBF, 0xFD,
0xFC, 0x7E, 0x3F, 0x1F, 0x8F, 0xC7, 0x7F, 0xBF, 0xC0, 0xE0, 0x70, 0x38,
0x1C, 0xCF, 0xFF, 0xF7, 0x0E, 0x1C, 0x38, 0x70, 0xE1, 0xC0, 0x3D, 0xFF,
0x17, 0x0F, 0x87, 0xC3, 0xC3, 0xFF, 0xF8, 0x10, 0x60, 0xFF, 0xF3, 0x06,
0x0C, 0x18, 0x30, 0x60, 0xF8, 0xF0, 0xE3, 0xF1, 0xF8, 0xFC, 0x7E, 0x3F,
0x1F, 0x8F, 0xC7, 0x7F, 0xBE, 0xC0, 0xE1, 0xF8, 0x76, 0x19, 0xCE, 0x33,
0x0C, 0xC3, 0xF0, 0x78, 0x1E, 0x07, 0x80, 0xE3, 0x8F, 0xC7, 0x1D, 0x8B,
0x33, 0xB6, 0xE7, 0x6D, 0xC6, 0xDB, 0x0D, 0x96, 0x1A, 0x3C, 0x3C, 0x78,
0x38, 0xE0, 0xE1, 0xDC, 0xE3, 0xB8, 0xFC, 0x1E, 0x07, 0x83, 0xF0, 0xEC,
0x73, 0xB8, 0x70, 0xE1, 0xF8, 0x77, 0x19, 0xCE, 0x33, 0x8E, 0xC3, 0xF0,
0x78, 0x1E, 0x03, 0x80, 0xC0, 0x70, 0x78, 0x1C, 0x00, 0xFF, 0xFC, 0x38,
0xE3, 0x86, 0x1C, 0x70, 0xFF, 0xFC, 0x04, 0x73, 0x8E, 0x38, 0xE3, 0xBC,
0xF0, 0xE3, 0x8E, 0x38, 0xE1, 0xC3, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x83,
0x86, 0x18, 0x61, 0x87, 0x0F, 0x3D, 0xC6, 0x18, 0x61, 0x8E, 0x30, 0x61,
0xFF, 0x9F };
const GFXglyph NotoSans_Bold9pt7bGlyphs[] PROGMEM = {
{ 0, 1, 1, 5, 0, 0 }, // 0x20 ' '
{ 1, 3, 13, 5, 1, -12 }, // 0x21 '!'
{ 6, 6, 5, 8, 1, -12 }, // 0x22 '"'
{ 10, 11, 13, 11, 0, -12 }, // 0x23 '#'
{ 28, 8, 14, 10, 1, -12 }, // 0x24 '$'
{ 42, 14, 13, 16, 1, -12 }, // 0x25 '%'
{ 65, 12, 13, 13, 1, -12 }, // 0x26 '&'
{ 85, 3, 5, 5, 1, -12 }, // 0x27 '''
{ 87, 4, 16, 6, 1, -12 }, // 0x28 '('
{ 95, 4, 16, 6, 1, -12 }, // 0x29 ')'
{ 103, 8, 8, 10, 1, -12 }, // 0x2A '*'
{ 111, 8, 9, 10, 1, -10 }, // 0x2B '+'
{ 120, 3, 4, 5, 1, -1 }, // 0x2C ','
{ 122, 5, 2, 6, 0, -5 }, // 0x2D '-'
{ 124, 3, 3, 5, 1, -2 }, // 0x2E '.'
{ 126, 7, 13, 7, 0, -12 }, // 0x2F '/'
{ 138, 8, 13, 10, 1, -12 }, // 0x30 '0'
{ 151, 6, 13, 10, 1, -12 }, // 0x31 '1'
{ 161, 9, 13, 10, 1, -12 }, // 0x32 '2'
{ 176, 8, 13, 10, 1, -12 }, // 0x33 '3'
{ 189, 10, 13, 10, 0, -12 }, // 0x34 '4'
{ 206, 8, 13, 10, 1, -12 }, // 0x35 '5'
{ 219, 9, 13, 10, 1, -12 }, // 0x36 '6'
{ 234, 10, 13, 10, 0, -12 }, // 0x37 '7'
{ 251, 8, 13, 10, 1, -12 }, // 0x38 '8'
{ 264, 8, 13, 10, 1, -12 }, // 0x39 '9'
{ 277, 3, 10, 5, 1, -9 }, // 0x3A ':'
{ 281, 3, 12, 5, 1, -9 }, // 0x3B ';'
{ 286, 8, 9, 10, 1, -10 }, // 0x3C '<'
{ 295, 8, 5, 10, 1, -8 }, // 0x3D '='
{ 300, 8, 9, 10, 1, -10 }, // 0x3E '>'
{ 309, 8, 13, 8, 0, -12 }, // 0x3F '?'
{ 322, 14, 14, 16, 1, -12 }, // 0x40 '@'
{ 347, 12, 13, 12, 0, -12 }, // 0x41 'A'
{ 367, 10, 13, 12, 1, -12 }, // 0x42 'B'
{ 384, 10, 13, 11, 1, -12 }, // 0x43 'C'
{ 401, 11, 13, 13, 1, -12 }, // 0x44 'D'
{ 419, 7, 13, 10, 2, -12 }, // 0x45 'E'
{ 431, 7, 13, 10, 2, -12 }, // 0x46 'F'
{ 443, 10, 13, 13, 1, -12 }, // 0x47 'G'
{ 460, 10, 13, 13, 2, -12 }, // 0x48 'H'
{ 477, 5, 13, 7, 1, -12 }, // 0x49 'I'
{ 486, 5, 17, 6, -1, -12 }, // 0x4A 'J'
{ 497, 10, 13, 12, 2, -12 }, // 0x4B 'K'
{ 514, 8, 13, 10, 1, -12 }, // 0x4C 'L'
{ 527, 13, 13, 17, 2, -12 }, // 0x4D 'M'
{ 549, 11, 13, 14, 2, -12 }, // 0x4E 'N'
{ 567, 12, 13, 14, 1, -12 }, // 0x4F 'O'
{ 587, 9, 13, 11, 1, -12 }, // 0x50 'P'
{ 602, 12, 16, 14, 1, -12 }, // 0x51 'Q'
{ 626, 11, 13, 12, 1, -12 }, // 0x52 'R'
{ 644, 8, 13, 10, 1, -12 }, // 0x53 'S'
{ 657, 10, 13, 10, 0, -12 }, // 0x54 'T'
{ 674, 11, 13, 13, 1, -12 }, // 0x55 'U'
{ 692, 11, 13, 11, 0, -12 }, // 0x56 'V'
{ 710, 17, 13, 17, 0, -12 }, // 0x57 'W'
{ 738, 12, 13, 12, 0, -12 }, // 0x58 'X'
{ 758, 11, 13, 11, 0, -12 }, // 0x59 'Y'
{ 776, 10, 13, 10, 0, -12 }, // 0x5A 'Z'
{ 793, 4, 16, 6, 1, -12 }, // 0x5B '['
{ 801, 7, 13, 7, 0, -12 }, // 0x5C '\'
{ 813, 5, 16, 6, 0, -12 }, // 0x5D ']'
{ 823, 10, 9, 10, 0, -12 }, // 0x5E '^'
{ 835, 7, 1, 7, 0, 3 }, // 0x5F '_'
{ 836, 5, 3, 6, 1, -13 }, // 0x60 '`'
{ 838, 8, 10, 11, 1, -9 }, // 0x61 'a'
{ 848, 9, 13, 11, 1, -12 }, // 0x62 'b'
{ 863, 8, 10, 9, 1, -9 }, // 0x63 'c'
{ 873, 9, 13, 11, 1, -12 }, // 0x64 'd'
{ 888, 9, 10, 11, 1, -9 }, // 0x65 'e'
{ 900, 8, 13, 7, 0, -12 }, // 0x66 'f'
{ 913, 9, 14, 11, 1, -9 }, // 0x67 'g'
{ 929, 9, 13, 11, 1, -12 }, // 0x68 'h'
{ 944, 3, 13, 5, 1, -12 }, // 0x69 'i'
{ 949, 5, 17, 5, -1, -12 }, // 0x6A 'j'
{ 960, 10, 13, 11, 1, -12 }, // 0x6B 'k'
{ 977, 3, 13, 5, 1, -12 }, // 0x6C 'l'
{ 982, 15, 10, 17, 1, -9 }, // 0x6D 'm'
{ 1001, 9, 10, 11, 1, -9 }, // 0x6E 'n'
{ 1013, 9, 10, 11, 1, -9 }, // 0x6F 'o'
{ 1025, 9, 14, 11, 1, -9 }, // 0x70 'p'
{ 1041, 9, 14, 11, 1, -9 }, // 0x71 'q'
{ 1057, 7, 10, 8, 1, -9 }, // 0x72 'r'
{ 1066, 7, 10, 9, 1, -9 }, // 0x73 's'
{ 1075, 7, 12, 8, 0, -11 }, // 0x74 't'
{ 1086, 9, 10, 11, 1, -9 }, // 0x75 'u'
{ 1098, 10, 10, 10, 0, -9 }, // 0x76 'v'
{ 1111, 15, 10, 15, 0, -9 }, // 0x77 'w'
{ 1130, 10, 10, 10, 0, -9 }, // 0x78 'x'
{ 1143, 10, 14, 10, 0, -9 }, // 0x79 'y'
{ 1161, 7, 10, 9, 1, -9 }, // 0x7A 'z'
{ 1170, 6, 16, 7, 0, -12 }, // 0x7B '{'
{ 1182, 2, 17, 10, 4, -12 }, // 0x7C '|'
{ 1187, 6, 16, 7, 1, -12 }, // 0x7D '}'
{ 1199, 8, 3, 10, 1, -7 } }; // 0x7E '~'
const GFXfont NotoSans_Bold9pt7b PROGMEM = {
(uint8_t *)NotoSans_Bold9pt7bBitmaps,
(GFXglyph *)NotoSans_Bold9pt7bGlyphs,
0x20, 0x7E, 24 };
// Approx. 1874 bytes
#endif // NOTOSANSBOLD9PT7B_H
@@ -46,4 +46,18 @@ static const uint8_t icon_notepad[] PROGMEM = {
static const uint8_t icon_search[] PROGMEM = {
0x3C,0x00, 0x42,0x00, 0x81,0x00, 0x81,0x00, 0x81,0x00, 0x42,0x00,
0x3C,0x00, 0x03,0x00, 0x01,0x80, 0x00,0xC0, 0x00,0x40, 0x00,0x00,
};
// ⏰ Alarm Clock (AlarmScreen) — 12x12 home tile icon
static const uint8_t icon_alarm[] PROGMEM = {
0x40,0x40, 0x9E,0x20, 0x20,0x80, 0x44,0x40, 0x44,0x40, 0x46,0x40,
0x40,0x40, 0x20,0x80, 0x1F,0x00, 0x00,0x00, 0x20,0x40, 0x40,0x20,
};
// 🔔 Bell — 7x8 status bar indicator (alarm enabled)
// MSB-first, 1 byte per row
#define BELL_ICON_W 7
#define BELL_ICON_H 8
static const uint8_t icon_bell_small[] PROGMEM = {
0x10, 0x38, 0x7C, 0x7C, 0x7C, 0xFE, 0x00, 0x10,
};
+194 -21
View File
@@ -18,6 +18,7 @@
#include <Arduino.h>
#include <helpers/ui/DisplayDriver.h>
#include "EmojiSprites.h"
enum VKBStatus { VKB_EDITING, VKB_SUBMITTED, VKB_CANCELLED };
@@ -45,7 +46,8 @@ public:
static const int MAX_TEXT = 140;
VirtualKeyboard() : _status(VKB_CANCELLED), _purpose(VKB_CHANNEL_MSG),
_contextIdx(0), _textLen(0), _shifted(false), _symbols(false) {
_contextIdx(0), _textLen(0), _shifted(false), _symbols(false),
_emojiMode(false), _emojiScroll(0) {
_text[0] = '\0';
_label[0] = '\0';
}
@@ -56,6 +58,8 @@ public:
_status = VKB_EDITING;
_shifted = false;
_symbols = false;
_emojiMode = false;
_emojiScroll = 0;
_maxLen = (maxLen > 0 && maxLen < MAX_TEXT) ? maxLen : MAX_TEXT;
strncpy(_label, label, sizeof(_label) - 1);
@@ -90,13 +94,8 @@ public:
display.setColor(DisplayDriver::LIGHT);
display.drawRect(0, 10, 128, 18); // Border
display.setCursor(2, 12);
display.setColor(DisplayDriver::LIGHT);
// Show text with cursor
char dispBuf[MAX_TEXT + 2];
snprintf(dispBuf, sizeof(dispBuf), "%s_", _text);
display.print(dispBuf);
// Render text with inline emoji sprites
renderTextField(display);
// Character count
{
@@ -111,6 +110,11 @@ public:
// Separator
display.drawRect(0, 30, 128, 1);
if (_emojiMode) {
renderEmojiGrid(display);
return;
}
// --- Draw keyboard rows ---
const char* const* layout = getLayout();
@@ -183,6 +187,8 @@ public:
bool handleTap(int vx, int vy) {
if (_status != VKB_EDITING) return false;
if (_emojiMode) return handleEmojiTap(vx, vy);
// Check keyboard rows 0-2
const char* const* layout = getLayout();
@@ -253,6 +259,169 @@ private:
char _label[40];
bool _shifted;
bool _symbols;
bool _emojiMode;
int _emojiScroll;
// Emoji grid constants (virtual coords)
static const int EMJ_COLS = 8;
static const int EMJ_CELL = 15; // 12px sprite + 3px gap
static const int EMJ_GRID_X = 4;
static const int EMJ_GRID_Y = 34;
static const int EMJ_VIS_ROWS = 5;
int emojiTotalRows() const { return (EMOJI_COUNT + EMJ_COLS - 1) / EMJ_COLS; }
int emojiMaxScroll() const { int m = emojiTotalRows() - EMJ_VIS_ROWS; return m < 0 ? 0 : m; }
void renderEmojiGrid(DisplayDriver& display) {
display.setTextSize(0);
for (int vr = 0; vr < EMJ_VIS_ROWS; vr++) {
int absRow = _emojiScroll + vr;
if (absRow >= emojiTotalRows()) break;
for (int col = 0; col < EMJ_COLS; col++) {
int idx = absRow * EMJ_COLS + col;
if (idx >= EMOJI_COUNT) break;
int cx = EMJ_GRID_X + col * EMJ_CELL;
int cy = EMJ_GRID_Y + vr * EMJ_CELL;
display.setColor(DisplayDriver::LIGHT);
const uint8_t* sprite = (const uint8_t*)pgm_read_ptr(&EMOJI_SPRITES_LG[idx]);
if (sprite) {
display.drawXbm(cx + 1, cy + 1, sprite, EMOJI_LG_W, EMOJI_LG_H);
}
}
}
// Footer: [Back] [▲] page/total [▼]
int fy = EMJ_GRID_Y + EMJ_VIS_ROWS * EMJ_CELL + 2;
display.setColor(DisplayDriver::LIGHT);
display.drawRect(0, fy - 1, 128, 1);
// Back button (inverted)
display.fillRect(4, fy + 1, 30, 12);
display.setColor(DisplayDriver::DARK);
int bw = display.getTextWidth("Back");
display.setCursor(4 + (30 - bw) / 2, fy + 2);
display.print("Back");
display.setColor(DisplayDriver::LIGHT);
// Scroll arrows (only if scrollable)
if (emojiTotalRows() > EMJ_VIS_ROWS) {
// Up arrow
if (_emojiScroll > 0) {
display.fillRect(50, fy + 1, 12, 12);
display.setColor(DisplayDriver::DARK);
display.setCursor(53, fy + 2);
display.print("^");
display.setColor(DisplayDriver::LIGHT);
}
// Page info
char pg[8];
snprintf(pg, sizeof(pg), "%d/%d", _emojiScroll + 1, emojiMaxScroll() + 1);
int pw = display.getTextWidth(pg);
display.setCursor(75 - pw / 2, fy + 2);
display.print(pg);
// Down arrow
if (_emojiScroll < emojiMaxScroll()) {
display.fillRect(90, fy + 1, 12, 12);
display.setColor(DisplayDriver::DARK);
display.setCursor(93, fy + 2);
display.print("v");
display.setColor(DisplayDriver::LIGHT);
}
}
}
bool handleEmojiTap(int vx, int vy) {
int fy = EMJ_GRID_Y + EMJ_VIS_ROWS * EMJ_CELL + 2;
// Footer area
if (vy >= fy) {
if (vx >= 4 && vx < 34) {
// Back button
_emojiMode = false;
return true;
}
if (vx >= 50 && vx < 62 && _emojiScroll > 0) {
_emojiScroll--;
return true;
}
if (vx >= 90 && vx < 102 && _emojiScroll < emojiMaxScroll()) {
_emojiScroll++;
return true;
}
return true; // Consume tap in footer
}
// Grid area
if (vy >= EMJ_GRID_Y && vy < EMJ_GRID_Y + EMJ_VIS_ROWS * EMJ_CELL) {
int col = (vx - EMJ_GRID_X) / EMJ_CELL;
int vr = (vy - EMJ_GRID_Y) / EMJ_CELL;
if (col < 0 || col >= EMJ_COLS || vr < 0 || vr >= EMJ_VIS_ROWS) return true;
int idx = (_emojiScroll + vr) * EMJ_COLS + col;
if (idx >= 0 && idx < EMOJI_COUNT) {
insertEmoji(idx);
_emojiMode = false;
}
return true;
}
return true; // Consume any tap while in emoji mode
}
void insertEmoji(int idx) {
// Insert as UTF-8 directly (not escape bytes) so sent messages are valid
uint8_t utf8[8];
int len = emojiEncodeUtf8(EMOJI_CODEPOINTS[idx].cp, utf8);
if (EMOJI_CODEPOINTS[idx].cp2 != 0)
len += emojiEncodeUtf8(EMOJI_CODEPOINTS[idx].cp2, utf8 + len);
if (_textLen + len > _maxLen) return;
memcpy(_text + _textLen, utf8, len);
_textLen += len;
_text[_textLen] = '\0';
}
// Render text field with inline emoji sprites (10×10)
void renderTextField(DisplayDriver& display) {
// Convert UTF-8 emoji to escape bytes for sprite lookup
char sanitized[MAX_TEXT + 1];
emojiSanitize(_text, sanitized, sizeof(sanitized));
int x = 2;
int maxX = 124;
display.setColor(DisplayDriver::LIGHT);
display.setTextSize(0);
for (int i = 0; sanitized[i] && x < maxX; i++) {
uint8_t b = (uint8_t)sanitized[i];
if (b == EMOJI_PAD_BYTE) continue;
if (isEmojiEscape(b)) {
const uint8_t* sprite = getEmojiSpriteSm(b);
if (sprite && x + EMOJI_SM_W < maxX) {
display.drawXbm(x, 14, sprite, EMOJI_SM_W, EMOJI_SM_H);
x += EMOJI_SM_W + 1;
}
} else {
char ch[2] = { (char)b, '\0' };
display.setCursor(x, 12);
display.print(ch);
x += display.getTextWidth(ch);
}
}
// Blinking cursor
if (x < maxX) {
display.setCursor(x, 12);
display.print("_");
}
}
// Layout constants (virtual coords)
static const int KEY_W = 11;
@@ -261,7 +430,7 @@ private:
static const int KEY_START_Y = 34;
// Key layouts — rows 0-2 as char arrays
// Special: ^ = shift, < = backspace, # = symbols, > = enter, ~ = space
// Special: ^ = shift, < = backspace, \x01 = sym toggle, \x02 = emoji, > = enter, ~ = space
const char* const* getLayout() const {
static const char* const lower[3] = { "qwertyuiop", "asdfghjkl", "^zxcvbnm<" };
static const char* const upper[3] = { "QWERTYUIOP", "ASDFGHJKL", "^ZXCVBNM<" };
@@ -269,26 +438,22 @@ private:
return _symbols ? syms : (_shifted ? upper : lower);
}
// Row 4: variable-width keys [#/ABC] [,] [SPACE] [.] [Enter]
// Row 4: variable-width keys [#/ABC] [,] [$] [SPACE] [.] [Enter]
// Defined by physical zones, not the char-array approach
struct R4Key { int x; int w; char ch; const char* label; };
void drawRow4(DisplayDriver& display, int y) {
// # or ABC toggle: x=4, w=20
// comma: x=26, w=11
// space: x=39, w=50
// period: x=91, w=11
// enter: x=104, w=20
const R4Key keys[] = {
{ 4, 20, '\x01', _symbols ? "ABC" : "123" },
{ 26, 11, ',', "," },
{ 39, 50, '~', "space" },
{ 39, 11, '\x02', "$" },
{ 52, 37, '~', "space" },
{ 91, 11, '.', "." },
{ 104, 20, '>', "Send" }
};
for (int i = 0; i < 5; i++) {
bool special = (keys[i].ch == '\x01' || keys[i].ch == '>');
for (int i = 0; i < 6; i++) {
bool special = (keys[i].ch == '\x01' || keys[i].ch == '>' || keys[i].ch == '\x02');
if (special) {
display.setColor(DisplayDriver::LIGHT);
display.fillRect(keys[i].x, y + 1, keys[i].w, KEY_H - 1);
@@ -312,11 +477,12 @@ private:
const R4Key keys[] = {
{ 4, 20, '\x01', nullptr },
{ 26, 11, ',', nullptr },
{ 39, 50, '~', nullptr },
{ 39, 11, '\x02', nullptr },
{ 52, 37, '~', nullptr },
{ 91, 11, '.', nullptr },
{ 104, 20, '>', nullptr }
};
for (int i = 0; i < 5; i++) {
for (int i = 0; i < 6; i++) {
if (vx >= keys[i].x && vx < keys[i].x + keys[i].w) {
processKey(keys[i].ch);
return true;
@@ -334,10 +500,17 @@ private:
// Symbol/letter toggle
_symbols = !_symbols;
_shifted = false;
} else if (ch == '\x02') {
// Emoji picker toggle
_emojiMode = !_emojiMode;
_emojiScroll = 0;
} else if (ch == '<') {
// Backspace
// Backspace — UTF-8 aware (walk back past continuation bytes 10xxxxxx)
if (_textLen > 0) {
_textLen--;
while (_textLen > 0 && ((uint8_t)_text[_textLen] & 0xC0) == 0x80) {
_textLen--;
}
_text[_textLen] = '\0';
}
} else if (ch == '>') {
+372
View File
@@ -0,0 +1,372 @@
#pragma once
// =============================================================================
// ApnDatabase.h - Embedded APN Lookup Table
//
// Maps MCC/MNC (Mobile Country Code / Mobile Network Code) to default APN
// settings for common carriers worldwide. Compiled directly into flash (~3KB)
// so users never need to manually install a lookup file.
//
// The modem queries IMSI via AT+CIMI to extract MCC (3 digits) + MNC (2-3
// digits), then looks up the APN here. If not found, falls back to the
// modem's existing PDP context (AT+CGDCONT?) or user-configured APN.
//
// To add a carrier: append to APN_DATABASE[] with the MCC+MNC as a single
// integer. MNC can be 2 or 3 digits:
// MCC=310, MNC=260 → mccmnc = 310260
// MCC=505, MNC=01 → mccmnc = 50501
//
// Guard: HAS_4G_MODEM
// =============================================================================
#ifdef HAS_4G_MODEM
#ifndef APN_DATABASE_H
#define APN_DATABASE_H
struct ApnEntry {
uint32_t mccmnc; // MCC+MNC as integer (e.g. 310260 for T-Mobile US)
const char* apn; // APN string
const char* carrier; // Human-readable carrier name (for debug/display)
};
// ---------------------------------------------------------------------------
// APN Database — sorted by MCC for binary search potential (not required)
//
// Sources: carrier documentation, GSMA databases, community wikis.
// This covers ~120 major carriers across key regions. Users with less
// common carriers can set APN manually in Settings.
// ---------------------------------------------------------------------------
static const ApnEntry APN_DATABASE[] = {
// =========================================================================
// Australia (MCC 505)
// =========================================================================
{ 50501, "telstra.internet", "Telstra" },
{ 50502, "yesinternet", "Optus" },
{ 50503, "vfinternet.au", "Vodafone AU" },
{ 50506, "3netaccess", "Three AU" },
{ 50507, "telstra.internet", "Vodafone AU (MVNO)" }, // Many MVNOs on Telstra
{ 50510, "telstra.internet", "Norfolk Tel" },
{ 50512, "3netaccess", "Amaysim" }, // Optus MVNO
{ 50514, "yesinternet", "Aussie Broadband" }, // Optus MVNO
{ 50590, "yesinternet", "Optus MVNO" },
// =========================================================================
// New Zealand (MCC 530)
// =========================================================================
{ 53001, "internet", "Vodafone NZ" },
{ 53005, "internet", "Spark NZ" },
{ 53024, "internet", "2degrees" },
// =========================================================================
// United States (MCC 310, 311, 312, 313, 316)
// =========================================================================
{ 310012, "fast.t-mobile.com", "Verizon (old)" },
{ 310026, "fast.t-mobile.com", "T-Mobile US" },
{ 310030, "fast.t-mobile.com", "T-Mobile US" },
{ 310032, "fast.t-mobile.com", "T-Mobile US" },
{ 310060, "fast.t-mobile.com", "T-Mobile US" },
{ 310160, "fast.t-mobile.com", "T-Mobile US" },
{ 310200, "fast.t-mobile.com", "T-Mobile US" },
{ 310210, "fast.t-mobile.com", "T-Mobile US" },
{ 310220, "fast.t-mobile.com", "T-Mobile US" },
{ 310230, "fast.t-mobile.com", "T-Mobile US" },
{ 310240, "fast.t-mobile.com", "T-Mobile US" },
{ 310250, "fast.t-mobile.com", "T-Mobile US" },
{ 310260, "fast.t-mobile.com", "T-Mobile US" },
{ 310270, "fast.t-mobile.com", "T-Mobile US" },
{ 310310, "fast.t-mobile.com", "T-Mobile US" },
{ 310490, "fast.t-mobile.com", "T-Mobile US" },
{ 310530, "fast.t-mobile.com", "T-Mobile US" },
{ 310580, "fast.t-mobile.com", "T-Mobile US" },
{ 310660, "fast.t-mobile.com", "T-Mobile US" },
{ 310800, "fast.t-mobile.com", "T-Mobile US" },
{ 311480, "vzwinternet", "Verizon" },
{ 311481, "vzwinternet", "Verizon" },
{ 311482, "vzwinternet", "Verizon" },
{ 311483, "vzwinternet", "Verizon" },
{ 311484, "vzwinternet", "Verizon" },
{ 311489, "vzwinternet", "Verizon" },
{ 310410, "fast.t-mobile.com", "AT&T (migrated)" },
{ 310120, "att.mvno", "AT&T (Sprint)" },
{ 312530, "iot.1nce.net", "1NCE IoT" },
{ 310120, "tfdata", "Tracfone" },
// =========================================================================
// Canada (MCC 302)
// =========================================================================
{ 30220, "internet.com", "Rogers" },
{ 30221, "internet.com", "Rogers" },
{ 30237, "internet.com", "Rogers" },
{ 30272, "internet.com", "Rogers" },
{ 30234, "sp.telus.com", "Telus" },
{ 30286, "sp.telus.com", "Telus" },
{ 30236, "sp.telus.com", "Telus" },
{ 30261, "sp.bell.ca", "Bell" },
{ 30263, "sp.bell.ca", "Bell" },
{ 30267, "sp.bell.ca", "Bell" },
{ 30268, "fido-core-appl1.apn", "Fido" },
{ 30278, "internet.com", "SaskTel" },
{ 30266, "sp.mb.com", "MTS" },
// =========================================================================
// United Kingdom (MCC 234, 235)
// =========================================================================
{ 23410, "o2-internet", "O2 UK" },
{ 23415, "three.co.uk", "Vodafone UK" },
{ 23420, "three.co.uk", "Three UK" },
{ 23430, "everywhere", "EE" },
{ 23431, "everywhere", "EE" },
{ 23432, "everywhere", "EE" },
{ 23433, "everywhere", "EE" },
{ 23450, "data.lycamobile.co.uk","Lycamobile UK" },
{ 23486, "three.co.uk", "Three UK" },
// =========================================================================
// Germany (MCC 262)
// =========================================================================
{ 26201, "internet.t-mobile", "Telekom DE" },
{ 26202, "web.vodafone.de", "Vodafone DE" },
{ 26203, "internet", "O2 DE" },
{ 26207, "internet", "O2 DE" },
// =========================================================================
// France (MCC 208)
// =========================================================================
{ 20801, "orange", "Orange FR" },
{ 20810, "sl2sfr", "SFR" },
{ 20815, "free", "Free Mobile" },
{ 20820, "ofnew.fr", "Bouygues" },
// =========================================================================
// Italy (MCC 222)
// =========================================================================
{ 22201, "mobile.vodafone.it", "TIM" },
{ 22210, "mobile.vodafone.it", "Vodafone IT" },
{ 22250, "internet.it", "Iliad IT" },
{ 22288, "internet.wind", "WindTre" },
{ 22299, "internet.wind", "WindTre" },
// =========================================================================
// Spain (MCC 214)
// =========================================================================
{ 21401, "internet", "Vodafone ES" },
{ 21403, "internet", "Orange ES" },
{ 21404, "internet", "Yoigo" },
{ 21407, "internet", "Movistar" },
// =========================================================================
// Netherlands (MCC 204)
// =========================================================================
{ 20404, "internet", "Vodafone NL" },
{ 20408, "internet", "KPN" },
{ 20412, "internet", "Telfort" },
{ 20416, "internet", "T-Mobile NL" },
{ 20420, "internet", "T-Mobile NL" },
// =========================================================================
// Sweden (MCC 240)
// =========================================================================
{ 24001, "internet.telia.se", "Telia SE" },
{ 24002, "tre.se", "Three SE" },
{ 24007, "internet.telenor.se", "Telenor SE" },
// =========================================================================
// Norway (MCC 242)
// =========================================================================
{ 24201, "internet.telenor.no", "Telenor NO" },
{ 24202, "internet.netcom.no", "Telia NO" },
// =========================================================================
// Denmark (MCC 238)
// =========================================================================
{ 23801, "internet", "TDC" },
{ 23802, "internet", "Telenor DK" },
{ 23806, "internet", "Three DK" },
{ 23820, "internet", "Telia DK" },
// =========================================================================
// Switzerland (MCC 228)
// =========================================================================
{ 22801, "gprs.swisscom.ch", "Swisscom" },
{ 22802, "internet", "Sunrise" },
{ 22803, "internet", "Salt" },
// =========================================================================
// Austria (MCC 232)
// =========================================================================
{ 23201, "a1.net", "A1" },
{ 23203, "web.one.at", "Three AT" },
{ 23205, "web", "T-Mobile AT" },
// =========================================================================
// Japan (MCC 440, 441)
// =========================================================================
{ 44010, "spmode.ne.jp", "NTT Docomo" },
{ 44020, "plus.4g", "SoftBank" },
{ 44051, "au.au-net.ne.jp", "KDDI au" },
// =========================================================================
// South Korea (MCC 450)
// =========================================================================
{ 45005, "lte.sktelecom.com", "SK Telecom" },
{ 45006, "lte.ktfwing.com", "KT" },
{ 45008, "lte.lguplus.co.kr", "LG U+" },
// =========================================================================
// India (MCC 404, 405)
// =========================================================================
{ 40445, "airtelgprs.com", "Airtel" },
{ 40410, "airtelgprs.com", "Airtel" },
{ 40411, "www", "Vodafone IN (Vi)" },
{ 40413, "www", "Vodafone IN (Vi)" },
{ 40486, "www", "Vodafone IN (Vi)" },
{ 40553, "jionet", "Jio" },
{ 40554, "jionet", "Jio" },
{ 40512, "bsnlnet", "BSNL" },
// =========================================================================
// Singapore (MCC 525)
// =========================================================================
{ 52501, "internet", "Singtel" },
{ 52503, "internet", "M1" },
{ 52505, "internet", "StarHub" },
// =========================================================================
// Hong Kong (MCC 454)
// =========================================================================
{ 45400, "internet", "CSL" },
{ 45406, "internet", "SmarTone" },
{ 45412, "internet", "CMHK" },
// =========================================================================
// Brazil (MCC 724)
// =========================================================================
{ 72405, "claro.com.br", "Claro BR" },
{ 72406, "wap.oi.com.br", "Vivo" },
{ 72410, "wap.oi.com.br", "Vivo" },
{ 72411, "wap.oi.com.br", "Vivo" },
{ 72415, "internet.tim.br", "TIM BR" },
{ 72431, "gprs.oi.com.br", "Oi" },
// =========================================================================
// Mexico (MCC 334)
// =========================================================================
{ 33402, "internet.itelcel.com","Telcel" },
{ 33403, "internet.movistar.mx","Movistar MX" },
{ 33404, "internet.att.net.mx", "AT&T MX" },
// =========================================================================
// South Africa (MCC 655)
// =========================================================================
{ 65501, "internet", "Vodacom" },
{ 65502, "internet", "Telkom ZA" },
{ 65507, "internet", "Cell C" },
{ 65510, "internet", "MTN ZA" },
// =========================================================================
// Philippines (MCC 515)
// =========================================================================
{ 51502, "internet.globe.com.ph","Globe" },
{ 51503, "internet", "Smart" },
{ 51505, "internet", "Sun Cellular" },
// =========================================================================
// Thailand (MCC 520)
// =========================================================================
{ 52001, "internet", "AIS" },
{ 52004, "internet", "TrueMove" },
{ 52005, "internet", "dtac" },
// =========================================================================
// Indonesia (MCC 510)
// =========================================================================
{ 51001, "internet", "Telkomsel" },
{ 51010, "internet", "Telkomsel" },
{ 51011, "3gprs", "XL Axiata" },
{ 51028, "3gprs", "XL Axiata (Axis)" },
// =========================================================================
// Malaysia (MCC 502)
// =========================================================================
{ 50212, "celcom3g", "Celcom" },
{ 50213, "celcom3g", "Celcom" },
{ 50216, "internet", "Digi" },
{ 50219, "celcom3g", "Celcom" },
// =========================================================================
// Czech Republic (MCC 230)
// =========================================================================
{ 23001, "internet.t-mobile.cz","T-Mobile CZ" },
{ 23002, "internet", "O2 CZ" },
{ 23003, "internet.vodafone.cz","Vodafone CZ" },
// =========================================================================
// Poland (MCC 260)
// =========================================================================
{ 26001, "internet", "Plus PL" },
{ 26002, "internet", "T-Mobile PL" },
{ 26003, "internet", "Orange PL" },
{ 26006, "internet", "Play" },
// =========================================================================
// Portugal (MCC 268)
// =========================================================================
{ 26801, "internet", "Vodafone PT" },
{ 26803, "internet", "NOS" },
{ 26806, "internet", "MEO" },
// =========================================================================
// Ireland (MCC 272)
// =========================================================================
{ 27201, "internet", "Vodafone IE" },
{ 27202, "open.internet", "Three IE" },
{ 27205, "three.ie", "Three IE" },
// =========================================================================
// IoT / Global SIMs
// =========================================================================
{ 901028, "iot.1nce.net", "1NCE (IoT)" },
{ 90143, "hologram", "Hologram" },
};
#define APN_DATABASE_SIZE (sizeof(APN_DATABASE) / sizeof(APN_DATABASE[0]))
// ---------------------------------------------------------------------------
// Lookup function — returns nullptr if not found
// ---------------------------------------------------------------------------
inline const ApnEntry* apnLookup(uint32_t mccmnc) {
for (int i = 0; i < (int)APN_DATABASE_SIZE; i++) {
if (APN_DATABASE[i].mccmnc == mccmnc) {
return &APN_DATABASE[i];
}
}
return nullptr;
}
// Parse IMSI string into MCC+MNC. Tries 3-digit MNC first (6-digit mccmnc),
// falls back to 2-digit MNC (5-digit mccmnc) if not found.
inline const ApnEntry* apnLookupFromIMSI(const char* imsi) {
if (!imsi || strlen(imsi) < 5) return nullptr;
// Extract MCC (always 3 digits)
uint32_t mcc = (imsi[0] - '0') * 100 + (imsi[1] - '0') * 10 + (imsi[2] - '0');
// Try 3-digit MNC first (more specific)
if (strlen(imsi) >= 6) {
uint32_t mnc3 = (imsi[3] - '0') * 100 + (imsi[4] - '0') * 10 + (imsi[5] - '0');
uint32_t mccmnc6 = mcc * 1000 + mnc3;
const ApnEntry* entry = apnLookup(mccmnc6);
if (entry) return entry;
}
// Fall back to 2-digit MNC
uint32_t mnc2 = (imsi[3] - '0') * 10 + (imsi[4] - '0');
uint32_t mccmnc5 = mcc * 100 + mnc2;
return apnLookup(mccmnc5);
}
#endif // APN_DATABASE_H
#endif // HAS_4G_MODEM
+227
View File
@@ -0,0 +1,227 @@
#pragma once
// =============================================================================
// CellularMQTT — A7682E Modem + MQTT via native AT commands
// =============================================================================
#ifdef HAS_4G_MODEM
#ifndef CELLULAR_MQTT_H
#define CELLULAR_MQTT_H
#include <Arduino.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/queue.h>
#include <freertos/semphr.h>
#include "variant.h"
#include "ApnDatabase.h"
// ---------------------------------------------------------------------------
// Configuration
// ---------------------------------------------------------------------------
#define MQTT_TOPIC_MAX 80
#define MQTT_PAYLOAD_MAX 512
#define MQTT_CLIENT_ID_MAX 32
#define CMD_QUEUE_SIZE 4
#define RSP_QUEUE_SIZE 4
#define TELEMETRY_INTERVAL 60000
#define CELL_TASK_PRIORITY 1
#define CELL_TASK_STACK_SIZE 8192
#define CELL_TASK_CORE 0
#define MQTT_RECONNECT_MIN 5000
#define MQTT_RECONNECT_MAX 300000
#define MQTT_PUB_FAIL_MAX 5
#define OTA_CHUNK_SIZE 1024
// ---------------------------------------------------------------------------
// State machine
// ---------------------------------------------------------------------------
enum class CellState : uint8_t {
OFF,
POWERING_ON,
INITIALIZING,
REGISTERING,
DATA_ACTIVATING,
MQTT_STARTING,
MQTT_CONNECTING,
CONNECTED,
RECONNECTING,
OTA_IN_PROGRESS,
ERROR
};
// ---------------------------------------------------------------------------
// Queue message types
// ---------------------------------------------------------------------------
struct MQTTCommand {
char cmd[MQTT_PAYLOAD_MAX];
};
struct MQTTResponse {
char topic[MQTT_TOPIC_MAX];
char payload[MQTT_PAYLOAD_MAX];
};
// ---------------------------------------------------------------------------
// MQTT config (loaded from SD: /remote/mqtt.cfg)
// ---------------------------------------------------------------------------
struct MQTTConfig {
char broker[80];
uint16_t port;
char username[40];
char password[40];
char deviceId[MQTT_CLIENT_ID_MAX];
};
// ---------------------------------------------------------------------------
// Telemetry snapshot
// ---------------------------------------------------------------------------
struct TelemetryData {
uint32_t uptime_secs;
uint16_t battery_mv;
uint8_t battery_pct;
int16_t temperature;
int csq;
uint8_t neighbor_count;
float freq;
float bw;
uint8_t sf;
uint8_t cr;
uint8_t tx_power;
char node_name[32];
char apn[40];
char oper[24];
bool mqtt_connected;
};
// ---------------------------------------------------------------------------
// CellularMQTT class
// ---------------------------------------------------------------------------
class CellularMQTT {
public:
void begin();
void stop();
// --- Queue API (called from main loop) ---
bool recvCommand(MQTTCommand& out);
bool sendResponse(const char* topic, const char* payload);
// --- Telemetry ---
void updateTelemetry(const TelemetryData& data);
// --- OTA ---
void requestOTA(const char* url);
bool isOTAInProgress() const { return _state == CellState::OTA_IN_PROGRESS; }
// --- State queries ---
CellState getState() const { return _state; }
bool isConnected() const { return _state == CellState::CONNECTED; }
int getCSQ() const { return _csq; }
int getSignalBars() const;
const char* getOperator() const { return _operator; }
const char* getIPAddress() const { return _ipAddr; }
const char* getBroker() const { return _config.broker; }
const char* getAPN() const { return _apn; }
const char* getRspTopic() const { return _topicRsp; }
const char* stateString() const;
uint32_t getLastCmdTime() const { return _lastCmdTime; }
static bool loadConfig(MQTTConfig& cfg);
private:
volatile CellState _state = CellState::OFF;
volatile int _csq = 99;
volatile uint32_t _lastCmdTime = 0;
char _operator[24] = {0};
char _ipAddr[20] = {0};
char _imei[20] = {0};
char _imsi[20] = {0};
char _apn[64] = {0};
MQTTConfig _config = {};
TelemetryData _telemetry = {};
SemaphoreHandle_t _telemetryMutex = nullptr;
char _topicCmd[MQTT_TOPIC_MAX] = {0};
char _topicRsp[MQTT_TOPIC_MAX] = {0};
char _topicTelem[MQTT_TOPIC_MAX] = {0};
char _topicOta[MQTT_TOPIC_MAX] = {0};
TaskHandle_t _taskHandle = nullptr;
QueueHandle_t _cmdQueue = nullptr;
QueueHandle_t _rspQueue = nullptr;
SemaphoreHandle_t _uartMutex = nullptr;
uint8_t _pubFailCount = 0;
static const int AT_BUF_SIZE = 512;
char _atBuf[AT_BUF_SIZE];
static const int URC_BUF_SIZE = 600;
char _urcBuf[URC_BUF_SIZE];
int _urcPos = 0;
enum MqttRxState { RX_IDLE, RX_WAIT_TOPIC, RX_WAIT_PAYLOAD };
MqttRxState _rxState = RX_IDLE;
int _rxTopicLen = 0;
int _rxPayloadLen = 0;
char _rxTopic[MQTT_TOPIC_MAX];
char _rxPayload[MQTT_PAYLOAD_MAX];
uint32_t _reconnectDelay = MQTT_RECONNECT_MIN;
// OTA state
volatile bool _otaPending = false;
char _otaUrl[256] = {0};
// --- Modem UART helpers ---
bool modemPowerOn();
bool sendAT(const char* cmd, const char* expect, uint32_t timeout_ms = 2000);
bool waitResponse(const char* expect, uint32_t timeout_ms, char* buf = nullptr, size_t bufLen = 0);
bool waitPrompt(uint32_t timeout_ms = 5000);
void drainURCs();
void processURCLine(const char* line);
// --- Data connection ---
void resolveAPN();
bool activateData();
// --- MQTT operations ---
bool mqttStart();
bool mqttConnect();
bool mqttSubscribe(const char* topic);
bool mqttPublish(const char* topic, const char* payload);
void mqttDisconnect();
// --- URC handlers ---
void handleMqttRxStart(const char* line);
void handleMqttRxTopic(const char* data, int len);
void handleMqttRxPayload(const char* data, int len);
void handleMqttRxEnd();
void handleMqttConnLost(const char* line);
// --- OTA operations (modem task only) ---
void performOTA();
int httpGet(const char* url);
bool httpReadChunk(int offset, int len, uint8_t* dest, int* bytesRead);
void httpTerm();
int readRawBytes(uint8_t* dest, int count, uint32_t timeout_ms);
// --- Task ---
static void taskEntry(void* param);
void taskLoop();
};
extern CellularMQTT cellularMQTT;
#endif // CELLULAR_MQTT_H
#endif // HAS_4G_MODEM
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -68,11 +68,11 @@ struct NeighbourInfo {
};
#ifndef FIRMWARE_BUILD_DATE
#define FIRMWARE_BUILD_DATE "30 Nov 2025"
#define FIRMWARE_BUILD_DATE "3 April 2026"
#endif
#ifndef FIRMWARE_VERSION
#define FIRMWARE_VERSION "v1.11.0"
#define FIRMWARE_VERSION "v0.2"
#endif
#define FIRMWARE_ROLE "repeater"
+126 -25
View File
@@ -2,7 +2,21 @@
#include <Arduino.h>
#include <helpers/CommonCLI.h>
#define AUTO_OFF_MILLIS 20000 // 20 seconds
#ifdef HAS_4G_MODEM
#include "CellularMQTT.h"
#endif
#ifdef MECK_WIFI_REMOTE
#include "WiFiMQTT.h"
#endif
#if defined(HAS_4G_MODEM) || defined(MECK_WIFI_REMOTE)
#define AUTO_OFF_DISABLED true
#else
#define AUTO_OFF_DISABLED false
#endif
#define AUTO_OFF_MILLIS 20000 // 20 seconds (ignored when AUTO_OFF_DISABLED)
#define BOOT_SCREEN_MILLIS 4000 // 4 seconds
// 'meshcore', 128x13px
@@ -28,55 +42,144 @@ void UITask::begin(NodePrefs* node_prefs, const char* build_date, const char* fi
_node_prefs = node_prefs;
_display->turnOn();
// strip off dash and commit hash by changing dash to null terminator
// e.g: v1.2.3-abcdef -> v1.2.3
char *version = strdup(firmware_version);
char *dash = strchr(version, '-');
if(dash){
*dash = 0;
}
if (dash) *dash = 0;
// v1.2.3 (1 Jan 2025)
sprintf(_version_info, "%s (%s)", version, build_date);
snprintf(_version_info, sizeof(_version_info), "%s (%s)", version, build_date);
free(version);
}
void UITask::renderCurrScreen() {
char tmp[80];
if (millis() < BOOT_SCREEN_MILLIS) { // boot screen
// meshcore logo
if (millis() < BOOT_SCREEN_MILLIS) {
// Boot screen — logo + version
_display->setColor(DisplayDriver::BLUE);
int logoWidth = 128;
_display->drawXbm((_display->width() - logoWidth) / 2, 3, meshcore_logo, logoWidth, 13);
// version info
_display->setColor(DisplayDriver::LIGHT);
_display->setTextSize(1);
uint16_t versionWidth = _display->getTextWidth(_version_info);
_display->setCursor((_display->width() - versionWidth) / 2, 22);
_display->print(_version_info);
// node type
#if defined(HAS_4G_MODEM)
const char* node_type = "< Remote Repeater >";
#elif defined(MECK_WIFI_REMOTE)
const char* node_type = "< WiFi Repeater >";
#else
const char* node_type = "< Repeater >";
#endif
uint16_t typeWidth = _display->getTextWidth(node_type);
_display->setCursor((_display->width() - typeWidth) / 2, 35);
_display->print(node_type);
} else { // home screen
// node name
} else {
// Home screen — node info + connection status
_display->setCursor(0, 0);
_display->setTextSize(1);
_display->setColor(DisplayDriver::GREEN);
_display->print(_node_prefs->node_name);
// freq / sf
_display->setCursor(0, 20);
_display->setColor(DisplayDriver::YELLOW);
sprintf(tmp, "FREQ: %06.3f SF%d", _node_prefs->freq, _node_prefs->sf);
_display->print(tmp);
// bw / cr
_display->setCursor(0, 30);
sprintf(tmp, "BW: %03.2f CR: %d", _node_prefs->bw, _node_prefs->cr);
_display->print(tmp);
// --- Cellular status (4G variant) ---
#ifdef HAS_4G_MODEM
int y = 44;
_display->setCursor(0, y);
_display->setColor(DisplayDriver::LIGHT);
sprintf(tmp, "4G: %s", cellularMQTT.stateString());
_display->print(tmp);
y += 10;
_display->setCursor(0, y);
sprintf(tmp, "CSQ: %d (%d bars)", cellularMQTT.getCSQ(), cellularMQTT.getSignalBars());
_display->print(tmp);
y += 10;
const char* oper = cellularMQTT.getOperator();
if (oper[0]) {
_display->setCursor(0, y);
sprintf(tmp, "Op: %.16s", oper);
_display->print(tmp);
y += 10;
}
_display->setCursor(0, y);
_display->setColor(cellularMQTT.isConnected() ? DisplayDriver::GREEN : DisplayDriver::YELLOW);
sprintf(tmp, "MQTT: %s", cellularMQTT.isConnected() ? "Connected" : "---");
_display->print(tmp);
y += 10;
const char* ip4g = cellularMQTT.getIPAddress();
if (ip4g[0]) {
_display->setColor(DisplayDriver::LIGHT);
_display->setCursor(0, y);
sprintf(tmp, "IP: %s", ip4g);
_display->print(tmp);
y += 10;
}
uint32_t upSec = millis() / 1000;
uint32_t upH = upSec / 3600;
uint32_t upM = (upSec % 3600) / 60;
_display->setColor(DisplayDriver::LIGHT);
_display->setCursor(0, y);
sprintf(tmp, "Up: %luh %lum Heap:%dk", upH, upM, ESP.getFreeHeap() / 1024);
_display->print(tmp);
#endif
// --- WiFi status (WiFi variant) ---
#ifdef MECK_WIFI_REMOTE
int y = 44;
_display->setCursor(0, y);
_display->setColor(DisplayDriver::LIGHT);
sprintf(tmp, "WiFi: %s", wifiMQTT.stateString());
_display->print(tmp);
y += 10;
_display->setCursor(0, y);
sprintf(tmp, "RSSI: %d (%d bars)", wifiMQTT.getRSSI(), wifiMQTT.getSignalBars());
_display->print(tmp);
y += 10;
_display->setCursor(0, y);
sprintf(tmp, "SSID: %.16s", wifiMQTT.getSSID());
_display->print(tmp);
y += 10;
_display->setCursor(0, y);
_display->setColor(wifiMQTT.isConnected() ? DisplayDriver::GREEN : DisplayDriver::YELLOW);
sprintf(tmp, "MQTT: %s", wifiMQTT.isConnected() ? "Connected" : "---");
_display->print(tmp);
y += 10;
const char* ipWifi = wifiMQTT.getIPAddress();
if (ipWifi[0]) {
_display->setColor(DisplayDriver::LIGHT);
_display->setCursor(0, y);
sprintf(tmp, "IP: %s", ipWifi);
_display->print(tmp);
y += 10;
}
uint32_t upSec = millis() / 1000;
uint32_t upH = upSec / 3600;
uint32_t upM = (upSec % 3600) / 60;
_display->setColor(DisplayDriver::LIGHT);
_display->setCursor(0, y);
sprintf(tmp, "Up: %luh %lum Heap:%dk", upH, upM, ESP.getFreeHeap() / 1024);
_display->print(tmp);
#endif
}
}
@@ -85,17 +188,15 @@ void UITask::loop() {
if (millis() >= _next_read) {
int btnState = digitalRead(PIN_USER_BTN);
if (btnState != _prevBtnState) {
if (btnState == LOW) { // pressed?
if (_display->isOn()) {
// TODO: any action ?
} else {
if (btnState == LOW) {
if (!_display->isOn()) {
_display->turnOn();
}
_auto_off = millis() + AUTO_OFF_MILLIS; // extend auto-off timer
_auto_off = millis() + AUTO_OFF_MILLIS;
}
_prevBtnState = btnState;
}
_next_read = millis() + 200; // 5 reads per second
_next_read = millis() + 200;
}
#endif
@@ -105,10 +206,10 @@ void UITask::loop() {
renderCurrScreen();
_display->endFrame();
_next_refresh = millis() + 1000; // refresh every second
_next_refresh = millis() + 10000;
}
if (millis() > _auto_off) {
if (!AUTO_OFF_DISABLED && millis() > _auto_off) {
_display->turnOff();
}
}
}
}
+1 -1
View File
@@ -8,7 +8,7 @@ class UITask {
unsigned long _next_read, _next_refresh, _auto_off;
int _prevBtnState;
NodePrefs* _node_prefs;
char _version_info[32];
char _version_info[48];
void renderCurrScreen();
public:
File diff suppressed because it is too large Load Diff
+198 -8
View File
@@ -1,8 +1,20 @@
#include <Arduino.h> // needed for PlatformIO
#include <Mesh.h>
#include <time.h>
#include "MyMesh.h"
#ifdef HAS_4G_MODEM
#include <SD.h>
#include "CellularMQTT.h"
#endif
#ifdef MECK_WIFI_REMOTE
#if defined(HAS_SDCARD) || defined(SDCARD_CS)
#include <SD.h>
#endif
#include "WiFiMQTT.h"
#endif
#ifdef DISPLAY_CLASS
#include "UITask.h"
static UITask ui_task(display);
@@ -23,6 +35,10 @@ static char command[160];
unsigned long lastActive = 0; // mark last active time
unsigned long nextSleepinSecs = 120; // next sleep in seconds. The first sleep (if enabled) is after 2 minutes from boot
#if (defined(HAS_4G_MODEM) || defined(MECK_WIFI_REMOTE)) && (defined(HAS_SDCARD) || defined(SDCARD_CS))
static bool sdCardReady = false;
#endif
void setup() {
Serial.begin(115200);
delay(1000);
@@ -83,6 +99,72 @@ void setup() {
the_mesh.begin(fs);
// ---------------------------------------------------------------------------
// SD card init — needed for MQTT config on devices with SD slots.
// T-Deck Pro: SD shares display SPI bus (HSPI via displaySpi)
// T5S3: SD shares LoRa SPI bus (SCK=14, MOSI=13, MISO=21)
// Heltec V4 and others without SD: config lives in SPIFFS (already init'd)
// ---------------------------------------------------------------------------
#if (defined(HAS_4G_MODEM) || defined(MECK_WIFI_REMOTE)) && (defined(HAS_SDCARD) || defined(SDCARD_CS))
{
// Deselect all SPI devices before SD init to prevent bus contention
#ifdef SDCARD_CS
pinMode(SDCARD_CS, OUTPUT);
digitalWrite(SDCARD_CS, HIGH);
#endif
#ifdef PIN_DISPLAY_CS
pinMode(PIN_DISPLAY_CS, OUTPUT);
digitalWrite(PIN_DISPLAY_CS, HIGH);
#endif
#ifdef P_LORA_NSS
pinMode(P_LORA_NSS, OUTPUT);
digitalWrite(P_LORA_NSS, HIGH);
#endif
delay(100);
for (int i = 0; i < 3; i++) {
#if defined(LilyGo_T5S3_EPaper_Pro)
// T5S3: SD shares LoRa SPI bus — create local HSPI reference
static SPIClass sdSpi(HSPI);
sdSpi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI, SDCARD_CS);
if (SD.begin(SDCARD_CS, sdSpi, 4000000)) { sdCardReady = true; break; }
#elif defined(SDCARD_CS)
extern SPIClass displaySpi;
if (SD.begin(SDCARD_CS, displaySpi)) { sdCardReady = true; break; }
#else
if (SD.begin(SPI_CS)) { sdCardReady = true; break; }
#endif
delay(200);
}
Serial.printf("SD card: %s\n", sdCardReady ? "ready" : "FAILED");
}
#endif
// Start MQTT backhaul
#ifdef HAS_4G_MODEM
if (sdCardReady) {
cellularMQTT.begin();
Serial.println("Cellular MQTT starting...");
} else {
Serial.println("Cellular MQTT skipped — no SD card for config");
}
#endif
#ifdef MECK_WIFI_REMOTE
#if defined(HAS_SDCARD) || defined(SDCARD_CS)
if (sdCardReady) {
wifiMQTT.begin();
Serial.println("WiFi MQTT starting...");
} else {
Serial.println("WiFi MQTT skipped — no SD card for config");
}
#else
// No SD card slot — config lives in SPIFFS (already initialized above)
wifiMQTT.begin();
Serial.println("WiFi MQTT starting (SPIFFS config)...");
#endif
#endif
#ifdef DISPLAY_CLASS
ui_task.begin(the_mesh.getNodePrefs(), FIRMWARE_BUILD_DATE, FIRMWARE_VERSION);
#endif
@@ -118,6 +200,112 @@ void loop() {
command[0] = 0; // reset command buffer
}
// ---------------------------------------------------------------------------
// MQTT → CLI bridge: process incoming commands from MQTT (cellular)
// ---------------------------------------------------------------------------
#ifdef HAS_4G_MODEM
{
MQTTCommand mqttCmd;
while (cellularMQTT.recvCommand(mqttCmd)) {
Serial.printf("[MQTT] CLI: %s\n", mqttCmd.cmd);
char reply[512];
reply[0] = '\0';
the_mesh.handleCommand((uint32_t)time(nullptr), mqttCmd.cmd, reply);
if (reply[0] == '\0') strcpy(reply, "OK");
cellularMQTT.sendResponse(cellularMQTT.getRspTopic(), reply);
Serial.printf("[MQTT] Reply: %.80s\n", reply);
}
}
// Periodic telemetry snapshot for cellular MQTT
{
static unsigned long lastTelemUpdate = 0;
if (millis() - lastTelemUpdate > 10000) {
NodePrefs* p = the_mesh.getNodePrefs();
TelemetryData td;
memset(&td, 0, sizeof(td));
td.uptime_secs = millis() / 1000;
td.battery_mv = board.getBattMilliVolts();
#ifdef HAS_BQ27220
td.battery_pct = board.getBatteryPercent();
td.temperature = board.getBattTemperature();
#else
td.battery_pct = 0;
td.temperature = 0;
#endif
td.csq = cellularMQTT.getCSQ();
td.freq = p->freq;
td.bw = p->bw;
td.sf = p->sf;
td.cr = p->cr;
td.tx_power = p->tx_power_dbm;
strncpy(td.node_name, p->node_name, sizeof(td.node_name) - 1);
strncpy(td.apn, cellularMQTT.getAPN(), sizeof(td.apn) - 1);
strncpy(td.oper, cellularMQTT.getOperator(), sizeof(td.oper) - 1);
td.mqtt_connected = cellularMQTT.isConnected();
td.neighbor_count = 0; // TODO: expose from MyMesh
cellularMQTT.updateTelemetry(td);
lastTelemUpdate = millis();
}
}
#endif
// ---------------------------------------------------------------------------
// MQTT → CLI bridge: process incoming commands from MQTT (WiFi)
// ---------------------------------------------------------------------------
#ifdef MECK_WIFI_REMOTE
wifiMQTT.loop();
{
MQTTCommand mqttCmd;
while (wifiMQTT.recvCommand(mqttCmd)) {
Serial.printf("[MQTT] CLI: %s\n", mqttCmd.cmd);
char reply[512];
reply[0] = '\0';
the_mesh.handleCommand((uint32_t)time(nullptr), mqttCmd.cmd, reply);
if (reply[0] == '\0') strcpy(reply, "OK");
wifiMQTT.sendResponse(wifiMQTT.getRspTopic(), reply);
Serial.printf("[MQTT] Reply: %.80s\n", reply);
}
}
// Periodic telemetry snapshot for WiFi MQTT
{
static unsigned long lastTelemUpdate = 0;
if (millis() - lastTelemUpdate > 10000) {
NodePrefs* p = the_mesh.getNodePrefs();
TelemetryData td;
memset(&td, 0, sizeof(td));
td.uptime_secs = millis() / 1000;
td.battery_mv = board.getBattMilliVolts();
#ifdef HAS_BQ27220
td.battery_pct = board.getBatteryPercent();
td.temperature = board.getBattTemperature();
#else
td.battery_pct = 0;
td.temperature = 0;
#endif
td.rssi = wifiMQTT.getRSSI();
td.freq = p->freq;
td.bw = p->bw;
td.sf = p->sf;
td.cr = p->cr;
td.tx_power = p->tx_power_dbm;
strncpy(td.node_name, p->node_name, sizeof(td.node_name) - 1);
td.mqtt_connected = wifiMQTT.isConnected();
td.neighbor_count = 0;
wifiMQTT.updateTelemetry(td);
lastTelemUpdate = millis();
}
}
#endif
the_mesh.loop();
sensors.loop();
#ifdef DISPLAY_CLASS
@@ -125,14 +313,16 @@ void loop() {
#endif
rtc_clock.tick();
if (the_mesh.getNodePrefs()->powersaving_enabled && // To check if power saving is enabled
the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) { // To check if it is time to sleep
if (!the_mesh.hasPendingWork()) { // No pending work. Safe to sleep
board.sleep(1800); // To sleep. Wake up after 30 minutes or when receiving a LoRa packet
#if !defined(HAS_4G_MODEM) && !defined(MECK_WIFI_REMOTE)
if (the_mesh.getNodePrefs()->powersaving_enabled &&
the_mesh.millisHasNowPassed(lastActive + nextSleepinSecs * 1000)) {
if (!the_mesh.hasPendingWork()) {
board.sleep(1800);
lastActive = millis();
nextSleepinSecs = 5; // Default: To work for 5s and sleep again
nextSleepinSecs = 5;
} else {
nextSleepinSecs += 5; // When there is pending work, to work another 5s
nextSleepinSecs += 5;
}
}
}
#endif
}
+509
View File
@@ -0,0 +1,509 @@
#ifdef MECK_WIFI_REMOTE
#include "WiFiMQTT.h"
#include <esp_mac.h>
#include <Update.h>
#include <HTTPClient.h>
#include "target.h"
WiFiMQTT wifiMQTT;
#define WIFI_CONFIG_FILE "/remote/wifi.cfg"
#define MQTT_CONFIG_FILE "/remote/mqtt.cfg"
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
void WiFiMQTT::begin() {
Serial.println("[WiFi] begin()");
_state = WiFiMQTTState::OFF;
_cmdHead = _cmdTail = 0;
_rspHead = _rspTail = 0;
_activeNetwork = 0;
if (!loadConfig(_config)) {
Serial.println("[WiFi] ERROR: Missing config files — cannot start");
_state = WiFiMQTTState::ERROR;
return;
}
Serial.printf("[WiFi] Config: %d network(s), broker=%s:%d id=%s\n",
_config.networkCount, _config.broker, _config.port, _config.deviceId);
for (int i = 0; i < _config.networkCount; i++) {
Serial.printf("[WiFi] %d: %s\n", i + 1, _config.networks[i].ssid);
}
snprintf(_topicCmd, sizeof(_topicCmd), "meck/%s/cmd", _config.deviceId);
snprintf(_topicRsp, sizeof(_topicRsp), "meck/%s/rsp", _config.deviceId);
snprintf(_topicTelem, sizeof(_topicTelem), "meck/%s/telemetry", _config.deviceId);
snprintf(_topicOta, sizeof(_topicOta), "meck/%s/ota", _config.deviceId);
// Configure TLS — skip server cert verification (same as cellular)
_wifiClient.setInsecure();
_mqttClient.setClient(_wifiClient);
_mqttClient.setServer(_config.broker, _config.port);
_mqttClient.setCallback(mqttCallback);
_mqttClient.setBufferSize(MQTT_PAYLOAD_MAX + MQTT_TOPIC_MAX);
_state = WiFiMQTTState::WIFI_CONNECTING;
}
void WiFiMQTT::loop() {
if (_state == WiFiMQTTState::OFF || _state == WiFiMQTTState::ERROR) return;
// Check for pending OTA
if (_otaPending && _state == WiFiMQTTState::CONNECTED) {
performOTA();
return;
}
// WiFi connection management
if (WiFi.status() != WL_CONNECTED) {
if (_state == WiFiMQTTState::CONNECTED || _state == WiFiMQTTState::MQTT_CONNECTING) {
Serial.println("[WiFi] Connection lost");
_state = WiFiMQTTState::WIFI_CONNECTING;
}
if (millis() - _lastWifiAttempt > WIFI_RECONNECT_MS) {
connectWiFi();
_lastWifiAttempt = millis();
}
return;
}
// WiFi is up — check MQTT
if (!_mqttClient.connected()) {
if (_state == WiFiMQTTState::CONNECTED) {
Serial.println("[WiFi] MQTT disconnected");
}
_state = WiFiMQTTState::MQTT_CONNECTING;
if (millis() - _lastMqttAttempt > MQTT_RECONNECT_MS) {
connectMQTT();
_lastMqttAttempt = millis();
}
return;
}
// Connected — run MQTT loop
_mqttClient.loop();
// Publish queued responses
publishQueuedResponses();
// Periodic RSSI
if (millis() - _lastRSSI > 30000) {
_rssi = WiFi.RSSI();
_lastRSSI = millis();
}
// Periodic telemetry
if (millis() - _lastTelem > TELEMETRY_INTERVAL) {
publishTelemetry();
_lastTelem = millis();
}
}
bool WiFiMQTT::recvCommand(MQTTCommand& out) {
if (_cmdHead == _cmdTail) return false;
memcpy(&out, &_cmdBuf[_cmdTail], sizeof(MQTTCommand));
_cmdTail = (_cmdTail + 1) % CMD_QUEUE_SIZE;
return true;
}
bool WiFiMQTT::sendResponse(const char* topic, const char* payload) {
int next = (_rspHead + 1) % RSP_QUEUE_SIZE;
if (next == _rspTail) return false; // Full
memset(&_rspBuf[_rspHead], 0, sizeof(MQTTResponse));
strncpy(_rspBuf[_rspHead].topic, topic, MQTT_TOPIC_MAX - 1);
strncpy(_rspBuf[_rspHead].payload, payload, MQTT_PAYLOAD_MAX - 1);
_rspHead = next;
return true;
}
void WiFiMQTT::updateTelemetry(const TelemetryData& data) {
memcpy(&_telemetry, &data, sizeof(data));
}
void WiFiMQTT::requestOTA(const char* url) {
if (_state == WiFiMQTTState::OTA_IN_PROGRESS) return;
strncpy(_otaUrl, url, sizeof(_otaUrl) - 1);
_otaUrl[sizeof(_otaUrl) - 1] = '\0';
_otaPending = true;
Serial.printf("[OTA] Requested: %s\n", url);
}
int WiFiMQTT::getSignalBars() const {
if (_rssi == 0) return 0;
if (_rssi > -50) return 5;
if (_rssi > -60) return 4;
if (_rssi > -70) return 3;
if (_rssi > -80) return 2;
return 1;
}
const char* WiFiMQTT::stateString() const {
switch (_state) {
case WiFiMQTTState::OFF: return "OFF";
case WiFiMQTTState::WIFI_CONNECTING: return "WiFi...";
case WiFiMQTTState::WIFI_CONNECTED: return "WiFi OK";
case WiFiMQTTState::MQTT_CONNECTING: return "MQTT...";
case WiFiMQTTState::CONNECTED: return "CONNECTED";
case WiFiMQTTState::OTA_IN_PROGRESS: return "OTA";
case WiFiMQTTState::ERROR: return "ERROR";
default: return "???";
}
}
// ---------------------------------------------------------------------------
// Config files
//
// /remote/wifi.cfg — SSID/password pairs, two lines each:
// HomeNetwork
// HomePassword
// BackupNetwork
// BackupPassword
//
// /remote/mqtt.cfg — same format as cellular variant
// ---------------------------------------------------------------------------
bool WiFiMQTT::loadConfig(WiFiMQTTConfig& cfg) {
memset(&cfg, 0, sizeof(cfg));
// Determine filesystem: SD if available, otherwise SPIFFS
// Heltec V4 and other headless boards have no SD slot — config lives in SPIFFS.
// Upload config files via: pio run -t uploadfs (with data/ folder)
#if defined(HAS_SDCARD) || defined(SDCARD_CS)
fs::FS& configFS = SD;
Serial.println("[WiFi] Config source: SD card");
#else
fs::FS& configFS = SPIFFS;
Serial.println("[WiFi] Config source: SPIFFS");
#endif
// WiFi config: read SSID/password pairs
File wf = configFS.open(WIFI_CONFIG_FILE, FILE_READ);
if (!wf) {
Serial.printf("[WiFi] No %s\n", WIFI_CONFIG_FILE);
return false;
}
cfg.networkCount = 0;
while (wf.available() && cfg.networkCount < MAX_WIFI_NETWORKS) {
String ssid = wf.readStringUntil('\n'); ssid.trim();
if (ssid.length() == 0) break;
String pass = wf.readStringUntil('\n'); pass.trim();
strncpy(cfg.networks[cfg.networkCount].ssid, ssid.c_str(), sizeof(cfg.networks[0].ssid) - 1);
strncpy(cfg.networks[cfg.networkCount].password, pass.c_str(), sizeof(cfg.networks[0].password) - 1);
cfg.networkCount++;
}
wf.close();
if (cfg.networkCount == 0) {
Serial.println("[WiFi] No networks in wifi.cfg");
return false;
}
// MQTT config: /remote/mqtt.cfg (same format as cellular)
File mf = configFS.open(MQTT_CONFIG_FILE, FILE_READ);
if (!mf) {
Serial.printf("[WiFi] No %s\n", MQTT_CONFIG_FILE);
return false;
}
String line;
line = mf.readStringUntil('\n'); line.trim();
strncpy(cfg.broker, line.c_str(), sizeof(cfg.broker) - 1);
line = mf.readStringUntil('\n'); line.trim();
cfg.port = line.length() > 0 ? line.toInt() : 8883;
line = mf.readStringUntil('\n'); line.trim();
strncpy(cfg.username, line.c_str(), sizeof(cfg.username) - 1);
line = mf.readStringUntil('\n'); line.trim();
strncpy(cfg.password, line.c_str(), sizeof(cfg.password) - 1);
if (mf.available()) {
line = mf.readStringUntil('\n'); line.trim();
if (line.length() > 0) {
strncpy(cfg.deviceId, line.c_str(), sizeof(cfg.deviceId) - 1);
}
}
mf.close();
// Auto-generate device ID if not provided
if (cfg.deviceId[0] == '\0') {
uint8_t mac[6];
esp_efuse_mac_get_default(mac);
snprintf(cfg.deviceId, sizeof(cfg.deviceId), "meck-%02x%02x%02x%02x",
mac[2], mac[3], mac[4], mac[5]);
}
return cfg.broker[0] != '\0';
}
// ---------------------------------------------------------------------------
// WiFi connection — tries each configured network in order
// ---------------------------------------------------------------------------
bool WiFiMQTT::connectWiFi() {
WiFi.mode(WIFI_STA);
for (int n = 0; n < _config.networkCount; n++) {
Serial.printf("[WiFi] Trying %s (%d/%d)...\n",
_config.networks[n].ssid, n + 1, _config.networkCount);
WiFi.begin(_config.networks[n].ssid, _config.networks[n].password);
unsigned long start = millis();
while (WiFi.status() != WL_CONNECTED && millis() - start < 10000) {
delay(100);
}
if (WiFi.status() == WL_CONNECTED) {
IPAddress ip = WiFi.localIP();
snprintf(_ipAddr, sizeof(_ipAddr), "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
_rssi = WiFi.RSSI();
_activeNetwork = n;
Serial.printf("[WiFi] Connected to %s — IP: %s RSSI: %d\n",
_config.networks[n].ssid, _ipAddr, _rssi);
if (WiFi.status() == WL_CONNECTED) {
IPAddress ip = WiFi.localIP();
snprintf(_ipAddr, sizeof(_ipAddr), "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
_rssi = WiFi.RSSI();
_activeNetwork = n;
Serial.printf("[WiFi] Connected to %s — IP: %s RSSI: %d\n",
_config.networks[n].ssid, _ipAddr, _rssi);
// Sync clock via NTP
configTime(0, 0, "pool.ntp.org", "time.google.com");
Serial.print("[WiFi] NTP sync...");
int tries = 0;
while (time(nullptr) < 1700000000 && tries < 20) {
delay(500);
tries++;
}
time_t now = time(nullptr);
if (now > 1700000000) {
extern AutoDiscoverRTCClock rtc_clock;
rtc_clock.setCurrentTime((uint32_t)now);
Serial.printf(" OK (%lu)\n", (unsigned long)now);
} else {
Serial.println(" timeout");
}
_state = WiFiMQTTState::WIFI_CONNECTED;
return true;
}
}
WiFi.disconnect();
delay(500);
}
Serial.println("[WiFi] All networks failed");
return false;
}
// ---------------------------------------------------------------------------
// MQTT connection
// ---------------------------------------------------------------------------
bool WiFiMQTT::connectMQTT() {
Serial.printf("[WiFi] MQTT connecting to %s:%d...\n", _config.broker, _config.port);
char clientId[48];
snprintf(clientId, sizeof(clientId), "%s-%lu", _config.deviceId, millis() & 0xFFFF);
if (_mqttClient.connect(clientId, _config.username, _config.password)) {
Serial.println("[WiFi] MQTT connected!");
_mqttClient.subscribe(_topicCmd, 1);
_mqttClient.subscribe(_topicOta, 1);
_state = WiFiMQTTState::CONNECTED;
// Publish boot event
_mqttClient.publish(_topicTelem, "{\"event\":\"boot\",\"state\":\"connected\"}", true);
return true;
}
Serial.printf("[WiFi] MQTT connect failed, rc=%d\n", _mqttClient.state());
return false;
}
// ---------------------------------------------------------------------------
// MQTT message callback
// ---------------------------------------------------------------------------
void WiFiMQTT::mqttCallback(char* topic, byte* payload, unsigned int length) {
wifiMQTT.onMessage(topic, payload, length);
}
void WiFiMQTT::onMessage(char* topic, byte* payload, unsigned int length) {
char buf[MQTT_PAYLOAD_MAX];
int len = (length < MQTT_PAYLOAD_MAX - 1) ? length : MQTT_PAYLOAD_MAX - 1;
memcpy(buf, payload, len);
buf[len] = '\0';
Serial.printf("[WiFi] RX [%s]: %.80s\n", topic, buf);
if (strstr(topic, "/cmd")) {
int next = (_cmdHead + 1) % CMD_QUEUE_SIZE;
if (next != _cmdTail) {
memset(&_cmdBuf[_cmdHead], 0, sizeof(MQTTCommand));
strncpy(_cmdBuf[_cmdHead].cmd, buf, MQTT_PAYLOAD_MAX - 1);
_cmdHead = next;
Serial.printf("[WiFi] Queued CLI: %s\n", buf);
} else {
Serial.println("[WiFi] Command queue full");
}
} else if (strstr(topic, "/ota")) {
requestOTA(buf);
}
}
// ---------------------------------------------------------------------------
// Publish helpers
// ---------------------------------------------------------------------------
void WiFiMQTT::publishQueuedResponses() {
while (_rspHead != _rspTail) {
_mqttClient.publish(_rspBuf[_rspTail].topic, _rspBuf[_rspTail].payload);
_rspTail = (_rspTail + 1) % RSP_QUEUE_SIZE;
}
}
void WiFiMQTT::publishTelemetry() {
_rssi = WiFi.RSSI();
char json[400];
snprintf(json, sizeof(json),
"{\"uptime\":%lu,\"batt_mv\":%d,\"batt_pct\":%d,\"temp\":%.1f,"
"\"rssi\":%d,\"bars\":%d,\"neighbors\":%d,"
"\"freq\":%.3f,\"bw\":%.1f,\"sf\":%d,\"cr\":%d,\"tx\":%d,"
"\"name\":\"%s\",\"ip\":\"%s\",\"ssid\":\"%s\","
"\"heap\":%d}",
_telemetry.uptime_secs, _telemetry.battery_mv, _telemetry.battery_pct,
_telemetry.temperature / 10.0f,
_rssi, getSignalBars(), _telemetry.neighbor_count,
_telemetry.freq, _telemetry.bw, _telemetry.sf, _telemetry.cr, _telemetry.tx_power,
_telemetry.node_name, _ipAddr, _config.networks[_activeNetwork].ssid,
ESP.getFreeHeap());
_mqttClient.publish(_topicTelem, json);
}
// ---------------------------------------------------------------------------
// OTA — HTTP download over WiFi + ESP32 flash
// ---------------------------------------------------------------------------
void WiFiMQTT::performOTA() {
_otaPending = false;
_state = WiFiMQTTState::OTA_IN_PROGRESS;
Serial.printf("[OTA] URL: %s\n", _otaUrl);
_mqttClient.publish(_topicRsp, "OTA: Starting download...");
_mqttClient.loop();
HTTPClient http;
http.setFollowRedirects(HTTPC_STRICT_FOLLOW_REDIRECTS);
http.setTimeout(180000);
if (!http.begin(_wifiClient, _otaUrl)) {
Serial.println("[OTA] HTTP begin failed");
_mqttClient.publish(_topicRsp, "OTA: HTTP begin failed");
_state = WiFiMQTTState::CONNECTED;
return;
}
int httpCode = http.GET();
if (httpCode != HTTP_CODE_OK) {
Serial.printf("[OTA] HTTP error: %d\n", httpCode);
char msg[60];
snprintf(msg, sizeof(msg), "OTA: HTTP error %d", httpCode);
_mqttClient.publish(_topicRsp, msg);
http.end();
_state = WiFiMQTTState::CONNECTED;
return;
}
int fileSize = http.getSize();
if (fileSize <= 0) {
Serial.println("[OTA] Unknown content length");
_mqttClient.publish(_topicRsp, "OTA: Unknown file size");
http.end();
_state = WiFiMQTTState::CONNECTED;
return;
}
Serial.printf("[OTA] File size: %d bytes\n", fileSize);
if (!Update.begin(fileSize)) {
Serial.printf("[OTA] Update.begin failed: %s\n", Update.errorString());
_mqttClient.publish(_topicRsp, "OTA: Flash init failed");
http.end();
_state = WiFiMQTTState::CONNECTED;
return;
}
WiFiClient* stream = http.getStreamPtr();
uint8_t buf[1024];
int offset = 0;
int lastPct = -1;
while (offset < fileSize) {
int avail = stream->available();
if (avail <= 0) {
if (!stream->connected()) break;
delay(10);
continue;
}
int toRead = (avail < (int)sizeof(buf)) ? avail : sizeof(buf);
int got = stream->readBytes(buf, toRead);
if (got <= 0) break;
size_t written = Update.write(buf, got);
if (written != (size_t)got) {
Serial.printf("[OTA] Write failed: %d of %d\n", written, got);
break;
}
offset += got;
int pct = (offset * 100) / fileSize;
if (pct / 10 != lastPct / 10) {
Serial.printf("[OTA] Progress: %d%% (%d/%d)\n", pct, offset, fileSize);
char msg[60];
snprintf(msg, sizeof(msg), "OTA: Flashing %d%%", pct);
_mqttClient.publish(_topicRsp, msg);
_mqttClient.loop();
lastPct = pct;
}
delay(1);
}
http.end();
if (offset < fileSize) {
Serial.printf("[OTA] Incomplete: %d of %d\n", offset, fileSize);
Update.abort();
_mqttClient.publish(_topicRsp, "OTA: Download incomplete");
_state = WiFiMQTTState::CONNECTED;
return;
}
if (!Update.end(true)) {
Serial.printf("[OTA] Update.end failed: %s\n", Update.errorString());
_mqttClient.publish(_topicRsp, "OTA: Verification failed");
_state = WiFiMQTTState::CONNECTED;
return;
}
Serial.println("[OTA] SUCCESS — rebooting in 3 seconds");
_mqttClient.publish(_topicRsp, "OTA: Success! Rebooting...");
_mqttClient.loop();
delay(3000);
ESP.restart();
}
#endif // MECK_WIFI_REMOTE
+191
View File
@@ -0,0 +1,191 @@
#pragma once
// =============================================================================
// WiFiMQTT — WiFi + MQTT for audio variant remote repeater
//
// Same interface as CellularMQTT but uses ESP32 native WiFi + PubSubClient.
// No modem, no AT commands, no FreeRTOS task — runs in the main loop.
//
// Supports multiple WiFi networks in wifi.cfg (SSID/password pairs).
// Tries each in order on connect/reconnect.
//
// Guard: MECK_WIFI_REMOTE (set in platformio env build_flags)
// =============================================================================
#ifdef MECK_WIFI_REMOTE
#ifndef WIFI_MQTT_H
#define WIFI_MQTT_H
#include <Arduino.h>
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
#if defined(HAS_SDCARD) || defined(SDCARD_CS)
#include <SD.h>
#endif
#include <SPIFFS.h>
// ---------------------------------------------------------------------------
// Configuration
// ---------------------------------------------------------------------------
#define MQTT_TOPIC_MAX 80
#define MQTT_PAYLOAD_MAX 512
#define MQTT_CLIENT_ID_MAX 32
#define CMD_QUEUE_SIZE 8
#define RSP_QUEUE_SIZE 8
#define MAX_WIFI_NETWORKS 4
#define TELEMETRY_INTERVAL 60000 // 60 seconds
#define WIFI_RECONNECT_MS 10000 // 10 seconds between WiFi reconnect attempts
#define MQTT_RECONNECT_MS 5000 // 5 seconds between MQTT reconnect attempts
// ---------------------------------------------------------------------------
// State machine
// ---------------------------------------------------------------------------
enum class WiFiMQTTState : uint8_t {
OFF,
WIFI_CONNECTING,
WIFI_CONNECTED,
MQTT_CONNECTING,
CONNECTED,
OTA_IN_PROGRESS,
ERROR
};
// ---------------------------------------------------------------------------
// Queue message types (same as CellularMQTT for compatibility)
// ---------------------------------------------------------------------------
struct MQTTCommand {
char cmd[MQTT_PAYLOAD_MAX];
};
struct MQTTResponse {
char topic[MQTT_TOPIC_MAX];
char payload[MQTT_PAYLOAD_MAX];
};
// ---------------------------------------------------------------------------
// Config (loaded from SD)
// ---------------------------------------------------------------------------
struct WiFiNetwork {
char ssid[40];
char password[64];
};
struct WiFiMQTTConfig {
WiFiNetwork networks[MAX_WIFI_NETWORKS];
int networkCount;
char broker[80];
uint16_t port; // 8883 for MQTT TLS
char username[40];
char password[40];
char deviceId[MQTT_CLIENT_ID_MAX];
};
// ---------------------------------------------------------------------------
// Telemetry snapshot
// ---------------------------------------------------------------------------
struct TelemetryData {
uint32_t uptime_secs;
uint16_t battery_mv;
uint8_t battery_pct;
int16_t temperature;
int rssi;
uint8_t neighbor_count;
float freq;
float bw;
uint8_t sf;
uint8_t cr;
uint8_t tx_power;
char node_name[32];
bool mqtt_connected;
};
// ---------------------------------------------------------------------------
// WiFiMQTT class
// ---------------------------------------------------------------------------
class WiFiMQTT {
public:
void begin();
void loop(); // Call from main loop — handles WiFi, MQTT, publish/subscribe
// --- Queue API (called from main loop) ---
bool recvCommand(MQTTCommand& out);
bool sendResponse(const char* topic, const char* payload);
// --- Telemetry ---
void updateTelemetry(const TelemetryData& data);
// --- OTA ---
void requestOTA(const char* url);
bool isOTAInProgress() const { return _state == WiFiMQTTState::OTA_IN_PROGRESS; }
// --- State queries ---
WiFiMQTTState getState() const { return _state; }
bool isConnected() const { return _state == WiFiMQTTState::CONNECTED; }
int getRSSI() const { return _rssi; }
int getSignalBars() const;
const char* getSSID() const { return _config.networks[_activeNetwork].ssid; }
const char* getIPAddress() const { return _ipAddr; }
const char* getBroker() const { return _config.broker; }
const char* getRspTopic() const { return _topicRsp; }
const char* stateString() const;
static bool loadConfig(WiFiMQTTConfig& cfg);
private:
WiFiMQTTState _state = WiFiMQTTState::OFF;
int _rssi = 0;
int _activeNetwork = 0;
char _ipAddr[20] = {0};
WiFiMQTTConfig _config = {};
TelemetryData _telemetry = {};
// Topic strings
char _topicCmd[MQTT_TOPIC_MAX] = {0};
char _topicRsp[MQTT_TOPIC_MAX] = {0};
char _topicTelem[MQTT_TOPIC_MAX] = {0};
char _topicOta[MQTT_TOPIC_MAX] = {0};
// Command/response ring buffers (no FreeRTOS queues needed — single-threaded)
MQTTCommand _cmdBuf[CMD_QUEUE_SIZE];
int _cmdHead = 0, _cmdTail = 0;
MQTTResponse _rspBuf[RSP_QUEUE_SIZE];
int _rspHead = 0, _rspTail = 0;
// MQTT client stack
WiFiClientSecure _wifiClient;
PubSubClient _mqttClient;
// Timers
unsigned long _lastWifiAttempt = 0;
unsigned long _lastMqttAttempt = 0;
unsigned long _lastTelem = 0;
unsigned long _lastRSSI = 0;
// OTA state
bool _otaPending = false;
char _otaUrl[256] = {0};
// --- Internal ---
bool connectWiFi();
bool connectMQTT();
void publishTelemetry();
void publishQueuedResponses();
void performOTA();
// PubSubClient callback (static → instance)
static void mqttCallback(char* topic, byte* payload, unsigned int length);
void onMessage(char* topic, byte* payload, unsigned int length);
};
extern WiFiMQTT wifiMQTT;
#endif // WIFI_MQTT_H
#endif // MECK_WIFI_REMOTE
+96 -2
View File
@@ -1,7 +1,10 @@
"""
PlatformIO post-build script: merge bootloader + partitions + firmware
PlatformIO post-build script: merge bootloader + partitions + firmware + SPIFFS
into a single flashable binary.
Includes a pre-formatted empty SPIFFS image so first-boot doesn't need to
format the partition (which takes 1-2 minutes on 16MB flash).
Output: .pio/build/<env>/firmware_merged.bin
Flash: esptool.py --chip esp32s3 write_flash 0x0 firmware_merged.bin
@@ -12,6 +15,87 @@ Add to each environment (or the base section):
Import("env")
def find_spiffs_partition(partitions_bin):
"""Parse compiled partitions.bin to find SPIFFS partition offset and size.
ESP32 partition entry format (32 bytes each):
0xAA50 magic, type, subtype, offset(u32le), size(u32le), label(16), flags(u32le)
SPIFFS: type=0x01(data), subtype=0x82(spiffs)
"""
import struct
with open(partitions_bin, "rb") as f:
data = f.read()
for i in range(0, len(data) - 32, 32):
magic = struct.unpack_from("<H", data, i)[0]
if magic != 0xAA50:
continue
ptype = data[i + 2]
subtype = data[i + 3]
offset = struct.unpack_from("<I", data, i + 4)[0]
size = struct.unpack_from("<I", data, i + 8)[0]
label = data[i + 12:i + 28].split(b'\x00')[0].decode("ascii", errors="ignore")
if ptype == 0x01 and subtype == 0x82: # data/spiffs
return offset, size, label
return None, None, None
def build_spiffs_image(env, size):
"""Generate an empty formatted SPIFFS image using mkspiffs."""
import subprocess, os, tempfile, glob
build_dir = env.subst("$BUILD_DIR")
spiffs_bin = os.path.join(build_dir, "spiffs_empty.bin")
# If already generated for this build, reuse it
if os.path.isfile(spiffs_bin) and os.path.getsize(spiffs_bin) == size:
return spiffs_bin
# Find mkspiffs in PlatformIO packages
pio_home = os.path.expanduser("~/.platformio")
mkspiffs_paths = glob.glob(os.path.join(pio_home, "packages", "tool-mkspiffs*", "mkspiffs*"))
if not mkspiffs_paths:
# Also check platform-specific tool paths
mkspiffs_paths = glob.glob(os.path.join(pio_home, "packages", "tool-mklittlefs*", "mkspiffs*"))
mkspiffs = None
for p in mkspiffs_paths:
if os.path.isfile(p) and os.access(p, os.X_OK):
mkspiffs = p
break
if not mkspiffs:
print("[merge] WARNING: mkspiffs not found, skipping SPIFFS image")
return None
# Create empty data directory for mkspiffs
data_dir = os.path.join(build_dir, "_empty_spiffs_data")
os.makedirs(data_dir, exist_ok=True)
# SPIFFS block/page sizes — ESP32 Arduino defaults
block_size = 4096
page_size = 256
cmd = [
mkspiffs,
"-c", data_dir,
"-b", str(block_size),
"-p", str(page_size),
"-s", str(size),
spiffs_bin,
]
print(f"[merge] Generating empty SPIFFS image ({size // 1024} KB)...")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0 and os.path.isfile(spiffs_bin):
print(f"[merge] SPIFFS image OK: {spiffs_bin}")
return spiffs_bin
else:
print(f"[merge] mkspiffs failed: {result.stderr}")
return None
def merge_bin(source, target, env):
import subprocess, os
@@ -52,8 +136,18 @@ def merge_bin(source, target, env):
"0x10000", firmware,
]
# Try to include a pre-formatted SPIFFS image (eliminates 1-2 min first-boot format)
spiffs_offset, spiffs_size, spiffs_label = find_spiffs_partition(partitions)
if spiffs_offset and spiffs_size:
spiffs_bin = build_spiffs_image(env, spiffs_size)
if spiffs_bin:
cmd.extend([f"0x{spiffs_offset:x}", spiffs_bin])
print(f"[merge] Including SPIFFS image at 0x{spiffs_offset:x} ({spiffs_size // 1024} KB)")
else:
print("[merge] No SPIFFS partition found in partition table, skipping SPIFFS image")
print(f"\n[merge] Creating merged firmware for {env_name}...")
print(f"[merge] {' '.join(cmd[-6:])}")
print(f"[merge] {' '.join(cmd[-8:])}")
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode == 0:
+39 -4
View File
@@ -36,7 +36,7 @@ uint32_t Dispatcher::getCADFailRetryDelay() const {
return 200;
}
uint32_t Dispatcher::getCADFailMaxDuration() const {
return 4000; // 4 seconds
return 6000; // 6 seconds
}
void Dispatcher::loop() {
@@ -52,10 +52,28 @@ void Dispatcher::loop() {
prev_isrecv_mode = is_recv;
if (!is_recv) {
radio_nonrx_start = _ms->getMillis();
} else {
rx_stuck_count = 0; // radio recovered — reset counter
}
}
if (!is_recv && _ms->getMillis() - radio_nonrx_start > 8000) { // radio has not been in Rx mode for 8 seconds!
_err_flags |= ERR_EVENT_STARTRX_TIMEOUT;
rx_stuck_count++;
MESH_DEBUG_PRINTLN("%s Dispatcher::loop(): RX stuck (attempt %d), calling onRxStuck()", getLogDateTime(), rx_stuck_count);
onRxStuck();
uint8_t reboot_threshold = getRxFailRebootThreshold();
if (reboot_threshold > 0 && rx_stuck_count >= reboot_threshold) {
MESH_DEBUG_PRINTLN("%s Dispatcher::loop(): RX unrecoverable after %d attempts", getLogDateTime(), rx_stuck_count);
onRxUnrecoverable();
}
// Reset state to give recovery the full 8s window before re-triggering
radio_nonrx_start = _ms->getMillis();
prev_isrecv_mode = true;
cad_busy_start = 0;
next_agc_reset_time = futureMillis(getAGCResetInterval());
}
if (outbound) { // waiting for outbound send to be completed
@@ -273,14 +291,31 @@ void Dispatcher::checkSend() {
outbound_start = _ms->getMillis();
bool success = _radio->startSendRaw(raw, len);
if (!success) {
MESH_DEBUG_PRINTLN("%s Dispatcher::loop(): ERROR: send start failed!", getLogDateTime());
MESH_DEBUG_PRINTLN("%s Dispatcher::checkSend(): ERROR: send start failed!", getLogDateTime());
logTxFail(outbound, outbound->getRawLength());
releasePacket(outbound); // return to pool
// re-queue packet for retry instead of dropping it
int retry_delay = getCADFailRetryDelay();
unsigned long retry_time = futureMillis(retry_delay);
_mgr->queueOutbound(outbound, 0, retry_time);
outbound = NULL;
next_tx_time = retry_time;
// count consecutive failures and reset radio if stuck
uint8_t threshold = getTxFailResetThreshold();
if (threshold > 0) {
tx_fail_count++;
if (tx_fail_count >= threshold) {
MESH_DEBUG_PRINTLN("%s Dispatcher::checkSend(): TX stuck (%d failures), resetting radio", getLogDateTime(), tx_fail_count);
onTxStuck();
tx_fail_count = 0;
next_tx_time = futureMillis(2000);
}
}
return;
}
tx_fail_count = 0; // clear counter on successful TX start
outbound_expiry = futureMillis(max_airtime);
#if MESH_PACKET_LOGGING
+10 -1
View File
@@ -122,6 +122,8 @@ class Dispatcher {
bool prev_isrecv_mode;
uint32_t n_sent_flood, n_sent_direct;
uint32_t n_recv_flood, n_recv_direct;
uint8_t tx_fail_count;
uint8_t rx_stuck_count;
void processRecvPacket(Packet* pkt);
@@ -142,6 +144,8 @@ protected:
_err_flags = 0;
radio_nonrx_start = 0;
prev_isrecv_mode = true;
tx_fail_count = 0;
rx_stuck_count = 0;
}
virtual DispatcherAction onRecvPacket(Packet* pkt) = 0;
@@ -159,6 +163,11 @@ protected:
virtual uint32_t getCADFailMaxDuration() const;
virtual int getInterferenceThreshold() const { return 0; } // disabled by default
virtual int getAGCResetInterval() const { return 0; } // disabled by default
virtual uint8_t getTxFailResetThreshold() const { return 3; } // reset radio after N consecutive TX failures; 0=disabled
virtual void onTxStuck() { _radio->resetAGC(); } // override to use doFullRadioReset() when available
virtual uint8_t getRxFailRebootThreshold() const { return 3; } // reboot after N failed RX recovery attempts; 0=disabled
virtual void onRxStuck() { _radio->resetAGC(); } // called each time RX stuck for 8s; override for deeper reset
virtual void onRxUnrecoverable() { } // called when reboot threshold exceeded; override to call _board->reboot()
public:
void begin();
@@ -188,4 +197,4 @@ private:
void checkSend();
};
}
}
+2 -2
View File
@@ -10,10 +10,10 @@
#endif
void BaseChatMesh::sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis) {
sendFlood(pkt, delay_millis);
sendFlood(pkt, delay_millis, getPathHashSize());
}
void BaseChatMesh::sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis) {
sendFlood(pkt, delay_millis);
sendFlood(pkt, delay_millis, getPathHashSize());
}
mesh::Packet* BaseChatMesh::createSelfAdvert(const char* name) {
+1
View File
@@ -130,6 +130,7 @@ protected:
virtual void onContactResponse(const ContactInfo& contact, const uint8_t* data, uint8_t len) = 0;
virtual void handleReturnPathRetry(const ContactInfo& contact, const uint8_t* path, uint8_t path_len);
virtual uint8_t getPathHashSize() const = 0;
virtual void sendFloodScoped(const ContactInfo& recipient, mesh::Packet* pkt, uint32_t delay_millis=0);
virtual void sendFloodScoped(const mesh::GroupChannel& channel, mesh::Packet* pkt, uint32_t delay_millis=0);
+4 -1
View File
@@ -6,4 +6,7 @@
struct ChannelDetails {
mesh::GroupChannel channel;
char name[32];
};
char scope_name[31]; // Region scope name (e.g. "au-nsw"), empty = use device default
ChannelDetails() { memset(name, 0, sizeof(name)); memset(scope_name, 0, sizeof(scope_name)); }
};
+11 -8
View File
@@ -81,7 +81,8 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
file.read((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
file.read((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
file.read((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
// 290
file.read((uint8_t *)&_prefs->path_hash_mode, sizeof(_prefs->path_hash_mode)); // 290
// 291
// sanitise bad pref values
_prefs->rx_delay_base = constrain(_prefs->rx_delay_base, 0, 20.0f);
@@ -107,6 +108,7 @@ void CommonCLI::loadPrefsInt(FILESYSTEM* fs, const char* filename) {
_prefs->gps_enabled = constrain(_prefs->gps_enabled, 0, 1);
_prefs->advert_loc_policy = constrain(_prefs->advert_loc_policy, 0, 2);
_prefs->path_hash_mode = constrain(_prefs->path_hash_mode, 0, 2);
file.close();
}
@@ -165,7 +167,8 @@ void CommonCLI::savePrefs(FILESYSTEM* fs) {
file.write((uint8_t *)&_prefs->discovery_mod_timestamp, sizeof(_prefs->discovery_mod_timestamp)); // 162
file.write((uint8_t *)&_prefs->adc_multiplier, sizeof(_prefs->adc_multiplier)); // 166
file.write((uint8_t *)_prefs->owner_info, sizeof(_prefs->owner_info)); // 170
// 290
file.write((uint8_t *)&_prefs->path_hash_mode, sizeof(_prefs->path_hash_mode)); // 290
// 291
file.close();
}
@@ -285,7 +288,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
sprintf(reply, "> %d", ((uint32_t) _prefs->advert_interval) * 2);
} else if (memcmp(config, "guest.password", 14) == 0) {
sprintf(reply, "> %s", _prefs->guest_password);
} else if (sender_timestamp == 0 && memcmp(config, "prv.key", 7) == 0) { // from serial command line only
} else if (memcmp(config, "prv.key", 7) == 0) { // from serial command line only
uint8_t prv_key[PRV_KEY_SIZE];
int len = _callbacks->getSelfId().writeTo(prv_key, PRV_KEY_SIZE);
mesh::Utils::toHex(tmp, prv_key, len);
@@ -545,7 +548,7 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
savePrefs();
_callbacks->setTxPower(_prefs->tx_power_dbm);
strcpy(reply, "OK");
} else if (sender_timestamp == 0 && memcmp(config, "freq ", 5) == 0) {
} else if (memcmp(config, "freq ", 5) == 0) {
_prefs->freq = atof(&config[5]);
savePrefs();
strcpy(reply, "OK - reboot to apply");
@@ -767,13 +770,13 @@ void CommonCLI::handleCommand(uint32_t sender_timestamp, const char* command, ch
} else if (sender_timestamp == 0 && memcmp(command, "log", 3) == 0) {
_callbacks->dumpLogFile();
strcpy(reply, " EOF");
} else if (sender_timestamp == 0 && memcmp(command, "stats-packets", 13) == 0 && (command[13] == 0 || command[13] == ' ')) {
} else if (memcmp(command, "stats-packets", 13) == 0 && (command[13] == 0 || command[13] == ' ')) {
_callbacks->formatPacketStatsReply(reply);
} else if (sender_timestamp == 0 && memcmp(command, "stats-radio", 11) == 0 && (command[11] == 0 || command[11] == ' ')) {
} else if (memcmp(command, "stats-radio", 11) == 0 && (command[11] == 0 || command[11] == ' ')) {
_callbacks->formatRadioStatsReply(reply);
} else if (sender_timestamp == 0 && memcmp(command, "stats-core", 10) == 0 && (command[10] == 0 || command[10] == ' ')) {
} else if (memcmp(command, "stats-core", 10) == 0 && (command[10] == 0 || command[10] == ' ')) {
_callbacks->formatStatsReply(reply);
} else {
strcpy(reply, "Unknown command");
}
}
}
+3 -1
View File
@@ -52,6 +52,8 @@ struct NodePrefs { // persisted to file
uint32_t discovery_mod_timestamp;
float adc_multiplier;
char owner_info[120];
// Multi-byte path hash support (added for Meck remote repeater)
uint8_t path_hash_mode; // 0=1-byte (legacy), 1=2-byte, 2=3-byte path hashes
};
class CommonCLICallbacks {
@@ -110,4 +112,4 @@ public:
void savePrefs(FILESYSTEM* _fs);
void handleCommand(uint32_t sender_timestamp, const char* command, char* reply);
uint8_t buildAdvertData(uint8_t node_type, uint8_t* app_data);
};
};
+20 -8
View File
@@ -10,6 +10,7 @@
#include <Wire.h>
#include "esp_wifi.h"
#include "driver/rtc_io.h"
#include "driver/gpio.h"
class ESP32Board : public mesh::MainBoard {
protected:
@@ -60,13 +61,20 @@ public:
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(P_LORA_DIO_1) // Supported ESP32 variants
if (rtc_gpio_is_valid_gpio((gpio_num_t)P_LORA_DIO_1)) { // Only enter sleep mode if P_LORA_DIO_1 is RTC pin
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
esp_sleep_enable_ext1_wakeup((1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // To wake up when receiving a LoRa packet
esp_sleep_enable_ext1_wakeup((1ULL << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // Wake on LoRa packet
// T5S3: Also wake on boot button press (GPIO0, active LOW).
// gpio_wakeup uses level trigger — works for light sleep only.
#if defined(LilyGo_T5S3_EPaper_Pro) && defined(PIN_USER_BTN)
gpio_wakeup_enable((gpio_num_t)PIN_USER_BTN, GPIO_INTR_LOW_LEVEL);
esp_sleep_enable_gpio_wakeup();
#endif
if (secs > 0) {
esp_sleep_enable_timer_wakeup(secs * 1000000); // To wake up every hour to do periodically jobs
esp_sleep_enable_timer_wakeup(secs * 1000000ULL); // Timer wake (microseconds)
}
esp_light_sleep_start(); // CPU enters light sleep
esp_light_sleep_start(); // CPU halts here, resumes on wake
}
#endif
}
@@ -132,11 +140,15 @@ class ESP32RTCClock : public mesh::RTCClock {
public:
ESP32RTCClock() { }
void begin() {
esp_reset_reason_t reason = esp_reset_reason();
if (reason == ESP_RST_POWERON) {
// start with some date/time in the recent past
// Check if the ESP32 RTC peripheral retained a sane time across reset.
// On power-on the value is undefined; on watchdog/brownout/SW reset it
// may retain valid time OR garbage. Accept times in a plausible window
// (Nov 2023 → May 2033) and re-seed anything outside that range.
time_t _now;
time(&_now);
if (_now < 1700000000 || _now > 2000000000) {
struct timeval tv;
tv.tv_sec = 1715770351; // 15 May 2024, 8:50pm
tv.tv_sec = 1715770351; // 15 May 2024, 8:50pm UTC (safe seed)
tv.tv_usec = 0;
settimeofday(&tv, NULL);
}
@@ -154,4 +166,4 @@ public:
}
};
#endif
#endif
+21 -1
View File
@@ -1,4 +1,6 @@
#include "SerialBLEInterface.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
// See the following for generating UUIDs:
// https://www.uuidgenerator.net/
@@ -27,6 +29,11 @@ void SerialBLEInterface::begin(const char* prefix, char* name, uint32_t pin_code
BLEDevice::setSecurityCallbacks(this);
BLEDevice::setMTU(MAX_FRAME_SIZE);
// Boost BLE TX power for improved range (+9 dBm, up from default +3 dBm)
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_DEFAULT, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_ADV, ESP_PWR_LVL_P9);
esp_ble_tx_power_set(ESP_BLE_PWR_TYPE_SCAN, ESP_PWR_LVL_P9);
BLESecurity sec;
sec.setStaticPIN(pin_code);
sec.setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND);
@@ -77,6 +84,18 @@ void SerialBLEInterface::onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl) {
if (cmpl.success) {
BLE_DEBUG_PRINTLN(" - SecurityCallback - Authentication Success");
deviceConnected = true;
// Request fast connection interval (15ms) for faster contact sync.
// Phone may negotiate higher, but most modern phones accept 15ms.
// Units are 1.25ms, so 12 = 15ms, 16 = 20ms.
esp_ble_conn_update_params_t conn_params;
memcpy(conn_params.bda, _remote_bda, 6);
conn_params.min_int = 12; // 15ms (12 × 1.25ms)
conn_params.max_int = 16; // 20ms (16 × 1.25ms)
conn_params.latency = 0; // no skipped intervals
conn_params.timeout = 400; // 4 seconds supervision timeout
esp_ble_gap_update_conn_params(&conn_params);
BLE_DEBUG_PRINTLN(" - Requested fast connection interval (15-20ms)");
} else {
BLE_DEBUG_PRINTLN(" - SecurityCallback - Authentication Failure*");
@@ -94,6 +113,7 @@ void SerialBLEInterface::onConnect(BLEServer* pServer) {
void SerialBLEInterface::onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t *param) {
BLE_DEBUG_PRINTLN("onConnect(), conn_id=%d, mtu=%d", param->connect.conn_id, pServer->getPeerMTU(param->connect.conn_id));
last_conn_id = param->connect.conn_id;
memcpy(_remote_bda, param->connect.remote_bda, 6);
}
void SerialBLEInterface::onMtuChanged(BLEServer* pServer, esp_ble_gatts_cb_param_t* param) {
@@ -185,7 +205,7 @@ size_t SerialBLEInterface::writeFrame(const uint8_t src[], size_t len) {
return 0;
}
#define BLE_WRITE_MIN_INTERVAL 60
#define BLE_WRITE_MIN_INTERVAL 15
bool SerialBLEInterface::isWriteBusy() const {
return millis() < _last_write + BLE_WRITE_MIN_INTERVAL; // still too soon to start another write?
+3 -1
View File
@@ -14,6 +14,7 @@ class SerialBLEInterface : public BaseSerialInterface, BLESecurityCallbacks, BLE
bool oldDeviceConnected;
bool _isEnabled;
uint16_t last_conn_id;
uint8_t _remote_bda[6]; // peer BDA, stored in onConnect for conn param updates
uint32_t _pin_code;
unsigned long _last_write;
unsigned long adv_restart_time;
@@ -23,7 +24,7 @@ class SerialBLEInterface : public BaseSerialInterface, BLESecurityCallbacks, BLE
uint8_t buf[MAX_FRAME_SIZE];
};
#define FRAME_QUEUE_SIZE 4
#define FRAME_QUEUE_SIZE 16
int recv_queue_len;
Frame recv_queue[FRAME_QUEUE_SIZE];
int send_queue_len;
@@ -58,6 +59,7 @@ public:
_isEnabled = false;
_last_write = 0;
last_conn_id = 0;
memset(_remote_bda, 0, 6);
send_queue_len = recv_queue_len = 0;
}
+55 -57
View File
@@ -40,7 +40,7 @@ size_t SerialWifiInterface::writeFrame(const uint8_t src[], size_t len) {
}
bool SerialWifiInterface::isWriteBusy() const {
return false;
return send_queue_len >= (FRAME_QUEUE_SIZE * 3 / 4); // backpressure at 75% full
}
bool SerialWifiInterface::hasReceivedFrameHeader() {
@@ -82,8 +82,8 @@ size_t SerialWifiInterface::checkRecvFrame(uint8_t dest[]) {
}
if (deviceConnected) {
if (send_queue_len > 0) { // first, check send queue
// drain all pending send frames — WiFi TCP can handle the throughput
while (send_queue_len > 0) {
_last_write = millis();
int len = send_queue[0].len;
@@ -97,70 +97,68 @@ size_t SerialWifiInterface::checkRecvFrame(uint8_t dest[]) {
for (int i = 0; i < send_queue_len; i++) { // delete top item from queue
send_queue[i] = send_queue[i + 1];
}
} else {
}
// check if we are waiting for a frame header
if(!hasReceivedFrameHeader()){
// check if we are waiting for a frame header
if(!hasReceivedFrameHeader()){
// make sure we have received enough bytes for a frame header
// 3 bytes frame header = (1 byte frame type) + (2 bytes frame length as unsigned 16-bit little endian)
int frame_header_length = 3;
if(client.available() >= frame_header_length){
// make sure we have received enough bytes for a frame header
// 3 bytes frame header = (1 byte frame type) + (2 bytes frame length as unsigned 16-bit little endian)
int frame_header_length = 3;
if(client.available() >= frame_header_length){
// read frame header
client.readBytes(&received_frame_header.type, 1);
client.readBytes((uint8_t*)&received_frame_header.length, 2);
}
// read frame header
client.readBytes(&received_frame_header.type, 1);
client.readBytes((uint8_t*)&received_frame_header.length, 2);
}
// check if we have received a frame header
if(hasReceivedFrameHeader()){
}
// make sure we have received enough bytes for the required frame length
int available = client.available();
int frame_type = received_frame_header.type;
int frame_length = received_frame_header.length;
if(frame_length > available){
WIFI_DEBUG_PRINTLN("Waiting for %d more bytes", frame_length - available);
return 0;
// check if we have received a frame header
if(hasReceivedFrameHeader()){
// make sure we have received enough bytes for the required frame length
int available = client.available();
int frame_type = received_frame_header.type;
int frame_length = received_frame_header.length;
if(frame_length > available){
WIFI_DEBUG_PRINTLN("Waiting for %d more bytes", frame_length - available);
return 0;
}
// skip frames that are larger than MAX_FRAME_SIZE
if(frame_length > MAX_FRAME_SIZE){
WIFI_DEBUG_PRINTLN("Skipping frame: length=%d is larger than MAX_FRAME_SIZE=%d", frame_length, MAX_FRAME_SIZE);
while(frame_length > 0){
uint8_t skip[1];
int skipped = client.read(skip, 1);
frame_length -= skipped;
}
// skip frames that are larger than MAX_FRAME_SIZE
if(frame_length > MAX_FRAME_SIZE){
WIFI_DEBUG_PRINTLN("Skipping frame: length=%d is larger than MAX_FRAME_SIZE=%d", frame_length, MAX_FRAME_SIZE);
while(frame_length > 0){
uint8_t skip[1];
int skipped = client.read(skip, 1);
frame_length -= skipped;
}
resetReceivedFrameHeader();
return 0;
}
// skip frames that are not expected type
// '<' is 0x3c which indicates a frame sent from app to radio
if(frame_type != '<'){
WIFI_DEBUG_PRINTLN("Skipping frame: type=0x%x is unexpected", frame_type);
while(frame_length > 0){
uint8_t skip[1];
int skipped = client.read(skip, 1);
frame_length -= skipped;
}
resetReceivedFrameHeader();
return 0;
}
// read frame data to provided buffer
client.readBytes(dest, frame_length);
// ready for next frame
resetReceivedFrameHeader();
return frame_length;
return 0;
}
// skip frames that are not expected type
// '<' is 0x3c which indicates a frame sent from app to radio
if(frame_type != '<'){
WIFI_DEBUG_PRINTLN("Skipping frame: type=0x%x is unexpected", frame_type);
while(frame_length > 0){
uint8_t skip[1];
int skipped = client.read(skip, 1);
frame_length -= skipped;
}
resetReceivedFrameHeader();
return 0;
}
// read frame data to provided buffer
client.readBytes(dest, frame_length);
// ready for next frame
resetReceivedFrameHeader();
return frame_length;
}
}
+2 -2
View File
@@ -24,7 +24,7 @@ class SerialWifiInterface : public BaseSerialInterface {
FrameHeader received_frame_header;
#define FRAME_QUEUE_SIZE 4
#define FRAME_QUEUE_SIZE 64
int recv_queue_len;
Frame recv_queue[FRAME_QUEUE_SIZE];
int send_queue_len;
@@ -68,4 +68,4 @@ public:
#else
#define WIFI_DEBUG_PRINT(...) {}
#define WIFI_DEBUG_PRINTLN(...) {}
#endif
#endif
-350
View File
@@ -1,350 +0,0 @@
#if defined(TBEAM_SUPREME_SX1262) || defined(TBEAM_SX1262) || defined(TBEAM_SX1276)
#include <Arduino.h>
#include "TBeamBoard.h"
//#include <RadioLib.h>
uint32_t deviceOnline = 0x00;
bool pmuInterrupt;
static void setPmuFlag()
{
pmuInterrupt = true;
}
void TBeamBoard::begin() {
ESP32Board::begin();
power_init();
//Configure user button
pinMode(PIN_USER_BTN, INPUT);
#ifndef TBEAM_SUPREME_SX1262
digitalWrite(P_LORA_TX_LED, HIGH); //inverted pin for SX1276 - HIGH for off
#endif
//radiotype_detect();
esp_reset_reason_t reason = esp_reset_reason();
if (reason == ESP_RST_DEEPSLEEP) {
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
startup_reason = BD_STARTUP_RX_PACKET;
}
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
}
}
#ifdef MESH_DEBUG
void TBeamBoard::scanDevices(TwoWire *w)
{
uint8_t err, addr;
int nDevices = 0;
uint32_t start = 0;
Serial.println("Scanning I2C for Devices");
for (addr = 1; addr < 127; addr++) {
start = millis();
w->beginTransmission(addr); delay(2);
err = w->endTransmission();
if (err == 0) {
nDevices++;
switch (addr) {
case 0x77:
case 0x76:
Serial.println("\tFound BME280 Sensor");
deviceOnline |= BME280_ONLINE;
break;
case 0x34:
Serial.println("\tFound AXP192/AXP2101 PMU");
deviceOnline |= POWERMANAGE_ONLINE;
break;
case 0x3C:
Serial.println("\tFound SSD1306/SH1106 display");
deviceOnline |= DISPLAY_ONLINE;
break;
case 0x51:
Serial.println("\tFound PCF8563 RTC");
deviceOnline |= PCF8563_ONLINE;
break;
case 0x1C:
Serial.println("\tFound QMC6310 MAG Sensor");
deviceOnline |= QMC6310_ONLINE;
break;
default:
Serial.print("\tI2C device found at address 0x");
if (addr < 16) {
Serial.print("0");
}
Serial.print(addr, HEX);
Serial.println(" !");
break;
}
} else if (err == 4) {
Serial.print("Unknow error at address 0x");
if (addr < 16) {
Serial.print("0");
}
Serial.println(addr, HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
Serial.println("Scan for devices is complete.");
Serial.println("\n");
Serial.printf("GPS RX pin: %d", PIN_GPS_RX);
Serial.printf(" GPS TX pin: %d", PIN_GPS_TX);
Serial.println();
}
void TBeamBoard::printPMU()
{
Serial.print("isCharging:"); Serial.println(PMU->isCharging() ? "YES" : "NO");
Serial.print("isDischarge:"); Serial.println(PMU->isDischarge() ? "YES" : "NO");
Serial.print("isVbusIn:"); Serial.println(PMU->isVbusIn() ? "YES" : "NO");
Serial.print("getBattVoltage:"); Serial.print(PMU->getBattVoltage()); Serial.println("mV");
Serial.print("getVbusVoltage:"); Serial.print(PMU->getVbusVoltage()); Serial.println("mV");
Serial.print("getSystemVoltage:"); Serial.print(PMU->getSystemVoltage()); Serial.println("mV");
// The battery percentage may be inaccurate at first use, the PMU will automatically
// learn the battery curve and will automatically calibrate the battery percentage
// after a charge and discharge cycle
if (PMU->isBatteryConnect()) {
Serial.print("getBatteryPercent:"); Serial.print(PMU->getBatteryPercent()); Serial.println("%");
}
Serial.println();
}
#endif
bool TBeamBoard::power_init()
{
if (!PMU) {
#ifdef TBEAM_SUPREME_SX1262
PMU = new XPowersAXP2101(PMU_WIRE_PORT, PIN_BOARD_SDA1, PIN_BOARD_SCL1, I2C_PMU_ADD);
#else
PMU = new XPowersAXP2101(PMU_WIRE_PORT, PIN_BOARD_SDA, PIN_BOARD_SCL, I2C_PMU_ADD);
#endif
if (!PMU->init()) {
MESH_DEBUG_PRINTLN("Warning: Failed to find AXP2101 power management");
delete PMU;
PMU = NULL;
} else {
MESH_DEBUG_PRINTLN("AXP2101 PMU init succeeded, using AXP2101 PMU");
}
}
if (!PMU) {
PMU = new XPowersAXP192(PMU_WIRE_PORT, PIN_BOARD_SDA, PIN_BOARD_SCL, I2C_PMU_ADD);
if (!PMU->init()) {
MESH_DEBUG_PRINTLN("Warning: Failed to find AXP192 power management");
delete PMU;
PMU = NULL;
} else {
MESH_DEBUG_PRINTLN("AXP192 PMU init succeeded, using AXP192 PMU");
}
}
if (!PMU) {
return false;
}
deviceOnline |= POWERMANAGE_ONLINE;
PMU->setChargingLedMode(XPOWERS_CHG_LED_CTRL_CHG);
// Set up PMU interrupts
pinMode(PIN_PMU_IRQ, INPUT_PULLUP);
attachInterrupt(PIN_PMU_IRQ, setPmuFlag, FALLING);
if (PMU->getChipModel() == XPOWERS_AXP192) {
PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300); //Set up LoRa power rail
PMU->enablePowerOutput(XPOWERS_LDO2); //Enable the LoRa power rail
PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300); //Set up OLED power rail
PMU->enablePowerOutput(XPOWERS_DCDC1); //Enable the OLED power rail
PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300); //Set up GPS power rail
PMU->enablePowerOutput(XPOWERS_LDO3); //Enable the GPS power rail
PMU->setProtectedChannel(XPOWERS_DCDC1); //Protect the OLED power rail
PMU->setProtectedChannel(XPOWERS_DCDC3); //Protect the ESP32 power rail
PMU->disablePowerOutput(XPOWERS_DCDC2); //Disable unsused power rail DC2
PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ); //Disable PMU IRQ
PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_450MA); //Set battery charging current
PMU->setChargeTargetVoltage(XPOWERS_AXP192_CHG_VOL_4V2); //Set battery charge-stop voltage
}
else if(PMU->getChipModel() == XPOWERS_AXP2101){
#ifdef TBEAM_SUPREME_SX1262
//Set up the GPS power rail
PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO4);
//Set up the LoRa power rail
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO3);
//Set up power rail for the M.2 interface
PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300);
PMU->enablePowerOutput(XPOWERS_DCDC3);
if (ESP_SLEEP_WAKEUP_UNDEFINED == esp_sleep_get_wakeup_cause()) {
MESH_DEBUG_PRINTLN("Power off and restart ALDO BLDO..");
PMU->disablePowerOutput(XPOWERS_ALDO1);
PMU->disablePowerOutput(XPOWERS_ALDO2);
PMU->disablePowerOutput(XPOWERS_BLDO1);
delay(250);
}
//Set up power rail for QMC6310U
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO2);
//Set up power rail for BME280 and OLED
PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300);
PMU->enablePowerOutput(XPOWERS_ALDO1);
//Set up pwer rail for SD Card
PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300);
PMU->enablePowerOutput(XPOWERS_BLDO1);
//Set up power rail BLDO2 to headers
PMU->setPowerChannelVoltage(XPOWERS_BLDO2, 3300);
PMU->enablePowerOutput(XPOWERS_BLDO2);
//Set up power rail DCDC4 to headers
PMU->setPowerChannelVoltage(XPOWERS_DCDC4, XPOWERS_AXP2101_DCDC4_VOL2_MAX);
PMU->enablePowerOutput(XPOWERS_DCDC4);
//Set up power rail DCDC5 to headers
PMU->setPowerChannelVoltage(XPOWERS_DCDC5, 3300);
PMU->enablePowerOutput(XPOWERS_DCDC5);
//Disable unused power rails
PMU->disablePowerOutput(XPOWERS_DCDC2);
PMU->disablePowerOutput(XPOWERS_DLDO1);
PMU->disablePowerOutput(XPOWERS_DLDO2);
PMU->disablePowerOutput(XPOWERS_VBACKUP);
#else
//Turn off unused power rails
PMU->disablePowerOutput(XPOWERS_DCDC2);
PMU->disablePowerOutput(XPOWERS_DCDC3);
PMU->disablePowerOutput(XPOWERS_DCDC4);
PMU->disablePowerOutput(XPOWERS_DCDC5);
PMU->disablePowerOutput(XPOWERS_ALDO1);
PMU->disablePowerOutput(XPOWERS_ALDO4);
PMU->disablePowerOutput(XPOWERS_BLDO1);
PMU->disablePowerOutput(XPOWERS_BLDO2);
PMU->disablePowerOutput(XPOWERS_DLDO1);
PMU->disablePowerOutput(XPOWERS_DLDO2);
//PMU->disablePowerOutput(XPOWERS_CPULDO);
PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300); //Set up GPS RTC power
PMU->enablePowerOutput(XPOWERS_VBACKUP); //Turn on GPS RTC power
PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); //Set up LoRa power rail
PMU->enablePowerOutput(XPOWERS_ALDO2); //Enable LoRa power rail
PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); //Set up GPS power rail
PMU->enablePowerOutput(XPOWERS_ALDO3); //Enable GPS power rail
#endif
PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); //Disable all PMU interrupts
PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA); //Set battery charging current to 500mA
PMU->setChargeTargetVoltage(XPOWERS_AXP2101_CHG_VOL_4V2); //Set battery charging cutoff voltage to 4.2V
}
PMU->clearIrqStatus(); //Clear interrupt flags
PMU->disableTSPinMeasure(); //Disable TS detection, since it is not used
//Enable voltage measurements
PMU->enableSystemVoltageMeasure();
PMU->enableVbusVoltageMeasure();
PMU->enableBattVoltageMeasure();
#ifdef MESH_DEBUG
scanDevices(&Wire);
printPMU();
#endif
// Set the power key off press time
PMU->setPowerKeyPressOffTime(XPOWERS_POWEROFF_4S);
return true;
}
#pragma region "Debug code"
// void TBeamBoard::radiotype_detect(){
// static SPIClass spi;
// char chipTypeInfo;
// #if defined(P_LORA_SCLK)
// spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI);
// #endif
// for(int i = 0; i<radioVersions; i++){
// switch(i){
// case 0:
// CustomSX1262 radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi);
// int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8);
// if (status != RADIOLIB_ERR_NONE) {
// Serial.print("ERROR: SX1262 not found: ");
// Serial.println(status);
// //delete radio;
// radio = NULL;
// break;
// }
// else{
// MESH_DEBUG_PRINTLN("SX1262 detected");
// P_LORA_BUSY = 32;
// RADIO_CLASS = CustomSX1262;
// WRAPPER_CLASS = CustomSX1262Wrapper;
// SX126X_RX_BOOSTED_GAIN = true;
// SX126X_CURRENT_LIMIT = 140;
// //delete radio;
// radio = NULL;
// break;
// }
// case 1:
// SX1276 radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi);
// int status1 = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8);
// if (status1 != RADIOLIB_ERR_NONE) {
// Serial.print("ERROR: SX1272 not found: ");
// Serial.println(status1);
// //delete radio;
// radio = NULL;
// }
// else{
// MESH_DEBUG_PRINTLN("SX1272 detected");
// P_LORA_BUSY = RADIOLIB_NC;
// P_LORA_DIO_2 = 32;
// RADIO_CLASS = CustomSX1272;
// WRAPPER_CLASS = CustomSX1272Wrapper;
// SX127X_CURRENT_LIMIT = 120;
// //delete radio;
// radio = NULL;
// return;
// }
// default:
// }
// }
// }
#pragma endregion
#endif
-166
View File
@@ -1,166 +0,0 @@
#pragma once
#if defined(TBEAM_SUPREME_SX1262) || defined(TBEAM_SX1262) || defined(TBEAM_SX1276)
// Define pin mappings BEFORE including ESP32Board.h so sleep() can use P_LORA_DIO_1
#ifdef TBEAM_SUPREME_SX1262
// LoRa radio module pins for TBeam S3 Supreme SX1262
#define P_LORA_DIO_0 -1 //NC
#define P_LORA_DIO_1 1 //SX1262 IRQ pin
#define P_LORA_NSS 10 //SX1262 SS pin
#define P_LORA_RESET 5 //SX1262 Rest pin
#define P_LORA_BUSY 4 //SX1262 Busy pin
#define P_LORA_SCLK 12 //SX1262 SCLK pin
#define P_LORA_MISO 13 //SX1262 MISO pin
#define P_LORA_MOSI 11 //SX1262 MOSI pin
#define PIN_BOARD_SDA1 42 //SDA for PMU and PFC8563 (RTC)
#define PIN_BOARD_SCL1 41 //SCL for PMU and PFC8563 (RTC)
#define PIN_PMU_IRQ 40 //IRQ pin for PMU
// #define PIN_GPS_RX 9
// #define PIN_GPS_TX 8
// #define PIN_GPS_EN 7
#define P_BOARD_SPI_MOSI 35 //SPI for SD Card and QMI8653 (IMU)
#define P_BOARD_SPI_MISO 37 //SPI for SD Card and QMI8653 (IMU)
#define P_BOARD_SPI_SCK 36 //SPI for SD Card and QMI8653 (IMU)
#define P_BPARD_SPI_CS 47 //Pin for SD Card CS
#define P_BOARD_IMU_CS 34 //Pin for QMI8653 (IMU) CS
#define P_BOARD_IMU_INT 33 //IMU Int pin
#define P_BOARD_RTC_INT 14 //RTC Int pin
//I2C Wire addresses
#define I2C_BME280_ADD 0x76 //BME280 sensor I2C address on Wire
#define I2C_OLED_ADD 0x3C //SH1106 OLED I2C address on Wire
#define I2C_QMC6310U_ADD 0x1C //QMC6310U mag sensor I2C address on Wire
//I2C Wire1 addresses
#define I2C_RTC_ADD 0x51 //RTC I2C address on Wire1
#define I2C_PMU_ADD 0x34 //AXP2101 I2C address on Wire1
#define PMU_WIRE_PORT Wire1
#define RTC_WIRE_PORT Wire1
#endif
#ifdef TBEAM_SX1262
#define P_LORA_BUSY 32
#endif
#ifdef TBEAM_SX1276
#define P_LORA_DIO_2 32
#define P_LORA_BUSY RADIOLIB_NC
#endif
#if defined(TBEAM_SX1262) || defined(TBEAM_SX1276)
// LoRa radio module pins for TBeam
// uint32_t P_LORA_BUSY = 0; //shared, so define at run
// uint32_t P_LORA_DIO_2 = 0; //SX1276 only, so define at run
#define P_LORA_DIO_0 26
#define P_LORA_DIO_1 33
#define P_LORA_NSS 18
#define P_LORA_RESET 23
#define P_LORA_SCLK 5
#define P_LORA_MISO 19
#define P_LORA_MOSI 27
// #define PIN_GPS_RX 34
// #define PIN_GPS_TX 12
#define PIN_PMU_IRQ 35
#define PMU_WIRE_PORT Wire
#define RTC_WIRE_PORT Wire
#define I2C_PMU_ADD 0x34
#endif
// enum RadioType {
// SX1262,
// SX1276
// };
// Include headers AFTER pin definitions so ESP32Board::sleep() can use P_LORA_DIO_1
#include <Wire.h>
#include <Arduino.h>
#include "XPowersLib.h"
#include "helpers/ESP32Board.h"
#include <driver/rtc_io.h>
class TBeamBoard : public ESP32Board {
XPowersLibInterface *PMU = NULL;
//PhysicalLayer * pl;
//RadioType * radio = NULL;
// int radioVersions = 2;
enum {
POWERMANAGE_ONLINE = _BV(0),
DISPLAY_ONLINE = _BV(1),
RADIO_ONLINE = _BV(2),
GPS_ONLINE = _BV(3),
PSRAM_ONLINE = _BV(4),
SDCARD_ONLINE = _BV(5),
AXDL345_ONLINE = _BV(6),
BME280_ONLINE = _BV(7),
BMP280_ONLINE = _BV(8),
BME680_ONLINE = _BV(9),
QMC6310_ONLINE = _BV(10),
QMI8658_ONLINE = _BV(11),
PCF8563_ONLINE = _BV(12),
OSC32768_ONLINE = _BV(13),
};
bool power_init();
//void radiotype_detect();
public:
#ifdef MESH_DEBUG
void printPMU();
void scanDevices(TwoWire *w);
#endif
void begin();
#ifndef TBEAM_SUPREME_SX1262
void onBeforeTransmit() override{
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED on - invert pin for SX1276
}
void onAfterTransmit() override{
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED off - invert pin for SX1276
}
#endif
void enterDeepSleep(uint32_t secs, int pin_wake_btn) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
if (pin_wake_btn < 0) {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet
} else {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet OR wake btn
}
if (secs > 0) {
esp_sleep_enable_timer_wakeup(secs * 1000000);
}
// Finally set ESP32 into sleep
esp_deep_sleep_start(); // CPU halts here and never returns!
}
uint16_t getBattMilliVolts(){
return PMU->getBattVoltage();
}
const char* getManufacturerName() const{
return "LilyGo T-Beam";
}
};
#endif
+6 -1
View File
@@ -6,6 +6,7 @@
class DisplayDriver {
int _w, _h;
protected:
uint8_t _fontStyle = 0; // 0=Classic, 1=Noto Sans, 2=Montserrat
DisplayDriver(int w, int h) { _w = w; _h = h; }
public:
enum Color { DARK=0, LIGHT, RED, GREEN, BLUE, YELLOW, ORANGE }; // on b/w screen, colors will be !=0 synonym of light
@@ -13,6 +14,10 @@ public:
int width() const { return _w; }
int height() const { return _h; }
// Font style — controls typeface used by setTextSize()
void setFontStyle(uint8_t s) { _fontStyle = s; }
uint8_t getFontStyle() const { return _fontStyle; }
virtual bool isOn() = 0;
virtual void turnOn() = 0;
virtual void turnOff() = 0;
@@ -97,4 +102,4 @@ public:
}
virtual void endFrame() = 0;
};
};
+11 -1
View File
@@ -117,13 +117,23 @@ void FastEPDDisplay::startFrame(Color bkg) {
_frameCRC.reset();
_frameCRC.update<bool>(_darkMode);
_frameCRC.update<bool>(_portraitMode);
_frameCRC.update<uint8_t>(_fontStyle);
}
void FastEPDDisplay::setTextSize(int sz) {
if (!_canvas) return;
_frameCRC.update<int>(sz);
// Font mapping for 960×540 display at ~234 DPI
// Check for custom font style first (Noto Sans, Montserrat)
const GFXfont* customFont = meckGetFont(_fontStyle, sz);
if (customFont) {
_canvas->setFont(customFont);
// textSize 5 (clock face) uses ×5 scaling even with custom fonts
_canvas->setTextSize(sz == 5 ? 5 : 1);
return;
}
// Classic style (or fallback) — original FreeSans/FreeSerif fonts
// Toggle between font families via -D MECK_SERIF_FONT build flag
switch(sz) {
case 0: // Body text — reader content, settings rows, messages, footers
+3
View File
@@ -24,6 +24,9 @@
#include <Fonts/FreeSerif12pt7b.h>
#include <Fonts/FreeSerif18pt7b.h>
// Meck custom font styles (Noto Sans, Montserrat)
#include "MeckFonts.h"
#include "DisplayDriver.h"
// GxEPD2 color constant compatibility — MapScreen uses these directly
+12
View File
@@ -98,6 +98,18 @@ void GxEPDDisplay::startFrame(Color bkg) {
void GxEPDDisplay::setTextSize(int sz) {
display_crc.update<int>(sz);
display_crc.update<uint8_t>(_fontStyle);
// Check for custom font style first (Noto Sans, Montserrat)
const GFXfont* customFont = meckGetFont(_fontStyle, sz);
if (customFont) {
display.setFont(customFont);
// textSize 5 (clock face) uses ×2 scaling even with custom fonts
display.setTextSize(sz == 5 ? 2 : 1);
return;
}
// Classic style (or fallback) — original FreeSans fonts
switch(sz) {
case 0: // Tiny - built-in 6x8 pixel font
display.setFont(NULL);
+3
View File
@@ -19,6 +19,9 @@
#include <Fonts/FreeSansBold12pt7b.h>
#include <Fonts/FreeSans18pt7b.h>
// Meck custom font styles (Noto Sans, Montserrat)
#include "MeckFonts.h"
// Inline CRC32 for frame change detection (replaces bakercp/CRC32
// to avoid naming collision with PNGdec's bundled CRC32.h)
class FrameCRC32 {
+97
View File
@@ -0,0 +1,97 @@
#pragma once
#include <Arduino.h>
#include <helpers/RefCountedDigitalPin.h>
#include <helpers/ESP32Board.h>
// built-ins
#ifndef PIN_VBAT_READ // set in platformio.ini for boards like Heltec Wireless Paper (20)
#define PIN_VBAT_READ 1
#endif
#ifndef PIN_ADC_CTRL // set in platformio.ini for Heltec Wireless Tracker (2)
#define PIN_ADC_CTRL 37
#endif
#define PIN_ADC_CTRL_ACTIVE LOW
#define PIN_ADC_CTRL_INACTIVE HIGH
#include <driver/rtc_io.h>
class HeltecV3Board : public ESP32Board {
private:
bool adc_active_state;
public:
RefCountedDigitalPin periph_power;
HeltecV3Board() : periph_power(PIN_VEXT_EN) { }
void begin() {
ESP32Board::begin();
// Auto-detect correct ADC_CTRL pin polarity (different for boards >3.2)
pinMode(PIN_ADC_CTRL, INPUT);
adc_active_state = !digitalRead(PIN_ADC_CTRL);
pinMode(PIN_ADC_CTRL, OUTPUT);
digitalWrite(PIN_ADC_CTRL, !adc_active_state); // Initially inactive
periph_power.begin();
esp_reset_reason_t reason = esp_reset_reason();
if (reason == ESP_RST_DEEPSLEEP) {
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
startup_reason = BD_STARTUP_RX_PACKET;
}
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
}
}
void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
if (pin_wake_btn < 0) {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet
} else {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet OR wake btn
}
if (secs > 0) {
esp_sleep_enable_timer_wakeup(secs * 1000000);
}
// Finally set ESP32 into sleep
esp_deep_sleep_start(); // CPU halts here and never returns!
}
void powerOff() override {
enterDeepSleep(0);
}
uint16_t getBattMilliVolts() override {
analogReadResolution(10);
digitalWrite(PIN_ADC_CTRL, adc_active_state);
uint32_t raw = 0;
for (int i = 0; i < 8; i++) {
raw += analogRead(PIN_VBAT_READ);
}
raw = raw / 8;
digitalWrite(PIN_ADC_CTRL, !adc_active_state);
return (5.42 * (3.3 / 1024.0) * raw) * 1000;
}
const char* getManufacturerName() const override {
return "Heltec V3";
}
};
+61
View File
@@ -0,0 +1,61 @@
[Heltec_lora32_v3]
extends = esp32_base
board = esp32-s3-devkitc-1
build_flags =
${esp32_base.build_flags}
${sensor_base.build_flags}
-I variants/heltec_v3
-D HELTEC_LORA_V3
-D ESP32_CPU_FREQ=80
-D P_LORA_DIO_1=14
-D P_LORA_NSS=8
-D P_LORA_RESET=RADIOLIB_NC
-D P_LORA_BUSY=13
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
; -D P_LORA_TX_LED=35
-D PIN_BOARD_SDA=17
-D PIN_BOARD_SCL=18
-D PIN_USER_BTN=0
-D PIN_VEXT_EN=36
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D PIN_GPS_RX=47
-D PIN_GPS_TX=48
-D PIN_GPS_EN=26
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/heltec_v3>
+<helpers/sensors>
lib_deps =
${esp32_base.lib_deps}
${sensor_base.lib_deps}
[env:meck_wifi_repeater_heltec_v3]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"WiFi Repeater"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
-D MECK_WIFI_REMOTE=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/simple_repeater>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
knolleary/PubSubClient @ ^2.8
bakercp/CRC32 @ ^2.0.0
+61
View File
@@ -0,0 +1,61 @@
#include <Arduino.h>
#include "target.h"
HeltecV3Board board;
#if defined(P_LORA_SCLK)
static SPIClass spi;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
#else
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY);
#endif
WRAPPER_CLASS radio_driver(radio, board);
ESP32RTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
#include <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
#endif
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif
bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
#if defined(P_LORA_SCLK)
return radio.std_init(&spi);
#else
return radio.std_init();
#endif
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(int8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <HeltecV3Board.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/SensorManager.h>
#include <helpers/sensors/EnvironmentSensorManager.h>
#ifdef DISPLAY_CLASS
#include <helpers/ui/SSD1306Display.h>
#include <helpers/ui/MomentaryButton.h>
#endif
extern HeltecV3Board board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
extern EnvironmentSensorManager sensors;
#ifdef DISPLAY_CLASS
extern DISPLAY_CLASS display;
extern MomentaryButton user_btn;
#endif
bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();
+103
View File
@@ -0,0 +1,103 @@
#include "HeltecV4Board.h"
void HeltecV4Board::begin() {
ESP32Board::begin();
pinMode(PIN_ADC_CTRL, OUTPUT);
digitalWrite(PIN_ADC_CTRL, LOW); // Initially inactive
// Set up digital GPIO registers before releasing RTC hold. The hold latches
// the pad state including function select, so register writes accumulate
// without affecting the pad. On hold release, all changes apply atomically
// (IO MUX switches to digital GPIO with output already HIGH — no glitch).
pinMode(P_LORA_PA_POWER, OUTPUT);
digitalWrite(P_LORA_PA_POWER,HIGH);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_POWER);
pinMode(P_LORA_PA_EN, OUTPUT);
digitalWrite(P_LORA_PA_EN,HIGH);
rtc_gpio_hold_dis((gpio_num_t)P_LORA_PA_EN);
pinMode(P_LORA_PA_TX_EN, OUTPUT);
digitalWrite(P_LORA_PA_TX_EN,LOW);
esp_reset_reason_t reason = esp_reset_reason();
if (reason != ESP_RST_DEEPSLEEP) {
delay(1); // GC1109 startup time after cold power-on
}
periph_power.begin();
if (reason == ESP_RST_DEEPSLEEP) {
long wakeup_source = esp_sleep_get_ext1_wakeup_status();
if (wakeup_source & (1 << P_LORA_DIO_1)) { // received a LoRa packet (while in deep sleep)
startup_reason = BD_STARTUP_RX_PACKET;
}
rtc_gpio_hold_dis((gpio_num_t)P_LORA_NSS);
rtc_gpio_deinit((gpio_num_t)P_LORA_DIO_1);
}
}
void HeltecV4Board::onBeforeTransmit(void) {
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED on
digitalWrite(P_LORA_PA_TX_EN,HIGH);
}
void HeltecV4Board::onAfterTransmit(void) {
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off
digitalWrite(P_LORA_PA_TX_EN,LOW);
}
void HeltecV4Board::enterDeepSleep(uint32_t secs, int pin_wake_btn) {
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
// Make sure the DIO1 and NSS GPIOs are hold on required levels during deep sleep
rtc_gpio_set_direction((gpio_num_t)P_LORA_DIO_1, RTC_GPIO_MODE_INPUT_ONLY);
rtc_gpio_pulldown_en((gpio_num_t)P_LORA_DIO_1);
rtc_gpio_hold_en((gpio_num_t)P_LORA_NSS);
// Hold GC1109 FEM pins during sleep to keep LNA active for RX wake
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_POWER);
rtc_gpio_hold_en((gpio_num_t)P_LORA_PA_EN);
if (pin_wake_btn < 0) {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet
} else {
esp_sleep_enable_ext1_wakeup( (1L << P_LORA_DIO_1) | (1L << pin_wake_btn), ESP_EXT1_WAKEUP_ANY_HIGH); // wake up on: recv LoRa packet OR wake btn
}
if (secs > 0) {
esp_sleep_enable_timer_wakeup(secs * 1000000);
}
// Finally set ESP32 into sleep
esp_deep_sleep_start(); // CPU halts here and never returns!
}
void HeltecV4Board::powerOff() {
enterDeepSleep(0);
}
uint16_t HeltecV4Board::getBattMilliVolts() {
analogReadResolution(10);
digitalWrite(PIN_ADC_CTRL, HIGH);
delay(10);
uint32_t raw = 0;
for (int i = 0; i < 8; i++) {
raw += analogRead(PIN_VBAT_READ);
}
raw = raw / 8;
digitalWrite(PIN_ADC_CTRL, LOW);
return (5.42 * (3.3 / 1024.0) * raw) * 1000;
}
const char* HeltecV4Board::getManufacturerName() const {
#ifdef HELTEC_LORA_V4_TFT
return "Heltec V4 TFT";
#else
return "Heltec V4 OLED";
#endif
}
+23
View File
@@ -0,0 +1,23 @@
#pragma once
#include <Arduino.h>
#include <helpers/RefCountedDigitalPin.h>
#include <helpers/ESP32Board.h>
#include <driver/rtc_io.h>
class HeltecV4Board : public ESP32Board {
public:
RefCountedDigitalPin periph_power;
HeltecV4Board() : periph_power(PIN_VEXT_EN,PIN_VEXT_EN_ACTIVE) { }
void begin();
void onBeforeTransmit(void) override;
void onAfterTransmit(void) override;
void enterDeepSleep(uint32_t secs, int pin_wake_btn = -1);
void powerOff() override;
uint16_t getBattMilliVolts() override;
const char* getManufacturerName() const override ;
};
+61
View File
@@ -0,0 +1,61 @@
# Heltec V4 WiFi Remote Repeater — Setup Guide
## Variant Files
Copy the following into `variants/heltec_v4/`:
- `HeltecV4Board.h`, `HeltecV4Board.cpp`
- `target.h`, `target.cpp`
- `pins_arduino.h`
Copy `heltec_v4.json` into `boards/`
## Config Files (SPIFFS)
The Heltec V4 has no SD card slot — config lives in SPIFFS.
Create a `data/remote/` folder in your project root:
```
data/
remote/
wifi.cfg
mqtt.cfg
```
### data/remote/wifi.cfg
```
YourSSID
YourPassword
BackupSSID
BackupPassword
```
### data/remote/mqtt.cfg
```
6818ce5f77dd45bb90facf753ba81d81.s1.eu.hivemq.cloud
8883
meckremote
yourpassword
heltec-wifi-1
```
### Upload config to SPIFFS
```bash
pio run -e meck_wifi_repeater_heltec_v4 -t uploadfs
```
This uploads the `data/` folder contents to SPIFFS on the device.
### Flash firmware
```bash
pio run -e meck_wifi_repeater_heltec_v4 -t upload
```
## Notes
- The OLED display shows basic repeater status (same as stock repeater)
- WiFi MQTT and Mycelium dashboard work identically to T-Deck Pro builds
- OTA firmware updates work over WiFi via the Mycelium dashboard
- Config changes require re-uploading SPIFFS (`-t uploadfs`)
- The same `main.cpp`, `WiFiMQTT.h/cpp`, and `MyMesh.cpp` are shared
with T-Deck Pro and T5S3 builds — no Heltec-specific source changes
+67
View File
@@ -0,0 +1,67 @@
#ifndef Pins_Arduino_h
#define Pins_Arduino_h
#include <stdint.h>
static const uint8_t LED_BUILTIN = 35;
#define BUILTIN_LED LED_BUILTIN // backward compatibility
#define LED_BUILTIN LED_BUILTIN // allow testing #ifdef LED_BUILTIN
static const uint8_t TX = 43;
static const uint8_t RX = 44;
static const uint8_t SDA = 3;
static const uint8_t SCL = 4;
static const uint8_t SS = 8;
static const uint8_t MOSI = 10;
static const uint8_t MISO = 11;
static const uint8_t SCK = 9;
static const uint8_t A0 = 1;
static const uint8_t A1 = 2;
static const uint8_t A2 = 3;
static const uint8_t A3 = 4;
static const uint8_t A4 = 5;
static const uint8_t A5 = 6;
static const uint8_t A6 = 7;
static const uint8_t A7 = 8;
static const uint8_t A8 = 9;
static const uint8_t A9 = 10;
static const uint8_t A10 = 11;
static const uint8_t A11 = 12;
static const uint8_t A12 = 13;
static const uint8_t A13 = 14;
static const uint8_t A14 = 15;
static const uint8_t A15 = 16;
static const uint8_t A16 = 17;
static const uint8_t A17 = 18;
static const uint8_t A18 = 19;
static const uint8_t A19 = 20;
static const uint8_t T1 = 1;
static const uint8_t T2 = 2;
static const uint8_t T3 = 3;
static const uint8_t T4 = 4;
static const uint8_t T5 = 5;
static const uint8_t T6 = 6;
static const uint8_t T7 = 7;
static const uint8_t T8 = 8;
static const uint8_t T9 = 9;
static const uint8_t T10 = 10;
static const uint8_t T11 = 11;
static const uint8_t T12 = 12;
static const uint8_t T13 = 13;
static const uint8_t T14 = 14;
static const uint8_t Vext = 36;
static const uint8_t LED = 35;
static const uint8_t RST_OLED = 21;
static const uint8_t SCL_OLED = 18;
static const uint8_t SDA_OLED = 17;
static const uint8_t RST_LoRa = 12;
static const uint8_t BUSY_LoRa = 13;
static const uint8_t DIO0 = 14;
#endif /* Pins_Arduino_h */
+208
View File
@@ -0,0 +1,208 @@
[Heltec_lora32_v4]
extends = esp32_base
board = heltec_v4
build_flags =
${esp32_base.build_flags}
${sensor_base.build_flags}
-I variants/heltec_v4
-D HELTEC_LORA_V4
-D USE_SX1262
-D ESP32_CPU_FREQ=80
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D P_LORA_TX_LED=35
-D P_LORA_DIO_1=14
-D P_LORA_NSS=8
-D P_LORA_RESET=12
-D P_LORA_BUSY=13
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D P_LORA_PA_POWER=7 ; VFEM_Ctrl - Power on GC1109
-D P_LORA_PA_EN=2 ; PA CSD - Enable GC1109
-D P_LORA_PA_TX_EN=46 ; PA CPS - GC1109 TX PA full(High) / bypass(Low)
-D PIN_USER_BTN=0
-D PIN_VEXT_EN=36
-D PIN_VEXT_EN_ACTIVE=HIGH
-D LORA_TX_POWER=10 ;If it is configured as 10 here, the final output will be 22 dbm.
-D MAX_LORA_TX_POWER=22 ; Max SX1262 output
-D SX126X_REGISTER_PATCH=1 ; Patch register 0x8B5 for improved RX
-D SX126X_DIO2_AS_RF_SWITCH=true ; GC1109 CTX is controlled by SX1262 DIO2
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1 ; In some cases, commenting this out will improve RX
-D PIN_GPS_RX=38
-D PIN_GPS_TX=39
-D PIN_GPS_RESET=42
-D PIN_GPS_RESET_ACTIVE=LOW
-D PIN_GPS_EN=34
-D PIN_GPS_EN_ACTIVE=LOW
-D ENV_INCLUDE_GPS=1
-D PIN_ADC_CTRL=37
-D PIN_VBAT_READ=1
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/heltec_v4>
+<helpers/sensors>
lib_deps =
${esp32_base.lib_deps}
${sensor_base.lib_deps}
[heltec_v4_oled]
extends = Heltec_lora32_v4
build_flags =
${Heltec_lora32_v4.build_flags}
-D HELTEC_LORA_V4_OLED
-D PIN_BOARD_SDA=17
-D PIN_BOARD_SCL=18
-D PIN_OLED_RESET=21
build_src_filter= ${Heltec_lora32_v4.build_src_filter}
lib_deps = ${Heltec_lora32_v4.lib_deps}
[heltec_v4_tft]
extends = Heltec_lora32_v4
build_flags =
${Heltec_lora32_v4.build_flags}
-D HELTEC_LORA_V4_TFT
-D PIN_BOARD_SDA=4
-D PIN_BOARD_SCL=3
-D DISPLAY_SCALE_X=2.5
-D DISPLAY_SCALE_Y=3.75
-D PIN_TFT_RST=18
-D PIN_TFT_VDD_CTL=-1
-D PIN_TFT_LEDA_CTL=21
-D PIN_TFT_LEDA_CTL_ACTIVE=HIGH
-D PIN_TFT_CS=15
-D PIN_TFT_DC=16
-D PIN_TFT_SCL=17
-D PIN_TFT_SDA=33
build_src_filter= ${Heltec_lora32_v4.build_src_filter}
lib_deps =
${Heltec_lora32_v4.lib_deps}
adafruit/Adafruit ST7735 and ST7789 Library @ ^1.11.0
; ---------------------------------------------------------------------------
; Heltec V4 WiFi Remote Repeater — WiFi MQTT backhaul, remote management
; No SD card — config files stored in SPIFFS.
; Upload config: create data/remote/ folder with wifi.cfg and mqtt.cfg,
; then run: pio run -e meck_wifi_repeater_heltec_v4 -t uploadfs
; OLED display shows status (optional — works headless too)
; Flash: pio run -e meck_wifi_repeater_heltec_v4 -t upload
; ---------------------------------------------------------------------------
[env:meck_wifi_repeater_heltec_v4]
extends = heltec_v4_oled
upload_port = /dev/cu.usbmodem101
build_src_filter = ${heltec_v4_oled.build_src_filter}
+<helpers/esp32/*.cpp>
-<helpers/esp32/SerialBLEInterface.cpp>
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/simple_repeater/*.cpp>
build_flags =
${heltec_v4_oled.build_flags}
-D FIRMWARE_VERSION='"Meck HV4 WiFi Rptr v0.1"'
-D FIRMWARE_BUILD_DATE='"5 Apr 2026"'
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"Heltec Repeater"'
-D ADMIN_PASSWORD='"password"'
-D MECK_WIFI_REMOTE
-D MECK_REMOTE_REPEATER=1
-D DISABLE_WIFI_OTA=1
-D MAX_NEIGHBOURS=50
-D RADIOLIB_EXCLUDE_CC1101=1
-D RADIOLIB_EXCLUDE_NRF24=1
-D RADIOLIB_EXCLUDE_RF69=1
-D RADIOLIB_EXCLUDE_SX1231=1
-D RADIOLIB_EXCLUDE_SX1233=1
-D RADIOLIB_EXCLUDE_SI443X=1
-D RADIOLIB_EXCLUDE_RFM2X=1
-D RADIOLIB_EXCLUDE_SX127X=1
-D RADIOLIB_EXCLUDE_SX1272=1
-D RADIOLIB_EXCLUDE_SX1278=1
-D RADIOLIB_EXCLUDE_STM32WLX=1
-D RADIOLIB_EXCLUDE_LR11X0=1
-D RADIOLIB_EXCLUDE_LLCC68=1
-D RADIOLIB_EXCLUDE_SX128X=1
-D RADIOLIB_EXCLUDE_AFSK=1
-D RADIOLIB_EXCLUDE_AX25=1
-D RADIOLIB_EXCLUDE_HELLSCHREIBER=1
-D RADIOLIB_EXCLUDE_MORSE=1
-D RADIOLIB_EXCLUDE_RTTY=1
-D RADIOLIB_EXCLUDE_SSTV=1
-D RADIOLIB_EXCLUDE_APRS=1
-D RADIOLIB_EXCLUDE_LORAWAN=1
-D RADIOLIB_EXCLUDE_PAGER=1
-D RADIOLIB_EXCLUDE_FSK4=1
-D RADIOLIB_EXCLUDE_BELL=1
lib_deps =
${heltec_v4_oled.lib_deps}
knolleary/PubSubClient@^2.8
lib_ignore =
ESP32 BLE Arduino
AsyncTCP
RPAsyncTCP
ESPAsyncWebServer
AsyncElegantOTA
ESP32-audioI2S
esp32_codec2_arduino
board_build.partitions = default_16MB.csv
board_build.filesystem = spiffs
; ---------------------------------------------------------------------------
; Heltec V4 WiFi Remote Repeater — HEADLESS (no display)
; ---------------------------------------------------------------------------
[env:meck_wifi_repeater_heltec_v4_headless]
extends = Heltec_lora32_v4
upload_port = /dev/cu.usbmodem101
build_src_filter = ${Heltec_lora32_v4.build_src_filter}
+<helpers/esp32/*.cpp>
-<helpers/esp32/SerialBLEInterface.cpp>
+<../examples/simple_repeater/*.cpp>
build_flags =
${Heltec_lora32_v4.build_flags}
-D ESP32_CPU_FREQ=240
-D FIRMWARE_VERSION='"Meck HV4 WiFi Rptr v0.1"'
-D FIRMWARE_BUILD_DATE='"5 Apr 2026"'
-D ADVERT_NAME='"Heltec Repeater"'
-D ADMIN_PASSWORD='"password"'
-D MECK_WIFI_REMOTE
-D MECK_REMOTE_REPEATER=1
-D DISABLE_WIFI_OTA=1
-D MAX_NEIGHBOURS=50
-D RADIOLIB_EXCLUDE_CC1101=1
-D RADIOLIB_EXCLUDE_NRF24=1
-D RADIOLIB_EXCLUDE_RF69=1
-D RADIOLIB_EXCLUDE_SX1231=1
-D RADIOLIB_EXCLUDE_SX1233=1
-D RADIOLIB_EXCLUDE_SI443X=1
-D RADIOLIB_EXCLUDE_RFM2X=1
-D RADIOLIB_EXCLUDE_SX127X=1
-D RADIOLIB_EXCLUDE_SX1272=1
-D RADIOLIB_EXCLUDE_SX1278=1
-D RADIOLIB_EXCLUDE_STM32WLX=1
-D RADIOLIB_EXCLUDE_LR11X0=1
-D RADIOLIB_EXCLUDE_LLCC68=1
-D RADIOLIB_EXCLUDE_SX128X=1
-D RADIOLIB_EXCLUDE_AFSK=1
-D RADIOLIB_EXCLUDE_AX25=1
-D RADIOLIB_EXCLUDE_HELLSCHREIBER=1
-D RADIOLIB_EXCLUDE_MORSE=1
-D RADIOLIB_EXCLUDE_RTTY=1
-D RADIOLIB_EXCLUDE_SSTV=1
-D RADIOLIB_EXCLUDE_APRS=1
-D RADIOLIB_EXCLUDE_LORAWAN=1
-D RADIOLIB_EXCLUDE_PAGER=1
-D RADIOLIB_EXCLUDE_FSK4=1
-D RADIOLIB_EXCLUDE_BELL=1
lib_deps =
${Heltec_lora32_v4.lib_deps}
knolleary/PubSubClient@^2.8
lib_ignore =
ESP32 BLE Arduino
AsyncTCP
RPAsyncTCP
ESPAsyncWebServer
AsyncElegantOTA
ESP32-audioI2S
esp32_codec2_arduino
board_build.partitions = default_16MB.csv
board_build.filesystem = spiffs
+61
View File
@@ -0,0 +1,61 @@
#include <Arduino.h>
#include "target.h"
HeltecV4Board board;
#if defined(P_LORA_SCLK)
static SPIClass spi;
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
#else
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY);
#endif
WRAPPER_CLASS radio_driver(radio, board);
ESP32RTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
#include <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
#endif
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display(NULL);
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif
bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
#if defined(P_LORA_SCLK)
return radio.std_init(&spi);
#else
return radio.std_init();
#endif
}
uint32_t radio_get_rng_seed() {
return radio.random(0x7FFFFFFF);
}
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
radio.setFrequency(freq);
radio.setSpreadingFactor(sf);
radio.setBandwidth(bw);
radio.setCodingRate(cr);
}
void radio_set_tx_power(int8_t dbm) {
radio.setOutputPower(dbm);
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}
+35
View File
@@ -0,0 +1,35 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <HeltecV4Board.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/SensorManager.h>
#include <helpers/sensors/EnvironmentSensorManager.h>
#ifdef DISPLAY_CLASS
#ifdef HELTEC_LORA_V4_OLED
#include <helpers/ui/SSD1306Display.h>
#elif defined(HELTEC_LORA_V4_TFT)
#include <helpers/ui/ST7789LCDDisplay.h>
#endif
#include <helpers/ui/MomentaryButton.h>
#endif
extern HeltecV4Board board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
extern EnvironmentSensorManager sensors;
#ifdef DISPLAY_CLASS
extern DISPLAY_CLASS display;
extern MomentaryButton user_btn;
#endif
bool radio_init();
uint32_t radio_get_rng_seed();
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
void radio_set_tx_power(int8_t dbm);
mesh::LocalIdentity radio_new_identity();
@@ -24,7 +24,7 @@
#endif
#ifndef CPU_FREQ_LOW_POWER
#define CPU_FREQ_LOW_POWER 40 // MHz — lock screen / idle standby
#define CPU_FREQ_LOW_POWER 80 // MHz — lock screen / idle standby (40 MHz breaks I2C)
#endif
#ifndef CPU_BOOST_TIMEOUT_MS

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