Compare commits

...

191 Commits

Author SHA1 Message Date
Austin
9861e82f0a Manual bump metainfo version (#7049) 2025-06-15 20:16:33 -05:00
Ben Meadors
fcefd592e2 Update version.properties 2025-06-15 19:27:17 -05:00
Jonathan Bennett
8a8a7cdefc cppcheck-supress to ignore intentional error 2025-06-15 16:37:19 -05:00
Ben Meadors
8f9e569825 Create FUNDING.yml 2025-06-15 07:52:38 -05:00
Ben Meadors
b0c5327585 Trunk 2025-06-15 07:40:45 -05:00
Andy Shinn
f1dd623ce9 allow overriding INA3221 channels (#7035)
Co-authored-by: Jonathan Bennett <jbennett@incomsystems.biz>
2025-06-15 07:39:49 -05:00
Ben Meadors
ac52edd11a Add the ability to share ignored contacts (for blacklisting problematic nodes) (#7044) 2025-06-15 07:34:03 -05:00
github-actions[bot]
66d5dde956 [create-pull-request] automated change (#7043)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-06-15 06:45:00 -05:00
github-actions[bot]
7dfbcc8f1d Upgrade trunk (#7030)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-06-15 06:16:59 -05:00
renovate[bot]
28244148a2 chore(deps): update meshtastic/device-ui digest to 301f11e (#7042)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-15 06:14:53 -05:00
Jonathan Bennett
e623c70bd0 More clear key warning messages. 2025-06-14 19:35:57 -05:00
todd-herbert
425f384b1f InkHUD DIY builds for ProMicro & Heltec T114 (#7039)
* DIY InkHUD variants (ProMicro & T114)

* Fix file encoding
> We’ve detected the file encoding as ISO-8859-1. When you commit changes we will transcode it to UTF-8.

* Update comment justifying trunk suppression
2025-06-15 09:39:46 +10:00
Jonathan Bennett
1557219bad More low-entropy keys, and don't issue a false warning when changing … (#7041)
* More low-entropy keys, and don't issue a false warning when changing node name

* CopyPasta Wasn't Tasty

* When the phone sets the publickey size to 0, regenerate right away
2025-06-14 17:09:22 -05:00
Jonathan Bennett
691917b956 Add config for RAK 13300 on RAK6421 (#7037) 2025-06-14 09:59:25 -05:00
Ben Meadors
cc0fbfbd21 Fixed breaking of inkhud / tft suffix convention 2025-06-13 06:59:05 -05:00
Csrutil
5d0bf03b01 add support for GAT562 Mesh Trial Tracker (#6984)
* add support for GAT562 Mesh Trial Tracker

* Hardware Model Definition for GAT562_MESH_TRIAL_TRACKER

* Added RAK4630 for led pin 2 (blue)

* Added RAK4630 for led pin 2 (blue) comment

* don't touch src/mesh/NodeDB.cpp

* set fixed baudrate for gat562_mesh_trial_tracker

* adjust the order of the HW_VENDOR defines

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Tom Fifield <tom@tomfifield.net>
2025-06-13 17:27:48 +10:00
Jonathan Bennett
8ff99437cb Don't include the blank hash 2025-06-12 22:56:40 -05:00
todd-herbert
ba93097bb7 Add InkHUD driver for WeAct Studio 1.54" display module (#7000)
* Strip redundant code from E-Ink driver

* Begin polling for E-Ink update completion sooner
In some cases, we might be waiting longer than we need to.

* E-Ink driver for WeAct 1.54" display
Currently identical to the popular GDEY0154D67 model. Kept separate now in case the drivers need to diverge in future.

* Put back code which sets the number of gate lines
2025-06-12 19:59:28 -05:00
todd-herbert
de098cca4c E-Ink driver for WEAct 2.13" BW (#7001) 2025-06-12 19:58:38 -05:00
Christian Crank
8faa04afdb Validate short and long names so whitespace or empty names cannot be used (#6993)
* Say issue #6867 about adding validation for long_name and short_name. Firmware should expect at least 1 non-whitespace character for both long_name and short_name. added the USERPREFS_CONFIG_DEVICE_ROLE example to userPrefs.jsonc

* Validation for user long_name and short_name implemented. No longer can use whitespace characters. Return BAD_REQUEST error responses when validation fails and warning logs when validation rejects invalid names.

* Improve whitespace validation for user names with ctype.h, ensure logging works

* Add whitespace validation to ham mode to prevent validation bypass and to match python cli command

* punctuation change

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-06-12 19:58:15 -05:00
github-actions[bot]
fede1b8597 Upgrade trunk (#7006)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-06-12 19:56:53 -05:00
Tom Fifield
8557bd031d Remove GPS Baudrate locking for Seeed Xiao NRF52840 Kit (#7016)
The Seeed Xiao NRF52840 Kit's default GPS is an L76K which operates
at 9600 baud, so when this variant was defined that baud rate was
specified.

However, this is a development board and it is expected that users
can attach their own devices. This includes GPS, which may operate
at a different baud rate. The current fixed baud rate prevents this,
so this patch removes that setting.

This will revert to the regular automatic probe method. This will
sucessfully detect the L76K as before (probably the same as before
since 9600 baud is the first baud rate checked), but also allow other
GPSes at other baud rates to be detected.

Fixes https://github.com/meshtastic/firmware/issues/7012

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-06-12 19:56:40 -05:00
Chloe Bethel
4e6418b635 Don't use assert() with side effects in a couple more places (#7009)
* Don't use assert for Lock

* Don't use assert for MQTT messages

* Split assert in getMacAddr to always run the function

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-06-12 19:55:35 -05:00
Jonathan Bennett
a1a5503fe9 Another known key 2025-06-12 15:18:26 -05:00
Jonathan Bennett
3b94981e56 Key erase (#7018)
* Wipe keys if low entropy

* Client Notification Payload variant

* Don't call service before it's created

* Lucky Number 14

* Catch for low-entropy keys even before region is set
2025-06-12 12:13:39 -05:00
renovate[bot]
f299447216 chore(deps): update platform-native digest to 681ee02 (#7022)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-12 05:55:51 -05:00
github-actions[bot]
5f0c8863fd [create-pull-request] automated change (#7019)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-06-11 20:18:47 -05:00
renovate[bot]
f9d17cdee0 chore(deps): update platform-native digest to 49634e9 (#7020)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-11 20:18:28 -05:00
Ben Meadors
68a28a177f Add elecrow panels to BIGDB_16MB 2025-06-11 16:11:32 -05:00
Ben Meadors
60ec05e536 elecrow-adv-35-tft 2025-06-11 10:54:08 -05:00
Ben Meadors
730cd388d6 Fix pio 2025-06-11 08:49:20 -05:00
Ben Meadors
6549b0477c Missed a spot 2025-06-11 06:10:34 -05:00
Ben Meadors
8304cae010 Fix issue with CI not picking up elecrow panels due to confusing env 2025-06-11 06:09:25 -05:00
Ben Meadors
0ad9758cfd Revert "chore(deps): update meshtastic/web to v2.6.4 (#6950)" (#7015)
This reverts commit 76f7207463.
2025-06-10 18:51:54 -05:00
Jonathan Bennett
e5f6804421 Add boolean to only warn a user of a duplicated key once per boot 2025-06-10 13:28:36 -05:00
Mark Trevor Birss
720add72b2 Create lora-lyra-picocalc-wio-sx1262.yaml (#7010) 2025-06-10 16:07:24 +02:00
github-actions[bot]
693b11db1d [create-pull-request] automated change (#7007)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-06-10 06:47:41 -05:00
Jonathan Bennett
4bf2dd04ae Warn users about low entropy keys (#7003)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-06-10 06:33:13 -05:00
Andreas 'count' Kotes
c6c2a4d4dd Improve support for Heltec Wireless Bridge (#6647)
* Use BLE_LED where present for CONNECTED/DISCONNECTED

* Use WIFI_LED where present for WiFi started/stopped (as AP) or connected/disconnected (as Station)

* improve support for Heltec Wireless Bridge

* satisfy 'trunk fmt'
2025-06-10 13:54:07 +10:00
github-actions[bot]
79b8e7b1cf Upgrade trunk (#6998)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-06-10 13:53:04 +10:00
Travis Hardiman
cf4f088337 Update URL for ThinkNode M1 (#7005) 2025-06-10 13:52:30 +10:00
Travis Hardiman
22cb20d294 Update heltec t114 URL (#7004) 2025-06-10 13:51:37 +10:00
Clément Hampaï
1eacdd0629 [Variant] nomadstar meteor pro (#6742)
* Initial support for NomadStar Meteor Pro

* Cleaned up Platformio variant comments

* Removed RTC & ETH deps.

* Removed RGB NCP5623 deps, Enabled AmbientLight by default

* Added HWID mapping

* Updated Armduino-Semihosting lib dep with archived version.

* Fixed trunk linting in AmbientLightingThread.h and hydra variant
2025-06-10 07:48:52 +10:00
renovate[bot]
67e3d57412 chore(deps): update meshtastic/device-ui digest to 1b520fc (#6991)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-09 05:56:48 -05:00
Manuel
7924ef87b5 enable custom driver (#6988)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-06-09 05:41:41 -05:00
HarukiToreda
3dec521f75 T-watch screen misalignment fix (#6996)
* T-watch screen misalignment fix

* Trunk fix
2025-06-09 05:27:52 -05:00
renovate[bot]
57a33790ed chore(deps): update meshtastic/device-ui digest to 2fd19f8 (#6982)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-08 04:02:47 -05:00
renovate[bot]
484af8eb9f chore(deps): update platformio/ststm32 to v19.2.0 (#6901)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-08 17:54:20 +10:00
Christian Crank
b8970d66a1 Addition of Device Role inside of userPrefs.jsonc (#6972)
* addition of device.role via userprefs. USERPREFS_CONFIG_DEVICE_ROLE now usable, ROUTER*, LOST_AND_FOUND, and REPEATER disabled.

* Removing added IS_ONE_OF macro definition since meshUtils.h exists - thanks Ben!

* Fix clang-format issues in NodeDB.cpp utilizing Trunk
2025-06-08 16:51:37 +10:00
Mario Murphy
e78033bb85 Clean up install & update shell scripts (#6839)
Fixed quoting of the `FILENAME` variable to work when the path of the
passed argument contains a space. Also fixed syntactical issues called
out by `shellcheck` in multi-condition `if` statements.

Also normalized indentation chars (was mix of tabs & spaces) and
trailing whitespace.

Co-authored-by: Tom Fifield <tom@tomfifield.net>
2025-06-08 14:04:31 +10:00
Austin
8bd7adca47 Update Alpine to 3.22 (#6927) 2025-06-08 07:49:24 +10:00
renovate[bot]
f67aec40e8 chore(deps): update platformio/espressif32 to v6.11.0 (#6900)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-08 07:48:34 +10:00
github-actions[bot]
46c7d74760 Upgrade trunk (#6968)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-06-07 07:58:01 -05:00
Tom
15d2ae17f8 Add note to hydra to note that the button pin has no pull-up (#6979)
Add note to hydra to note that the button pin has no pull-up. Use an external resistor or remove the `#define`.
2025-06-07 06:55:58 -05:00
github-actions[bot]
91579c4650 [create-pull-request] automated change (#6980)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-06-07 06:55:25 -05:00
Andrew Yong
79b710a108 fix: Respect LED_STATE_ON for power and user LED (#6976)
Signed-off-by: Andrew Yong <me@ndoo.sg>
2025-06-07 06:44:54 -05:00
todd-herbert
ba296db701 Add InkHUD driver for WeAct Studio 2.9" display module (#6963)
* Driver for WeAct Studio 2.9" ePaper module

* Clarify that flex connector marking is not a unique id

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-06-06 17:35:47 +12:00
github-actions[bot]
c0e1616382 Upgrade trunk (#6948)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-06-05 10:11:43 -05:00
Andrew Yong
070deb290f seeed_xiao_nrf52840_kit improvements (#6930)
* feat: seeed_xiao_nrf52840_kit improvements
- LEDs:
  - Change RGB LED to be active low as it is common anode
  - Remove re-definition of LED_PIN
  - Use red LED to indicate flash writes
  - Use blue LED as user LED (External Notification module)
- GPIO: Re-word unused BUTTON_PIN comment
- Wire: Set I2C pins to match XIAO nRF52840 Sense's LSM6DS3TR IMU
- Battery:
  - Use charge LED to detect charging state
  - Move voltage divider boilerplate out of src/main.cpp and into initVariant()
  - Fix dependencies for above in related XIAO BLE DIY variants

Build tested variants:
- seeed_xiao_nrf52840_kit
- xiao_ble
- seeed-xiao-nrf52840-wio-sx1262

Flashed to and tested on hardware:
- seeed_xiao_nrf52840_kit

Signed-off-by: Andrew Yong <me@ndoo.sg>

* chore(seeed_xiao_nrf52840_kit): Re-order generic GPIO definitions

Signed-off-by: Andrew Yong <me@ndoo.sg>

* chore: Use ADC_CTRL for XIAO nRF52840

Signed-off-by: Andrew Yong <me@ndoo.sg>

---------

Signed-off-by: Andrew Yong <me@ndoo.sg>
2025-06-05 06:45:43 -05:00
renovate[bot]
76f7207463 chore(deps): update meshtastic/web to v2.6.4 (#6950)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-04 15:15:51 -05:00
Jonathan Bennett
55b2bbf937 Generate keys when Lora Region is set (#6951)
* Generate keys when Lora Region changes

* Nest the ifs

* Even more entropy

* Namespacing
2025-06-04 12:16:37 -05:00
github-actions[bot]
a5716cf25c automated bumps (#6944)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-06-03 07:08:46 -05:00
Kalle Lilja
4d81280ac2 Add --1200bps-reset param to device-install/update scripts (#6752)
* add change-mode support

* add change-mode support

* tab to space

* fix if check

* change param name to 1200bps-reset

* update help section

* missed one in help seciton

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-06-02 20:35:26 -05:00
renovate[bot]
9ce44556ce chore(deps): update meshtastic/device-ui digest to 649e095 (#6943)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 06:29:41 -05:00
github-actions[bot]
be0c7d73a3 Upgrade trunk (#6941)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-06-02 06:16:24 -05:00
renovate[bot]
d833a9ea61 chore(deps): update meshtastic/device-ui digest to 04e3a07 (#6942)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-06-02 06:16:01 -05:00
Jonathan Bennett
5cd74f4b53 Don't give LOG_INFO a null 2025-06-01 21:03:38 -05:00
renovate[bot]
284b8bcff2 chore(deps): update meshtastic/device-ui digest to 37e2fb8 (#6925)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-31 06:15:37 -05:00
github-actions[bot]
9799f10e63 Upgrade trunk (#6922)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-30 08:38:13 -05:00
ArgoNavi
f9d4fdbb52 Update TSL2591Sensor.cpp (#6921)
Lower gain and timing to avoid saturation in bright light
2025-05-30 06:00:20 -05:00
Austin
b6cb0b148c Fix renovate for Adafruit PCT2075 (#6919) 2025-05-30 07:33:10 +10:00
Ben Meadors
7a7166d575 Revert "Add a new screen for heltec_wireless_paper. (#6894)" (#6918)
This reverts commit ba53543354.
2025-05-29 10:17:20 -05:00
Quency-D
ba53543354 Add a new screen for heltec_wireless_paper. (#6894)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-29 09:10:25 -05:00
dmarman
cb9429e83e Added full support for LTR390UV readings of UV and Lux (#6872)
* Added full support for LTR390UV readings of UV and Lux

* Trunk formatting

* Added full support for LTR390UV readings of UV and Lux

* Trunk formatting

* fix library check and unnecessary bit resolution change

* fixed log info messages and removed unused dependency

* Hopefully fixes git mess

* fix variable scope and getMetrics returns

* set metrics flags bavk to false in case something wrong happens while reading LTR390UV  mode

---------

Co-authored-by: Domingo <domingo@waxman.local>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-29 09:09:33 -05:00
github-actions[bot]
f972b62d89 Upgrade trunk to 1.24.0 (#6915)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-29 09:06:52 -05:00
Ben Meadors
7849a3d291 Trunk 2025-05-29 06:35:18 -05:00
dylanli
c0c2ec195f add support for seeed wio tracker L1 (#6907)
* add support for seeed  wio tracker l1

* add support in nrf52 arch

* fix ADC problem and comments incorrect

* fix gps wakeup pin

* fix gps pin
2025-05-29 06:33:22 -05:00
renovate[bot]
e31cd0bc77 chore(deps): update meshtastic/device-ui digest to 3dfcc97 (#6912)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-29 06:27:36 -05:00
todd-herbert
5195815df0 Parse own short name in LogoApplet (#6913) 2025-05-29 06:21:09 -05:00
Ben Meadors
42a80d8aed Coerce user.id to always be derive from the nodenum (#6906)
* Coerce user.id to always be derive from the nodenum

* Additionally null it out on send

* Revert "Additionally null it out on send"

This reverts commit 22a2d68723.
2025-05-28 11:30:59 -05:00
github-actions[bot]
da69d88790 [create-pull-request] automated change (#6909)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-28 06:20:51 -05:00
Thomas Göttgens
96c18d9908 Add LINK32 (Lilygo) Board with Light+Environment sensors (#6899)
* Add LINK32 (Lilygo) Board with Light+Environment sensors
TODO: replace PRIVATE_HW with actual HWID

* Add LINK32 (Lilygo) Board with Light+Environment sensors
TODO: replace PRIVATE_HW with actual HWID

* Update to real HWID and trunk fmt
2025-05-27 18:11:32 -05:00
GUVWAF
8908805894 Don't cancel sending ReTx for relayer if we're ROUTER(_LATE)/REPEATER (#6904)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-27 18:10:14 -05:00
github-actions[bot]
158c88ddef [create-pull-request] automated change (#6905)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2025-05-27 15:41:35 -05:00
github-actions[bot]
138dc89442 Upgrade trunk (#6898)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-27 06:19:35 -05:00
Austin
baefda213a Linux: Adjust udev rules for gpio (#6891) 2025-05-26 06:31:10 -05:00
github-actions[bot]
106dd08710 automated bumps (#6890)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-25 16:53:02 -05:00
todd-herbert
f223b8a55d Add missing parsing of UTF-8 chars (#6889) 2025-05-25 13:12:52 -05:00
Ben Meadors
75a49d3486 Add heap metrics to Local stats (#6887) 2025-05-25 11:08:56 -05:00
Michael Cullen
7d95b487ef Add PCT2075 Temperature Sensor (#6829)
This is an I2C temperature sensor. It is intended to be a drop-in
compatible sensor for the LM75, however it is more accurate.

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-25 07:29:02 -05:00
Ben Meadors
2e72850d99 Fix is_unmessagable plumbing (#6886) 2025-05-25 07:24:28 -05:00
renovate[bot]
5fbdf4b6dc chore(deps): update meshtastic/device-ui digest to e63b219 (#6883)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-25 07:12:03 -05:00
github-actions[bot]
c47bdd11f9 [create-pull-request] automated change (#6885)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-25 06:56:21 -05:00
github-actions[bot]
d3b16c1e47 Upgrade trunk (#6843)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-25 06:29:00 -05:00
Andrew Yong
e29588d2e2 feat(RadioInterface): Tx power gain calculation rework (#6796)
- Rename REGULATORY_GAIN_LORA to TX_GAIN_LORA
- Move gain-based Tx power clamping from RadioInterface::applyModemConfig() to RadioInterface::limitPower()
  - User-configured Tx power now matches the Tx power out of the device connector
- Re-order [LoRa Chip]Interface.cpp limitPower() to take place before the final Tx power clamping so we clamp based on the pre-PA Tx power rather than user-configured Tx power

Tested on XIAO BLE variant.

Signed-off-by: Andrew Yong <me@ndoo.sg>
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-25 06:26:31 -05:00
Chiho Sin
9b69c2a9af graphics: Add GDEY0213B74 E-Ink display driver (#6879)
Implement the GDEY0213B74 driver with configuration methods for scanning, waveform, update sequence, and polling for refresh completion. This driver supports both fast and full update types for the 2.13 inch E-Ink display.

Signed-off-by: ChihoSin chihosin@icloud.com

Signed-off-by: ChihoSin chihosin@icloud.com
2025-05-25 06:08:41 -05:00
renovate[bot]
30e83d36b7 Update meshtastic/device-ui digest to 2fba9de (#6882)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-24 19:55:19 -05:00
renovate[bot]
2c9e169451 Update meshtastic/device-ui digest to 0e9bb79 (#6880)
fix bluetooth fixedPin during restart (#135)
2025-05-24 11:33:21 +02:00
Austin
067d01b832 Bosch bsec2: Switch back to official releases (#6870) 2025-05-23 22:35:13 +02:00
renovate[bot]
3aed7b4190 Update Adafruit PM25 AQI Sensor to v2 (#6778) 2025-05-23 15:51:26 +02:00
dylanli
c01db98819 update seeed solar node led pin (#6871) 2025-05-23 08:04:17 -05:00
Ben Meadors
beba1b4882 Added map report precision bounds (#6862)
* Added map report precision bounds

* Log warning

* Precision range should be 12-15

* Missed commit

* Update tests

* That method was renamed

* Removed now-defunct test call

* Remove defunct test
2025-05-22 20:33:46 -05:00
todd-herbert
ba1ef45024 InkHUD Extended ASCII (#6768)
* Custom AdafruitGFX fonts with extended ASCII encodings

* AppletFont handles re-encoding of UTF-8 text

* Manual parsing of text which may contain non-ASCII chars

* Display emoji reactions, even when unprintable
Important to indicate to users that a message has been received, even if meaning is unclear.

* Superstitious shrink_to_fit
I don't think these help, but they're not hurting!

* Use Windows-1252 fonts by default

* Spelling

* Tidy up nicheGraphics.h

* Documentation

* Fix inverted logic
Slipped in during a last minute renaming while tidying up to push..
2025-05-22 18:16:53 -05:00
renovate[bot]
b12e9d43be Update meshtastic/device-ui digest to 405ca49 (#6865)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-22 14:53:16 -05:00
Ben Meadors
7cd50d7044 If a contact is add from a QR, it's "verified" manually (#6858)
* If a contact is add from a QR, it's "verified" manually

* Update src/mesh/NodeDB.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-22 07:40:36 -05:00
Jonathan Bennett
41c1b29d70 Add basic handling for is_manually_validated (#6856) 2025-05-20 21:29:29 -05:00
Ben Meadors
6041357cbb Increase the debt ceiling 2025-05-20 20:31:01 -05:00
github-actions[bot]
cf3f35d566 [create-pull-request] automated change (#6857)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-20 19:51:03 -05:00
Jonathan Bennett
e0f878872f Hostmetrics user string (#6850) 2025-05-20 13:04:05 -05:00
renovate[bot]
c70fa0ef13 Update meshtastic/device-ui digest to c9a55f6 (#6845)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-19 19:10:22 +02:00
HarukiToreda
16994c8725 Fix for ICM-20948 not initializing (#6827)
* Fix for ICM-20948 not initializing

* trunk fix
2025-05-19 06:49:38 -05:00
renovate[bot]
3dd6dc0296 Update meshtastic/device-ui digest to 48e963f (#6841)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-18 14:37:54 -05:00
renovate[bot]
b2d81b740f Update dorny/test-reporter action to v2.1.0 (#6833)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-18 21:11:02 +10:00
Jonathan Bennett
61e4eb12e6 Use the _init_zero macro correctly for HostMetrics (#6837) 2025-05-17 14:02:39 -05:00
github-actions[bot]
5b312ab917 [create-pull-request] automated change (#6836)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2025-05-17 12:29:18 -05:00
github-actions[bot]
a50a94150a [create-pull-request] automated change (#6834)
Co-authored-by: jp-bennett <5630967+jp-bennett@users.noreply.github.com>
2025-05-17 10:44:02 -05:00
renovate[bot]
3398a52a34 Update meshtastic/device-ui digest to 55f7152 (#6830)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-17 06:15:44 -05:00
Jonathan Bennett
066609a718 Remove incomplete compass boot calibration (#6825)
The made it in from testing unintentionally.
2025-05-16 12:29:08 +10:00
Jonathan Bennett
1ef4caea05 Host metrics (#6817)
* Add std::string exec() function to PortduinoGlue for future work

* MVP for HostMetrics module.

* Fix compilation for other targets

* Remove extra debug calls

* Big numbers don't do well as INTs.

* Add HostMetrics to config.yaml
2025-05-15 09:23:37 -05:00
Austin
7d8f9c7f6d Stop the madness! Run as a user (not root) (#6718)
* Stop the madness! Run as a user (not root)

* Trigger fsdir migration for < 2.6.9

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-15 06:40:46 -05:00
github-actions[bot]
c2d5862161 automated bumps (#6820)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-15 06:40:07 -05:00
Tom Fifield
6bba17d463 Add suppport for Quectel L80 (#6803)
* Add suppport for Quectel L80

Another PMTK family chip, requires only a modification to the
probe code.

* Update support for L80 based on testing.
2025-05-15 19:26:41 +10:00
Ben Meadors
ef9d0d7805 Go 2025-05-14 20:22:01 -05:00
Ben Meadors
60d2cb35e0 Namespace 2025-05-14 18:55:27 -05:00
github-actions[bot]
ed6de5095e [create-pull-request] automated change (#6815)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-14 17:54:21 -05:00
Ben Meadors
b63b73ab84 Fix 2025-05-14 17:16:46 -05:00
Ben Meadors
3901ae8956 Default 2025-05-14 16:44:32 -05:00
Ben Meadors
7cffd9ba70 Added new map report opt-in for compliance and limit map report (and default) to one hour (#6813)
* Added new map report opt-in for compliance and limit map report (and default) to one hour

* Trunk
2025-05-14 15:31:28 -05:00
Ben Meadors
fc64bea698 Unmessagable implementation and defaults (#6811)
* Unmessagable implementation and defaults

* Router and router late are unmessagable by default

* Update src/modules/AdminModule.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-14 15:28:09 -05:00
github-actions[bot]
a51a6b8c47 [create-pull-request] automated change (#6812)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-14 14:41:37 -05:00
github-actions[bot]
1af4a0bdc9 Upgrade trunk (#6797)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-14 14:10:45 -05:00
github-actions[bot]
bc313da064 [create-pull-request] automated change (#6810)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-14 13:48:14 -05:00
Austin
f16402dec1 MQTT userprefs (#6802) 2025-05-14 13:39:46 -05:00
todd-herbert
feafd2bc0c Protect T-Echo's touch button against phantom presses in OLED UI (#6735)
* Guard T-Echo touch button during LoRa TX

* Guard for T-Echo only

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-14 06:33:51 -05:00
rcarteraz
b1955c34aa Update Seeed Solar Node (#6763)
* Update Seeed Solar Node

* Update Seeed Solar Node

* updates

* updates

* updates

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-14 06:32:24 -05:00
Ben Meadors
94af3bd1ab Formatting 2025-05-14 06:31:18 -05:00
Richard Zhang
d9ad2322e8 Fixes BUG #6243 Heltec Tracker (#6781)
* fix wireless tracker screen issues

* fix SHTC3 BUG

* Remove the 32K crystal oscillator option for the Wireless Paper and Vision Master series.

* Correct spelling errors

* Update src/graphics/Screen.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-14 06:29:05 -05:00
Ben Meadors
0a8bd1e4be Add contact admin message (for QR code) (#6806) 2025-05-14 05:33:51 -05:00
Chris Vogel
a7415791a5 device-install.sh: detect t-eth-elite as s3 device (#6767)
device-install.sh: detect t-eth-elite as s3 device
fixes https://github.com/meshtastic/firmware/issues/6754#issuecomment-2857468902
Thanks @mverch67!
2025-05-13 15:10:57 +02:00
Thomas Göttgens
cc66f7c79b Crowpanel 4.3, 5.0, 7.0 support (#6611)
* SD software SPI control
* fix notification crash;
* allow wake on touch
* don't build non-MUI variants
* use pwm buzzer
* Finalize support for Crowpanel TFT 2.4, 2.8 and 3.5
* add hardware ID for TFT panels
* Add stubs for the bigger panels. WIP!
* fix braces
* elecrow 4.3, 5.0, 7.0 support
* completed implementation 4.3, 5.0, 7.0 variants
* NodeDB default config & simplified light sleep macros
* trunk fmt
* remove flags
* removed leftovers (note: rtc gpios are only needed for deep sleep; the remove section caused issues with the elecrows)
---------
Co-authored-by: mverch67 <manuel.verch@gmx.de>
Co-authored-by: Manuel <71137295+mverch67@users.noreply.github.com>
Co-authored-by: Austin <vidplace7@gmail.com>
2025-05-13 14:15:52 +02:00
github-actions[bot]
e1417cff2e [create-pull-request] automated change (#6804)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-13 06:59:26 -05:00
Ben Meadors
b9fcd9da23 Add some no-nonsense coercion for self-reporting node values (#6793)
* Add some no-nonsense coercion for self-reporting node values

* Update src/mesh/PhoneAPI.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-11 18:08:29 -05:00
Ben Meadors
2a06b058fd Only send nodes on want_config of 69421 (#6792) 2025-05-11 15:18:53 -05:00
Tom
62e1974d09 Add clarifying note about AHT20 also being included with AHT10 library (#6787)
* Update AHT10.h

Add clarifying note about AHT20 also being included

* Update AHT10.cpp

Add clarifying note about AHT20 also being included
2025-05-11 17:17:37 +08:00
renovate[bot]
b208e1924f chore(deps): update meshtastic/device-ui digest to 7dee10a (#6786)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-11 00:59:38 +02:00
Austin
b17bb49a63 Actions: Fix end to end tests (#6776) 2025-05-10 16:21:23 -05:00
renovate[bot]
7c9296b0f4 chore(deps): update meshtastic/device-ui digest to 027f5a5 (#6783)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-10 18:48:39 +02:00
renovate[bot]
23fe093a65 chore(config): migrate renovate config (#6784)
* chore(config): migrate config renovate.json

* Prettier: Ignore renovate

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: vidplace7 <vidplace7@gmail.com>
2025-05-10 11:49:01 -04:00
renovate[bot]
c2a38357f1 chore(deps): update meshtastic/device-ui digest to 09b1780 (#6782)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-10 14:54:58 +02:00
github-actions[bot]
3aee4bfc6b Upgrade trunk (#6758)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-10 19:01:03 +08:00
Ben Meadors
981ecfdb61 Add client notification before role based power saving (sleep) (#6759)
* Add client notification before role based power saving (sleep)

* Unsigned
2025-05-07 21:20:32 -05:00
Tom
ca9bf6b31a Update XIAO_NRF_KIT RXEN Pin definition (#6717)
The XIAO NRF kit comes with a hat which has a slightly different pinout than the one supplied with the XIAO S3. At the last update, the RXEN pin was not moved with the rest.
2025-05-07 21:20:15 -05:00
renovate[bot]
ff2a12d579 chore(deps): update adafruit bme280 to v2.3.0 (#6708)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-08 08:32:01 +08:00
Jonathan Bennett
3a6fc668d8 20948 compass support (#6707)
* Add __has_include blocks for sensors

* Put BMP and BME back in the right sensors

* Split environmental_base to environmental_extra, to compile the working sensor libs for Native

* Remove hard-coded checks for ARCH_PORTDUINO

* Un-clobber bmx160

* Move BusIO to environmental_extra due to Armv7 compile error

* Move to forked BusIO for the moment

* Switch to Meshtastic ICM-20948 lib for Portduino support

* Use 20948 for compass direction

* Compass is more than just RAK4631

* Cleanup for 20948 compass

* use Meshtastic branch of 20948 lib

* Check for HAS_SCREEN for showing calibration screen

* No accelerometerThread on STM32
2025-05-07 18:38:42 -05:00
renovate[bot]
b657ba1abb chore(deps): update sparkfun 9dof imu breakout icm 20948 to v1.3.2 (#6761)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-07 13:27:44 -05:00
Ben Meadors
6f256c06f6 Fix warning 2025-05-07 09:26:10 -05:00
Benjamin Faershtein
86217111b2 Update SECURITY.md (#6757) 2025-05-07 06:28:18 -05:00
Austin
57d6c1fa85 Fix event templates (names, PSKs) (#6753) 2025-05-06 18:05:22 -04:00
Austin
62421a83fd Fix EVENT_MODE on mqttless targets (#6750) 2025-05-06 13:12:25 -04:00
Austin
867f50ab11 Don't run test-native for event firmwares (#6749) 2025-05-06 12:03:01 -05:00
renovate[bot]
1e81ebed06 chore(deps): update meshtastic/device-ui digest to 35576e1 (#6747)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-06 11:14:45 -05:00
github-actions[bot]
dd2cf633b0 Upgrade trunk (#6745)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-06 11:09:25 -05:00
github-actions[bot]
fdbe16f650 Bump release version (#6743)
* automated bumps

* Bump org.meshtastic.meshtasticd, fix GHA

---------

Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
Co-authored-by: vidplace7 <vidplace7@gmail.com>
2025-05-06 11:09:14 -05:00
Austin
a2903921cd Renovate: fix device-ui match (#6748) 2025-05-06 11:09:01 -05:00
Austin
2d6181fca0 update bosch bsec2 (#6727)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-05 06:03:36 -05:00
github-actions[bot]
a32e45f8f2 Upgrade trunk (#6737)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-05 05:16:51 -05:00
Austin
055fdcb7f6 Renovate: Add changelogs for device-ui, cleanup (#6733) 2025-05-05 08:08:39 +08:00
Austin
8bb1f3e869 Update template for event userprefs (#6720) 2025-05-04 13:18:48 -05:00
github-actions[bot]
d75c91a760 [create-pull-request] automated change (#6732)
Co-authored-by: thebentern <9000580+thebentern@users.noreply.github.com>
2025-05-04 08:39:59 -05:00
renovate[bot]
9d31d9f43b chore(deps): update meshtastic-device-ui digest to b9e2ad1 (#6729)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-03 22:18:39 +02:00
Austin
152b8b1b02 Revert "router: on linux add a mutex around the queue (#6709)" (#6726)
This reverts commit 987623567a.
2025-05-02 13:53:25 -04:00
todd-herbert
10693c4569 Lock SPI bus while in use by InkHUD (#6719)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-05-02 06:20:56 -05:00
renovate[bot]
7da8aea1df chore(deps): update meshtastic-device-ui digest to aa38459 (#6706)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-05-02 06:16:53 -05:00
github-actions[bot]
baae2503d5 Upgrade trunk to 1.22.15 (#6608)
Co-authored-by: sachaw <11172820+sachaw@users.noreply.github.com>
2025-05-02 16:24:21 +08:00
Ferdia McKeogh
947191a797 Add PA1010D GPS support (#6691) 2025-05-02 10:11:09 +08:00
Jorropo
987623567a router: on linux add a mutex around the queue (#6709)
UDP reception happens on an other thread, avoid data races and potential data corruption issues.
2025-05-01 06:32:20 -05:00
Manuel
a8ab6e82e6 MUI framebuffer support (#6703)
Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-30 20:50:30 -05:00
todd-herbert
5c005aaed5 Restore InkHUD to defaults on factory reset (#6637)
* Erase InkHUD settings on factory reset

* Documentation

* Captialn't
Lower case m. Also move the include statement to .cpp, because it doesn't really need to be in the .h
2025-05-01 12:28:05 +12:00
renovate[bot]
f9fbc3ff86 Update platform-native digest to 622341c (#6702)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 15:55:13 -05:00
renovate[bot]
124f4daa71 Update meshtastic-device-ui digest to 33aa689 (#6705)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 22:14:38 +02:00
renovate[bot]
00e2ac33ad Update platform-native digest to e19f77e (#6701)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-30 06:24:47 -05:00
Jonathan Bennett
845088e45b Add 100 msecond delay in tft_task_handler when deviceScreen is null (#6695)
* Add 100 msecond delay in tft_task_handler when deviceScreen is null, to fix 100% usage bug

* move portduino tft task creation into tftSetup

* remove superfluous check

* update platform-native commit

---------

Co-authored-by: mverch67 <manuel.verch@gmx.de>
2025-04-30 06:17:24 -05:00
Ben Meadors
e0b1fdb5e8 Rate limit waypoints and alerts and increase to allow every 10 seconds instead of 5 (#6699)
* Rate limit waypoints and alerts and increase to allow every 10 seconds instead of 5.

* Update src/mesh/PhoneAPI.cpp

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Doot

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-04-30 06:08:10 -05:00
Jorropo
a7ef9e9c08 udp-multicast: remove the thread from the multicast thread API (#6685)
* udp-multicast: remove the thread from the multicast thread API

The whole API is parallel & asynchronous we don't need to start a thread ourself,
the implementation probably does when we call start listening already.

* Take copilot advice and call it a handler

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-30 05:52:42 -05:00
Austin
216fbf2343 Update 'Adafruit BusIO' to 1.17.1 (#6694) 2025-04-29 19:24:00 -04:00
Jorropo
635de2d229 udp-multicast: bump platform-native to fix UDP read of unitialized memory bug (#6686)
* udp-multicast: bump platform-native to fix UDP read of unitialized memory bug

Fixes: #6683

* Update portduino.ini

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-29 06:31:53 -05:00
Colin
72eae42b81 PMSA003I: add support for driving SET pin low while not actively taking a telemetry reading (#6569)
* support manually shutting off power to the PMSA003I sensor when we aren't doing a telemetry reading

* add comment about PMSA003I_WARMUP_MS to AirQualityTelemetry.cpp

* fix typos, use arduino gpio defines instead of magic numbers

* support manually shutting off power to the PMSA003I sensor when we aren't doing a telemetry reading

* add comment about PMSA003I_WARMUP_MS to AirQualityTelemetry.cpp

* fix typos, use arduino gpio defines instead of magic numbers

* RAK4631: add PMSA003I_ENABLE_PIN define

* fix indentation

---------

Co-authored-by: Ben Meadors <benmmeadors@gmail.com>
2025-04-29 06:31:01 -05:00
renovate[bot]
b4e8f7dbb6 Update Adafruit BusIO digest to 159f86a (#6681)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-28 20:32:19 -05:00
Jonathan Bennett
473ef1bc03 Step one of Linux Sensor support (#6673)
* First addition of __has_include for sensor support

* Add __has_include blocks for sensors

* Put BMP and BME back in the right sensors

* Make TelemetrySensor::setup() a pure virtual finction

* Split environmental_base to environmental_extra, to compile the working sensor libs for Native

* Remove hard-coded checks for ARCH_PORTDUINO

* Un-clobber bmx160

* Move BusIO to environmental_extra due to Armv7 compile error

* Move to forked BusIO for the moment

* Enable HAS_SENSOR for Portduino

* Move back to Adafruit BusIO after patch
2025-04-28 18:35:13 -05:00
renovate[bot]
ca8c177363 Update meshtastic-device-ui digest to 8113d4f (#6677)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-29 08:24:00 +10:00
Kalle Lilja
77e6868d5d Fix create pull request (#6680)
* add base property

* bump to 2.6.7 - manual

* disable pip version check
2025-04-28 15:47:09 -05:00
345 changed files with 9427 additions and 2077 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
open_collective: meshtastic

View File

@@ -1,6 +1,7 @@
## 🙏 Thank you for sending in a pull request, here's some tips to get started!
### ❌ (Please delete all these tips and replace them with your text) ❌
- Before starting on some new big chunk of code, it it is optional but highly recommended to open an issue first
to say "Hey, I think this idea X should be implemented and I'm starting work on it. My general plan is Y, any feedback
is appreciated." This will allow other devs to potentially save you time by not accidentially duplicating work etc...
@@ -15,12 +16,12 @@
- If you do not have the affected hardware to test your code changes adequately against regressions, please indicate this, so that contributors and commnunity members can help test your changes.
- If your PR gets accepted you can request a "Contributor" role in the Meshtastic Discord
## 🤝 Attestations
- [ ] I have tested that my proposed changes behave as described.
- [ ] I have tested that my proposed changes do not cause any obvious regressions on the following devices:
- [ ] Heltec (Lora32) V3
- [ ] LilyGo T-Deck
- [ ] LilyGo T-Deck
- [ ] LilyGo T-Beam
- [ ] RAK WisBlock 4631
- [ ] Seeed Studio T-1000E tracker card

View File

@@ -149,6 +149,7 @@ jobs:
secrets: inherit
test-native:
if: ${{ !contains(github.ref_name, 'event/') }}
uses: ./.github/workflows/test_native.yml
docker-deb-amd64:

View File

@@ -63,21 +63,17 @@ jobs:
with:
python-version: 3.x
- name: Get release version string
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
id: version
env:
BUILD_LOCATION: local
- name: Bump version.properties
run: |
# Bump version.properties
chmod +x ./bin/bump_version.py
./bin/bump_version.py
- name: Get new release version string
run: |
echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT
id: new_version
- name: Ensure debian deps are installed
run: |
sudo apt-get update -y --fix-missing
@@ -94,11 +90,14 @@ jobs:
# Bump org.meshtastic.meshtasticd.metainfo.xml
pip install -r bin/bump_metainfo/requirements.txt -q
chmod +x ./bin/bump_metainfo/bump_metainfo.py
./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.version.outputs.short }}"
./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.new_version.outputs.short }}"
env:
PIP_DISABLE_PIP_VERSION_CHECK: 1
- name: Create Bumps pull request
uses: peter-evans/create-pull-request@v7
with:
base: ${{ github.event.repository.default_branch }}
title: Bump release version
commit-message: automated bumps
add-paths: |

View File

@@ -143,7 +143,7 @@ jobs:
merge-multiple: true
- name: Test Report
uses: dorny/test-reporter@v2.0.0
uses: dorny/test-reporter@v2.1.0
with:
name: PlatformIO Tests
path: testreport.xml

View File

@@ -5,7 +5,10 @@ on:
- cron: 0 0 * * * # Run every day at midnight
workflow_dispatch: {}
permissions: read-all
permissions:
contents: read
actions: read
checks: write
jobs:
native-tests:
@@ -44,7 +47,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 22
- name: Setup pnpm
uses: pnpm/action-setup@v4

View File

@@ -0,0 +1 @@
renovate.json

View File

@@ -1,25 +1,25 @@
version: 0.1
cli:
version: 1.22.12
version: 1.24.0
plugins:
sources:
- id: trunk
ref: v1.6.8
ref: v1.7.0
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- renovate@39.243.0
- checkov@3.2.440
- renovate@40.51.0
- prettier@3.5.3
- trufflehog@3.88.23
- yamllint@1.37.0
- trufflehog@3.89.1
- yamllint@1.37.1
- bandit@1.8.3
- terrascan@1.19.9
- trivy@0.61.0
- trivy@0.63.0
- taplo@0.9.3
- ruff@0.11.5
- ruff@0.11.13
- isort@6.0.1
- markdownlint@0.44.0
- oxipng@9.1.4
- markdownlint@0.45.0
- oxipng@9.1.5
- svgo@3.3.2
- actionlint@1.7.7
- flake8@7.2.0
@@ -28,7 +28,7 @@ lint:
- shellcheck@0.10.0
- black@25.1.0
- git-diff-check
- gitleaks@8.24.3
- gitleaks@8.27.2
- clang-format@16.0.3
ignore:
- linters: [ALL]
@@ -38,7 +38,7 @@ runtimes:
enabled:
- python@3.10.8
- go@1.21.0
- node@18.20.5
- node@22.16.0
actions:
disabled:
- trunk-announce

View File

@@ -1,4 +1,3 @@
# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue
# trunk-ignore-all(trivy/DS002): We must run as root for this container
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
# trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions
@@ -38,6 +37,13 @@ RUN curl -L "https://github.com/meshtastic/web/releases/download/v$(cat /tmp/fir
##### PRODUCTION BUILD #############
FROM debian:bookworm-slim
LABEL org.opencontainers.image.title="Meshtastic" \
org.opencontainers.image.description="Debian Meshtastic daemon and web interface" \
org.opencontainers.image.url="https://meshtastic.org" \
org.opencontainers.image.documentation="https://meshtastic.org/docs/" \
org.opencontainers.image.authors="Meshtastic" \
org.opencontainers.image.licenses="GPL-3.0-or-later" \
org.opencontainers.image.source="https://github.com/meshtastic/firmware/"
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
@@ -54,7 +60,7 @@ RUN apt-get update && apt-get --no-install-recommends -y install \
&& mkdir -p /etc/meshtasticd/ssl
# Fetch compiled binary from the builder
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/
COPY --from=builder /tmp/web /usr/share/meshtasticd/
# Copy config templates
COPY ./bin/config.d /etc/meshtasticd/available.d
@@ -65,8 +71,8 @@ VOLUME /var/lib/meshtasticd
# Expose Meshtastic TCP API port from the host
EXPOSE 4403
# Expose Meshtastic Web UI port from the host
EXPOSE 443
EXPOSE 9443
CMD [ "sh", "-cx", "meshtasticd -d /var/lib/meshtasticd" ]
CMD [ "sh", "-cx", "meshtasticd --fsdir=/var/lib/meshtasticd" ]
HEALTHCHECK NONE

View File

@@ -4,8 +4,8 @@
| Firmware Version | Supported |
| ---------------- | ------------------ |
| 2.5.x | :white_check_mark: |
| <= 2.4.x | :x: |
| 2.6.x | :white_check_mark: |
| <= 2.5.x | :x: |
## Reporting a Vulnerability

View File

@@ -3,7 +3,7 @@
# trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
FROM python:3.13-alpine3.21 AS builder
FROM python:3.13-alpine3.22 AS builder
ARG PIO_ENV=native
ENV PIP_ROOT_USER_ACTION=ignore
@@ -27,13 +27,20 @@ RUN bash ./bin/build-native.sh "$PIO_ENV" && \
# ##### PRODUCTION BUILD #############
FROM alpine:3.21
FROM alpine:3.22
LABEL org.opencontainers.image.title="Meshtastic" \
org.opencontainers.image.description="Alpine Meshtastic daemon" \
org.opencontainers.image.url="https://meshtastic.org" \
org.opencontainers.image.documentation="https://meshtastic.org/docs/" \
org.opencontainers.image.authors="Meshtastic" \
org.opencontainers.image.licenses="GPL-3.0-or-later" \
org.opencontainers.image.source="https://github.com/meshtastic/firmware/"
# nosemgrep: dockerfile.security.last-user-is-root.last-user-is-root
USER root
RUN apk --no-cache add \
libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \
shadow libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \
libx11 libinput libxkbcommon \
&& rm -rf /var/cache/apk/* \
&& mkdir -p /var/lib/meshtasticd \
@@ -41,7 +48,7 @@ RUN apk --no-cache add \
&& mkdir -p /etc/meshtasticd/ssl
# Fetch compiled binary from the builder
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/
# Copy config templates
COPY ./bin/config.d /etc/meshtasticd/available.d

View File

@@ -4,7 +4,7 @@ extends = arduino_base
custom_esp32_kind = esp32
platform =
# renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32
platformio/espressif32@6.10.0
platformio/espressif32@6.11.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
@@ -46,6 +46,7 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
# renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master
https://github.com/meshtastic/esp32_https_server/archive/896f1771ceb5979987a0b41028bf1b4e7aad419b.zip
@@ -58,7 +59,7 @@ lib_deps =
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@^0.4.0
rweather/Crypto@0.4.0
lib_ignore =
segger_rtt

View File

@@ -1,7 +1,7 @@
[esp32c6_base]
extends = esp32_base
platform =
# renovate: datasource=git-refs depName=ESP32c6 platform-espressif32 packageName=https://github.com/Jason2866/platform-espressif32 gitBranch=Arduino/IDF5
# Do not renovate until we have switched to pioarduino tagged builds
https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip
build_flags =
${arduino_base.build_flags}
@@ -25,13 +25,14 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
lewisxhe/XPowersLib@^0.2.7
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@^0.4.0
rweather/Crypto@0.4.0
build_src_filter =
${esp32_base.build_src_filter} -<mesh/http>

View File

@@ -28,7 +28,8 @@ build_src_filter =
lib_deps=
${arduino_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto@^0.4.0
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
lib_ignore =
BluetoothOTA

View File

@@ -6,6 +6,7 @@ build_flags = ${nrf52_base.build_flags}
lib_deps =
${nrf52_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
# renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/5f838d2709461a2c981f642917aa50254a25c14c.zip

View File

@@ -2,7 +2,7 @@
[portduino_base]
platform =
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
https://github.com/meshtastic/platform-native/archive/46f509b96ddce22d1bf38efc93319dfb3e4f5acf.zip
https://github.com/meshtastic/platform-native/archive/681ee029207e9fd040afa223df6e54074cbbe084.zip
framework = arduino
build_src_filter =
@@ -17,17 +17,15 @@ build_src_filter =
+<mesh/raspihttp/>
-<mesh/eth/>
-<modules/esp32>
-<modules/Telemetry/EnvironmentTelemetry.cpp>
-<modules/Telemetry/AirQualityTelemetry.cpp>
-<modules/Telemetry/Sensor>
+<../variants/portduino>
lib_deps =
${env.lib_deps}
${networking_base.lib_deps}
${radiolib_base.lib_deps}
${environmental_base.lib_deps}
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@^0.4.0
rweather/Crypto@0.4.0
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX
lovyan03/LovyanGFX@^1.2.0
# renovate: datasource=git-refs depName=libch341-spi-userspace packageName=https://github.com/pine64/libch341-spi-userspace gitBranch=main
@@ -49,3 +47,5 @@ build_flags =
-luv
-std=gnu17
-std=c++17
lib_ignore = Adafruit NeoPixel

View File

@@ -28,6 +28,7 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0

View File

@@ -25,6 +25,7 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0

View File

@@ -2,7 +2,7 @@
extends = arduino_base
platform =
# renovate: datasource=custom.pio depName=platformio/ststm32 packageName=platformio/platform/ststm32
platformio/ststm32@19.1.0
platformio/ststm32@19.2.0
platform_packages =
# TODO renovate
platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip

View File

@@ -0,0 +1,7 @@
# Set spidev ownership to 'spi' group
SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660"
# Allow access to USB CH341 devices
SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666"
# Set gpio ownership to 'gpio' group
SUBSYSTEM=="*gpiomem*", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660"

View File

@@ -23,4 +23,4 @@ for BOARD in $BOARDS; do
CHECK="${CHECK} -e ${BOARD}"
done
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high
pio check --flags "-DAPP_VERSION=${APP_VERSION} --suppressions-list=suppressions.txt --inline-suppr" $CHECK --skip-packages --pattern="src/" --fail-on-defect=medium --fail-on-defect=high

View File

@@ -188,11 +188,18 @@ Logging:
# AsciiLogs: true # default if not specified is !isatty() on stdout
Webserver:
# Port: 443 # Port for Webserver & Webservices
# Port: 9443 # Port for Webserver & Webservices
# RootPath: /usr/share/meshtasticd/web # Root Dir of WebServer
# SSLKey: /etc/meshtasticd/ssl/private_key.pem # Path to SSL Key, generated if not present
# SSLCert: /etc/meshtasticd/ssl/certificate.pem # Path to SSL Certificate, generated if not present
HostMetrics:
# ReportInterval: 30 # Interval in minutes between HostMetrics report packets, or 0 for disabled
# Channel: 0 # channel to send Host Metrics over. Defaults to the primary channel.
# UserStringCommand: cat /sys/firmware/devicetree/base/serial-number # Command to execute, to send the results as the userString
General:
MaxNodes: 200
MaxMessageQueue: 100

View File

@@ -0,0 +1,21 @@
Lora:
### RAK13300in Slot 1
Module: sx1262
IRQ: 22 #IO6
Reset: 16 # IO4
Busy: 24 # IO5
# Ant_sw: 13 # IO3
DIO3_TCXO_VOLTAGE: true
DIO2_AS_RF_SWITCH: true
spidev: spidev0.0
# CS: 8
### RAK13300in Slot 2 pins
# IRQ: 18 #IO6
# Reset: 24 # IO4
# Busy: 19 # IO5
# # Ant_sw: 23 # IO3
# spidev: spidev0.1
# # CS: 7

View File

@@ -0,0 +1,18 @@
Lora:
Module: sx1262
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
gpiochip: 0
MOSI: 12
MISO: 13
IRQ: 1
Busy: 23
Reset: 22
RXen: 0
gpiochip: 1
CS: 9
SCK: 11
# TXen: bridge to DIO2 on E22 module
SX126X_MAX_POWER: 22
spidev: spidev1.0
spiSpeed: 2000000

View File

@@ -12,6 +12,7 @@ SET "BIGDB16=0"
SET "ESPTOOL_BAUD=115200"
SET "ESPTOOL_CMD="
SET "LOGCOUNTER=0"
SET "BPS_RESET=0"
@REM FIXME: Determine mcu from PlatformIO variant, this is unmaintainable.
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
@@ -24,7 +25,7 @@ GOTO getopts
:help
ECHO Flash image file to device, but first erasing and writing system information.
ECHO.
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] (--web)
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] (--web) [--1200bps-reset]
ECHO.
ECHO Options:
ECHO -f filename The firmware .bin file to flash. Custom to your device type and region. (required)
@@ -35,13 +36,16 @@ ECHO -P python Specify alternate python interpreter to use to invoke
ECHO If supplied the script will use python.
ECHO If not supplied the script will try to find esptool in Path.
ECHO --web Enable WebUI. (default: false)
ECHO --1200bps-reset Attempt to place the device in correct mode. (1200bps Reset)
ECHO Some hardware requires this twice.
ECHO.
ECHO Example: %SCRIPT_NAME% -p COM17 --1200bps-reset
ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4.bin -p COM11
ECHO Example: %SCRIPT_NAME% -f firmware-unphone-2.6.0.0b106d4.bin -p COM11 --web
GOTO eof
:version
ECHO %SCRIPT_NAME% [Version 2.6.1]
ECHO %SCRIPT_NAME% [Version 2.6.2]
ECHO Meshtastic
GOTO eof
@@ -58,10 +62,13 @@ IF "%~1"=="-p" SET "ESPTOOL_PORT=%~2" & SHIFT
IF /I "%~1"=="--port" SET "ESPTOOL_PORT=%~2" & SHIFT
IF "%~1"=="-P" SET "PYTHON=%~2" & SHIFT
IF /I "%~1"=="--web" SET "WEB_APP=1"
IF /I "%~1"=="--1200bps-reset" SET "BPS_RESET=1"
SHIFT
GOTO getopts
:endopts
IF %BPS_RESET% EQU 1 GOTO skip-filename
CALL :LOG_MESSAGE DEBUG "Checking FILENAME parameter..."
IF "__!FILENAME!__"=="____" (
CALL :LOG_MESSAGE DEBUG "Missing -f filename input."
@@ -95,6 +102,9 @@ IF NOT "!FILENAME:update=!"=="!FILENAME!" (
CALL :LOG_MESSAGE DEBUG "We are NOT working with a *update* file. !FILENAME!"
)
:skip-filename
SET "ESPTOOL_BAUD=1200"
CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..."
IF NOT "__%PYTHON%__"=="____" (
SET "ESPTOOL_CMD=!PYTHON! -m esptool"
@@ -133,6 +143,12 @@ IF "__!ESPTOOL_PORT!__" == "____" (
)
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
IF %BPS_RESET% EQU 1 (
@REM Attempt to change mode via 1200bps Reset.
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! --after no_reset read_flash_status
GOTO eof
)
@REM Check if FILENAME contains "-tft-" and set target partitionScheme accordingly.
@REM https://github.com/meshtastic/web-flasher/blob/main/types/resources.ts#L3
IF NOT "!FILENAME:-tft-=!"=="!FILENAME!" (
@@ -254,6 +270,7 @@ EXIT /B %ERRORLEVEL%
IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
CALL :RESET_ERROR
!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4
IF %BPS_RESET% EQU 1 GOTO :eof
IF %ERRORLEVEL% NEQ 0 (
CALL :LOG_MESSAGE ERROR "Error running command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
EXIT /B %ERRORLEVEL%

View File

@@ -2,6 +2,7 @@
PYTHON=${PYTHON:-$(which python3 python | head -n 1)}
WEB_APP=false
BPS_RESET=false
TFT_BUILD=false
MCU=""
@@ -32,37 +33,50 @@ BIGDB_16MB=(
"ESP32-S3-Pico"
"m5stack-cores3"
"station-g2"
"t-eth-elite"
"t-watch-s3"
"t-eth-elite"
"t-watch-s3"
"elecrow-adv-35-tft"
"elecrow-adv-24-28-tft"
"elecrow-adv1-43-50-70-tft"
)
S3_VARIANTS=(
"s3"
"-v3"
"t-deck"
"wireless-paper"
"wireless-tracker"
"station-g2"
"unphone"
"s3"
"-v3"
"t-deck"
"wireless-paper"
"wireless-tracker"
"station-g2"
"unphone"
"t-eth-elite"
"mesh-tab"
"dreamcatcher"
"ESP32-S3-Pico"
"seeed-sensecap-indicator"
"heltec_capsule_sensor_v3"
"vision-master"
"icarus"
"tracksenger"
"elecrow-adv"
)
# Determine the correct esptool command to use
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
ESPTOOL_CMD="$PYTHON -m esptool"
ESPTOOL_CMD="$PYTHON -m esptool"
elif command -v esptool >/dev/null 2>&1; then
ESPTOOL_CMD="esptool"
ESPTOOL_CMD="esptool"
elif command -v esptool.py >/dev/null 2>&1; then
ESPTOOL_CMD="esptool.py"
ESPTOOL_CMD="esptool.py"
else
echo "Error: esptool not found"
exit 1
echo "Error: esptool not found"
exit 1
fi
set -e
# Usage info
show_help() {
cat <<EOF
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME] [--web]
cat <<EOF
Usage: $(basename "$0") [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME] [--web] [--1200bps-reset]
Flash image file to device, but first erasing and writing system information.
-h Display this help and exit.
@@ -70,137 +84,146 @@ Flash image file to device, but first erasing and writing system information.
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
-f FILENAME The firmware .bin file to flash. Custom to your device type and region.
--web Enable WebUI. (Default: false)
--1200bps-reset Attempt to place the device in correct mode. Some hardware requires this twice. (1200bps Reset)
EOF
}
# Parse arguments using a single while loop
while [ $# -gt 0 ]; do
case "$1" in
-h | --help)
show_help
exit 0
;;
-p)
ESPTOOL_CMD="$ESPTOOL_CMD --port $2"
shift
;;
-P)
PYTHON="$2"
shift
;;
-f)
FILENAME="$2"
shift
;;
--web)
WEB_APP=true
;;
--) # Stop parsing options
shift
break
;;
*)
echo "Unknown argument: $1" >&2
exit 1
;;
esac
shift # Move to the next argument
case "$1" in
-h | --help)
show_help
exit 0
;;
-p)
ESPTOOL_CMD="$ESPTOOL_CMD --port $2"
shift
;;
-P)
PYTHON="$2"
shift
;;
-f)
FILENAME="$2"
shift
;;
--web)
WEB_APP=true
;;
--1200bps-reset)
BPS_RESET=true
;;
--) # Stop parsing options
shift
break
;;
*)
echo "Unknown argument: $1" >&2
exit 1
;;
esac
shift # Move to the next argument
done
[ -z "$FILENAME" -a -n "$1" ] && {
FILENAME=$1
shift
if [[ $BPS_RESET == true ]]; then
$ESPTOOL_CMD --baud 1200 --after no_reset read_flash_status
exit 0
fi
[ -z "$FILENAME" ] && [ -n "$1" ] && {
FILENAME="$1"
shift
}
if [[ $FILENAME != firmware-* ]]; then
if [[ "$FILENAME" != firmware-* ]]; then
echo "Filename must be a firmware-* file."
exit 1
fi
# Check if FILENAME contains "-tft-" and prevent web/mui comingling.
if [[ ${FILENAME//-tft-/} != "$FILENAME" ]]; then
TFT_BUILD=true
if [[ $WEB_APP == true ]] && [[ $TFT_BUILD == true ]]; then
echo "Cannot enable WebUI (--web) and MUI."
exit 1
fi
if [[ "${FILENAME//-tft-/}" != "$FILENAME" ]]; then
TFT_BUILD=true
if [[ $WEB_APP == true ]] && [[ $TFT_BUILD == true ]]; then
echo "Cannot enable WebUI (--web) and MUI."
exit 1
fi
fi
# Extract BASENAME from %FILENAME% for later use.
BASENAME="${FILENAME/firmware-/}"
if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
# Default littlefs* offset (--web).
OFFSET=0x300000
# Default littlefs* offset (--web).
OFFSET=0x300000
# Default OTA Offset
OTA_OFFSET=0x260000
# Default OTA Offset
OTA_OFFSET=0x260000
# littlefs* offset for BigDB 8mb and OTA OFFSET.
for variant in "${BIGDB_8MB[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
OFFSET=0x670000
OTA_OFFSET=0x340000
fi
done
# littlefs* offset for BigDB 8mb and OTA OFFSET.
for variant in "${BIGDB_8MB[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
OFFSET=0x670000
OTA_OFFSET=0x340000
fi
done
# littlefs* offset for BigDB 16mb and OTA OFFSET.
for variant in "${BIGDB_16MB[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
OFFSET=0xc90000
OTA_OFFSET=0x650000
fi
done
# littlefs* offset for BigDB 16mb and OTA OFFSET.
for variant in "${BIGDB_16MB[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
OFFSET=0xc90000
OTA_OFFSET=0x650000
fi
done
# Account for S3 board's different OTA partition
# FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
for variant in "${S3_VARIANTS[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
MCU="esp32s3"
fi
done
# Account for S3 board's different OTA partition
# FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
for variant in "${S3_VARIANTS[@]}"; do
if [ -z "${FILENAME##*"$variant"*}" ]; then
MCU="esp32s3"
fi
done
if [ "$MCU" != "esp32s3" ]; then
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
OTAFILE=bleota.bin
else
OTAFILE=bleota-c3.bin
fi
else
OTAFILE=bleota-s3.bin
fi
if [ "$MCU" != "esp32s3" ]; then
if [ -n "${FILENAME##*"esp32c3"*}" ]; then
OTAFILE=bleota.bin
else
OTAFILE=bleota-c3.bin
fi
else
OTAFILE=bleota-s3.bin
fi
# Check if WEB_APP (--web) is enabled and add "littlefswebui-" to BASENAME else "littlefs-".
if [ "$WEB_APP" = true ]; then
SPIFFSFILE=littlefswebui-${BASENAME}
else
SPIFFSFILE=littlefs-${BASENAME}
fi
# Check if WEB_APP (--web) is enabled and add "littlefswebui-" to BASENAME else "littlefs-".
if [ "$WEB_APP" = true ]; then
SPIFFSFILE=littlefswebui-${BASENAME}
else
SPIFFSFILE=littlefs-${BASENAME}
fi
if [[ ! -f $FILENAME ]]; then
echo "Error: file ${FILENAME} wasn't found. Terminating."
exit 1
fi
if [[ ! -f $OTAFILE ]]; then
echo "Error: file ${OTAFILE} wasn't found. Terminating."
exit 1
fi
if [[ ! -f $SPIFFSFILE ]]; then
echo "Error: file ${SPIFFSFILE} wasn't found. Terminating."
exit 1
fi
if [[ ! -f "$FILENAME" ]]; then
echo "Error: file ${FILENAME} wasn't found. Terminating."
exit 1
fi
if [[ ! -f "$OTAFILE" ]]; then
echo "Error: file ${OTAFILE} wasn't found. Terminating."
exit 1
fi
if [[ ! -f "$SPIFFSFILE" ]]; then
echo "Error: file ${SPIFFSFILE} wasn't found. Terminating."
exit 1
fi
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
$ESPTOOL_CMD erase_flash
$ESPTOOL_CMD write_flash 0x00 "${FILENAME}"
echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
$ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}"
echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
$ESPTOOL_CMD write_flash $OFFSET "${SPIFFSFILE}"
echo "Trying to flash ${FILENAME}, but first erasing and writing system information"
$ESPTOOL_CMD erase_flash
$ESPTOOL_CMD write_flash 0x00 "${FILENAME}"
echo "Trying to flash ${OTAFILE} at offset ${OTA_OFFSET}"
$ESPTOOL_CMD write_flash $OTA_OFFSET "${OTAFILE}"
echo "Trying to flash ${SPIFFSFILE}, at offset ${OFFSET}"
$ESPTOOL_CMD write_flash $OFFSET "${SPIFFSFILE}"
else
show_help
echo "Invalid file: ${FILENAME}"
show_help
echo "Invalid file: ${FILENAME}"
fi
exit 0

View File

@@ -8,12 +8,13 @@ SET "PYTHON="
SET "ESPTOOL_BAUD=115200"
SET "ESPTOOL_CMD="
SET "LOGCOUNTER=0"
SET "CHANGE_MODE=0"
GOTO getopts
:help
ECHO Flash image file to device, but leave existing system intact.
ECHO.
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python]
ECHO Usage: %SCRIPT_NAME% -f filename [-p PORT] [-P python] [--change-mode]
ECHO.
ECHO Options:
ECHO -f filename The update .bin file to flash. Custom to your device type and region. (required)
@@ -23,12 +24,15 @@ ECHO If not set, ESPTOOL iterates all ports (Dangerous).
ECHO -P python Specify alternate python interpreter to use to invoke esptool. (default: python)
ECHO If supplied the script will use python.
ECHO If not supplied the script will try to find esptool in Path.
ECHO --change-mode Attempt to place the device in correct mode. (1200bps Reset)
ECHO Some hardware requires this twice.
ECHO.
ECHO Example: %SCRIPT_NAME% -p COM17 --change-mode
ECHO Example: %SCRIPT_NAME% -f firmware-t-deck-tft-2.6.0.0b106d4-update.bin -p COM11
GOTO eof
:version
ECHO %SCRIPT_NAME% [Version 2.6.1]
ECHO %SCRIPT_NAME% [Version 2.6.2]
ECHO Meshtastic
GOTO eof
@@ -44,10 +48,13 @@ IF /I "%~1"=="-f" SET "FILENAME=%~2" & SHIFT
IF "%~1"=="-p" SET "ESPTOOL_PORT=%~2" & SHIFT
IF /I "%~1"=="--port" SET "ESPTOOL_PORT=%~2" & SHIFT
IF "%~1"=="-P" SET "PYTHON=%~2" & SHIFT
IF /I "%~1"=="--change-mode" SET "CHANGE_MODE=1"
SHIFT
GOTO getopts
:endopts
IF %CHANGE_MODE% EQU 1 GOTO skip-filename
CALL :LOG_MESSAGE DEBUG "Checking FILENAME parameter..."
IF "__!FILENAME!__"=="____" (
CALL :LOG_MESSAGE DEBUG "Missing -f filename input."
@@ -77,6 +84,9 @@ IF "!FILENAME:update=!"=="!FILENAME!" (
CALL :LOG_MESSAGE DEBUG "We are working with a *update* file. !FILENAME!"
)
:skip-filename
SET "ESPTOOL_BAUD=1200"
CALL :LOG_MESSAGE DEBUG "Determine the correct esptool command to use..."
IF NOT "__%PYTHON%__"=="____" (
SET "ESPTOOL_CMD=!PYTHON! -m esptool"
@@ -115,6 +125,12 @@ IF "__!ESPTOOL_PORT!__" == "____" (
)
CALL :LOG_MESSAGE INFO "Using esptool baud: !ESPTOOL_BAUD!."
IF %CHANGE_MODE% EQU 1 (
@REM Attempt to change mode via 1200bps Reset.
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! --after no_reset read_flash_status
GOTO eof
)
@REM Flashing operations.
CALL :LOG_MESSAGE INFO "Trying to flash update "!FILENAME!" at OFFSET 0x10000..."
CALL :RUN_ESPTOOL !ESPTOOL_BAUD! write_flash 0x10000 "!FILENAME!" || GOTO eof
@@ -135,6 +151,7 @@ EXIT /B %ERRORLEVEL%
IF %DEBUG% EQU 1 CALL :LOG_MESSAGE DEBUG "About to run command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
CALL :RESET_ERROR
!ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4
IF %CHANGE_MODE% EQU 1 GOTO :eof
IF %ERRORLEVEL% NEQ 0 (
CALL :LOG_MESSAGE ERROR "Error running command: !ESPTOOL_CMD! --baud %~1 %~2 %~3 %~4"
EXIT /B %ERRORLEVEL%

View File

@@ -1,6 +1,7 @@
#!/bin/sh
PYTHON=${PYTHON:-$(which python3 python|head -n 1)}
CHANGE_MODE=false
# Determine the correct esptool command to use
if "$PYTHON" -m esptool version >/dev/null 2>&1; then
@@ -17,14 +18,15 @@ fi
# Usage info
show_help() {
cat << EOF
Usage: $(basename $0) [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME]
Usage: $(basename "$0") [-h] [-p ESPTOOL_PORT] [-P PYTHON] [-f FILENAME|FILENAME] [--change-mode]
Flash image file to device, leave existing system intact."
-h Display this help and exit
-p ESPTOOL_PORT Set the environment variable for ESPTOOL_PORT. If not set, ESPTOOL iterates all ports (Dangerous).
-P PYTHON Specify alternate python interpreter to use to invoke esptool. (Default: "$PYTHON")
-f FILENAME The *update.bin file to flash. Custom to your device type.
--change-mode Attempt to place the device in correct mode. Some hardware requires this twice. (1200bps Reset)
EOF
}
@@ -36,13 +38,16 @@ while getopts ":hp:P:f:" opt; do
exit 0
;;
p) ESPTOOL_CMD="$ESPTOOL_CMD --port ${OPTARG}"
;;
;;
P) PYTHON=${OPTARG}
;;
f) FILENAME=${OPTARG}
;;
--change-mode)
CHANGE_MODE=true
;;
*)
echo "Invalid flag."
echo "Invalid flag."
show_help >&2
exit 1
;;
@@ -50,17 +55,22 @@ while getopts ":hp:P:f:" opt; do
done
shift "$((OPTIND-1))"
[ -z "$FILENAME" -a -n "$1" ] && {
FILENAME=$1
if [[ $CHANGE_MODE == true ]]; then
$ESPTOOL_CMD --baud 1200 --after no_reset read_flash_status
exit 0
fi
[ -z "$FILENAME" ] && [ -n "$1" ] && {
FILENAME="$1"
shift
}
if [ -f "${FILENAME}" ] && [ -z "${FILENAME##*"update"*}" ]; then
printf "Trying to flash update ${FILENAME}"
$ESPTOOL_CMD --baud 115200 write_flash 0x10000 ${FILENAME}
echo "Trying to flash update ${FILENAME}"
$ESPTOOL_CMD --baud 115200 write_flash 0x10000 "${FILENAME}"
else
show_help
echo "Invalid file: ${FILENAME}"
show_help
echo "Invalid file: ${FILENAME}"
fi
exit 0

View File

@@ -27,7 +27,7 @@ for subdir, dirs, files in os.walk(rootdir):
if c.startswith("env:"):
section = config[c].name[4:]
if "extends" in config[config[c].name]:
if config[config[c].name]["extends"] == options[0] + "_base":
if options[0] + "_base" in config[config[c].name]["extends"]:
if "board_level" in config[config[c].name]:
if (
config[config[c].name]["board_level"] == "extra"

View File

@@ -5,10 +5,11 @@ StartLimitInterval=200
StartLimitBurst=5
[Service]
User=root
Group=root
AmbientCapabilities=CAP_NET_BIND_SERVICE
User=meshtasticd
Group=meshtasticd
Type=simple
ExecStart=/usr/sbin/meshtasticd
ExecStart=/usr/bin/meshtasticd
Restart=always
RestartSec=3

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd
cp "release/meshtasticd_linux_$(uname -m)" /usr/bin/meshtasticd
mkdir -p /etc/meshtasticd
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml

View File

@@ -87,6 +87,24 @@
</screenshots>
<releases>
<release version="2.6.12" date="2025-06-15">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.12</url>
</release>
<release version="2.6.11" date="2025-06-02">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.11</url>
</release>
<release version="2.6.10" date="2025-05-25">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.10</url>
</release>
<release version="2.6.9" date="2025-05-15">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.9</url>
</release>
<release version="2.6.8" date="2025-05-05">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.8</url>
</release>
<release version="2.6.7" date="2025-04-28">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.7</url>
</release>
<release version="2.6.6" date="2025-04-15">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.6</url>
</release>

View File

@@ -48,6 +48,6 @@
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "FIXME",
"url": "https://www.elecrow.com/thinknode-m1-meshtastic-lora-signal-transceiver-powered-by-nrf52840-with-154-screen-support-gps.html",
"vendor": "ELECROW"
}

View File

@@ -8,8 +8,8 @@
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DARDUINO_USB_MODE=0",
"-DARDUINO_USB_CDC_ON_BOOT=0",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=0"
],

View File

@@ -0,0 +1,52 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_FEATHER -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x8029"],
["0x239A", "0x0029"],
["0x239A", "0x002A"],
["0x239A", "0x802A"]
],
"usb_product": "GAT562 Mesh Trial Tracker",
"mcu": "nrf52840",
"variant": "gat562_mesh_trial_tracker",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino", "freertos"],
"name": "GAT562 Mesh Trial Tracker",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "http://www.gat-iot.com/",
"vendor": "GAT-IOT"
}

View File

@@ -48,6 +48,6 @@
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "FIXME",
"url": "https://heltec.org/project/mesh-node-t114/",
"vendor": "Heltec"
}

View File

@@ -10,7 +10,7 @@
"hwids": [["0x2886", "0x0059"]],
"usb_product": "XIAO-BOOT",
"mcu": "nrf52840",
"variant": "Seeed_Solar_Node",
"variant": "seeed_solar_node",
"bsp": {
"name": "adafruit"
},
@@ -31,7 +31,7 @@
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Seeed_Solar_Node",
"name": "seeed_solar_node",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,

View File

@@ -0,0 +1,54 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v7.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [["0x2886", "0x1668"]],
"usb_product": "TRACKER L1",
"mcu": "nrf52840",
"variant": "seeed_wio_tracker_L1",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "7.3.0",
"sd_fwid": "0x0123"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "seeed_wio_tracker_L1",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": [
"jlink",
"nrfjprog",
"nrfutil",
"stlink",
"cmsis-dap",
"blackmagic"
],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://www.seeedstudio.com/Wio-Tracker-L1-p-6477.html",
"vendor": "Seeed Studio"
}

View File

@@ -7,9 +7,7 @@
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x2886", "0x0166"]
],
"hwids": [["0x2886", "0x0166"]],
"usb_product": "XIAO-BOOT",
"mcu": "nrf52840",
"variant": "seeed_xiao_nrf52840_kit",

17
debian/changelog vendored
View File

@@ -1,9 +1,22 @@
meshtasticd (2.5.22.0) UNRELEASED; urgency=medium
meshtasticd (2.6.11.0) UNRELEASED; urgency=medium
[ Austin Lane ]
* Initial packaging
* GitHub Actions Automatic version bump
* GitHub Actions Automatic version bump
* GitHub Actions Automatic version bump
* GitHub Actions Automatic version bump
-- Austin Lane <github-actions[bot]@users.noreply.github.com> Wed, 05 Feb 2025 01:10:33 +0000
[ ]
* GitHub Actions Automatic version bump
[ ]
* GitHub Actions Automatic version bump
[ ]
* GitHub Actions Automatic version bump
[ ]
* GitHub Actions Automatic version bump
-- <github-actions[bot]@users.noreply.github.com> Mon, 02 Jun 2025 20:00:55 +0000

6
debian/control vendored
View File

@@ -31,7 +31,9 @@ Rules-Requires-Root: no
Package: meshtasticd
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}
Depends: adduser,
${misc:Depends},
${shlibs:Depends}
Description: Meshtastic daemon for communicating with Meshtastic devices
Meshtastic is an off-grid text communication platform that uses inexpensive
LoRa radios.
LoRa radios.

View File

@@ -1,5 +1,6 @@
var/lib/meshtasticd
etc/meshtasticd
etc/meshtasticd/config.d
etc/meshtasticd/available.d
usr/share/meshtasticd/web
etc/meshtasticd/ssl
etc/meshtasticd/ssl

View File

@@ -1,8 +1,8 @@
.pio/build/native-tft/meshtasticd usr/sbin
.pio/build/native-tft/meshtasticd usr/bin
bin/config.yaml etc/meshtasticd
bin/config.d/* etc/meshtasticd/available.d
bin/meshtasticd.service lib/systemd/system
web/* usr/share/meshtasticd/web
web/* usr/share/meshtasticd/web

80
debian/meshtasticd.postinst vendored Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/sh
# postinst script for meshtasticd
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure|reconfigure)
# create spi, gpio groups (for udev rules)
# these groups already exist on Raspberry Pi OS
getent group spi >/dev/null 2>/dev/null || addgroup --system spi
getent group gpio >/dev/null 2>/dev/null || addgroup --system gpio
# create a meshtasticd group and user
getent passwd meshtasticd >/dev/null 2>/dev/null || adduser --system --home /var/lib/meshtasticd --no-create-home meshtasticd
getent group meshtasticd >/dev/null 2>/dev/null || addgroup --system meshtasticd
adduser meshtasticd meshtasticd >/dev/null 2>/dev/null
adduser meshtasticd spi >/dev/null 2>/dev/null
adduser meshtasticd gpio >/dev/null 2>/dev/null
# add meshtasticd user to appropriate groups (if they exist)
getent group plugdev >/dev/null 2>/dev/null && adduser meshtasticd plugdev >/dev/null 2>/dev/null
getent group dialout >/dev/null 2>/dev/null && adduser meshtasticd dialout >/dev/null 2>/dev/null
getent group i2c >/dev/null 2>/dev/null && adduser meshtasticd i2c >/dev/null 2>/dev/null
getent group video >/dev/null 2>/dev/null && adduser meshtasticd video >/dev/null 2>/dev/null
getent group audio >/dev/null 2>/dev/null && adduser meshtasticd audio >/dev/null 2>/dev/null
getent group input >/dev/null 2>/dev/null && adduser meshtasticd input >/dev/null 2>/dev/null
# migrate /root/.portduino to /var/lib/meshtasticd/.portduino
# should only run once, upon upgrade from < 2.6.9
if [ -n "$2" ] && dpkg --compare-versions "$2" lt 2.6.9; then
if [ -d /root/.portduino ] && [ ! -e /var/lib/meshtasticd/.portduino ]; then
cp -r /root/.portduino /var/lib/meshtasticd/.portduino
echo "Migrated meshtasticd VFS from /root/.portduino to /var/lib/meshtasticd/.portduino"
echo "meshtasticd now runs as the 'meshtasticd' user, not 'root'."
echo "See https://github.com/meshtastic/firmware/pull/6718 for details"
fi
fi
if [ -d /var/lib/meshtasticd ]; then
chown -R meshtasticd:meshtasticd /var/lib/meshtasticd
fi
if [ -d /etc/meshtasticd ]; then
chown -R meshtasticd:meshtasticd /etc/meshtasticd
fi
if [ -d /usr/share/meshtasticd ]; then
chown -R meshtasticd:meshtasticd /usr/share/meshtasticd
fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

41
debian/meshtasticd.postrm vendored Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/sh
# postrm script for meshtasticd
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postrm> `remove'
# * <postrm> `purge'
# * <old-postrm> `upgrade' <new-version>
# * <new-postrm> `failed-upgrade' <old-version>
# * <new-postrm> `abort-install'
# * <new-postrm> `abort-install' <old-version>
# * <new-postrm> `abort-upgrade' <old-version>
# * <disappearer's-postrm> `disappear' <overwriter>
# <overwriter-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
# Only remove /var/lib/meshtasticd on purge
if [ "${1}" = "purge" ] ; then
rm -rf /var/lib/meshtasticd
fi
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0

7
debian/meshtasticd.udev vendored Normal file
View File

@@ -0,0 +1,7 @@
# Set spidev ownership to 'spi' group
SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660"
# Allow access to USB CH341 devices
SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666"
# Set gpio ownership to 'gpio' group
SUBSYSTEM=="*gpiomem*", GROUP="gpio", MODE="0660"
SUBSYSTEM=="gpio", GROUP="gpio", MODE="0660"

View File

@@ -10,6 +10,8 @@
# - https://docs.pagure.org/rpkg-util/v3/index.html
# - https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/
%global meshtasticd_user meshtasticd
Name: meshtasticd
# Version Ex: 2.5.19
Version: {{{ meshtastic_version }}}
@@ -47,6 +49,8 @@ BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(libinput)
BuildRequires: pkgconfig(xkbcommon-x11)
Requires: systemd-udev
%description
Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid
text communication platform that uses inexpensive LoRa radios.
@@ -63,15 +67,25 @@ gzip -dr web
platformio run -e native-tft
%install
mkdir -p %{buildroot}%{_sbindir}
install -m 0755 .pio/build/native-tft/program %{buildroot}%{_sbindir}/meshtasticd
# Install meshtasticd binary
mkdir -p %{buildroot}%{_bindir}
install -m 0755 .pio/build/native-tft/program %{buildroot}%{_bindir}/meshtasticd
# Install portduino VFS dir
install -p -d -m 0770 %{buildroot}%{_localstatedir}/lib/meshtasticd
# Install udev rules
mkdir -p %{buildroot}%{_udevrulesdir}
install -m 0644 bin/99-meshtasticd-udev.rules %{buildroot}%{_udevrulesdir}/99-meshtasticd-udev.rules
# Install config dirs
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd
install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/config.d
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/available.d
cp -r bin/config.d/* %{buildroot}%{_sysconfdir}/meshtasticd/available.d
# Install systemd service
install -D -m 0644 bin/meshtasticd.service %{buildroot}%{_unitdir}/meshtasticd.service
# Install the web files under /usr/share/meshtasticd/web
@@ -80,10 +94,54 @@ cp -r web/* %{buildroot}%{_datadir}/meshtasticd/web
# Install default SSL storage directory (for web)
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl
%pre
# create spi group (for udev rules)
getent group spi > /dev/null || groupadd -r spi
# create a meshtasticd group and user
getent group %{meshtasticd_user} > /dev/null || groupadd -r %{meshtasticd_user}
getent passwd %{meshtasticd_user} > /dev/null || \
useradd -r -d %{_localstatedir}/lib/meshtasticd -g %{meshtasticd_user} -G spi \
-s /sbin/nologin -c "Meshtastic Daemon" %{meshtasticd_user}
# add meshtasticd user to appropriate groups (if they exist)
getent group gpio > /dev/null && usermod -a -G gpio %{meshtasticd_user} > /dev/null
getent group plugdev > /dev/null && usermod -a -G plugdev %{meshtasticd_user} > /dev/null
getent group dialout > /dev/null && usermod -a -G dialout %{meshtasticd_user} > /dev/null
getent group i2c > /dev/null && usermod -a -G i2c %{meshtasticd_user} > /dev/null
getent group video > /dev/null && usermod -a -G video %{meshtasticd_user} > /dev/null
getent group audio > /dev/null && usermod -a -G audio %{meshtasticd_user} > /dev/null
getent group input > /dev/null && usermod -a -G input %{meshtasticd_user} > /dev/null
exit 0
%triggerin -- meshtasticd < 2.6.9
# migrate .portduino (if it exists and hasnt already been copied)
if [ -d /root/.portduino ] && [ ! -e /var/lib/meshtasticd/.portduino ]; then
mkdir -p /var/lib/meshtasticd
cp -r /root/.portduino /var/lib/meshtasticd/.portduino
chown -R %{meshtasticd_user}:%{meshtasticd_user} \
%{_localstatedir}/lib/meshtasticd || :
# Fix SELinux labels if present (no-op on non-SELinux systems)
restorecon -R /var/lib/meshtasticd/.portduino 2>/dev/null || :
echo "Migrated meshtasticd VFS from /root/.portduino to /var/lib/meshtasticd/.portduino"
echo "meshtasticd now runs as the 'meshtasticd' user, not 'root'."
echo "See https://github.com/meshtastic/firmware/pull/6718 for details"
fi
%post
%systemd_post meshtasticd.service
%preun
%systemd_preun meshtasticd.service
%postun
%systemd_postun_with_restart meshtasticd.service
%files
%defattr(-,%{meshtasticd_user},%{meshtasticd_user})
%license LICENSE
%doc README.md
%{_sbindir}/meshtasticd
%{_bindir}/meshtasticd
%dir %{_localstatedir}/lib/meshtasticd
%{_udevrulesdir}/99-meshtasticd-udev.rules
%dir %{_sysconfdir}/meshtasticd
%dir %{_sysconfdir}/meshtasticd/config.d
%dir %{_sysconfdir}/meshtasticd/available.d
@@ -96,4 +154,4 @@ mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl
%dir %{_sysconfdir}/meshtasticd/ssl
%changelog
%autochangelog
%autochangelog

View File

@@ -107,15 +107,14 @@ lib_deps =
[device-ui_base]
lib_deps =
# renovate: datasource=git-refs depName=meshtastic-device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/189ed6cba42c218e79142a876987f4516d0c87fd.zip
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/301f11e584cbeccf08af923bb2a0e02b669bda0b.zip
; Common libs for environmental measurements in telemetry module
; (not included in native / portduino)
[environmental_base]
lib_deps =
# renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO
adafruit/Adafruit BusIO@1.17.0
adafruit/Adafruit BusIO@1.17.1
# renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor
adafruit/Adafruit Unified Sensor@1.1.15
# renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library
@@ -123,9 +122,7 @@ lib_deps =
# renovate: datasource=custom.pio depName=Adafruit BMP085 packageName=adafruit/library/Adafruit BMP085 Library
adafruit/Adafruit BMP085 Library@1.2.4
# renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library
adafruit/Adafruit BME280 Library@2.2.4
# renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library
adafruit/Adafruit BMP3XX Library@2.1.6
adafruit/Adafruit BME280 Library@2.3.0
# renovate: datasource=custom.pio depName=Adafruit DPS310 packageName=adafruit/library/Adafruit DPS310
adafruit/Adafruit DPS310@1.1.5
# renovate: datasource=custom.pio depName=Adafruit MCP9808 packageName=adafruit/library/Adafruit MCP9808 Library
@@ -134,16 +131,8 @@ lib_deps =
adafruit/Adafruit INA260 Library@1.5.2
# renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219
adafruit/Adafruit INA219@1.2.3
# renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X
adafruit/Adafruit MAX1704X@1.0.3
# renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library
adafruit/Adafruit SHTC3 Library@1.0.1
# renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X
adafruit/Adafruit LPS2X@2.0.6
# renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library
adafruit/Adafruit SHT31 Library@2.2.2
# renovate: datasource=custom.pio depName=Adafruit PM25 AQI Sensor packageName=adafruit/library/Adafruit PM25 AQI Sensor
adafruit/Adafruit PM25 AQI Sensor@1.2.0
adafruit/Adafruit PM25 AQI Sensor@2.0.0
# renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050
adafruit/Adafruit MPU6050@2.2.6
# renovate: datasource=custom.pio depName=Adafruit LIS3DH packageName=adafruit/library/Adafruit LIS3DH
@@ -152,39 +141,55 @@ lib_deps =
adafruit/Adafruit AHTX0@2.0.5
# renovate: datasource=custom.pio depName=Adafruit LSM6DS packageName=adafruit/library/Adafruit LSM6DS
adafruit/Adafruit LSM6DS@4.7.4
# renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library
adafruit/Adafruit VEML7700 Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit SHT4x packageName=adafruit/library/Adafruit SHT4x Library
adafruit/Adafruit SHT4x Library@1.0.5
# renovate: datasource=custom.pio depName=Adafruit TSL2591 packageName=adafruit/library/Adafruit TSL2591 Library
adafruit/Adafruit TSL2591 Library@1.4.5
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
# renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.0
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
ClosedCube OPT3001@1.1.2
# renovate: datasource=custom.pio depName=EmotiBit MLX90632 packageName=emotibit/library/EmotiBit MLX90632
emotibit/EmotiBit MLX90632@1.0.8
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
adafruit/Adafruit MLX90614 Library@2.1.5
# renovate: datasource=github-tags depName=Bosch BSEC2 packageName=boschsensortec/Bosch-BSEC2-Library
https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/v1.7.2502.zip
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
boschsensortec/BME68x Sensor Library@1.1.40407
# renovate: datasource=github-tags depName=INA3221 packageName=KodinLanewave/INA3221
https://github.com/KodinLanewave/INA3221/archive/1.0.1.zip
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
mprograms/QMC5883LCompass@1.2.3
# renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU
dfrobot/DFRobot_RTU@1.0.3
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
# renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master
https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip
# renovate: datasource=custom.pio depName=INA226 packageName=robtillaart/library/INA226
robtillaart/INA226@0.6.4
; Health Sensor Libraries
# renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
# renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2
# renovate: datasource=custom.pio depName=Adafruit LTR390 Library packageName=adafruit/library/Adafruit LTR390 Library
adafruit/Adafruit LTR390 Library@1.1.2
# renovate: datasource=custom.pio depName=Adafruit PCT2075 packageName=adafruit/library/Adafruit PCT2075
adafruit/Adafruit PCT2075@1.0.5
; (not included in native / portduino)
[environmental_extra]
lib_deps =
# renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library
adafruit/Adafruit BMP3XX Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X
adafruit/Adafruit MAX1704X@1.0.3
# renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library
adafruit/Adafruit SHTC3 Library@1.0.1
# renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X
adafruit/Adafruit LPS2X@2.0.6
# renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library
adafruit/Adafruit SHT31 Library@2.2.2
# renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library
adafruit/Adafruit VEML7700 Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit SHT4x packageName=adafruit/library/Adafruit SHT4x Library
adafruit/Adafruit SHT4x Library@1.0.5
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
ClosedCube OPT3001@1.1.2
# renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2
boschsensortec/bsec2@1.10.2610
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
boschsensortec/BME68x Sensor Library@1.3.40408
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip

View File

@@ -9,15 +9,21 @@
"workarounds:all"
],
"forkProcessing": "enabled",
"ignoreDeps": ["protobufs"],
"ignoreDeps": [
"protobufs"
],
"git-submodules": {
"enabled": true
},
"pip_requirements": {
"fileMatch": ["bin/bump_metainfo/requirements.txt"]
"managerFilePatterns": [
"/bin/bump_metainfo/requirements.txt/"
]
},
"commitMessageTopic": "{{depName}}",
"labels": ["dependencies"],
"labels": [
"dependencies"
],
"customDatasources": {
"pio": {
"description": "PlatformIO Registry",
@@ -32,8 +38,12 @@
{
"customType": "regex",
"description": "Match meshtastic/web version",
"fileMatch": ["bin/web.version"],
"matchStrings": ["(?<currentValue>.+)$"],
"managerFilePatterns": [
"/bin/web.version/"
],
"matchStrings": [
"(?<currentValue>.+)$"
],
"datasourceTemplate": "github-releases",
"depNameTemplate": "meshtastic/web",
"versioningTemplate": "semver-coerced"
@@ -41,7 +51,9 @@
{
"customType": "regex",
"description": "Match normal PIO dependencies",
"fileMatch": [".*\\.ini$"],
"managerFilePatterns": [
"/.*\\.ini$/"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>.*?)(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\s+?.+?@(?<currentValue>.+?)\\s"
],
@@ -50,9 +62,11 @@
{
"customType": "regex",
"description": "Match PIO zipped dependencies with github tag ref",
"fileMatch": [".*\\.ini$"],
"managerFilePatterns": [
"/.*\\.ini$/"
],
"matchStrings": [
"# renovate: datasource=github-tags(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\s+?https:\/\/.+?archive\/(?<currentValue>.+?).zip\\s"
"# renovate: datasource=github-tags(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\s+?https://.+?archive/(?<currentValue>.+?).zip\\s"
],
"datasourceTemplate": "github-tags",
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}"
@@ -60,14 +74,26 @@
{
"customType": "regex",
"description": "Match PIO zipped dependencies with git commit ref",
"fileMatch": [".*\\.ini$"],
"managerFilePatterns": [
"/.*\\.ini$/"
],
"matchStrings": [
"# renovate: datasource=git-refs(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\sgitBranch=(?<gitBranch>.+?)\\s+?https:\/\/.+?archive\/(?<currentDigest>.+?).zip\\s"
"# renovate: datasource=git-refs(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\sgitBranch=(?<gitBranch>.+?)\\s+?https://.+?archive/(?<currentDigest>.+?).zip\\s"
],
"datasourceTemplate": "git-refs",
"currentValueTemplate": "{{{gitBranch}}}",
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}git{{/if}}"
}
],
"packageRules": []
"packageRules": [
{
"matchDepNames": [
"meshtastic/device-ui"
],
"reviewers": [
"mverch67"
],
"changelogUrl": "https://github.com/meshtastic/device-ui/compare/{{currentDigest}}...{{newDigest}}"
}
]
}

View File

@@ -59,82 +59,82 @@ class AmbientLightingThread : public concurrency::OSThread
return;
}
LOG_DEBUG("AmbientLighting init");
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
#ifdef HAS_NCP5623
if (_type == ScanI2C::NCP5623) {
rgb.begin();
#endif
#ifdef HAS_LP5562
} else if (_type == ScanI2C::LP5562) {
rgbw.begin();
if (_type == ScanI2C::LP5562) {
rgbw.begin();
#endif
#ifdef RGBLED_RED
pinMode(RGBLED_RED, OUTPUT);
pinMode(RGBLED_GREEN, OUTPUT);
pinMode(RGBLED_BLUE, OUTPUT);
pinMode(RGBLED_RED, OUTPUT);
pinMode(RGBLED_GREEN, OUTPUT);
pinMode(RGBLED_BLUE, OUTPUT);
#endif
#ifdef HAS_NEOPIXEL
pixels.begin(); // Initialise the pixel(s)
pixels.clear(); // Set all pixel colors to 'off'
pixels.setBrightness(moduleConfig.ambient_lighting.current);
pixels.begin(); // Initialise the pixel(s)
pixels.clear(); // Set all pixel colors to 'off'
pixels.setBrightness(moduleConfig.ambient_lighting.current);
#endif
setLighting();
setLighting();
#endif
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
}
}
#endif
}
}
protected:
int32_t runOnce() override
{
protected:
int32_t runOnce() override
{
#ifdef HAS_RGB_LED
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) {
if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) {
#endif
setLighting();
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
setLighting();
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
}
#endif
#endif
return disable();
}
#endif
#endif
return disable();
}
// When shutdown() is issued, setLightingOff will be called.
CallbackObserver<AmbientLightingThread, void *> notifyDeepSleepObserver =
CallbackObserver<AmbientLightingThread, void *>(this, &AmbientLightingThread::setLightingOff);
// When shutdown() is issued, setLightingOff will be called.
CallbackObserver<AmbientLightingThread, void *> notifyDeepSleepObserver =
CallbackObserver<AmbientLightingThread, void *>(this, &AmbientLightingThread::setLightingOff);
private:
ScanI2C::DeviceType _type = ScanI2C::DeviceType::NONE;
private:
ScanI2C::DeviceType _type = ScanI2C::DeviceType::NONE;
// Turn RGB lighting off, is used in junction to shutdown()
int setLightingOff(void *unused)
{
// Turn RGB lighting off, is used in junction to shutdown()
int setLightingOff(void *unused)
{
#ifdef HAS_NCP5623
rgb.setCurrent(0);
rgb.setRed(0);
rgb.setGreen(0);
rgb.setBlue(0);
LOG_INFO("OFF: NCP5623 Ambient lighting");
rgb.setCurrent(0);
rgb.setRed(0);
rgb.setGreen(0);
rgb.setBlue(0);
LOG_INFO("OFF: NCP5623 Ambient lighting");
#endif
#ifdef HAS_LP5562
rgbw.setCurrent(0);
rgbw.setRed(0);
rgbw.setGreen(0);
rgbw.setBlue(0);
rgbw.setWhite(0);
LOG_INFO("OFF: LP5562 Ambient lighting");
rgbw.setCurrent(0);
rgbw.setRed(0);
rgbw.setGreen(0);
rgbw.setBlue(0);
rgbw.setWhite(0);
LOG_INFO("OFF: LP5562 Ambient lighting");
#endif
#ifdef HAS_NEOPIXEL
pixels.clear();
pixels.show();
LOG_INFO("OFF: NeoPixel Ambient lighting");
pixels.clear();
pixels.show();
LOG_INFO("OFF: NeoPixel Ambient lighting");
#endif
#ifdef RGBLED_CA
analogWrite(RGBLED_RED, 255 - 0);
analogWrite(RGBLED_GREEN, 255 - 0);
analogWrite(RGBLED_BLUE, 255 - 0);
LOG_INFO("OFF: Ambient light RGB Common Anode");
analogWrite(RGBLED_RED, 255 - 0);
analogWrite(RGBLED_GREEN, 255 - 0);
analogWrite(RGBLED_BLUE, 255 - 0);
LOG_INFO("OFF: Ambient light RGB Common Anode");
#elif defined(RGBLED_RED)
analogWrite(RGBLED_RED, 0);
analogWrite(RGBLED_GREEN, 0);
@@ -142,56 +142,57 @@ class AmbientLightingThread : public concurrency::OSThread
LOG_INFO("OFF: Ambient light RGB Common Cathode");
#endif
#ifdef UNPHONE
unphone.rgb(0, 0, 0);
LOG_INFO("OFF: unPhone Ambient lighting");
unphone.rgb(0, 0, 0);
LOG_INFO("OFF: unPhone Ambient lighting");
#endif
return 0;
}
return 0;
}
void setLighting()
{
void setLighting()
{
#ifdef HAS_NCP5623
rgb.setCurrent(moduleConfig.ambient_lighting.current);
rgb.setRed(moduleConfig.ambient_lighting.red);
rgb.setGreen(moduleConfig.ambient_lighting.green);
rgb.setBlue(moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
rgb.setCurrent(moduleConfig.ambient_lighting.current);
rgb.setRed(moduleConfig.ambient_lighting.red);
rgb.setGreen(moduleConfig.ambient_lighting.green);
rgb.setBlue(moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d",
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef HAS_LP5562
rgbw.setCurrent(moduleConfig.ambient_lighting.current);
rgbw.setRed(moduleConfig.ambient_lighting.red);
rgbw.setGreen(moduleConfig.ambient_lighting.green);
rgbw.setBlue(moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
rgbw.setCurrent(moduleConfig.ambient_lighting.current);
rgbw.setRed(moduleConfig.ambient_lighting.red);
rgbw.setGreen(moduleConfig.ambient_lighting.green);
rgbw.setBlue(moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef HAS_NEOPIXEL
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue),
0, NEOPIXEL_COUNT);
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue),
0, NEOPIXEL_COUNT);
// RadioMaster Bandit has addressable LED at the two buttons
// this allow us to set different lighting for them in variant.h file.
#ifdef RADIOMASTER_900_BANDIT
#if defined(BUTTON1_COLOR) && defined(BUTTON1_COLOR_INDEX)
pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1);
pixels.fill(BUTTON1_COLOR, BUTTON1_COLOR_INDEX, 1);
#endif
#if defined(BUTTON2_COLOR) && defined(BUTTON2_COLOR_INDEX)
pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1);
pixels.fill(BUTTON2_COLOR, BUTTON2_COLOR_INDEX, 1);
#endif
#endif
pixels.show();
LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue);
pixels.show();
LOG_DEBUG("Init NeoPixel Ambient light w/ brightness(current)=%d, red=%d, green=%d, blue=%d",
moduleConfig.ambient_lighting.current, moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef RGBLED_CA
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
analogWrite(RGBLED_RED, 255 - moduleConfig.ambient_lighting.red);
analogWrite(RGBLED_GREEN, 255 - moduleConfig.ambient_lighting.green);
analogWrite(RGBLED_BLUE, 255 - moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init Ambient light RGB Common Anode w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#elif defined(RGBLED_RED)
analogWrite(RGBLED_RED, moduleConfig.ambient_lighting.red);
analogWrite(RGBLED_GREEN, moduleConfig.ambient_lighting.green);
@@ -200,11 +201,12 @@ class AmbientLightingThread : public concurrency::OSThread
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef UNPHONE
unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
unphone.rgb(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init unPhone Ambient light w/ red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.red,
moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
}
};
}
};
} // namespace concurrency

View File

@@ -88,10 +88,16 @@ class BluetoothStatus : public Status
break;
case ConnectionState::CONNECTED:
LOG_DEBUG("BluetoothStatus CONNECTED");
#ifdef BLE_LED
digitalWrite(BLE_LED, HIGH);
#endif
break;
case ConnectionState::DISCONNECTED:
LOG_DEBUG("BluetoothStatus DISCONNECTED");
#ifdef BLE_LED
digitalWrite(BLE_LED, LOW);
#endif
break;
}
}
@@ -102,4 +108,4 @@ class BluetoothStatus : public Status
} // namespace meshtastic
extern meshtastic::BluetoothStatus *bluetoothStatus;
extern meshtastic::BluetoothStatus *bluetoothStatus;

View File

@@ -255,7 +255,7 @@ int32_t ButtonThread::runOnce()
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
break;
#endif
#if defined(RAK_4631)
#if !MESHTASTIC_EXCLUDE_SCREEN && HAS_SCREEN
// 5 clicks: start accelerometer/magenetometer calibration for 30 seconds
case 5:
if (accelerometerThread) {
@@ -300,14 +300,23 @@ int32_t ButtonThread::runOnce()
#ifdef BUTTON_PIN_TOUCH
case BUTTON_EVENT_TOUCH_LONG_PRESSED: {
LOG_BUTTON("Touch press!");
if (screen) {
// Wake if asleep
if (powerFSM.getState() == &stateDARK)
powerFSM.trigger(EVENT_PRESS);
// Ignore if: no screen
if (!screen)
break;
// Update display (legacy behaviour)
screen->forceDisplay();
}
#ifdef TTGO_T_ECHO
// Ignore if: TX in progress
// Uncommon T-Echo hardware bug, LoRa TX triggers touch button
if (!RadioLibInterface::instance || RadioLibInterface::instance->isSending())
break;
#endif
// Wake if asleep
if (powerFSM.getState() == &stateDARK)
powerFSM.trigger(EVENT_PRESS);
// Update display (legacy behaviour)
screen->forceDisplay();
break;
}
#endif // BUTTON_PIN_TOUCH

View File

@@ -76,23 +76,47 @@ static const uint8_t ext_chrg_detect_value = EXT_CHRG_DETECT_VALUE;
#endif
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if __has_include(<Adafruit_INA219.h>)
INA219Sensor ina219Sensor;
INA226Sensor ina226Sensor;
INA260Sensor ina260Sensor;
INA3221Sensor ina3221Sensor;
#else
NullSensor ina219Sensor;
#endif
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if __has_include(<INA226.h>)
INA226Sensor ina226Sensor;
#else
NullSensor ina226Sensor;
#endif
#if __has_include(<Adafruit_INA260.h>)
INA260Sensor ina260Sensor;
#else
NullSensor ina260Sensor;
#endif
#if __has_include(<INA3221.h>)
INA3221Sensor ina3221Sensor;
#else
NullSensor ina3221Sensor;
#endif
#endif
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_STM32WL)
#include "modules/Telemetry/Sensor/MAX17048Sensor.h"
#include <utility>
extern std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
#if HAS_TELEMETRY && (!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR || !MESHTASTIC_EXCLUDE_POWER_TELEMETRY)
#if __has_include(<Adafruit_MAX1704X.h>)
MAX17048Sensor max17048Sensor;
#else
NullSensor max17048Sensor;
#endif
#endif
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT && !defined(ARCH_PORTDUINO)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT
RAK9154Sensor rak9154Sensor;
#endif
@@ -203,7 +227,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
*/
virtual int getBatteryPercent() override
{
#if defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU)
#if defined(HAS_RAKPROT) && !defined(HAS_PMU)
if (hasRAK()) {
return rak9154Sensor.getBusBatteryPercent();
}
@@ -248,15 +272,13 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual uint16_t getBattVoltage() override
{
#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU) && \
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasRAK()) {
return getRAKVoltage();
}
#endif
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && \
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if HAS_TELEMETRY && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasINA()) {
return getINAVoltage();
}
@@ -426,8 +448,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
/// we can't be smart enough to say 'full'?
virtual bool isCharging() override
{
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && \
!defined(HAS_PMU)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(HAS_PMU)
if (hasRAK()) {
return (rak9154Sensor.isCharging()) ? OptTrue : OptFalse;
}
@@ -435,7 +456,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
#ifdef EXT_CHRG_DETECT
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
#else
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && \
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL) && \
!defined(DISABLE_INA_CHARGING_DETECTION)
if (hasINA()) {
// get current flow from INA sensor - negative value means power flowing into the battery
@@ -482,7 +503,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
}
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL)
uint16_t getINAVoltage()
{
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {

View File

@@ -9,17 +9,23 @@ namespace concurrency
Lock::Lock() : handle(xSemaphoreCreateBinary())
{
assert(handle);
assert(xSemaphoreGive(handle));
if (xSemaphoreGive(handle) == false) {
abort();
}
}
void Lock::lock()
{
assert(xSemaphoreTake(handle, portMAX_DELAY));
if (xSemaphoreTake(handle, portMAX_DELAY) == false) {
abort();
}
}
void Lock::unlock()
{
assert(xSemaphoreGive(handle));
if (xSemaphoreGive(handle) == false) {
abort();
}
}
#else
Lock::Lock() {}

View File

@@ -80,10 +80,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// Override user saved region, for producing region-locked builds
// #define REGULATORY_LORA_REGIONCODE meshtastic_Config_LoRaConfig_RegionCode_SG_923
// Total system gain in dBm to subtract from Tx power to remain within regulatory ERP limit for non-licensed operators
// This value should be set in variant.h and is PA gain + antenna gain (if system ships with an antenna)
#ifndef REGULATORY_GAIN_LORA
#define REGULATORY_GAIN_LORA 0
// Total system gain in dBm to subtract from Tx power to remain within regulatory and Tx PA limits
// This value should be set in variant.h and is PA gain + antenna gain (if variant has a non-removable antenna)
#ifndef TX_GAIN_LORA
#define TX_GAIN_LORA 0
#endif
// -----------------------------------------------------------------------------
@@ -99,8 +99,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// -----------------------------------------------------------------------------
// OLED & Input
// -----------------------------------------------------------------------------
#if defined(SEEED_WIO_TRACKER_L1)
#define SSD1306_ADDRESS 0x3D
#define USE_SH1106
#else
#define SSD1306_ADDRESS 0x3C
#endif
#define ST7567_ADDRESS 0x3F
// The SH1106 controller is almost, but not quite, the same as SSD1306
@@ -153,6 +157,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define CGRADSENS_ADDR 0x66
#define LTR390UV_ADDR 0x53
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418
#define PCT2075_ADDR 0x37
// -----------------------------------------------------------------------------
// ACCELEROMETER

View File

@@ -71,6 +71,7 @@ class ScanI2C
DPS310,
LTR390UV,
TCA8418KB,
PCT2075,
} DeviceType;
// typedef uint8_t DeviceAddress;

View File

@@ -434,6 +434,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address);
SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address);
#ifdef HAS_TPS65233
SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address);
#endif

View File

@@ -570,6 +570,19 @@ bool GPS::setup()
// Switch to Fitness Mode, for running and walking purpose with low speed (<5 m/s)
_serial_gps->write("$PMTK886,1*29\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_MTK_PA1010D) {
// PA1010D is used in the Pimoroni GPS board.
// Enable all constellations.
_serial_gps->write("$PMTK353,1,1,1,1,1*2A\r\n");
// Above command will reset the GPS and takes longer before it will accept new commands
delay(1000);
// Only ask for RMC and GGA (GNRMC and GNGGA)
_serial_gps->write("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n");
delay(250);
// Enable SBAS / WAAS
_serial_gps->write("$PMTK301,2*2E\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_MTK_PA1616S) {
// PA1616S is used in some GPS breakout boards from Adafruit
// PA1616S does not have GLONASS capability. PA1616D does, but is not implemented here.
@@ -1237,10 +1250,11 @@ GnssModel_t GPS::probe(int serialSpeed)
// Close all NMEA sentences, valid for MTK3333 and MTK3339 platforms
_serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
delay(20);
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B},
{"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S},
{"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B},
{"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}};
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B}, {"PA1010D", "1010D", GNSS_MODEL_MTK_PA1010D},
{"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S}, {"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B},
{"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}, {"L80-R", "_3337_", GNSS_MODEL_MTK_L76B},
{"L80", "_3339_", GNSS_MODEL_MTK_L76B}};
PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500);
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};

View File

@@ -27,6 +27,7 @@ typedef enum {
GNSS_MODEL_UC6580,
GNSS_MODEL_UNKNOWN,
GNSS_MODEL_MTK_L76B,
GNSS_MODEL_MTK_PA1010D,
GNSS_MODEL_MTK_PA1616S,
GNSS_MODEL_AG3335,
GNSS_MODEL_AG3352,

View File

@@ -1612,6 +1612,9 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
#ifdef T_WATCH_S3
PMU->enablePowerOutput(XPOWERS_ALDO2);
#endif
#ifdef HELTEC_TRACKER_V1_X
uint8_t tft_vext_enabled = digitalRead(VEXT_ENABLE);
#endif
#if !ARCH_PORTDUINO
dispdev->displayOn();
#endif
@@ -1622,6 +1625,12 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
#endif
dispdev->displayOn();
#ifdef HELTEC_TRACKER_V1_X
// If the TFT VEXT power is not enabled, initialize the UI.
if (!tft_vext_enabled) {
ui->init();
}
#endif
#ifdef USE_ST7789
pinMode(VTFT_CTRL, OUTPUT);
digitalWrite(VTFT_CTRL, LOW);
@@ -2840,9 +2849,6 @@ int Screen::handleInputEvent(const InputEvent *event)
int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
{
// Note: only selected admin messages notify this observer
// If you wish to handle a new type of message, you should modify AdminModule.cpp first
switch (arg->which_payload_variant) {
// Node removed manually (i.e. via app)
case meshtastic_AdminMessage_remove_by_nodenum_tag:

View File

@@ -65,8 +65,8 @@
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) || \
defined(ILI9488_CS) && !defined(DISPLAY_FORCE_SMALL_FONTS)
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19
#define FONT_MEDIUM FONT_LARGE_LOCAL // Height: 28

View File

@@ -467,18 +467,27 @@ class LGFX : public lgfx::LGFX_Device
// The following setting values are general initial values for each panel, so please comment out any
// unknown items and try them.
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
#if defined(T_WATCH_S3)
cfg.panel_width = 240;
cfg.panel_height = 240;
cfg.memory_width = 240;
cfg.memory_height = 320;
cfg.offset_x = 0;
cfg.offset_y = 0; // No vertical shift needed — panel is top-aligned
cfg.offset_rotation = 2; // Rotate 180° to correct upside-down layout
#else
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
#endif
#ifdef TFT_DUMMY_READ_PIXELS
cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout
#else
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
#endif
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read

View File

@@ -5,7 +5,7 @@ E-Ink display driver
- Manufacturer: DKE
- Size: 2.13 inch
- Resolution: 122px x 250px
- Flex connector marking: FPC-7528B
- Flex connector marking (not a unique identifier): FPC-7528B
Note: this is from an older generation of DKE panels, which still used Solomon Systech controller ICs.
DKE's website suggests that the latest DEPG0213BN displays may use Fitipower controllers instead.

View File

@@ -5,7 +5,7 @@ E-Ink display driver
- Manufacturer: DKE
- Size: 2.9 inch
- Resolution: 128px x 296px
- Flex connector marking: FPC-7519 rev.b
- Flex connector marking (not a unique identifier): FPC-7519 rev.b
*/

View File

@@ -9,12 +9,9 @@ void GDEY0154D67::configScanning()
{
// "Driver output control"
sendCommand(0x01);
sendData(0xC7);
sendData(0xC7); // Scan until gate 199 (200px vertical res.)
sendData(0x00);
sendData(0x00);
// To-do: delete this method?
// Values set here might be redundant: C7, 00, 00 seems to be default
}
// Specify which information is used to control the sequence of voltages applied to move the pixels
@@ -52,10 +49,10 @@ void GDEY0154D67::detachFromUpdate()
{
switch (updateType) {
case FAST:
return beginPolling(50, 500); // At least 500ms for fast refresh
return beginPolling(50, 300); // At least 300ms for fast refresh
case FULL:
default:
return beginPolling(100, 2000); // At least 2 seconds for full refresh
return beginPolling(100, 1500); // At least 1.5 seconds for full refresh
}
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -5,7 +5,7 @@ E-Ink display driver
- Manufacturer: Goodisplay
- Size: 1.54 inch
- Resolution: 200px x 200px
- Flex connector marking: FPC-B001
- Flex connector marking (not a unique identifier): FPC-B001
*/
@@ -31,9 +31,9 @@ class GDEY0154D67 : public SSD16XX
GDEY0154D67() : SSD16XX(width, height, supported) {}
protected:
virtual void configScanning() override;
virtual void configWaveform() override;
virtual void configUpdateSequence() override;
void configScanning() override;
void configWaveform() override;
void configUpdateSequence() override;
void detachFromUpdate() override;
};

View File

@@ -0,0 +1,58 @@
#include "./GDEY0213B74.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
using namespace NicheGraphics::Drivers;
// Map the display controller IC's output to the connected panel
void GDEY0213B74::configScanning()
{
// "Driver output control"
sendCommand(0x01);
sendData(0xF9);
sendData(0x00);
sendData(0x00);
}
// Specify which information is used to control the sequence of voltages applied to move the pixels
// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
// the controller IC's OTP memory, when the update procedure begins.
void GDEY0213B74::configWaveform()
{
sendCommand(0x3C); // Border waveform:
sendData(0x05); // Screen border should follow LUT1 waveform (actively drive pixels white)
sendCommand(0x18); // Temperature sensor:
sendData(0x80); // Use internal temperature sensor to select an appropriate refresh waveform
}
void GDEY0213B74::configUpdateSequence()
{
switch (updateType) {
case FAST:
sendCommand(0x22); // Set "update sequence"
sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
break;
case FULL:
default:
sendCommand(0x22); // Set "update sequence"
sendData(0xF7); // Will load LUT from OTP memory
break;
}
}
// Once the refresh operation has been started,
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
// Only used when refresh is "async"
void GDEY0213B74::detachFromUpdate()
{
switch (updateType) {
case FAST:
return beginPolling(50, 500); // At least 500ms for fast refresh
case FULL:
default:
return beginPolling(100, 2000); // At least 2 seconds for full refresh
}
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -0,0 +1,44 @@
/*
E-Ink display driver
- GDEY0213B74
- Manufacturer: Goodisplay
- Size: 2.13 inch
- Resolution: 250px x 122px
- Flex connector marking (not a unique identifier):
- FPC-A002
- FPC-A005 20.06.15 TRX
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./SSD16XX.h"
namespace NicheGraphics::Drivers
{
class GDEY0213B74 : public SSD16XX
{
// Display properties
private:
static constexpr uint32_t width = 122;
static constexpr uint32_t height = 250;
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
public:
GDEY0213B74() : SSD16XX(width, height, supported) {}
protected:
virtual void configScanning() override;
virtual void configWaveform() override;
virtual void configUpdateSequence() override;
void detachFromUpdate() override;
};
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -0,0 +1,61 @@
#include "./HINK_E0213A289.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
using namespace NicheGraphics::Drivers;
// Map the display controller IC's output to the connected panel
void HINK_E0213A289::configScanning()
{
// "Driver output control"
// Scan gates from 0 to 249 (vertical resolution 250px)
sendCommand(0x01);
sendData(0xF9); // Maximum gate # (249, bits 0-7)
sendData(0x00); // Maximum gate # (bit 8)
sendData(0x00); // (Do not invert scanning order)
}
// Specify which information is used to control the sequence of voltages applied to move the pixels
// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
// the controller IC's OTP memory, when the update procedure begins.
void HINK_E0213A289::configWaveform()
{
sendCommand(0x3C); // Border waveform:
sendData(0x05); // Screen border should follow LUT1 waveform (actively drive pixels white)
sendCommand(0x18); // Temperature sensor:
sendData(0x80); // Use internal temperature sensor to select an appropriate refresh waveform
}
// Describes the sequence of events performed by the displays controller IC during a refresh
// Includes "power up", "load settings from memory", "update the pixels", etc
void HINK_E0213A289::configUpdateSequence()
{
switch (updateType) {
case FAST:
sendCommand(0x22); // Set "update sequence"
sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
break;
case FULL:
default:
sendCommand(0x22); // Set "update sequence"
sendData(0xF7); // Will load LUT from OTP memory
break;
}
}
// Once the refresh operation has been started,
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
// Only used when refresh is "async"
void HINK_E0213A289::detachFromUpdate()
{
switch (updateType) {
case FAST:
return beginPolling(50, 500); // At least 500ms for fast refresh
case FULL:
default:
return beginPolling(100, 1000); // At least 1 second for full refresh (quick; display only blinks pixels once)
}
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -0,0 +1,44 @@
/*
E-Ink display driver
- HINK_E0213A289
- Manufacturer: Holitech
- Size: 2.13 inch
- Resolution: 122px x 250px
- Flex connector label (not a unique identifier): FPC-7528B
Note: as of Feb. 2025, these panels are used for "WeActStudio 2.13in B&W" display modules
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./SSD16XX.h"
namespace NicheGraphics::Drivers
{
class HINK_E0213A289 : public SSD16XX
{
// Display properties
private:
static constexpr uint32_t width = 122;
static constexpr uint32_t height = 250;
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
public:
HINK_E0213A289() : SSD16XX(width, height, supported, 1) {}
protected:
void configScanning() override;
void configWaveform() override;
void configUpdateSequence() override;
void detachFromUpdate() override;
};
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -5,7 +5,7 @@ E-Ink display driver
- Manufacturer: Holitech
- Size: 4.2 inch
- Resolution: 400px x 300px
- Flex connector marking: HINK-E042A07-FPC-A1
- Flex connector marking (not a unique identifier): HINK-E042A07-FPC-A1
- Silver sticker with QR code, marked: HE042A87
Note: as of Feb. 2025, these panels are used for "WeActStudio 4.2in B&W" display modules

View File

@@ -5,7 +5,6 @@ E-Ink display driver
- Manufacturer: WISEVAST
- Size: 2.13 inch
- Resolution: 122px x 255px
- Flex connector marking: Soldering connector, no connector is needed
*/

View File

@@ -1,9 +1,11 @@
#include "./LCMEN2R13EFC1.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./LCMEN2R13EFC1.h"
#include <assert.h>
#include "SPILock.h"
using namespace NicheGraphics::Drivers;
// Look up table: fast refresh, common electrode
@@ -150,6 +152,9 @@ void LCMEN213EFC1::reset()
void LCMEN213EFC1::sendCommand(const uint8_t command)
{
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, LOW); // DC pin low indicates command
digitalWrite(pin_cs, LOW);
@@ -157,6 +162,8 @@ void LCMEN213EFC1::sendCommand(const uint8_t command)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void LCMEN213EFC1::sendData(uint8_t data)
@@ -166,6 +173,9 @@ void LCMEN213EFC1::sendData(uint8_t data)
void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
{
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
digitalWrite(pin_cs, LOW);
@@ -183,6 +193,8 @@ void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void LCMEN213EFC1::configFull()

View File

@@ -5,7 +5,7 @@ E-Ink display driver
- Manufacturer: Wisevast
- Size: 2.13 inch
- Resolution: 122px x 250px
- Flex connector marking: HINK-E0213A162-FPC-A0 (Hidden, printed on back-side)
- Flex connector marking (not a unique identifier): HINK-E0213A162-FPC-A0 (Hidden, printed on back-side)
Note: this display uses an uncommon controller IC, Fitipower JD79656.
It is implemented as a "one-off", directly inheriting the EInk base class, unlike SSD16XX displays.

View File

@@ -1,6 +1,9 @@
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./SSD16XX.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "SPILock.h"
using namespace NicheGraphics::Drivers;
SSD16XX::SSD16XX(uint16_t width, uint16_t height, UpdateTypes supported, uint8_t bufferOffsetX)
@@ -82,6 +85,9 @@ void SSD16XX::sendCommand(const uint8_t command)
if (failed)
return;
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, LOW); // DC pin low indicates command
digitalWrite(pin_cs, LOW);
@@ -89,6 +95,8 @@ void SSD16XX::sendCommand(const uint8_t command)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void SSD16XX::sendData(uint8_t data)
@@ -103,6 +111,9 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
if (failed)
return;
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
digitalWrite(pin_cs, LOW);
@@ -119,6 +130,8 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void SSD16XX::configFullscreen()

View File

@@ -0,0 +1,59 @@
#include "./ZJY128296_029EAAMFGN.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
using namespace NicheGraphics::Drivers;
// Map the display controller IC's output to the connected panel
void ZJY128296_029EAAMFGN::configScanning()
{
// "Driver output control"
// Scan gates from 0 to 295 (vertical resolution 296px)
sendCommand(0x01);
sendData(0x27); // Number of gates (295, bits 0-7)
sendData(0x01); // Number of gates (295, bit 8)
sendData(0x00); // (Do not invert scanning order)
}
// Specify which information is used to control the sequence of voltages applied to move the pixels
// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
// the controller IC's OTP memory, when the update procedure begins.
void ZJY128296_029EAAMFGN::configWaveform()
{
sendCommand(0x3C); // Border waveform:
sendData(0x05); // Screen border should follow LUT1 waveform (actively drive pixels white)
sendCommand(0x18); // Temperature sensor:
sendData(0x80); // Use internal temperature sensor to select an appropriate refresh waveform
}
void ZJY128296_029EAAMFGN::configUpdateSequence()
{
switch (updateType) {
case FAST:
sendCommand(0x22); // Set "update sequence"
sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
break;
case FULL:
default:
sendCommand(0x22); // Set "update sequence"
sendData(0xF7); // Will load LUT from OTP memory
break;
}
}
// Once the refresh operation has been started,
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
// Only used when refresh is "async"
void ZJY128296_029EAAMFGN::detachFromUpdate()
{
switch (updateType) {
case FAST:
return beginPolling(50, 300); // At least 300ms for fast refresh
case FULL:
default:
return beginPolling(100, 2000); // At least 2 seconds for full refresh
}
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -0,0 +1,44 @@
/*
E-Ink display driver
- ZJY128296-029EAAMFGN
- Manufacturer: Zhongjingyuan
- Size: 2.9 inch
- Resolution: 128px x 296px
- Flex connector label (not a unique identifier): FPC-A005 20.06.15 TRX
Note: as of Feb. 2025, these panels are used for "WeActStudio 2.9in B&W" display modules
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./SSD16XX.h"
namespace NicheGraphics::Drivers
{
class ZJY128296_029EAAMFGN : public SSD16XX
{
// Display properties
private:
static constexpr uint32_t width = 128;
static constexpr uint32_t height = 296;
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
public:
ZJY128296_029EAAMFGN() : SSD16XX(width, height, supported) {}
protected:
void configScanning() override;
void configWaveform() override;
void configUpdateSequence() override;
void detachFromUpdate() override;
};
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -0,0 +1,32 @@
/*
E-Ink display driver
- ZJY200200-0154DAAMFGN
- Manufacturer: Zhongjingyuan
- Size: 1.54 inch
- Resolution: 200px x 200px
- Flex connector marking: FPC-B001
Note: as of Feb. 2025, these panels are used for "WeActStudio 1.54in B&W" display modules
This *is* a distinct panel, however the driver is currently identical to GDEY0154D67
We recognize it as separate now, to avoid breaking any custom builds if the drivers do need to diverge in future.
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./GDEY0154D67.h"
namespace NicheGraphics::Drivers
{
typedef GDEY0154D67 ZJY200200_0154DAAMFGN;
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS

View File

@@ -13,6 +13,7 @@ Avoid bloating everyone's protobuf code for our one-off UI implementations
#include "configuration.h"
#include "SPILock.h"
#include "SafeFile.h"
namespace NicheGraphics
@@ -46,6 +47,9 @@ template <typename T> class FlashData
public:
static bool load(T *data, const char *label)
{
// Take firmware's SPI lock
concurrency::LockGuard guard(spiLock);
// Set false if we run into issues
bool okay = true;
@@ -103,14 +107,18 @@ template <typename T> class FlashData
return okay;
}
// Save module's custom data (settings?) to flash. Does use protobufs
// Save module's custom data (settings?) to flash. Doesn't use protobufs
// Takes the firmware's SPI lock, in case the files are stored on SD card
// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally.
static void save(T *data, const char *label)
{
// Get a filename based on the label
std::string filename = getFilename(label);
#ifdef FSCom
spiLock->lock();
FSCom.mkdir("/NicheGraphics");
spiLock->unlock();
auto f = SafeFile(filename.c_str(), true); // "true": full atomic. Write new data to temp file, then rename.
@@ -119,10 +127,10 @@ template <typename T> class FlashData
// Calculate a hash of the data
uint32_t hash = getHash(data);
spiLock->lock();
f.write((uint8_t *)data, sizeof(T)); // Write the actual data
f.write((uint8_t *)&hash, sizeof(hash)); // Append the hash
// f.flush();
spiLock->unlock();
bool writeSucceeded = f.close();
@@ -135,6 +143,32 @@ template <typename T> class FlashData
}
};
// Erase contents of the NicheGraphics data directory
inline void clearFlashData()
{
// Take firmware's SPI lock, in case the files are stored on SD card
concurrency::LockGuard guard(spiLock);
#ifdef FSCom
File dir = FSCom.open("/NicheGraphics"); // Open the directory
File file = dir.openNextFile(); // Attempt to open the first file in the directory
// While the directory still contains files
while (file) {
std::string path = "/NicheGraphics/";
path += file.name();
LOG_DEBUG("Erasing %s", path.c_str());
file.close();
FSCom.remove(path.c_str());
file = dir.openNextFile();
}
#else
LOG_ERROR("ERROR: Filesystem not implemented\n");
#endif
}
} // namespace NicheGraphics
#endif

View File

@@ -1,129 +1,198 @@
#pragma once
const uint8_t FreeSans6pt7bBitmaps[] PROGMEM = {
0xAA, 0xA8, 0xC0, 0xF6, 0xA0, 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, 0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00,
0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, 0x70, 0x91, 0x23, 0x86, 0x12, 0xA2, 0x4E, 0xF4, 0xE0,
0x5A, 0xAA, 0x94, 0x89, 0x12, 0x49, 0x29, 0x00, 0x27, 0x50, 0x21, 0x3E, 0x42, 0x00, 0xE0, 0xC0, 0x80, 0x24, 0xA4, 0xA4, 0x80,
0x74, 0xE3, 0x18, 0xC6, 0x33, 0x70, 0x27, 0x92, 0x49, 0x20, 0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, 0x79, 0x30, 0x43, 0x18,
0x10, 0x71, 0x78, 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, 0x7D, 0x04, 0x1E, 0x44, 0x10, 0x51, 0x78, 0x74, 0x61, 0xE8, 0xC6,
0x31, 0x70, 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, 0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, 0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53,
0x78, 0x82, 0x87, 0x01, 0xF1, 0x83, 0x04, 0xF8, 0x3E, 0x07, 0x06, 0x36, 0x40, 0x74, 0x42, 0x11, 0x10, 0x80, 0x20, 0x0F, 0x86,
0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42,
0x42, 0xC3, 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, 0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, 0xF9, 0x0A, 0x1C,
0x18, 0x30, 0x61, 0xC2, 0xF8, 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, 0x1E, 0x61,
0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, 0xFF, 0x80, 0x08, 0x42, 0x10, 0x87,
0x29, 0x70, 0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, 0xC3, 0xC3, 0xC3, 0xA5, 0xA5,
0xA5, 0x99, 0x99, 0x99, 0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6,
0x1E, 0x00, 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1F, 0x00, 0x00,
0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, 0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04,
0x08, 0x10, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, 0xC2, 0x42, 0x42, 0x64, 0x24, 0x24, 0x38, 0x18, 0x18, 0xC4, 0x28,
0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, 0x42, 0x66, 0x24, 0x18, 0x18, 0x18, 0x24, 0x46, 0x42, 0xC3,
0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, 0xEA, 0xAA, 0xAB, 0x92, 0x24,
0x89, 0x20, 0xE9, 0x24, 0x92, 0x49, 0x70, 0x46, 0xA9, 0x10, 0xFE, 0x40, 0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, 0x84, 0x3D, 0x18,
0xC6, 0x31, 0xF0, 0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, 0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, 0x39, 0x38, 0x7F, 0x81, 0x13,
0x80, 0x6B, 0xA4, 0x92, 0x40, 0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, 0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, 0xBF, 0x80,
0x45, 0x55, 0x57, 0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, 0xFF, 0x80, 0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, 0xF4, 0x63, 0x18,
0xC6, 0x20, 0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, 0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, 0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04,
0xF2, 0x49, 0x20, 0x79, 0x24, 0x1C, 0x0B, 0x27, 0x80, 0x5D, 0x24, 0x93, 0x8C, 0x63, 0x18, 0xCF, 0xA0, 0x85, 0x24, 0x92, 0x30,
0xC3, 0x00, 0x89, 0x2C, 0x96, 0x4A, 0xA5, 0x61, 0x30, 0x98, 0x49, 0x23, 0x08, 0x31, 0x2C, 0x80, 0x89, 0x24, 0x94, 0x50, 0xC2,
0x08, 0x21, 0x00, 0x78, 0x44, 0x46, 0x23, 0xE0, 0x6A, 0xAA, 0xA9, 0xFF, 0xE0, 0x95, 0x55, 0x56, 0x66, 0x60};
/* ' ' 0x20 */
/* '!' 0x21 */ 0xFE, 0x80,
/* '"' 0x22 */ 0xB6, 0x80,
/* '#' 0x23 */ 0x24, 0x49, 0xF9, 0x42, 0x9F, 0x92, 0x28,
/* '$' 0x24 */ 0x23, 0xAB, 0x5A, 0x38, 0xB5, 0xAB, 0x88,
/* '%' 0x25 */ 0x71, 0x22, 0x88, 0xA2, 0x30, 0x74, 0x02, 0x60, 0xA4, 0x49, 0x11, 0x80,
/* '&' 0x26 */ 0x31, 0x24, 0x8C, 0x72, 0x58, 0xA3, 0x74,
/* ''' 0x27 */ 0xE0,
/* '(' 0x28 */ 0x5A, 0xAA, 0x94,
/* ')' 0x29 */ 0x89, 0x12, 0x49, 0x49, 0x00,
/* '*' 0x2A */ 0x5E, 0x80,
/* '+' 0x2B */ 0x21, 0x3E, 0x42, 0x00,
/* ',' 0x2C */ 0xE0,
/* '-' 0x2D */ 0xE0,
/* '.' 0x2E */ 0x80,
/* '/' 0x2F */ 0x25, 0x24, 0xA4, 0x80,
/* '0' 0x30 */ 0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70,
/* '1' 0x31 */ 0x5D, 0x55, 0x40,
/* '2' 0x32 */ 0x74, 0x42, 0x11, 0x11, 0x10, 0xF8,
/* '3' 0x33 */ 0x74, 0x42, 0x13, 0x04, 0x31, 0x70,
/* '4' 0x34 */ 0x11, 0x8C, 0xA9, 0x4B, 0xE2, 0x10,
/* '5' 0x35 */ 0x7D, 0x04, 0x1E, 0x4C, 0x10, 0x63, 0x78,
/* '6' 0x36 */ 0x72, 0x61, 0xE8, 0xC6, 0x39, 0x70,
/* '7' 0x37 */ 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40,
/* '8' 0x38 */ 0x7A, 0x18, 0x61, 0x7A, 0x18, 0x61, 0x78,
/* '9' 0x39 */ 0x7B, 0x28, 0x61, 0xCD, 0xD0, 0x62, 0x70,
/* ':' 0x3A */ 0x82,
/* ';' 0x3B */ 0x87,
/* '<' 0x3C */ 0x3E, 0x30, 0x60, 0x80,
/* '=' 0x3D */ 0xF8, 0x3E,
/* '>' 0x3E */ 0xE0, 0xC6, 0xC8, 0x00,
/* '?' 0x3F */ 0x74, 0x42, 0x11, 0x10, 0x80, 0x20,
/* '@' 0x40 */ 0x0F, 0x06, 0x19, 0x3B, 0xC4, 0x99, 0x13, 0x22, 0x64, 0x96, 0x6E, 0x40, 0x04, 0x00, 0x7C, 0x00,
/* 'A' 0x41 */ 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3,
/* 'B' 0x42 */ 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xF8,
/* 'C' 0x43 */ 0x3E, 0x41, 0x80, 0x80, 0x80, 0x80, 0x81, 0x43, 0x3E,
/* 'D' 0x44 */ 0xF9, 0x0A, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xF8,
/* 'E' 0x45 */ 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0xFC,
/* 'F' 0x46 */ 0xFC, 0x21, 0x0F, 0xC2, 0x10, 0x80,
/* 'G' 0x47 */ 0x3E, 0x41, 0x80, 0x80, 0x87, 0x81, 0xC1, 0x43, 0x3D,
/* 'H' 0x48 */ 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82,
/* 'I' 0x49 */ 0xFF, 0x80,
/* 'J' 0x4A */ 0x08, 0x42, 0x10, 0x86, 0x31, 0x70,
/* 'K' 0x4B */ 0x86, 0x29, 0x28, 0xD2, 0x48, 0xA1, 0x84,
/* 'L' 0x4C */ 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8,
/* 'M' 0x4D */ 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99,
/* 'N' 0x4E */ 0xC3, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86,
/* 'O' 0x4F */ 0x3E, 0x31, 0xB0, 0x70, 0x18, 0x0C, 0x07, 0x06, 0xC6, 0x3E, 0x00,
/* 'P' 0x50 */ 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80,
/* 'Q' 0x51 */ 0x3E, 0x31, 0xB0, 0x70, 0x18, 0x0C, 0x07, 0x06, 0xC6, 0x3F, 0x00, 0x40,
/* 'R' 0x52 */ 0xF9, 0x0A, 0x14, 0x2F, 0x90, 0xA1, 0x42, 0x86,
/* 'S' 0x53 */ 0x7A, 0x18, 0x30, 0x78, 0x38, 0x71, 0x78,
/* 'T' 0x54 */ 0xFC, 0x41, 0x04, 0x10, 0x41, 0x04, 0x10,
/* 'U' 0x55 */ 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE3, 0x7C,
/* 'V' 0x56 */ 0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18,
/* 'W' 0x57 */ 0x84, 0x38, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0xD2, 0x8C, 0x61, 0x8C, 0x31, 0x80,
/* 'X' 0x58 */ 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84,
/* 'Y' 0x59 */ 0x82, 0x89, 0x11, 0x43, 0x82, 0x04, 0x08, 0x10,
/* 'Z' 0x5A */ 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE,
/* '[' 0x5B */ 0xEA, 0xAA, 0xAB,
/* '\' 0x5C */ 0x92, 0x24, 0x91, 0x20,
/* ']' 0x5D */ 0xD5, 0x55, 0x57,
/* '^' 0x5E */ 0x46, 0xA9, 0x10,
/* '_' 0x5F */ 0xFE,
/* '`' 0x60 */ 0x80,
/* 'a' 0x61 */ 0x79, 0x08, 0x11, 0xEC, 0x51, 0x9D, 0x80,
/* 'b' 0x62 */ 0x84, 0x3D, 0xB8, 0xC6, 0x3B, 0xF0,
/* 'c' 0x63 */ 0x7B, 0x18, 0x20, 0x83, 0x17, 0x80,
/* 'd' 0x64 */ 0x04, 0x17, 0xF3, 0x86, 0x18, 0x73, 0x74,
/* 'e' 0x65 */ 0x7B, 0x38, 0x7F, 0x83, 0x17, 0x80,
/* 'f' 0x66 */ 0x6B, 0xA4, 0x92, 0x40,
/* 'g' 0x67 */ 0x77, 0x38, 0x61, 0x87, 0x37, 0x41, 0x8D, 0xE0,
/* 'h' 0x68 */ 0x84, 0x2D, 0x98, 0xC6, 0x31, 0x88,
/* 'i' 0x69 */ 0xBF, 0x80,
/* 'j' 0x6A */ 0x45, 0x55, 0x57,
/* 'k' 0x6B */ 0x84, 0x25, 0x6E, 0x72, 0x52, 0x88,
/* 'l' 0x6C */ 0xFF, 0x80,
/* 'm' 0x6D */ 0xFF, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91,
/* 'n' 0x6E */ 0xB6, 0x63, 0x18, 0xC6, 0x20,
/* 'o' 0x6F */ 0x7B, 0x38, 0x61, 0x87, 0x37, 0x80,
/* 'p' 0x70 */ 0xF6, 0xE3, 0x18, 0xEF, 0xD0, 0x80,
/* 'q' 0x71 */ 0x77, 0x38, 0x61, 0x87, 0x37, 0x41, 0x04,
/* 'r' 0x72 */ 0xBA, 0x49, 0x20,
/* 's' 0x73 */ 0x69, 0x8E, 0x19, 0x60,
/* 't' 0x74 */ 0x5D, 0x24, 0x93,
/* 'u' 0x75 */ 0x8C, 0x63, 0x18, 0xCD, 0xA0,
/* 'v' 0x76 */ 0x85, 0x24, 0x92, 0x30, 0xC3, 0x00,
/* 'w' 0x77 */ 0x89, 0x99, 0x59, 0x55, 0x56, 0x66, 0x26,
/* 'x' 0x78 */ 0x4A, 0x4C, 0x43, 0x27, 0x20,
/* 'y' 0x79 */ 0x85, 0x24, 0x92, 0x30, 0xC3, 0x08, 0x21, 0x80,
/* 'z' 0x7A */ 0x78, 0x44, 0x46, 0x23, 0xE0,
/* '{' 0x7B */ 0x69, 0x25, 0xB2, 0x49, 0x30,
/* '|' 0x7C */ 0xFF, 0xE0,
/* '}' 0x7D */ 0xC9, 0x24, 0xDA, 0x49, 0x60,
/* '~' 0x7E */ 0x66, 0x70,
};
const GFXglyph FreeSans6pt7bGlyphs[] PROGMEM = {{0, 0, 0, 3, 0, 1}, // 0x20 ' '
{0, 2, 9, 4, 1, -8}, // 0x21 '!'
{3, 4, 3, 4, 0, -8}, // 0x22 '"'
{5, 7, 8, 7, 0, -7}, // 0x23 '#'
{12, 6, 11, 7, 0, -9}, // 0x24 '$'
{21, 10, 9, 11, 0, -8}, // 0x25 '%'
{33, 7, 9, 8, 1, -8}, // 0x26 '&'
{41, 1, 3, 2, 1, -8}, // 0x27 '''
{42, 2, 11, 4, 1, -8}, // 0x28 '('
{45, 3, 11, 4, 0, -8}, // 0x29 ')'
{50, 4, 3, 5, 0, -8}, // 0x2A '*'
{52, 5, 5, 7, 1, -4}, // 0x2B '+'
{56, 1, 3, 3, 1, 0}, // 0x2C ','
{57, 2, 1, 4, 1, -3}, // 0x2D '-'
{58, 1, 1, 3, 1, 0}, // 0x2E '.'
{59, 3, 9, 3, 0, -8}, // 0x2F '/'
{63, 5, 9, 7, 1, -8}, // 0x30 '0'
{69, 3, 9, 7, 1, -8}, // 0x31 '1'
{73, 6, 9, 7, 0, -8}, // 0x32 '2'
{80, 6, 9, 7, 0, -8}, // 0x33 '3'
{87, 6, 9, 7, 0, -8}, // 0x34 '4'
{94, 6, 9, 7, 0, -8}, // 0x35 '5'
{101, 5, 9, 7, 1, -8}, // 0x36 '6'
{107, 5, 9, 7, 1, -8}, // 0x37 '7'
{113, 6, 9, 7, 0, -8}, // 0x38 '8'
{120, 6, 9, 7, 0, -8}, // 0x39 '9'
{127, 1, 7, 3, 1, -6}, // 0x3A ':'
{128, 1, 8, 3, 1, -5}, // 0x3B ';'
{129, 5, 6, 7, 1, -5}, // 0x3C '<'
{133, 5, 3, 7, 1, -3}, // 0x3D '='
{135, 5, 6, 7, 1, -5}, // 0x3E '>'
{139, 5, 9, 7, 1, -8}, // 0x3F '?'
{145, 11, 11, 12, 0, -8}, // 0x40 '@'
{161, 8, 9, 8, 0, -8}, // 0x41 'A'
{170, 6, 9, 8, 1, -8}, // 0x42 'B'
{177, 8, 9, 9, 0, -8}, // 0x43 'C'
{186, 7, 9, 8, 1, -8}, // 0x44 'D'
{194, 6, 9, 8, 1, -8}, // 0x45 'E'
{201, 6, 9, 7, 1, -8}, // 0x46 'F'
{208, 8, 9, 9, 0, -8}, // 0x47 'G'
{217, 7, 9, 9, 1, -8}, // 0x48 'H'
{225, 1, 9, 3, 1, -8}, // 0x49 'I'
{227, 5, 9, 6, 0, -8}, // 0x4A 'J'
{233, 7, 9, 8, 1, -8}, // 0x4B 'K'
{241, 5, 9, 7, 1, -8}, // 0x4C 'L'
{247, 8, 9, 10, 1, -8}, // 0x4D 'M'
{256, 7, 9, 9, 1, -8}, // 0x4E 'N'
{264, 9, 9, 9, 0, -8}, // 0x4F 'O'
{275, 6, 9, 8, 1, -8}, // 0x50 'P'
{282, 9, 10, 9, 0, -8}, // 0x51 'Q'
{294, 7, 9, 9, 1, -8}, // 0x52 'R'
{302, 6, 9, 8, 1, -8}, // 0x53 'S'
{309, 7, 9, 8, 0, -8}, // 0x54 'T'
{317, 7, 9, 9, 1, -8}, // 0x55 'U'
{325, 8, 9, 8, 0, -8}, // 0x56 'V'
{334, 11, 9, 11, 0, -8}, // 0x57 'W'
{347, 8, 9, 8, 0, -8}, // 0x58 'X'
{356, 8, 9, 8, 0, -8}, // 0x59 'Y'
{365, 7, 9, 7, 0, -8}, // 0x5A 'Z'
{373, 2, 12, 3, 1, -8}, // 0x5B '['
{376, 3, 9, 3, 0, -8}, // 0x5C '\'
{380, 3, 12, 3, 0, -8}, // 0x5D ']'
{385, 4, 5, 6, 1, -8}, // 0x5E '^'
{388, 7, 1, 7, 0, 2}, // 0x5F '_'
{389, 3, 1, 3, 0, -8}, // 0x60 '`'
{390, 6, 7, 7, 0, -6}, // 0x61 'a'
{396, 5, 9, 7, 1, -8}, // 0x62 'b'
{402, 6, 7, 6, 0, -6}, // 0x63 'c'
{408, 6, 9, 7, 0, -8}, // 0x64 'd'
{415, 6, 7, 6, 0, -6}, // 0x65 'e'
{421, 3, 9, 3, 0, -8}, // 0x66 'f'
{425, 6, 10, 7, 0, -6}, // 0x67 'g'
{433, 5, 9, 6, 1, -8}, // 0x68 'h'
{439, 1, 9, 3, 1, -8}, // 0x69 'i'
{441, 2, 12, 3, 0, -8}, // 0x6A 'j'
{444, 5, 9, 6, 1, -8}, // 0x6B 'k'
{450, 1, 9, 3, 1, -8}, // 0x6C 'l'
{452, 8, 7, 10, 1, -6}, // 0x6D 'm'
{459, 5, 7, 6, 1, -6}, // 0x6E 'n'
{464, 6, 7, 6, 0, -6}, // 0x6F 'o'
{470, 5, 9, 7, 1, -6}, // 0x70 'p'
{476, 6, 9, 7, 0, -6}, // 0x71 'q'
{483, 3, 7, 4, 1, -6}, // 0x72 'r'
{486, 6, 7, 6, 0, -6}, // 0x73 's'
{492, 3, 8, 3, 0, -7}, // 0x74 't'
{495, 5, 7, 6, 1, -6}, // 0x75 'u'
{500, 6, 7, 6, 0, -6}, // 0x76 'v'
{506, 9, 7, 9, 0, -6}, // 0x77 'w'
{514, 6, 7, 6, 0, -6}, // 0x78 'x'
{520, 6, 10, 6, 0, -6}, // 0x79 'y'
{528, 5, 7, 6, 0, -6}, // 0x7A 'z'
{533, 2, 12, 4, 1, -8}, // 0x7B '{'
{536, 1, 11, 3, 1, -8}, // 0x7C '|'
{538, 2, 12, 4, 1, -8}, // 0x7D '}'
{541, 6, 2, 6, 0, -4}}; // 0x7E '~'
const GFXglyph FreeSans6pt7bGlyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 3, 0, 0},
/* '!' 0x21 */ {0, 1, 9, 4, 2, -8},
/* '"' 0x22 */ {2, 3, 3, 4, 0, -8},
/* '#' 0x23 */ {4, 7, 8, 7, 0, -7},
/* '$' 0x24 */ {11, 5, 11, 7, 1, -9},
/* '%' 0x25 */ {18, 10, 9, 11, 0, -8},
/* '&' 0x26 */ {30, 6, 9, 8, 1, -8},
/* ''' 0x27 */ {37, 1, 3, 2, 1, -8},
/* '(' 0x28 */ {38, 2, 11, 4, 1, -8},
/* ')' 0x29 */ {41, 3, 11, 4, 0, -8},
/* '*' 0x2A */ {46, 3, 3, 5, 1, -8},
/* '+' 0x2B */ {48, 5, 5, 7, 1, -4},
/* ',' 0x2C */ {52, 1, 3, 3, 1, 0},
/* '-' 0x2D */ {53, 3, 1, 4, 1, -3},
/* '.' 0x2E */ {54, 1, 1, 3, 1, 0},
/* '/' 0x2F */ {55, 3, 9, 3, 0, -8},
/* '0' 0x30 */ {59, 5, 9, 7, 1, -8},
/* '1' 0x31 */ {65, 2, 9, 7, 2, -8},
/* '2' 0x32 */ {68, 5, 9, 7, 1, -8},
/* '3' 0x33 */ {74, 5, 9, 7, 1, -8},
/* '4' 0x34 */ {80, 5, 9, 7, 1, -8},
/* '5' 0x35 */ {86, 6, 9, 7, 0, -8},
/* '6' 0x36 */ {93, 5, 9, 7, 1, -8},
/* '7' 0x37 */ {99, 5, 9, 7, 1, -8},
/* '8' 0x38 */ {105, 6, 9, 7, 0, -8},
/* '9' 0x39 */ {112, 6, 9, 7, 0, -8},
/* ':' 0x3A */ {119, 1, 7, 3, 1, -6},
/* ';' 0x3B */ {120, 1, 8, 3, 1, -5},
/* '<' 0x3C */ {121, 5, 5, 7, 1, -4},
/* '=' 0x3D */ {125, 5, 3, 7, 1, -3},
/* '>' 0x3E */ {127, 5, 5, 7, 1, -4},
/* '?' 0x3F */ {131, 5, 9, 7, 1, -8},
/* '@' 0x40 */ {137, 11, 11, 12, 0, -8},
/* 'A' 0x41 */ {153, 8, 9, 8, 0, -8},
/* 'B' 0x42 */ {162, 6, 9, 8, 1, -8},
/* 'C' 0x43 */ {169, 8, 9, 9, 0, -8},
/* 'D' 0x44 */ {178, 7, 9, 8, 1, -8},
/* 'E' 0x45 */ {186, 6, 9, 8, 1, -8},
/* 'F' 0x46 */ {193, 5, 9, 7, 1, -8},
/* 'G' 0x47 */ {199, 8, 9, 9, 0, -8},
/* 'H' 0x48 */ {208, 7, 9, 9, 1, -8},
/* 'I' 0x49 */ {216, 1, 9, 3, 1, -8},
/* 'J' 0x4A */ {218, 5, 9, 6, 0, -8},
/* 'K' 0x4B */ {224, 6, 9, 8, 1, -8},
/* 'L' 0x4C */ {231, 5, 9, 7, 1, -8},
/* 'M' 0x4D */ {237, 8, 9, 10, 1, -8},
/* 'N' 0x4E */ {246, 7, 9, 9, 1, -8},
/* 'O' 0x4F */ {254, 9, 9, 9, 0, -8},
/* 'P' 0x50 */ {265, 6, 9, 8, 1, -8},
/* 'Q' 0x51 */ {272, 9, 10, 9, 0, -8},
/* 'R' 0x52 */ {284, 7, 9, 9, 1, -8},
/* 'S' 0x53 */ {292, 6, 9, 8, 1, -8},
/* 'T' 0x54 */ {299, 6, 9, 8, 0, -8},
/* 'U' 0x55 */ {306, 7, 9, 9, 1, -8},
/* 'V' 0x56 */ {314, 7, 9, 8, 0, -8},
/* 'W' 0x57 */ {322, 11, 9, 11, 0, -8},
/* 'X' 0x58 */ {335, 6, 9, 8, 1, -8},
/* 'Y' 0x59 */ {342, 7, 9, 8, 1, -8},
/* 'Z' 0x5A */ {350, 7, 9, 7, 0, -8},
/* '[' 0x5B */ {358, 2, 12, 3, 1, -8},
/* '\' 0x5C */ {361, 3, 9, 3, 0, -8},
/* ']' 0x5D */ {365, 2, 12, 3, 0, -8},
/* '^' 0x5E */ {368, 4, 5, 6, 1, -8},
/* '_' 0x5F */ {371, 7, 1, 7, 0, 2},
/* '`' 0x60 */ {372, 1, 1, 3, 1, -8},
/* 'a' 0x61 */ {373, 7, 7, 7, 0, -6},
/* 'b' 0x62 */ {380, 5, 9, 7, 1, -8},
/* 'c' 0x63 */ {386, 6, 7, 6, 0, -6},
/* 'd' 0x64 */ {392, 6, 9, 7, 0, -8},
/* 'e' 0x65 */ {399, 6, 7, 6, 0, -6},
/* 'f' 0x66 */ {405, 3, 9, 3, 0, -8},
/* 'g' 0x67 */ {409, 6, 10, 7, 0, -6},
/* 'h' 0x68 */ {417, 5, 9, 6, 1, -8},
/* 'i' 0x69 */ {423, 1, 9, 3, 1, -8},
/* 'j' 0x6A */ {425, 2, 12, 3, 0, -8},
/* 'k' 0x6B */ {428, 5, 9, 6, 1, -8},
/* 'l' 0x6C */ {434, 1, 9, 3, 1, -8},
/* 'm' 0x6D */ {436, 8, 7, 10, 1, -6},
/* 'n' 0x6E */ {443, 5, 7, 6, 1, -6},
/* 'o' 0x6F */ {448, 6, 7, 6, 0, -6},
/* 'p' 0x70 */ {454, 5, 9, 7, 1, -6},
/* 'q' 0x71 */ {460, 6, 9, 7, 0, -6},
/* 'r' 0x72 */ {467, 3, 7, 4, 1, -6},
/* 's' 0x73 */ {470, 4, 7, 6, 1, -6},
/* 't' 0x74 */ {474, 3, 8, 3, 0, -7},
/* 'u' 0x75 */ {477, 5, 7, 6, 1, -6},
/* 'v' 0x76 */ {482, 6, 7, 6, 0, -6},
/* 'w' 0x77 */ {488, 8, 7, 9, 0, -6},
/* 'x' 0x78 */ {495, 5, 7, 6, 0, -6},
/* 'y' 0x79 */ {500, 6, 10, 6, 0, -6},
/* 'z' 0x7A */ {508, 5, 7, 6, 0, -6},
/* '{' 0x7B */ {513, 3, 12, 4, 0, -8},
/* '|' 0x7C */ {518, 1, 11, 3, 1, -8},
/* '}' 0x7D */ {520, 3, 12, 4, 1, -8},
/* '~' 0x7E */ {525, 6, 2, 6, 0, -4},
};
const GFXfont FreeSans6pt7b PROGMEM = {(uint8_t *)FreeSans6pt7bBitmaps, (GFXglyph *)FreeSans6pt7bGlyphs, 0x20, 0x7E, 14};
// Approx. 1215 bytes

View File

@@ -1,302 +0,0 @@
/*
Uses Windows-1251 encoding to map translingual Cyrillic characters to range between (uint8_t)127 and (uint8_t)255
https://en.wikipedia.org/wiki/Windows-1251
Cyrillic characters present to the firmware as UTF8.
A NicheGraphics implementation needs to identify these, and substitute the appropriate Windows-1251 char value.
*/
#pragma once
const uint8_t FreeSans6pt8bCyrillicBitmaps[] PROGMEM = {
0xFF, 0xA0, 0xC0, 0xFF, 0xA0, 0xC0, 0xB6, 0x80, 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, 0x31, 0x75, 0x54, 0x78, 0x79, 0x75,
0x7C, 0x41, 0x00, 0x01, 0x1C, 0x49, 0x22, 0x50, 0x74, 0x02, 0x60, 0xA4, 0x49, 0x11, 0xC0, 0x21, 0x44, 0x94, 0x62, 0x59, 0xE2,
0xF4, 0xE0, 0x6A, 0xAA, 0x90, 0x48, 0x92, 0x49, 0x4A, 0x00, 0x5D, 0x40, 0x21, 0x09, 0xF2, 0x10, 0xE0, 0xC0, 0x80, 0x25, 0x25,
0x24, 0x26, 0xA3, 0x18, 0xC6, 0x31, 0xF0, 0x27, 0x92, 0x49, 0x20, 0x11, 0xB4, 0x41, 0x0C, 0xC6, 0x10, 0xFC, 0x26, 0xA2, 0x13,
0x04, 0x31, 0xF0, 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, 0xFF, 0xE1, 0x4D, 0x84, 0x31, 0xF0, 0x26, 0xE3, 0x0F, 0x46, 0x31,
0xF0, 0xFF, 0xC4, 0x22, 0x11, 0x08, 0x40, 0x11, 0xA4, 0x51, 0x39, 0x1C, 0x51, 0x78, 0x11, 0xA4, 0x71, 0x45, 0xF0, 0x51, 0x78,
0xC0, 0x30, 0xC0, 0x36, 0x1F, 0x20, 0xE0, 0x80, 0xF8, 0x3E, 0xC1, 0xC2, 0xE8, 0x00, 0x74, 0x62, 0x11, 0x10, 0x80, 0x20, 0x0F,
0x06, 0x18, 0x81, 0xA7, 0xD4, 0x93, 0x22, 0x64, 0x4A, 0x7E, 0x60, 0x06, 0x00, 0x3C, 0x00, 0x18, 0x18, 0x1C, 0x24, 0x24, 0x7E,
0x42, 0x42, 0xC3, 0xFA, 0x38, 0x61, 0xFA, 0x18, 0x61, 0xFC, 0x38, 0x8A, 0x0C, 0x08, 0x10, 0x20, 0xE3, 0x7C, 0xF9, 0x1A, 0x1C,
0x18, 0x30, 0x60, 0xC2, 0xF8, 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, 0x3C, 0x46,
0x82, 0x80, 0x8F, 0x81, 0x83, 0xC3, 0x7D, 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, 0xFF, 0x80, 0x08, 0x42, 0x10, 0x86,
0x31, 0x78, 0x87, 0x1A, 0x65, 0x8F, 0x1A, 0x22, 0x42, 0x86, 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, 0xC3, 0xC3, 0xC3, 0xA5, 0xA5,
0xA5, 0x99, 0x99, 0x99, 0x83, 0x87, 0x8D, 0x19, 0x32, 0x62, 0xC3, 0x86, 0x1E, 0x11, 0x90, 0x48, 0x1C, 0x0A, 0x05, 0x06, 0xC2,
0x3E, 0x00, 0xFA, 0x18, 0x61, 0xFE, 0x08, 0x20, 0x80, 0x1E, 0x11, 0x90, 0x48, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x3F, 0x00, 0xFD,
0x0E, 0x0C, 0x1F, 0xD0, 0xA0, 0xC1, 0x82, 0x7A, 0x18, 0x70, 0x78, 0x38, 0x61, 0x7C, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08,
0x10, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC3, 0x7C, 0xC3, 0x42, 0x42, 0x26, 0x24, 0x24, 0x14, 0x18, 0x18, 0xC4, 0x28, 0xC5,
0x39, 0xA5, 0x24, 0xA4, 0x52, 0x8C, 0x71, 0x8C, 0x30, 0x80, 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xB3, 0x84, 0xC3, 0x42, 0x26, 0x24,
0x18, 0x18, 0x08, 0x08, 0x08, 0x7E, 0x0C, 0x10, 0x41, 0x06, 0x08, 0x20, 0xFE, 0xEA, 0xAA, 0xAB, 0x92, 0x24, 0x89, 0x20, 0xED,
0xB6, 0xDB, 0x6D, 0xF0, 0x46, 0xAA, 0x90, 0xFC, 0x90, 0xFC, 0x4F, 0x98, 0xFC, 0x84, 0x21, 0xF8, 0xC6, 0x31, 0xF0, 0x79, 0x18,
0x20, 0x45, 0xE0, 0x04, 0x10, 0x5F, 0xC6, 0x18, 0x51, 0x7C, 0xFC, 0x7F, 0x08, 0xF8, 0x29, 0x74, 0x92, 0x40, 0x7D, 0x18, 0x61,
0x45, 0xF0, 0x52, 0x30, 0x84, 0x21, 0xF8, 0xC6, 0x31, 0x88, 0xDF, 0x80, 0x51, 0x55, 0x56, 0x84, 0x21, 0x2A, 0x72, 0x92, 0x98,
0xFF, 0x80, 0xFF, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFC, 0x63, 0x18, 0xC4, 0x79, 0x18, 0x71, 0x45, 0xE0, 0xFC, 0x63, 0x18, 0xFA,
0x10, 0x80, 0x7D, 0x18, 0x61, 0x45, 0xF0, 0x41, 0x04, 0xF2, 0x49, 0x00, 0x79, 0x07, 0x02, 0xCD, 0xE0, 0x4B, 0xA4, 0x93, 0x8C,
0x63, 0x18, 0xFC, 0xCD, 0x24, 0x94, 0x30, 0xC0, 0x99, 0x59, 0x55, 0x56, 0x66, 0x26, 0x96, 0x66, 0x99, 0xCA, 0x52, 0x63, 0x18,
0x84, 0x40, 0x78, 0xC4, 0x44, 0x7C, 0x6A, 0xAA, 0xA9, 0xFF, 0xF0, 0xC9, 0x24, 0x4A, 0x49, 0x40, 0xE8, 0xC0, 0xFE, 0x18, 0x61,
0x86, 0x18, 0x61, 0xFC, 0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, 0xC0, 0xC0, 0x10, 0x8F, 0xE0, 0x82,
0x08, 0x20, 0x82, 0x08, 0x00, 0x64, 0x0F, 0x88, 0x88, 0x80, 0x3D, 0x0C, 0x2E, 0xF9, 0x04, 0x0F, 0x7C, 0x08, 0x81, 0x10, 0x22,
0x04, 0x7C, 0x88, 0x51, 0x0A, 0x21, 0x87, 0xC0, 0x84, 0x10, 0x82, 0x10, 0x42, 0x0F, 0xFD, 0x08, 0xA1, 0x0C, 0x23, 0x87, 0xC0,
0x10, 0x88, 0xE6, 0xB3, 0x8C, 0x28, 0x92, 0x28, 0xC0, 0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, 0x83,
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xFE, 0x20, 0x40, 0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, 0x44, 0x11, 0x80, 0x78, 0x24, 0x13,
0xC9, 0x14, 0x8E, 0x7C, 0x88, 0x44, 0x3F, 0xD1, 0x38, 0x8C, 0x78, 0x60, 0x9A, 0xCC, 0xA9, 0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51,
0x44, 0x8C, 0x63, 0x18, 0xFC, 0x80, 0x24, 0x33, 0x0A, 0x36, 0x45, 0x8E, 0x0C, 0x10, 0x60, 0x80, 0x70, 0x22, 0x95, 0xA8, 0xC4,
0x23, 0x10, 0x08, 0x42, 0x10, 0x86, 0x31, 0x78, 0x07, 0xF8, 0x20, 0x82, 0x08, 0x20, 0x82, 0x00, 0x28, 0x0F, 0xE0, 0x82, 0x0F,
0xE0, 0x82, 0x0F, 0xC0, 0x38, 0x8A, 0x0C, 0x0F, 0x90, 0x20, 0xE3, 0x7C, 0x51, 0x55, 0x56, 0xA1, 0x24, 0x92, 0x49, 0x00, 0xFF,
0x80, 0xDF, 0x80, 0x27, 0xC9, 0x24, 0x8A, 0x28, 0xA2, 0x8B, 0xF8, 0x20, 0x80, 0x28, 0xA0, 0x1E, 0x47, 0xFC, 0x11, 0x78, 0x88,
0x44, 0x32, 0x59, 0xDA, 0xCD, 0x66, 0x6B, 0x32, 0x89, 0x80, 0x79, 0x1F, 0x30, 0x45, 0xE0, 0x7A, 0x18, 0x70, 0x78, 0x38, 0x61,
0x7C, 0x79, 0x07, 0x02, 0xCD, 0xE0, 0xB4, 0x24, 0x92, 0x40, 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, 0xFE, 0x08,
0x20, 0xFE, 0x18, 0x61, 0xFC, 0xFA, 0x38, 0x61, 0xFA, 0x18, 0x61, 0xFC, 0xFE, 0x08, 0x20, 0x82, 0x08, 0x20, 0x80, 0x1F, 0x08,
0x84, 0x42, 0x21, 0x10, 0x88, 0x44, 0x42, 0xFF, 0xC0, 0x60, 0x20, 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, 0x88, 0xA4, 0x9A,
0x87, 0xC1, 0xC1, 0xF1, 0xAD, 0x92, 0x88, 0x80, 0x7A, 0x18, 0x41, 0x38, 0x18, 0x61, 0x7C, 0x87, 0x0E, 0x2C, 0x59, 0x34, 0x68,
0xE1, 0xC2, 0x28, 0x22, 0x1C, 0x38, 0xB1, 0x64, 0xD1, 0xA3, 0x87, 0x08, 0x8E, 0x6B, 0x38, 0xC2, 0x89, 0x22, 0x8C, 0x3E, 0x44,
0x89, 0x12, 0x24, 0x58, 0xA1, 0xC2, 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60,
0xC1, 0x82, 0x3C, 0x46, 0x83, 0x81, 0x81, 0x81, 0x81, 0xC2, 0x7C, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x82, 0xFA, 0x18,
0x61, 0xFE, 0x08, 0x20, 0x80, 0x38, 0x8A, 0x0C, 0x08, 0x10, 0x20, 0xE3, 0x7C, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10,
0xC2, 0x8D, 0x91, 0x63, 0x83, 0x04, 0x18, 0x20, 0x08, 0x1E, 0x32, 0xD1, 0x38, 0x8C, 0x4F, 0x2C, 0xFC, 0x08, 0x00, 0x87, 0x34,
0x8C, 0x30, 0xC4, 0xB3, 0x84, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFF, 0x01, 0x01, 0x8E, 0x38, 0xE3, 0x8D, 0xF0,
0xC3, 0x0C, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFF, 0x99, 0x4C, 0xA6, 0x53, 0x29, 0x94, 0xCA, 0x65, 0x32, 0xFF,
0x80, 0x40, 0x20, 0xF0, 0x04, 0x01, 0x00, 0x40, 0x1F, 0x84, 0x21, 0x0C, 0x42, 0x1F, 0x00, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xDC,
0x2E, 0x17, 0x0B, 0xF9, 0x80, 0x82, 0x08, 0x20, 0xFE, 0x18, 0x61, 0xF8, 0x79, 0x8A, 0x18, 0x13, 0xE0, 0x60, 0xC2, 0x7C, 0x87,
0x26, 0x39, 0x06, 0x41, 0xF0, 0x64, 0x19, 0x06, 0x63, 0x8F, 0x80, 0x7E, 0x18, 0x61, 0x7C, 0xD6, 0x71, 0x84, 0x79, 0x11, 0xD9,
0xCD, 0xD0, 0x0D, 0xC4, 0x1E, 0x47, 0x1C, 0x51, 0x78, 0xF4, 0xBD, 0x29, 0xF8, 0xF8, 0x88, 0x88, 0x3C, 0x48, 0x91, 0x22, 0x5F,
0xE0, 0x80, 0x79, 0x1F, 0xF0, 0x45, 0xE0, 0x92, 0x54, 0x38, 0x3C, 0x56, 0x93, 0x78, 0x23, 0x82, 0xCD, 0xE0, 0x9C, 0xEB, 0x5C,
0xC4, 0x70, 0x27, 0x3A, 0xD7, 0x31, 0x9A, 0xCC, 0xA9, 0x7A, 0x52, 0x94, 0xE4, 0x8F, 0x3D, 0x6D, 0xA6, 0x90, 0x8C, 0x7F, 0x18,
0xC4, 0x79, 0x1C, 0x71, 0x45, 0xE0, 0xFC, 0x63, 0x18, 0xC4, 0xFC, 0x63, 0x18, 0xFA, 0x10, 0x80, 0x79, 0x1C, 0x30, 0x45, 0xE0,
0xF9, 0x08, 0x42, 0x10, 0x8A, 0x56, 0xA3, 0x10, 0x8C, 0x40, 0x04, 0x01, 0x07, 0xF9, 0x31, 0xC4, 0x71, 0x14, 0xC5, 0xFE, 0x04,
0x01, 0x00, 0x40, 0x4B, 0x8C, 0x65, 0xE4, 0x8A, 0x28, 0xA2, 0x8B, 0xF0, 0x40, 0x99, 0x97, 0x11, 0x96, 0x59, 0x65, 0x97, 0xF0,
0x95, 0x2A, 0x54, 0xA9, 0x5F, 0xC0, 0x80, 0xF0, 0x20, 0x78, 0x91, 0x23, 0xC0, 0x86, 0x1F, 0x63, 0x8F, 0xD0, 0x84, 0x3D, 0x18,
0xF8, 0xF4, 0xDE, 0x19, 0xF8, 0x9E, 0xA2, 0xE1, 0xA1, 0xA2, 0x9E, 0xFC, 0x7E, 0xD4, 0xC4,
};
const GFXglyph FreeSans6pt8bCyrillicGlyphs[] PROGMEM = {
{0, 0, 0, 3, 0, 0}, // 0x20 ' '
{3, 2, 9, 3, 1, -8}, // 0x21 '!'
{6, 3, 3, 4, 1, -8}, // 0x22 '"'
{8, 7, 8, 7, 0, -7}, // 0x23 '#'
{15, 6, 11, 7, 0, -8}, // 0x24 '$'
{24, 10, 9, 11, 0, -8}, // 0x25 '%'
{36, 6, 9, 8, 1, -8}, // 0x26 '&'
{43, 1, 3, 2, 1, -8}, // 0x27 '''
{44, 2, 10, 4, 1, -7}, // 0x28 '('
{47, 3, 11, 4, 0, -7}, // 0x29 ')'
{52, 3, 4, 5, 1, -8}, // 0x2A '*'
{54, 5, 6, 7, 1, -5}, // 0x2B '+'
{58, 1, 3, 3, 1, 0}, // 0x2C ','
{59, 2, 1, 4, 1, -3}, // 0x2D '-'
{60, 1, 1, 3, 1, 0}, // 0x2E '.'
{61, 3, 8, 3, 0, -7}, // 0x2F '/'
{64, 5, 9, 7, 1, -8}, // 0x30 '0'
{70, 3, 9, 7, 1, -8}, // 0x31 '1'
{74, 6, 9, 7, 0, -8}, // 0x32 '2'
{81, 5, 9, 7, 1, -8}, // 0x33 '3'
{87, 6, 9, 7, 0, -8}, // 0x34 '4'
{94, 5, 9, 7, 1, -8}, // 0x35 '5'
{100, 5, 9, 7, 1, -8}, // 0x36 '6'
{106, 5, 9, 7, 1, -8}, // 0x37 '7'
{112, 6, 9, 7, 0, -8}, // 0x38 '8'
{119, 6, 9, 7, 0, -8}, // 0x39 '9'
{126, 2, 6, 3, 1, -5}, // 0x3A ':'
{128, 2, 8, 3, 1, -5}, // 0x3B ';'
{130, 5, 5, 7, 1, -4}, // 0x3C '<'
{134, 5, 3, 7, 1, -3}, // 0x3D '='
{136, 5, 5, 7, 1, -4}, // 0x3E '>'
{140, 5, 9, 7, 1, -8}, // 0x3F '?'
{146, 11, 11, 12, 0, -8}, // 0x40 '@'
{162, 8, 9, 8, 0, -8}, // 0x41 'A'
{171, 6, 9, 8, 1, -8}, // 0x42 'B'
{178, 7, 9, 9, 1, -8}, // 0x43 'C'
{186, 7, 9, 9, 1, -8}, // 0x44 'D'
{194, 6, 9, 8, 1, -8}, // 0x45 'E'
{201, 6, 9, 7, 1, -8}, // 0x46 'F'
{208, 8, 9, 9, 1, -8}, // 0x47 'G'
{217, 7, 9, 9, 1, -8}, // 0x48 'H'
{225, 1, 9, 3, 1, -8}, // 0x49 'I'
{227, 5, 9, 6, 0, -8}, // 0x4A 'J'
{233, 7, 9, 8, 1, -8}, // 0x4B 'K'
{241, 5, 9, 7, 1, -8}, // 0x4C 'L'
{247, 8, 9, 10, 1, -8}, // 0x4D 'M'
{256, 7, 9, 9, 1, -8}, // 0x4E 'N'
{264, 9, 9, 9, 0, -8}, // 0x4F 'O'
{275, 6, 9, 8, 1, -8}, // 0x50 'P'
{282, 9, 9, 9, 0, -8}, // 0x51 'Q'
{293, 7, 9, 9, 1, -8}, // 0x52 'R'
{301, 6, 9, 8, 1, -8}, // 0x53 'S'
{308, 7, 9, 7, 0, -8}, // 0x54 'T'
{316, 7, 9, 9, 1, -8}, // 0x55 'U'
{324, 8, 9, 8, 0, -8}, // 0x56 'V'
{333, 11, 9, 11, 0, -8}, // 0x57 'W'
{346, 6, 9, 8, 1, -8}, // 0x58 'X'
{353, 8, 9, 8, 0, -8}, // 0x59 'Y'
{362, 7, 9, 7, 0, -8}, // 0x5A 'Z'
{370, 2, 12, 3, 1, -8}, // 0x5B '['
{373, 3, 9, 3, 0, -8}, // 0x5C '\'
{377, 3, 12, 3, 0, -8}, // 0x5D ']'
{382, 4, 5, 6, 1, -8}, // 0x5E '^'
{385, 6, 1, 7, 0, 2}, // 0x5F '_'
{386, 2, 2, 4, 1, -8}, // 0x60 '`'
{387, 5, 6, 7, 1, -5}, // 0x61 'a'
{391, 5, 9, 7, 1, -8}, // 0x62 'b'
{397, 6, 6, 6, 0, -5}, // 0x63 'c'
{402, 6, 9, 7, 0, -8}, // 0x64 'd'
{409, 5, 6, 7, 1, -5}, // 0x65 'e'
{413, 3, 9, 3, 0, -8}, // 0x66 'f'
{417, 6, 9, 7, 0, -5}, // 0x67 'g'
{424, 5, 9, 7, 1, -8}, // 0x68 'h'
{430, 1, 9, 3, 1, -8}, // 0x69 'i'
{432, 2, 12, 3, 0, -8}, // 0x6A 'j'
{435, 5, 9, 6, 1, -8}, // 0x6B 'k'
{441, 1, 9, 3, 1, -8}, // 0x6C 'l'
{443, 8, 6, 10, 1, -5}, // 0x6D 'm'
{449, 5, 6, 7, 1, -5}, // 0x6E 'n'
{453, 6, 6, 7, 0, -5}, // 0x6F 'o'
{458, 5, 9, 7, 1, -5}, // 0x70 'p'
{464, 6, 9, 7, 0, -5}, // 0x71 'q'
{471, 3, 6, 4, 1, -5}, // 0x72 'r'
{474, 6, 6, 6, 0, -5}, // 0x73 's'
{479, 3, 8, 3, 0, -7}, // 0x74 't'
{482, 5, 6, 7, 1, -5}, // 0x75 'u'
{486, 6, 6, 6, 0, -5}, // 0x76 'v'
{491, 8, 6, 9, 0, -5}, // 0x77 'w'
{497, 4, 6, 6, 1, -5}, // 0x78 'x'
{500, 5, 9, 6, 0, -5}, // 0x79 'y'
{506, 5, 6, 6, 0, -5}, // 0x7A 'z'
{510, 2, 12, 4, 1, -8}, // 0x7B '{'
{513, 1, 12, 3, 1, -8}, // 0x7C '|'
{515, 3, 12, 4, 0, -8}, // 0x7D '}'
{520, 5, 2, 7, 1, -4}, // 0x7E '~'
{522, 6, 9, 8, 1, -8}, //
{529, 9, 11, 9, 0, -8}, //
{542, 6, 11, 7, 1, -10}, //
{551, 0, 0, 8, 0, 0}, //
{551, 4, 9, 5, 1, -8}, //
{556, 0, 0, 8, 0, 0}, //
{556, 0, 0, 8, 0, 0}, //
{556, 0, 0, 8, 0, 0}, //
{556, 0, 0, 8, 0, 0}, //
{556, 6, 8, 8, 1, -7}, //
{562, 0, 0, 8, 0, 0}, //
{562, 11, 9, 13, 1, -8}, //
{575, 0, 0, 8, 0, 0}, //
{575, 11, 9, 12, 1, -8}, //
{588, 6, 11, 8, 1, -10}, //
{597, 9, 9, 9, 0, -8}, //
{608, 7, 11, 9, 1, -8}, //
{618, 6, 11, 7, 0, -8}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 9, 6, 10, 0, -5}, //
{634, 0, 0, 8, 0, 0}, //
{634, 9, 6, 10, 1, -5}, //
{641, 4, 8, 6, 1, -7}, //
{645, 6, 9, 7, 0, -8}, //
{652, 5, 7, 7, 1, -5}, //
{657, 0, 0, 8, 0, 0}, //
{657, 7, 11, 7, 0, -10}, //
{667, 5, 11, 6, 0, -7}, //
{674, 5, 9, 6, 0, -8}, //
{680, 0, 0, 8, 0, 0}, //
{680, 6, 10, 7, 1, -9}, //
{688, 0, 0, 8, 0, 0}, //
{688, 0, 0, 8, 0, 0}, //
{688, 6, 11, 8, 1, -10}, //
{697, 7, 9, 9, 1, -8}, //
{705, 0, 0, 8, 0, 0}, //
{705, 0, 0, 8, 0, 0}, //
{705, 2, 12, 3, 0, -8}, //
{708, 0, 0, 8, 0, 0}, //
{708, 0, 0, 8, 0, 0}, //
{708, 3, 11, 3, 0, -10}, //
{713, 0, 0, 8, 0, 0}, //
{713, 0, 0, 8, 0, 0}, //
{713, 1, 9, 3, 1, -8}, //
{715, 1, 9, 3, 1, -8}, //
{717, 3, 8, 5, 1, -7}, //
{720, 6, 9, 7, 1, -5}, //
{727, 0, 0, 8, 0, 0}, //
{727, 0, 0, 8, 0, 0}, //
{727, 6, 9, 7, 0, -8}, //
{734, 9, 9, 11, 1, -8}, //
{745, 6, 6, 6, 0, -5}, //
{750, 0, 0, 8, 0, 0}, //
{750, 0, 0, 8, 0, 0}, //
{750, 6, 9, 8, 1, -8}, //
{757, 6, 6, 6, 0, -5}, //
{762, 3, 9, 3, 0, -8}, //
{766, 8, 9, 8, 0, -8}, //
{775, 6, 9, 8, 1, -8}, //
{782, 6, 9, 8, 1, -8}, //
{789, 6, 9, 7, 1, -8}, //
{796, 9, 11, 10, 0, -8}, //
{809, 6, 9, 8, 1, -8}, //
{816, 9, 9, 11, 1, -8}, //
{827, 6, 9, 8, 1, -8}, //
{834, 7, 9, 9, 1, -8}, //
{842, 7, 11, 9, 1, -10}, //
{852, 6, 9, 8, 1, -8}, //
{859, 7, 9, 8, 0, -8}, //
{867, 8, 9, 10, 1, -8}, //
{876, 7, 9, 9, 1, -8}, //
{884, 8, 9, 10, 1, -8}, //
{893, 7, 9, 9, 1, -8}, //
{901, 6, 9, 8, 1, -8}, //
{908, 7, 9, 9, 1, -8}, //
{916, 7, 9, 7, 0, -8}, //
{924, 7, 9, 7, 0, -8}, //
{932, 9, 9, 10, 1, -8}, //
{943, 6, 9, 8, 1, -8}, //
{950, 8, 11, 9, 1, -8}, //
{961, 6, 9, 8, 1, -8}, //
{968, 8, 9, 10, 1, -8}, //
{977, 9, 11, 10, 1, -8}, //
{990, 10, 9, 10, 0, -8}, //
{1002, 9, 9, 10, 1, -8}, //
{1013, 6, 9, 8, 1, -8}, //
{1020, 7, 9, 9, 1, -8}, //
{1028, 10, 9, 12, 1, -8}, //
{1040, 6, 9, 8, 1, -8}, //
{1047, 6, 6, 7, 0, -5}, //
{1052, 6, 9, 7, 0, -8}, //
{1059, 5, 6, 6, 1, -5}, //
{1063, 4, 6, 5, 1, -5}, //
{1066, 7, 7, 7, 0, -5}, //
{1073, 6, 6, 7, 0, -5}, //
{1078, 8, 6, 9, 1, -5}, //
{1084, 6, 6, 6, 0, -5}, //
{1089, 5, 6, 7, 1, -5}, //
{1093, 5, 8, 7, 1, -7}, //
{1098, 4, 6, 6, 1, -5}, //
{1101, 5, 6, 6, 0, -5}, //
{1105, 6, 6, 7, 1, -5}, //
{1110, 5, 6, 7, 1, -5}, //
{1114, 6, 6, 7, 0, -5}, //
{1119, 5, 6, 7, 1, -5}, //
{1123, 5, 9, 7, 1, -5}, //
{1129, 6, 6, 6, 0, -5}, //
{1134, 5, 6, 5, 0, -5}, //
{1138, 5, 9, 6, 0, -5}, //
{1144, 10, 11, 10, 0, -7}, //
{1158, 5, 6, 6, 0, -5}, //
{1162, 6, 7, 7, 1, -5}, //
{1168, 4, 6, 6, 1, -5}, //
{1171, 6, 6, 8, 1, -5}, //
{1176, 7, 7, 9, 1, -5}, //
{1183, 7, 6, 8, 0, -5}, //
{1189, 6, 6, 8, 1, -5}, //
{1194, 5, 6, 6, 1, -5}, //
{1198, 5, 6, 6, 1, -5}, //
{1202, 8, 6, 9, 1, -5}, //
{1208, 5, 6, 7, 1, -5} //
};
const GFXfont FreeSans6pt8bCyrillic PROGMEM = {(uint8_t *)FreeSans6pt8bCyrillicBitmaps, (GFXglyph *)FreeSans6pt8bCyrillicGlyphs,
0x20, 0xFF, 16};

View File

@@ -0,0 +1,457 @@
#pragma once
const uint8_t FreeSans6pt_Win1250Bitmaps[] PROGMEM = {
/* ' ' 0x20 */
0xFC, 0x80, /* '!' 0x21 */
0xB6, 0x80, /* '"' 0x22 */
0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, /* '#' 0x23 */
0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, /* '$' 0x24 */
0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, /* '%' 0x25 */
0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4, /* '&' 0x26 */
0xE0, /* ''' 0x27 */
0x5A, 0xAA, 0x94, /* '(' 0x28 */
0x89, 0x12, 0x49, 0x29, 0x00, /* ')' 0x29 */
0x5E, 0x80, /* '*' 0x2A */
0x21, 0x3E, 0x42, 0x00, /* '+' 0x2B */
0xE0, /* ',' 0x2C */
0xC0, /* '-' 0x2D */
0x80, /* '.' 0x2E */
0x24, 0xA4, 0xA4, 0x80, /* '/' 0x2F */
0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, /* '0' 0x30 */
0x27, 0x92, 0x49, 0x20, /* '1' 0x31 */
0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, /* '2' 0x32 */
0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78, /* '3' 0x33 */
0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, /* '4' 0x34 */
0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0, /* '5' 0x35 */
0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70, /* '6' 0x36 */
0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, /* '7' 0x37 */
0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, /* '8' 0x38 */
0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78, /* '9' 0x39 */
0x82, /* ':' 0x3A */
0x87, /* ';' 0x3B */
0x3E, 0x30, 0x60, 0x80, /* '<' 0x3C */
0xF8, 0x3E, /* '=' 0x3D */
0xE0, 0xC6, 0xC8, 0x00, /* '>' 0x3E */
0x74, 0x42, 0x11, 0x10, 0x80, 0x20, /* '?' 0x3F */
0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, /* '@' 0x40 */
0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 'A' 0x41 */
0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 'B' 0x42 */
0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, /* 'C' 0x43 */
0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8, /* 'D' 0x44 */
0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 'E' 0x45 */
0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, /* 'F' 0x46 */
0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, /* 'G' 0x47 */
0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 'H' 0x48 */
0xFF, 0x80, /* 'I' 0x49 */
0x08, 0x42, 0x10, 0x87, 0x29, 0x70, /* 'J' 0x4A */
0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, /* 'K' 0x4B */
0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 'L' 0x4C */
0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 'M' 0x4D */
0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, /* 'N' 0x4E */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00, /* 'O' 0x4F */
0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, /* 'P' 0x50 */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40, /* 'Q' 0x51 */
0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, /* 'R' 0x52 */
0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, /* 'S' 0x53 */
0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 'T' 0x54 */
0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, /* 'U' 0x55 */
0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, /* 'V' 0x56 */
0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, /* 'W' 0x57 */
0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, /* 'X' 0x58 */
0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, /* 'Y' 0x59 */
0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, /* 'Z' 0x5A */
0xEA, 0xAA, 0xAB, /* '[' 0x5B */
0x92, 0x24, 0x89, 0x20, /* '\' 0x5C */
0xD5, 0x55, 0x57, /* ']' 0x5D */
0x46, 0xA9, /* '^' 0x5E */
0xFE, /* '_' 0x5F */
0x80, /* '`' 0x60 */
0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, /* 'a' 0x61 */
0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0, /* 'b' 0x62 */
0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, /* 'c' 0x63 */
0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, /* 'd' 0x64 */
0x39, 0x38, 0x7F, 0x81, 0x13, 0x80, /* 'e' 0x65 */
0x6B, 0xA4, 0x92, 0x40, /* 'f' 0x66 */
0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, /* 'g' 0x67 */
0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, /* 'h' 0x68 */
0xBF, 0x80, /* 'i' 0x69 */
0x45, 0x55, 0x57, /* 'j' 0x6A */
0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, /* 'k' 0x6B */
0xFF, 0x80, /* 'l' 0x6C */
0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, /* 'm' 0x6D */
0xF4, 0x63, 0x18, 0xC6, 0x20, /* 'n' 0x6E */
0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, /* 'o' 0x6F */
0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, /* 'p' 0x70 */
0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, /* 'q' 0x71 */
0xF2, 0x49, 0x20, /* 'r' 0x72 */
0x7A, 0x50, 0xE0, 0xE5, 0xE0, /* 's' 0x73 */
0x5D, 0x24, 0x93, /* 't' 0x74 */
0x8C, 0x63, 0x18, 0xCF, 0xA0, /* 'u' 0x75 */
0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, /* 'v' 0x76 */
0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26, /* 'w' 0x77 */
0x4A, 0x4C, 0x43, 0x27, 0x20, /* 'x' 0x78 */
0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00, /* 'y' 0x79 */
0x78, 0x44, 0x46, 0x23, 0xE0, /* 'z' 0x7A */
0x6A, 0xAA, 0xA9, /* '{' 0x7B */
0xFF, 0xE0, /* '|' 0x7C */
0x95, 0x55, 0x56, /* '}' 0x7D */
0x66, 0x60, /* '~' 0x7E */
0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0, /* 0x7F */
0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E, /* 0x80 */
/* 0x81 */
0xE0, /* 0x82 */
/* 0x83 */
0xB6, 0x80, /* 0x84 */
0xA8, /* 0x85 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, /* 0x86 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08, /* 0x87 */
/* 0x88 */
0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60, /* 0x89 */
0x28, 0x47, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80, /* 0x8A */
0x64, /* 0x8B */
0x10, 0x87, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80, /* 0x8C */
0x28, 0x4F, 0xC4, 0x10, 0x41, 0x04, 0x10, 0x40, /* 0x8D */
0x14, 0x11, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0x8E */
0x08, 0x21, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0x8F */
/* 0x90 */
0xE0, /* 0x91 */
0xE0, /* 0x92 */
0xB6, 0x80, /* 0x93 */
0xB6, 0x80, /* 0x94 */
0xFF, 0x80, /* 0x95 */
0xFC, /* 0x96 */
0xFF, 0xF0, /* 0x97 */
/* 0x98 */
0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68, /* 0x99 */
0x52, 0x69, 0x8E, 0x19, 0x60, /* 0x9A */
0x98, /* 0x9B */
0x24, 0x06, 0x98, 0xE1, 0x96, /* 0x9C */
0x15, 0xE4, 0x44, 0x44, 0x60, /* 0x9D */
0x51, 0x00, 0xF0, 0x88, 0x8C, 0x47, 0xC0, /* 0x9E */
0x11, 0x00, 0xF0, 0x88, 0x8C, 0x47, 0xC0, /* 0x9F */
/* 0xA0 */
0xA8, /* 0xA1 */
0x96, /* 0xA2 */
0x41, 0x05, 0x18, 0x43, 0x04, 0x10, 0x7C, /* 0xA3 */
0xFC, 0x63, 0xF0, /* 0xA4 */
0x30, 0x38, 0x28, 0x48, 0x4C, 0x7C, 0x84, 0x86, 0x82, 0x04, 0x07, /* 0xA5 */
0xF9, 0xF0, /* 0xA6 */
0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0, /* 0xA7 */
0xA0, /* 0xA8 */
0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00, /* 0xA9 */
0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, 0xC1, 0x0C, /* 0xAA */
0x5A, 0xA5, /* 0xAB */
0xFC, 0x10, 0x40, /* 0xAC */
/* 0xAD */
0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00, /* 0xAE */
0x18, 0x31, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0xAF */
0x69, 0x96, /* 0xB0 */
0x21, 0x3E, 0x42, 0x03, 0xE0, /* 0xB1 */
0x9C, /* 0xB2 */
0x49, 0x35, 0x92, 0x40, /* 0xB3 */
0x80, /* 0xB4 */
0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80, /* 0xB5 */
0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0, /* 0xB6 */
0x80, /* 0xB7 */
0x67, 0x80, /* 0xB8 */
0x78, 0x84, 0x04, 0x3C, 0xC4, 0x8C, 0x76, 0x04, 0x07, /* 0xB9 */
0x69, 0x8E, 0x19, 0x66, 0x26, /* 0xBA */
0xA5, 0x5A, /* 0xBB */
0xA5, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 0xBC */
0xA0, /* 0xBD */
0xBA, 0x49, 0x24, 0x90, /* 0xBE */
0x31, 0x9E, 0x11, 0x11, 0x88, 0xF8, /* 0xBF */
0x10, 0x43, 0xE4, 0x28, 0x50, 0xBE, 0x42, 0x85, 0x0C, /* 0xC0 */
0x08, 0x10, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC1 */
0x18, 0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC2 */
0x24, 0x18, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC3 */
0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 0xC4 */
0x11, 0x21, 0x08, 0x42, 0x10, 0x87, 0xC0, /* 0xC5 */
0x08, 0x20, 0x01, 0xE4, 0x30, 0x20, 0x40, 0x82, 0x8C, 0xF0, /* 0xC6 */
0x3E, 0x61, 0xC0, 0x80, 0x80, 0x80, 0xC1, 0x63, 0x3E, 0x0C, 0x04, 0x1C, /* 0xC7 */
0x28, 0x20, 0x01, 0xE4, 0x30, 0x20, 0x40, 0x82, 0x8C, 0xF0, /* 0xC8 */
0x08, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xC9 */
0xFD, 0x02, 0x04, 0x0F, 0xD0, 0x20, 0x40, 0xFC, 0x10, 0x38, /* 0xCA */
0x28, 0x0F, 0xE0, 0x83, 0xE8, 0x20, 0x83, 0xF0, /* 0xCB */
0x28, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x82, 0x0F, 0xC0, /* 0xCC */
0x62, 0xAA, 0xA0, /* 0xCD */
0x54, 0x24, 0x92, 0x48, /* 0xCE */
0x50, 0x43, 0xE4, 0x28, 0x30, 0x60, 0xC1, 0x85, 0xF0, /* 0xCF */
0x7C, 0x42, 0x41, 0x41, 0xF1, 0x41, 0x41, 0x42, 0x7C, /* 0xD0 */
0x08, 0x23, 0x0F, 0x1B, 0x32, 0x66, 0xC7, 0x87, 0x04, /* 0xD1 */
0x28, 0x23, 0x0F, 0x1B, 0x32, 0x66, 0xC7, 0x87, 0x04, /* 0xD2 */
0x04, 0x04, 0x0F, 0x8C, 0x6C, 0x1C, 0x06, 0x03, 0x83, 0x63, 0x1F, 0x00, /* 0xD3 */
0x08, 0x0A, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD4 */
0x0A, 0x0A, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD5 */
0x14, 0x00, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD6 */
0x8A, 0x88, 0xA8, 0x80, /* 0xD7 */
0x50, 0x43, 0xE4, 0x28, 0x50, 0xBE, 0x42, 0x85, 0x0C, /* 0xD8 */
0x10, 0x52, 0x4C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xD9 */
0x08, 0x22, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDA */
0x14, 0x52, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDB */
0x29, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDC */
0x09, 0x25, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20, /* 0xDD */
0xFC, 0x41, 0x04, 0x10, 0x41, 0x04, 0x10, 0x60, 0x8E, /* 0xDE */
0x7A, 0x18, 0x61, 0x8A, 0x18, 0x61, 0xB8, /* 0xDF */
0x42, 0xE9, 0x24, 0x80, /* 0xE0 */
0x10, 0x40, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE1 */
0x10, 0x50, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE2 */
0x48, 0x60, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE3 */
0x28, 0x01, 0xE4, 0x20, 0x47, 0xB1, 0x46, 0x76, /* 0xE4 */
0x62, 0xAA, 0xA0, /* 0xE5 */
0x10, 0x80, 0x1E, 0xC6, 0x08, 0x20, 0xC5, 0xE0, /* 0xE6 */
0x7B, 0x18, 0x20, 0x83, 0x17, 0x8C, 0x11, 0xC0, /* 0xE7 */
0x28, 0x40, 0x1E, 0xC6, 0x08, 0x20, 0xC5, 0xE0, /* 0xE8 */
0x10, 0x80, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xE9 */
0x7B, 0x38, 0x7F, 0x83, 0x37, 0x84, 0x1C, /* 0xEA */
0x28, 0x07, 0xB3, 0x87, 0xF8, 0x31, 0x78, /* 0xEB */
0x28, 0x40, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xEC */
0x62, 0xAA, 0xA0, /* 0xED */
0x54, 0x24, 0x92, 0x48, /* 0xEE */
0x02, 0x0C, 0x13, 0xEC, 0xD0, 0xA1, 0x42, 0xCC, 0xE8, /* 0xEF */
0x04, 0x1D, 0xD6, 0x68, 0x50, 0xA1, 0x66, 0x74, /* 0xF0 */
0x11, 0x01, 0x6C, 0xC6, 0x31, 0x8C, 0x40, /* 0xF1 */
0x20, 0x81, 0x6C, 0xC6, 0x31, 0x8C, 0x40, /* 0xF2 */
0x10, 0x80, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF3 */
0x10, 0xA0, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF4 */
0x29, 0x40, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF5 */
0x28, 0x07, 0xB3, 0x86, 0x18, 0x73, 0x78, /* 0xF6 */
0x20, 0x3E, 0x02, 0x00, /* 0xF7 */
0xA8, 0x5D, 0x24, 0x90, /* 0xF8 */
0x22, 0x89, 0x18, 0xC6, 0x31, 0x9B, 0x40, /* 0xF9 */
0x11, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFA */
0x2A, 0x81, 0x18, 0xC6, 0x31, 0x9B, 0x40, /* 0xFB */
0x50, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFC */
0x10, 0x88, 0x52, 0x49, 0x23, 0x0C, 0x30, 0x82, 0x18, /* 0xFD */
0x4E, 0x44, 0x44, 0x46, 0x31, 0x70, /* 0xFE */
0x80, /* 0xFF */
};
const GFXglyph FreeSans6pt_Win1250Glyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 3, 0, 0},
/* '!' 0x21 */ {0, 1, 9, 4, 2, -8},
/* '"' 0x22 */ {2, 3, 3, 4, 0, -8},
/* '#' 0x23 */ {4, 7, 8, 7, 0, -7},
/* '$' 0x24 */ {11, 6, 11, 7, 0, -9},
/* '%' 0x25 */ {20, 10, 9, 11, 0, -8},
/* '&' 0x26 */ {32, 6, 9, 8, 1, -8},
/* ''' 0x27 */ {39, 1, 3, 2, 1, -8},
/* '(' 0x28 */ {40, 2, 11, 4, 1, -8},
/* ')' 0x29 */ {43, 3, 11, 4, 0, -8},
/* '*' 0x2A */ {48, 3, 3, 5, 1, -8},
/* '+' 0x2B */ {50, 5, 5, 7, 1, -4},
/* ',' 0x2C */ {54, 1, 3, 3, 1, 0},
/* '-' 0x2D */ {55, 2, 1, 4, 1, -3},
/* '.' 0x2E */ {56, 1, 1, 3, 1, 0},
/* '/' 0x2F */ {57, 3, 9, 3, 0, -8},
/* '0' 0x30 */ {61, 5, 9, 7, 1, -8},
/* '1' 0x31 */ {67, 3, 9, 7, 1, -8},
/* '2' 0x32 */ {71, 6, 9, 7, 0, -8},
/* '3' 0x33 */ {78, 6, 9, 7, 0, -8},
/* '4' 0x34 */ {85, 6, 9, 7, 0, -8},
/* '5' 0x35 */ {92, 5, 9, 7, 1, -8},
/* '6' 0x36 */ {98, 5, 9, 7, 1, -8},
/* '7' 0x37 */ {104, 5, 9, 7, 1, -8},
/* '8' 0x38 */ {110, 6, 9, 7, 0, -8},
/* '9' 0x39 */ {117, 6, 9, 7, 0, -8},
/* ':' 0x3A */ {124, 1, 7, 3, 1, -6},
/* ';' 0x3B */ {125, 1, 8, 3, 1, -5},
/* '<' 0x3C */ {126, 5, 5, 7, 1, -4},
/* '=' 0x3D */ {130, 5, 3, 7, 1, -3},
/* '>' 0x3E */ {132, 5, 5, 7, 1, -4},
/* '?' 0x3F */ {136, 5, 9, 7, 1, -8},
/* '@' 0x40 */ {142, 11, 11, 12, 0, -8},
/* 'A' 0x41 */ {158, 8, 9, 8, 0, -8},
/* 'B' 0x42 */ {167, 6, 9, 8, 1, -8},
/* 'C' 0x43 */ {174, 8, 9, 9, 0, -8},
/* 'D' 0x44 */ {183, 7, 9, 8, 1, -8},
/* 'E' 0x45 */ {191, 6, 9, 8, 1, -8},
/* 'F' 0x46 */ {198, 6, 9, 7, 1, -8},
/* 'G' 0x47 */ {205, 8, 9, 9, 0, -8},
/* 'H' 0x48 */ {214, 7, 9, 9, 1, -8},
/* 'I' 0x49 */ {222, 1, 9, 3, 1, -8},
/* 'J' 0x4A */ {224, 5, 9, 6, 0, -8},
/* 'K' 0x4B */ {230, 7, 9, 8, 1, -8},
/* 'L' 0x4C */ {238, 5, 9, 7, 1, -8},
/* 'M' 0x4D */ {244, 8, 9, 10, 1, -8},
/* 'N' 0x4E */ {253, 7, 9, 9, 1, -8},
/* 'O' 0x4F */ {261, 9, 9, 9, 0, -8},
/* 'P' 0x50 */ {272, 6, 9, 8, 1, -8},
/* 'Q' 0x51 */ {279, 9, 10, 9, 0, -8},
/* 'R' 0x52 */ {291, 7, 9, 9, 1, -8},
/* 'S' 0x53 */ {299, 6, 9, 8, 1, -8},
/* 'T' 0x54 */ {306, 7, 9, 8, 0, -8},
/* 'U' 0x55 */ {314, 7, 9, 9, 1, -8},
/* 'V' 0x56 */ {322, 7, 9, 8, 0, -8},
/* 'W' 0x57 */ {330, 11, 9, 11, 0, -8},
/* 'X' 0x58 */ {343, 6, 9, 8, 1, -8},
/* 'Y' 0x59 */ {350, 8, 9, 8, 0, -8},
/* 'Z' 0x5A */ {359, 7, 9, 7, 0, -8},
/* '[' 0x5B */ {367, 2, 12, 3, 1, -8},
/* '\' 0x5C */ {370, 3, 9, 3, 0, -8},
/* ']' 0x5D */ {374, 2, 12, 3, 0, -8},
/* '^' 0x5E */ {377, 4, 4, 6, 1, -8},
/* '_' 0x5F */ {379, 7, 1, 7, 0, 2},
/* '`' 0x60 */ {380, 1, 1, 3, 1, -8},
/* 'a' 0x61 */ {381, 6, 7, 7, 0, -6},
/* 'b' 0x62 */ {387, 5, 9, 7, 1, -8},
/* 'c' 0x63 */ {393, 6, 7, 6, 0, -6},
/* 'd' 0x64 */ {399, 6, 9, 7, 0, -8},
/* 'e' 0x65 */ {406, 6, 7, 6, 0, -6},
/* 'f' 0x66 */ {412, 3, 9, 3, 0, -8},
/* 'g' 0x67 */ {416, 6, 10, 7, 0, -6},
/* 'h' 0x68 */ {424, 5, 9, 6, 1, -8},
/* 'i' 0x69 */ {430, 1, 9, 3, 1, -8},
/* 'j' 0x6A */ {432, 2, 12, 3, 0, -8},
/* 'k' 0x6B */ {435, 5, 9, 6, 1, -8},
/* 'l' 0x6C */ {441, 1, 9, 3, 1, -8},
/* 'm' 0x6D */ {443, 8, 7, 10, 1, -6},
/* 'n' 0x6E */ {450, 5, 7, 6, 1, -6},
/* 'o' 0x6F */ {455, 6, 7, 6, 0, -6},
/* 'p' 0x70 */ {461, 5, 9, 7, 1, -6},
/* 'q' 0x71 */ {467, 6, 9, 7, 0, -6},
/* 'r' 0x72 */ {474, 3, 7, 4, 1, -6},
/* 's' 0x73 */ {477, 5, 7, 6, 0, -6},
/* 't' 0x74 */ {482, 3, 8, 3, 0, -7},
/* 'u' 0x75 */ {485, 5, 7, 6, 1, -6},
/* 'v' 0x76 */ {490, 6, 7, 6, 0, -6},
/* 'w' 0x77 */ {496, 8, 7, 9, 0, -6},
/* 'x' 0x78 */ {503, 5, 7, 6, 0, -6},
/* 'y' 0x79 */ {508, 5, 10, 6, 0, -6},
/* 'z' 0x7A */ {515, 5, 7, 6, 0, -6},
/* '{' 0x7B */ {520, 2, 12, 4, 1, -8},
/* '|' 0x7C */ {523, 1, 11, 3, 1, -8},
/* '}' 0x7D */ {525, 2, 12, 4, 1, -8},
/* '~' 0x7E */ {528, 6, 2, 6, 0, -4},
/* 0x7F */ {530, 9, 10, 11, 1, -8},
/* 0x80 */ {542, 7, 9, 8, 0, -8},
/* 0x81 */ {550, 0, 0, 8, 0, 0},
/* 0x82 */ {550, 1, 3, 3, 1, 0},
/* 0x83 */ {551, 0, 0, 8, 0, 0},
/* 0x84 */ {551, 3, 3, 5, 1, 0},
/* 0x85 */ {553, 5, 1, 7, 1, 0},
/* 0x86 */ {554, 5, 11, 7, 1, -8},
/* 0x87 */ {561, 5, 11, 7, 1, -8},
/* 0x88 */ {568, 0, 0, 8, 0, 0},
/* 0x89 */ {568, 12, 9, 12, 0, -8},
/* 0x8A */ {582, 6, 11, 8, 1, -9},
/* 0x8B */ {591, 2, 3, 4, 1, -4},
/* 0x8C */ {592, 6, 11, 8, 1, -10},
/* 0x8D */ {601, 6, 10, 8, 0, -9},
/* 0x8E */ {609, 7, 10, 7, 0, -9},
/* 0x8F */ {618, 7, 10, 7, 0, -9},
/* 0x90 */ {627, 0, 0, 8, 0, 0},
/* 0x91 */ {627, 1, 3, 3, 1, -8},
/* 0x92 */ {628, 1, 3, 2, 1, -8},
/* 0x93 */ {629, 3, 3, 5, 1, -8},
/* 0x94 */ {631, 3, 3, 5, 1, -8},
/* 0x95 */ {633, 3, 3, 5, 1, -5},
/* 0x96 */ {635, 6, 1, 6, 0, -3},
/* 0x97 */ {636, 12, 1, 12, 0, -3},
/* 0x98 */ {638, 0, 0, 8, 0, 0},
/* 0x99 */ {638, 11, 7, 12, 1, -8},
/* 0x9A */ {648, 4, 9, 6, 1, -8},
/* 0x9B */ {653, 2, 3, 3, 1, -4},
/* 0x9C */ {654, 4, 10, 6, 1, -9},
/* 0x9D */ {659, 4, 9, 5, 0, -8},
/* 0x9E */ {664, 5, 10, 6, 0, -9},
/* 0x9F */ {671, 5, 10, 6, 0, -9},
/* 0xA0 */ {678, 0, 0, 3, 0, 0},
/* 0xA1 */ {678, 3, 2, 4, 0, -8},
/* 0xA2 */ {679, 4, 2, 4, 0, -8},
/* 0xA3 */ {680, 6, 9, 7, 0, -8},
/* 0xA4 */ {687, 5, 4, 7, 1, -5},
/* 0xA5 */ {690, 8, 11, 8, 1, -8},
/* 0xA6 */ {701, 1, 12, 3, 1, -8},
/* 0xA7 */ {703, 5, 12, 7, 1, -8},
/* 0xA8 */ {711, 3, 1, 4, 0, -7},
/* 0xA9 */ {712, 9, 9, 10, 0, -8},
/* 0xAA */ {723, 6, 12, 8, 1, -8},
/* 0xAB */ {732, 4, 4, 6, 1, -4},
/* 0xAC */ {734, 6, 3, 7, 1, -4},
/* 0xAD */ {737, 0, 0, 0, 0, 0},
/* 0xAE */ {737, 9, 9, 10, 0, -8},
/* 0xAF */ {748, 7, 10, 7, 0, -9},
/* 0xB0 */ {757, 4, 4, 7, 2, -8},
/* 0xB1 */ {759, 5, 7, 7, 1, -6},
/* 0xB2 */ {764, 3, 2, 4, 1, 1},
/* 0xB3 */ {765, 3, 9, 3, 0, -8},
/* 0xB4 */ {769, 1, 1, 4, 1, -8},
/* 0xB5 */ {770, 6, 9, 7, 1, -6},
/* 0xB6 */ {777, 6, 10, 6, 1, -8},
/* 0xB7 */ {785, 1, 1, 3, 1, -2},
/* 0xB8 */ {786, 3, 3, 4, 1, 1},
/* 0xB9 */ {788, 8, 9, 7, 0, -6},
/* 0xBA */ {797, 4, 10, 6, 1, -6},
/* 0xBB */ {802, 4, 4, 6, 1, -5},
/* 0xBC */ {804, 5, 9, 7, 1, -8},
/* 0xBD */ {810, 3, 1, 4, 0, -8},
/* 0xBE */ {811, 3, 10, 3, 1, -9},
/* 0xBF */ {815, 5, 9, 6, 0, -8},
/* 0xC0 */ {821, 7, 10, 9, 1, -9},
/* 0xC1 */ {830, 8, 10, 8, 0, -9},
/* 0xC2 */ {840, 8, 10, 8, 0, -9},
/* 0xC3 */ {850, 8, 10, 8, 0, -9},
/* 0xC4 */ {860, 8, 10, 8, 0, -9},
/* 0xC5 */ {870, 5, 10, 7, 1, -9},
/* 0xC6 */ {877, 7, 11, 9, 0, -10},
/* 0xC7 */ {887, 8, 12, 9, 0, -8},
/* 0xC8 */ {899, 7, 11, 9, 0, -10},
/* 0xC9 */ {909, 6, 10, 8, 1, -9},
/* 0xCA */ {917, 7, 11, 8, 1, -8},
/* 0xCB */ {927, 6, 10, 8, 1, -9},
/* 0xCC */ {935, 6, 11, 8, 1, -10},
/* 0xCD */ {944, 2, 10, 3, 1, -9},
/* 0xCE */ {947, 3, 10, 4, 0, -9},
/* 0xCF */ {951, 7, 10, 8, 1, -9},
/* 0xD0 */ {960, 8, 9, 8, 0, -8},
/* 0xD1 */ {969, 7, 10, 9, 1, -9},
/* 0xD2 */ {978, 7, 10, 9, 1, -9},
/* 0xD3 */ {987, 9, 10, 9, 0, -9},
/* 0xD4 */ {999, 9, 11, 9, 0, -10},
/* 0xD5 */ {1012, 9, 11, 9, 0, -10},
/* 0xD6 */ {1025, 9, 11, 9, 0, -10},
/* 0xD7 */ {1038, 5, 5, 7, 1, -5},
/* 0xD8 */ {1042, 7, 10, 9, 1, -9},
/* 0xD9 */ {1051, 7, 10, 9, 1, -9},
/* 0xDA */ {1060, 7, 10, 9, 1, -9},
/* 0xDB */ {1069, 7, 10, 9, 1, -9},
/* 0xDC */ {1078, 7, 10, 9, 1, -9},
/* 0xDD */ {1087, 7, 10, 8, 1, -9},
/* 0xDE */ {1096, 6, 12, 7, 0, -8},
/* 0xDF */ {1105, 6, 9, 7, 1, -8},
/* 0xE0 */ {1112, 3, 9, 4, 1, -8},
/* 0xE1 */ {1116, 7, 10, 7, 0, -9},
/* 0xE2 */ {1125, 7, 10, 7, 0, -9},
/* 0xE3 */ {1134, 7, 10, 7, 0, -9},
/* 0xE4 */ {1143, 7, 9, 7, 0, -8},
/* 0xE5 */ {1151, 2, 10, 3, 1, -9},
/* 0xE6 */ {1154, 6, 10, 6, 0, -9},
/* 0xE7 */ {1162, 6, 10, 6, 0, -6},
/* 0xE8 */ {1170, 6, 10, 6, 0, -9},
/* 0xE9 */ {1178, 6, 10, 6, 0, -9},
/* 0xEA */ {1186, 6, 9, 6, 0, -6},
/* 0xEB */ {1193, 6, 9, 6, 0, -8},
/* 0xEC */ {1200, 6, 10, 6, 0, -9},
/* 0xED */ {1208, 2, 10, 3, 1, -9},
/* 0xEE */ {1211, 3, 10, 3, 0, -9},
/* 0xEF */ {1215, 7, 10, 7, 0, -9},
/* 0xF0 */ {1224, 7, 9, 7, 0, -8},
/* 0xF1 */ {1232, 5, 10, 6, 1, -9},
/* 0xF2 */ {1239, 5, 10, 6, 1, -9},
/* 0xF3 */ {1246, 6, 10, 6, 0, -9},
/* 0xF4 */ {1254, 6, 10, 6, 0, -9},
/* 0xF5 */ {1262, 6, 10, 6, 0, -9},
/* 0xF6 */ {1270, 6, 9, 6, 0, -8},
/* 0xF7 */ {1277, 5, 5, 7, 1, -5},
/* 0xF8 */ {1281, 3, 10, 4, 1, -9},
/* 0xF9 */ {1285, 5, 10, 6, 1, -9},
/* 0xFA */ {1292, 5, 9, 6, 1, -8},
/* 0xFB */ {1298, 5, 10, 6, 1, -9},
/* 0xFC */ {1305, 5, 9, 6, 1, -8},
/* 0xFD */ {1311, 6, 12, 6, 0, -8},
/* 0xFE */ {1320, 4, 11, 3, 0, -7},
/* 0xFF */ {1326, 1, 1, 4, 1, -7},
};
const GFXfont FreeSans6pt_Win1250 PROGMEM = {(uint8_t *)FreeSans6pt_Win1250Bitmaps, (GFXglyph *)FreeSans6pt_Win1250Glyphs, 0x20,
0xFF, 14};

View File

@@ -0,0 +1,457 @@
#pragma once
const uint8_t FreeSans6pt_Win1251Bitmaps[] PROGMEM = {
/* ' ' 0x20 */
0xFC, 0x80, /* '!' 0x21 */
0xB6, 0x80, /* '"' 0x22 */
0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, /* '#' 0x23 */
0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, /* '$' 0x24 */
0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, /* '%' 0x25 */
0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4, /* '&' 0x26 */
0xE0, /* ''' 0x27 */
0x5A, 0xAA, 0x94, /* '(' 0x28 */
0x89, 0x12, 0x49, 0x29, 0x00, /* ')' 0x29 */
0x5E, 0x80, /* '*' 0x2A */
0x21, 0x3E, 0x42, 0x00, /* '+' 0x2B */
0xE0, /* ',' 0x2C */
0xC0, /* '-' 0x2D */
0x80, /* '.' 0x2E */
0x24, 0xA4, 0xA4, 0x80, /* '/' 0x2F */
0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, /* '0' 0x30 */
0x27, 0x92, 0x49, 0x20, /* '1' 0x31 */
0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, /* '2' 0x32 */
0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78, /* '3' 0x33 */
0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, /* '4' 0x34 */
0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0, /* '5' 0x35 */
0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70, /* '6' 0x36 */
0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, /* '7' 0x37 */
0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, /* '8' 0x38 */
0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78, /* '9' 0x39 */
0x82, /* ':' 0x3A */
0x87, /* ';' 0x3B */
0x3E, 0x30, 0x60, 0x80, /* '<' 0x3C */
0xF8, 0x3E, /* '=' 0x3D */
0xE0, 0xC6, 0xC8, 0x00, /* '>' 0x3E */
0x74, 0x42, 0x11, 0x10, 0x80, 0x20, /* '?' 0x3F */
0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, /* '@' 0x40 */
0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 'A' 0x41 */
0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 'B' 0x42 */
0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, /* 'C' 0x43 */
0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8, /* 'D' 0x44 */
0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 'E' 0x45 */
0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, /* 'F' 0x46 */
0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, /* 'G' 0x47 */
0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 'H' 0x48 */
0xFF, 0x80, /* 'I' 0x49 */
0x08, 0x42, 0x10, 0x87, 0x29, 0x70, /* 'J' 0x4A */
0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, /* 'K' 0x4B */
0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 'L' 0x4C */
0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 'M' 0x4D */
0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, /* 'N' 0x4E */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00, /* 'O' 0x4F */
0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, /* 'P' 0x50 */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40, /* 'Q' 0x51 */
0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, /* 'R' 0x52 */
0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, /* 'S' 0x53 */
0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 'T' 0x54 */
0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, /* 'U' 0x55 */
0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, /* 'V' 0x56 */
0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, /* 'W' 0x57 */
0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, /* 'X' 0x58 */
0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, /* 'Y' 0x59 */
0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, /* 'Z' 0x5A */
0xEA, 0xAA, 0xAB, /* '[' 0x5B */
0x92, 0x24, 0x89, 0x20, /* '\' 0x5C */
0xD5, 0x55, 0x57, /* ']' 0x5D */
0x46, 0xA9, /* '^' 0x5E */
0xFE, /* '_' 0x5F */
0x80, /* '`' 0x60 */
0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, /* 'a' 0x61 */
0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0, /* 'b' 0x62 */
0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, /* 'c' 0x63 */
0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, /* 'd' 0x64 */
0x39, 0x38, 0x7F, 0x81, 0x13, 0x80, /* 'e' 0x65 */
0x6B, 0xA4, 0x92, 0x40, /* 'f' 0x66 */
0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, /* 'g' 0x67 */
0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, /* 'h' 0x68 */
0xBF, 0x80, /* 'i' 0x69 */
0x45, 0x55, 0x57, /* 'j' 0x6A */
0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, /* 'k' 0x6B */
0xFF, 0x80, /* 'l' 0x6C */
0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, /* 'm' 0x6D */
0xF4, 0x63, 0x18, 0xC6, 0x20, /* 'n' 0x6E */
0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, /* 'o' 0x6F */
0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, /* 'p' 0x70 */
0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, /* 'q' 0x71 */
0xF2, 0x49, 0x20, /* 'r' 0x72 */
0x7A, 0x50, 0xE0, 0xE5, 0xE0, /* 's' 0x73 */
0x5D, 0x24, 0x93, /* 't' 0x74 */
0x8C, 0x63, 0x18, 0xCF, 0xA0, /* 'u' 0x75 */
0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, /* 'v' 0x76 */
0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26, /* 'w' 0x77 */
0x4A, 0x4C, 0x43, 0x27, 0x20, /* 'x' 0x78 */
0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00, /* 'y' 0x79 */
0x78, 0x44, 0x46, 0x23, 0xE0, /* 'z' 0x7A */
0x6A, 0xAA, 0xA9, /* '{' 0x7B */
0xFF, 0xE0, /* '|' 0x7C */
0x95, 0x55, 0x56, /* '}' 0x7D */
0x66, 0x60, /* '~' 0x7E */
0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0, /* 0x7F */
0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, 0xC0, 0xC0, /* 0x80 */
0x10, 0x8F, 0xE0, 0x82, 0x08, 0x20, 0x82, 0x00, /* 0x81 */
0xE0, /* 0x82 */
0x24, 0x0F, 0x88, 0x88, 0x80, /* 0x83 */
0xB6, 0x80, /* 0x84 */
0xA8, /* 0x85 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, /* 0x86 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08, /* 0x87 */
0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E, /* 0x88 */
0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60, /* 0x89 */
0x7C, 0x08, 0x81, 0x10, 0x22, 0x04, 0x7C, 0x88, 0x51, 0x0A, 0x21, 0x87, 0xC0, /* 0x8A */
0x64, /* 0x8B */
0x84, 0x10, 0x82, 0x10, 0x42, 0x0F, 0xFD, 0x08, 0xA1, 0x0C, 0x23, 0x87, 0xC0, /* 0x8C */
0x10, 0x88, 0xE6, 0xB3, 0x8C, 0x28, 0x92, 0x28, 0xC0, /* 0x8D */
0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, /* 0x8E */
0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xFE, 0x20, 0x40, /* 0x8F */
0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, 0x44, 0x11, 0x80, /* 0x90 */
0xE0, /* 0x91 */
0xE0, /* 0x92 */
0xB6, 0x80, /* 0x93 */
0xB6, 0x80, /* 0x94 */
0xFF, 0x80, /* 0x95 */
0xFC, /* 0x96 */
0xFF, 0xF0, /* 0x97 */
/* 0x98 */
0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68, /* 0x99 */
0x78, 0x24, 0x13, 0xC9, 0x14, 0x8E, 0x7C, /* 0x9A */
0x98, /* 0x9B */
0x88, 0x44, 0x3F, 0xD1, 0x38, 0x8C, 0x78, /* 0x9C */
0x24, 0x09, 0xAC, 0xCA, 0x90, /* 0x9D */
0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, 0x44, /* 0x9E */
0x8C, 0x63, 0x18, 0xFC, 0x80, /* 0x9F */
/* 0xA0 */
0x24, 0x33, 0x0A, 0x36, 0x45, 0x8E, 0x0C, 0x10, 0x60, 0x80, /* 0xA1 */
0x51, 0x22, 0x95, 0xA8, 0xC4, 0x23, 0x10, /* 0xA2 */
0x08, 0x42, 0x10, 0x86, 0x31, 0x78, /* 0xA3 */
0xFC, 0x63, 0xF0, /* 0xA4 */
0x07, 0xF8, 0x20, 0x82, 0x08, 0x20, 0x82, 0x00, /* 0xA5 */
0xF9, 0xF0, /* 0xA6 */
0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0, /* 0xA7 */
0x28, 0x0F, 0xE0, 0x82, 0x0F, 0xE0, 0x82, 0x0F, 0xC0, /* 0xA8 */
0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00, /* 0xA9 */
0x38, 0x8A, 0x0C, 0x0F, 0x90, 0x20, 0xE3, 0x7C, /* 0xAA */
0x5A, 0xA5, /* 0xAB */
0x51, 0x55, 0x56, /* 0xAC */
/* 0xAD */
0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00, /* 0xAE */
0xA1, 0x24, 0x92, 0x49, 0x00, /* 0xAF */
0x69, 0x96, /* 0xB0 */
0x21, 0x3E, 0x42, 0x03, 0xE0, /* 0xB1 */
0xFF, 0x80, /* 0xB2 */
0xDF, 0x80, /* 0xB3 */
0x27, 0xC9, 0x24, /* 0xB4 */
0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80, /* 0xB5 */
0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0, /* 0xB6 */
0x80, /* 0xB7 */
0x28, 0xA0, 0x1E, 0x47, 0xFC, 0x11, 0x78, /* 0xB8 */
0x88, 0x44, 0x32, 0x59, 0xDA, 0xCD, 0x66, 0x6B, 0x32, 0x8B, 0x80, /* 0xB9 */
0x79, 0x1F, 0x30, 0x45, 0xE0, /* 0xBA */
0xA5, 0x5A, /* 0xBB */
0x45, 0x55, 0x57, /* 0xBC */
0x7A, 0x18, 0x70, 0x78, 0x38, 0x61, 0x7C, /* 0xBD */
0x7A, 0x1C, 0x1C, 0xBC, /* 0xBE */
0xB4, 0x24, 0x92, 0x40, /* 0xBF */
0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 0xC0 */
0xFE, 0x08, 0x20, 0xFA, 0x18, 0x61, 0xF8, /* 0xC1 */
0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 0xC2 */
0xFE, 0x08, 0x20, 0x82, 0x08, 0x20, 0x80, /* 0xC3 */
0x1F, 0x08, 0x84, 0x42, 0x21, 0x10, 0x88, 0x44, 0x42, 0xFF, 0xC0, 0x60, 0x20, /* 0xC4 */
0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 0xC5 */
0x88, 0xA4, 0x9A, 0x87, 0xC1, 0xC1, 0xF1, 0xAD, 0x92, 0x88, 0x80, /* 0xC6 */
0x7A, 0x18, 0x41, 0x38, 0x18, 0x61, 0x7C, /* 0xC7 */
0x87, 0x0E, 0x2C, 0x59, 0x34, 0x68, 0xE1, 0xC2, /* 0xC8 */
0x28, 0x22, 0x1C, 0x38, 0xB1, 0x64, 0xD1, 0xA3, 0x87, 0x08, /* 0xC9 */
0x8E, 0x6B, 0x38, 0xC2, 0x89, 0x22, 0x8C, /* 0xCA */
0x3E, 0x44, 0x89, 0x12, 0x24, 0x58, 0xA1, 0xC2, /* 0xCB */
0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 0xCC */
0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 0xCD */
0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0xC2, 0x7C, /* 0xCE */
0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x82, /* 0xCF */
0xFA, 0x18, 0x61, 0xFE, 0x08, 0x20, 0x80, /* 0xD0 */
0x38, 0x8A, 0x0C, 0x08, 0x10, 0x20, 0xE3, 0x7C, /* 0xD1 */
0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 0xD2 */
0xC2, 0x8D, 0x91, 0x63, 0x83, 0x04, 0x18, 0x20, /* 0xD3 */
0x08, 0x1F, 0x32, 0x71, 0x18, 0x8C, 0x47, 0x26, 0xFE, 0x08, 0x00, /* 0xD4 */
0x87, 0x34, 0x8C, 0x30, 0xC4, 0xB3, 0x84, /* 0xD5 */
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFF, 0x01, 0x01, /* 0xD6 */
0x8E, 0x38, 0xE3, 0x8D, 0xF0, 0xC3, 0x0C, /* 0xD7 */
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFF, /* 0xD8 */
0x99, 0x4C, 0xA6, 0x53, 0x29, 0x94, 0xCA, 0x65, 0x32, 0xFF, 0x80, 0x40, 0x20, /* 0xD9 */
0xF0, 0x04, 0x01, 0x00, 0x40, 0x1F, 0x84, 0x21, 0x0C, 0x42, 0x1F, 0x00, /* 0xDA */
0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xDC, 0x2E, 0x17, 0x0B, 0xF9, 0x80, /* 0xDB */
0x82, 0x08, 0x20, 0xFE, 0x18, 0x61, 0xF8, /* 0xDC */
0x79, 0x8A, 0x18, 0x13, 0xE0, 0x60, 0xC2, 0x7C, /* 0xDD */
0x87, 0x26, 0x39, 0x06, 0x41, 0xF0, 0x64, 0x19, 0x06, 0x63, 0x8F, 0x80, /* 0xDE */
0x7E, 0x18, 0x61, 0x7C, 0xD6, 0x71, 0x84, /* 0xDF */
0x79, 0x11, 0xD9, 0xCD, 0xD0, /* 0xE0 */
0x0D, 0xC4, 0x1E, 0x47, 0x1C, 0x51, 0x78, /* 0xE1 */
0xF4, 0xBD, 0x29, 0xF8, /* 0xE2 */
0xF8, 0x88, 0x88, /* 0xE3 */
0x3C, 0x48, 0x91, 0x22, 0x5F, 0xE0, 0x80, /* 0xE4 */
0x79, 0x1F, 0xF0, 0x45, 0xE0, /* 0xE5 */
0x92, 0x54, 0x38, 0x3C, 0x56, 0x93, /* 0xE6 */
0x78, 0x23, 0x82, 0xCD, 0xE0, /* 0xE7 */
0x9C, 0xEB, 0x5C, 0xC4, /* 0xE8 */
0x70, 0x27, 0x3A, 0xD7, 0x31, /* 0xE9 */
0x9A, 0xCC, 0xA9, /* 0xEA */
0x7A, 0x52, 0x94, 0xE4, /* 0xEB */
0x8F, 0x3D, 0x6D, 0xA6, 0x90, /* 0xEC */
0x8C, 0x7F, 0x18, 0xC4, /* 0xED */
0x79, 0x1C, 0x71, 0x45, 0xE0, /* 0xEE */
0xFC, 0x63, 0x18, 0xC4, /* 0xEF */
0xFC, 0x63, 0x18, 0xFA, 0x10, 0x80, /* 0xF0 */
0x79, 0x1C, 0x30, 0x45, 0xE0, /* 0xF1 */
0xF9, 0x08, 0x42, 0x10, /* 0xF2 */
0x8A, 0x56, 0xA3, 0x10, 0x8C, 0x40, /* 0xF3 */
0x04, 0x01, 0x07, 0xF9, 0x31, 0xC4, 0x71, 0x14, 0xC5, 0xFE, 0x04, 0x01, 0x00, 0x40, /* 0xF4 */
0x4B, 0x8C, 0x65, 0xE4, /* 0xF5 */
0x8A, 0x28, 0xA2, 0x8B, 0xF0, 0x40, /* 0xF6 */
0x99, 0x97, 0x11, /* 0xF7 */
0x96, 0x59, 0x65, 0x97, 0xF0, /* 0xF8 */
0x95, 0x2A, 0x54, 0xA9, 0x5F, 0xC0, 0x80, /* 0xF9 */
0xF0, 0x20, 0x78, 0x91, 0x23, 0xC0, /* 0xFA */
0x86, 0x1F, 0x63, 0x8F, 0xD0, /* 0xFB */
0x84, 0x3D, 0x18, 0xF8, /* 0xFC */
0xF4, 0xDE, 0x19, 0xF8, /* 0xFD */
0x9E, 0xA2, 0xE1, 0xA1, 0xA2, 0x9E, /* 0xFE */
0xFC, 0x7E, 0xD4, 0xC4, /* 0xFF */
};
const GFXglyph FreeSans6pt_Win1251Glyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 3, 0, 0},
/* '!' 0x21 */ {0, 1, 9, 4, 2, -8},
/* '"' 0x22 */ {2, 3, 3, 4, 0, -8},
/* '#' 0x23 */ {4, 7, 8, 7, 0, -7},
/* '$' 0x24 */ {11, 6, 11, 7, 0, -9},
/* '%' 0x25 */ {20, 10, 9, 11, 0, -8},
/* '&' 0x26 */ {32, 6, 9, 8, 1, -8},
/* ''' 0x27 */ {39, 1, 3, 2, 1, -8},
/* '(' 0x28 */ {40, 2, 11, 4, 1, -8},
/* ')' 0x29 */ {43, 3, 11, 4, 0, -8},
/* '*' 0x2A */ {48, 3, 3, 5, 1, -8},
/* '+' 0x2B */ {50, 5, 5, 7, 1, -4},
/* ',' 0x2C */ {54, 1, 3, 3, 1, 0},
/* '-' 0x2D */ {55, 2, 1, 4, 1, -3},
/* '.' 0x2E */ {56, 1, 1, 3, 1, 0},
/* '/' 0x2F */ {57, 3, 9, 3, 0, -8},
/* '0' 0x30 */ {61, 5, 9, 7, 1, -8},
/* '1' 0x31 */ {67, 3, 9, 7, 1, -8},
/* '2' 0x32 */ {71, 6, 9, 7, 0, -8},
/* '3' 0x33 */ {78, 6, 9, 7, 0, -8},
/* '4' 0x34 */ {85, 6, 9, 7, 0, -8},
/* '5' 0x35 */ {92, 5, 9, 7, 1, -8},
/* '6' 0x36 */ {98, 5, 9, 7, 1, -8},
/* '7' 0x37 */ {104, 5, 9, 7, 1, -8},
/* '8' 0x38 */ {110, 6, 9, 7, 0, -8},
/* '9' 0x39 */ {117, 6, 9, 7, 0, -8},
/* ':' 0x3A */ {124, 1, 7, 3, 1, -6},
/* ';' 0x3B */ {125, 1, 8, 3, 1, -5},
/* '<' 0x3C */ {126, 5, 5, 7, 1, -4},
/* '=' 0x3D */ {130, 5, 3, 7, 1, -3},
/* '>' 0x3E */ {132, 5, 5, 7, 1, -4},
/* '?' 0x3F */ {136, 5, 9, 7, 1, -8},
/* '@' 0x40 */ {142, 11, 11, 12, 0, -8},
/* 'A' 0x41 */ {158, 8, 9, 8, 0, -8},
/* 'B' 0x42 */ {167, 6, 9, 8, 1, -8},
/* 'C' 0x43 */ {174, 8, 9, 9, 0, -8},
/* 'D' 0x44 */ {183, 7, 9, 8, 1, -8},
/* 'E' 0x45 */ {191, 6, 9, 8, 1, -8},
/* 'F' 0x46 */ {198, 6, 9, 7, 1, -8},
/* 'G' 0x47 */ {205, 8, 9, 9, 0, -8},
/* 'H' 0x48 */ {214, 7, 9, 9, 1, -8},
/* 'I' 0x49 */ {222, 1, 9, 3, 1, -8},
/* 'J' 0x4A */ {224, 5, 9, 6, 0, -8},
/* 'K' 0x4B */ {230, 7, 9, 8, 1, -8},
/* 'L' 0x4C */ {238, 5, 9, 7, 1, -8},
/* 'M' 0x4D */ {244, 8, 9, 10, 1, -8},
/* 'N' 0x4E */ {253, 7, 9, 9, 1, -8},
/* 'O' 0x4F */ {261, 9, 9, 9, 0, -8},
/* 'P' 0x50 */ {272, 6, 9, 8, 1, -8},
/* 'Q' 0x51 */ {279, 9, 10, 9, 0, -8},
/* 'R' 0x52 */ {291, 7, 9, 9, 1, -8},
/* 'S' 0x53 */ {299, 6, 9, 8, 1, -8},
/* 'T' 0x54 */ {306, 7, 9, 8, 0, -8},
/* 'U' 0x55 */ {314, 7, 9, 9, 1, -8},
/* 'V' 0x56 */ {322, 7, 9, 8, 0, -8},
/* 'W' 0x57 */ {330, 11, 9, 11, 0, -8},
/* 'X' 0x58 */ {343, 6, 9, 8, 1, -8},
/* 'Y' 0x59 */ {350, 8, 9, 8, 0, -8},
/* 'Z' 0x5A */ {359, 7, 9, 7, 0, -8},
/* '[' 0x5B */ {367, 2, 12, 3, 1, -8},
/* '\' 0x5C */ {370, 3, 9, 3, 0, -8},
/* ']' 0x5D */ {374, 2, 12, 3, 0, -8},
/* '^' 0x5E */ {377, 4, 4, 6, 1, -8},
/* '_' 0x5F */ {379, 7, 1, 7, 0, 2},
/* '`' 0x60 */ {380, 1, 1, 3, 1, -8},
/* 'a' 0x61 */ {381, 6, 7, 7, 0, -6},
/* 'b' 0x62 */ {387, 5, 9, 7, 1, -8},
/* 'c' 0x63 */ {393, 6, 7, 6, 0, -6},
/* 'd' 0x64 */ {399, 6, 9, 7, 0, -8},
/* 'e' 0x65 */ {406, 6, 7, 6, 0, -6},
/* 'f' 0x66 */ {412, 3, 9, 3, 0, -8},
/* 'g' 0x67 */ {416, 6, 10, 7, 0, -6},
/* 'h' 0x68 */ {424, 5, 9, 6, 1, -8},
/* 'i' 0x69 */ {430, 1, 9, 3, 1, -8},
/* 'j' 0x6A */ {432, 2, 12, 3, 0, -8},
/* 'k' 0x6B */ {435, 5, 9, 6, 1, -8},
/* 'l' 0x6C */ {441, 1, 9, 3, 1, -8},
/* 'm' 0x6D */ {443, 8, 7, 10, 1, -6},
/* 'n' 0x6E */ {450, 5, 7, 6, 1, -6},
/* 'o' 0x6F */ {455, 6, 7, 6, 0, -6},
/* 'p' 0x70 */ {461, 5, 9, 7, 1, -6},
/* 'q' 0x71 */ {467, 6, 9, 7, 0, -6},
/* 'r' 0x72 */ {474, 3, 7, 4, 1, -6},
/* 's' 0x73 */ {477, 5, 7, 6, 0, -6},
/* 't' 0x74 */ {482, 3, 8, 3, 0, -7},
/* 'u' 0x75 */ {485, 5, 7, 6, 1, -6},
/* 'v' 0x76 */ {490, 6, 7, 6, 0, -6},
/* 'w' 0x77 */ {496, 8, 7, 9, 0, -6},
/* 'x' 0x78 */ {503, 5, 7, 6, 0, -6},
/* 'y' 0x79 */ {508, 5, 10, 6, 0, -6},
/* 'z' 0x7A */ {515, 5, 7, 6, 0, -6},
/* '{' 0x7B */ {520, 2, 12, 4, 1, -8},
/* '|' 0x7C */ {523, 1, 11, 3, 1, -8},
/* '}' 0x7D */ {525, 2, 12, 4, 1, -8},
/* '~' 0x7E */ {528, 6, 2, 6, 0, -4},
/* 0x7F */ {530, 9, 10, 11, 1, -8},
/* 0x80 */ {542, 9, 11, 9, 0, -8},
/* 0x81 */ {555, 6, 10, 7, 1, -9},
/* 0x82 */ {563, 1, 3, 3, 1, 0},
/* 0x83 */ {564, 4, 9, 5, 1, -8},
/* 0x84 */ {569, 3, 3, 5, 1, 0},
/* 0x85 */ {571, 5, 1, 7, 1, 0},
/* 0x86 */ {572, 5, 11, 7, 1, -8},
/* 0x87 */ {579, 5, 11, 7, 1, -8},
/* 0x88 */ {586, 7, 9, 8, 0, -8},
/* 0x89 */ {594, 12, 9, 12, 0, -8},
/* 0x8A */ {608, 11, 9, 13, 1, -8},
/* 0x8B */ {621, 2, 3, 4, 1, -4},
/* 0x8C */ {622, 11, 9, 12, 1, -8},
/* 0x8D */ {635, 6, 11, 8, 1, -10},
/* 0x8E */ {644, 9, 9, 9, 0, -8},
/* 0x8F */ {655, 7, 11, 9, 1, -8},
/* 0x90 */ {665, 6, 11, 7, 0, -8},
/* 0x91 */ {674, 1, 3, 3, 1, -8},
/* 0x92 */ {675, 1, 3, 2, 1, -8},
/* 0x93 */ {676, 3, 3, 5, 1, -8},
/* 0x94 */ {678, 3, 3, 5, 1, -8},
/* 0x95 */ {680, 3, 3, 5, 1, -5},
/* 0x96 */ {682, 6, 1, 6, 0, -3},
/* 0x97 */ {683, 12, 1, 12, 0, -3},
/* 0x98 */ {685, 0, 0, 8, 0, 0},
/* 0x99 */ {685, 11, 7, 12, 1, -8},
/* 0x9A */ {695, 9, 6, 10, 0, -5},
/* 0x9B */ {702, 2, 3, 3, 1, -4},
/* 0x9C */ {703, 9, 6, 10, 1, -5},
/* 0x9D */ {710, 4, 9, 6, 1, -8},
/* 0x9E */ {715, 6, 9, 7, 0, -8},
/* 0x9F */ {722, 5, 7, 7, 1, -5},
/* 0xA0 */ {727, 0, 0, 3, 0, 0},
/* 0xA1 */ {727, 7, 11, 7, 0, -10},
/* 0xA2 */ {737, 5, 11, 6, 0, -7},
/* 0xA3 */ {744, 5, 9, 6, 0, -8},
/* 0xA4 */ {750, 5, 4, 7, 1, -5},
/* 0xA5 */ {753, 6, 10, 7, 1, -9},
/* 0xA6 */ {761, 1, 12, 3, 1, -8},
/* 0xA7 */ {763, 5, 12, 7, 1, -8},
/* 0xA8 */ {771, 6, 11, 8, 1, -10},
/* 0xA9 */ {780, 9, 9, 10, 0, -8},
/* 0xAA */ {791, 7, 9, 9, 1, -8},
/* 0xAB */ {799, 4, 4, 6, 1, -4},
/* 0xAC */ {801, 2, 12, 3, 0, -8},
/* 0xAD */ {804, 0, 0, 0, 0, 0},
/* 0xAE */ {804, 9, 9, 10, 0, -8},
/* 0xAF */ {815, 3, 11, 3, 0, -10},
/* 0xB0 */ {820, 4, 4, 7, 2, -8},
/* 0xB1 */ {822, 5, 7, 7, 1, -6},
/* 0xB2 */ {827, 1, 9, 3, 1, -8},
/* 0xB3 */ {829, 1, 9, 3, 1, -8},
/* 0xB4 */ {831, 3, 8, 5, 1, -7},
/* 0xB5 */ {834, 6, 9, 7, 1, -6},
/* 0xB6 */ {841, 6, 10, 6, 1, -8},
/* 0xB7 */ {849, 1, 1, 3, 1, -2},
/* 0xB8 */ {850, 6, 9, 7, 0, -8},
/* 0xB9 */ {857, 9, 9, 11, 1, -8},
/* 0xBA */ {868, 6, 6, 6, 0, -5},
/* 0xBB */ {873, 4, 4, 6, 1, -5},
/* 0xBC */ {875, 2, 12, 3, 0, -8},
/* 0xBD */ {878, 6, 9, 8, 1, -8},
/* 0xBE */ {885, 5, 6, 6, 0, -5},
/* 0xBF */ {889, 3, 9, 3, 0, -8},
/* 0xC0 */ {893, 8, 9, 8, 0, -8},
/* 0xC1 */ {902, 6, 9, 8, 1, -8},
/* 0xC2 */ {909, 6, 9, 8, 1, -8},
/* 0xC3 */ {916, 6, 9, 7, 1, -8},
/* 0xC4 */ {923, 9, 11, 10, 0, -8},
/* 0xC5 */ {936, 6, 9, 8, 1, -8},
/* 0xC6 */ {943, 9, 9, 11, 1, -8},
/* 0xC7 */ {954, 6, 9, 8, 1, -8},
/* 0xC8 */ {961, 7, 9, 9, 1, -8},
/* 0xC9 */ {969, 7, 11, 9, 1, -10},
/* 0xCA */ {979, 6, 9, 8, 1, -8},
/* 0xCB */ {986, 7, 9, 8, 0, -8},
/* 0xCC */ {994, 8, 9, 10, 1, -8},
/* 0xCD */ {1003, 7, 9, 9, 1, -8},
/* 0xCE */ {1011, 8, 9, 10, 1, -8},
/* 0xCF */ {1020, 7, 9, 9, 1, -8},
/* 0xD0 */ {1028, 6, 9, 8, 1, -8},
/* 0xD1 */ {1035, 7, 9, 9, 1, -8},
/* 0xD2 */ {1043, 7, 9, 7, 0, -8},
/* 0xD3 */ {1051, 7, 9, 7, 0, -8},
/* 0xD4 */ {1059, 9, 9, 10, 1, -8},
/* 0xD5 */ {1070, 6, 9, 8, 1, -8},
/* 0xD6 */ {1077, 8, 11, 9, 1, -8},
/* 0xD7 */ {1088, 6, 9, 8, 1, -8},
/* 0xD8 */ {1095, 8, 9, 10, 1, -8},
/* 0xD9 */ {1104, 9, 11, 10, 1, -8},
/* 0xDA */ {1117, 10, 9, 10, 0, -8},
/* 0xDB */ {1129, 9, 9, 10, 1, -8},
/* 0xDC */ {1140, 6, 9, 8, 1, -8},
/* 0xDD */ {1147, 7, 9, 9, 1, -8},
/* 0xDE */ {1155, 10, 9, 12, 1, -8},
/* 0xDF */ {1167, 6, 9, 8, 1, -8},
/* 0xE0 */ {1174, 6, 6, 7, 0, -5},
/* 0xE1 */ {1179, 6, 9, 7, 0, -8},
/* 0xE2 */ {1186, 5, 6, 6, 1, -5},
/* 0xE3 */ {1190, 4, 6, 5, 1, -5},
/* 0xE4 */ {1193, 7, 7, 7, 0, -5},
/* 0xE5 */ {1200, 6, 6, 7, 0, -5},
/* 0xE6 */ {1205, 8, 6, 9, 1, -5},
/* 0xE7 */ {1211, 6, 6, 6, 0, -5},
/* 0xE8 */ {1216, 5, 6, 7, 1, -5},
/* 0xE9 */ {1220, 5, 8, 7, 1, -7},
/* 0xEA */ {1225, 4, 6, 6, 1, -5},
/* 0xEB */ {1228, 5, 6, 6, 0, -5},
/* 0xEC */ {1232, 6, 6, 7, 1, -5},
/* 0xED */ {1237, 5, 6, 7, 1, -5},
/* 0xEE */ {1241, 6, 6, 7, 0, -5},
/* 0xEF */ {1246, 5, 6, 7, 1, -5},
/* 0xF0 */ {1250, 5, 9, 7, 1, -5},
/* 0xF1 */ {1256, 6, 6, 6, 0, -5},
/* 0xF2 */ {1261, 5, 6, 5, 0, -5},
/* 0xF3 */ {1265, 5, 9, 6, 0, -5},
/* 0xF4 */ {1271, 10, 11, 10, 0, -7},
/* 0xF5 */ {1285, 5, 6, 6, 0, -5},
/* 0xF6 */ {1289, 6, 7, 7, 1, -5},
/* 0xF7 */ {1295, 4, 6, 6, 1, -5},
/* 0xF8 */ {1298, 6, 6, 8, 1, -5},
/* 0xF9 */ {1303, 7, 7, 9, 1, -5},
/* 0xFA */ {1310, 7, 6, 8, 0, -5},
/* 0xFB */ {1316, 6, 6, 8, 1, -5},
/* 0xFC */ {1321, 5, 6, 6, 1, -5},
/* 0xFD */ {1325, 5, 6, 6, 1, -5},
/* 0xFE */ {1329, 8, 6, 9, 1, -5},
/* 0xFF */ {1335, 5, 6, 7, 1, -5},
};
const GFXfont FreeSans6pt_Win1251 PROGMEM = {(uint8_t *)FreeSans6pt_Win1251Bitmaps, (GFXglyph *)FreeSans6pt_Win1251Glyphs, 0x20,
0xFF, 14};

View File

@@ -0,0 +1,457 @@
#pragma once
const uint8_t FreeSans6pt_Win1252Bitmaps[] PROGMEM = {
/* ' ' 0x20 */
0xFC, 0x80, /* '!' 0x21 */
0xB6, 0x80, /* '"' 0x22 */
0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, /* '#' 0x23 */
0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, /* '$' 0x24 */
0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, /* '%' 0x25 */
0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4, /* '&' 0x26 */
0xE0, /* ''' 0x27 */
0x5A, 0xAA, 0x94, /* '(' 0x28 */
0x89, 0x12, 0x49, 0x29, 0x00, /* ')' 0x29 */
0x5E, 0x80, /* '*' 0x2A */
0x21, 0x3E, 0x42, 0x00, /* '+' 0x2B */
0xE0, /* ',' 0x2C */
0xC0, /* '-' 0x2D */
0x80, /* '.' 0x2E */
0x24, 0xA4, 0xA4, 0x80, /* '/' 0x2F */
0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, /* '0' 0x30 */
0x27, 0x92, 0x49, 0x20, /* '1' 0x31 */
0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, /* '2' 0x32 */
0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78, /* '3' 0x33 */
0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, /* '4' 0x34 */
0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0, /* '5' 0x35 */
0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70, /* '6' 0x36 */
0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, /* '7' 0x37 */
0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, /* '8' 0x38 */
0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78, /* '9' 0x39 */
0x82, /* ':' 0x3A */
0x87, /* ';' 0x3B */
0x3E, 0x30, 0x60, 0x80, /* '<' 0x3C */
0xF8, 0x3E, /* '=' 0x3D */
0xE0, 0xC6, 0xC8, 0x00, /* '>' 0x3E */
0x74, 0x42, 0x11, 0x10, 0x80, 0x20, /* '?' 0x3F */
0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, /* '@' 0x40 */
0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 'A' 0x41 */
0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 'B' 0x42 */
0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, /* 'C' 0x43 */
0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8, /* 'D' 0x44 */
0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 'E' 0x45 */
0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, /* 'F' 0x46 */
0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, /* 'G' 0x47 */
0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 'H' 0x48 */
0xFF, 0x80, /* 'I' 0x49 */
0x08, 0x42, 0x10, 0x87, 0x29, 0x70, /* 'J' 0x4A */
0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, /* 'K' 0x4B */
0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 'L' 0x4C */
0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 'M' 0x4D */
0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, /* 'N' 0x4E */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00, /* 'O' 0x4F */
0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, /* 'P' 0x50 */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40, /* 'Q' 0x51 */
0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, /* 'R' 0x52 */
0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, /* 'S' 0x53 */
0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 'T' 0x54 */
0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, /* 'U' 0x55 */
0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, /* 'V' 0x56 */
0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, /* 'W' 0x57 */
0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, /* 'X' 0x58 */
0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, /* 'Y' 0x59 */
0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, /* 'Z' 0x5A */
0xEA, 0xAA, 0xAB, /* '[' 0x5B */
0x92, 0x24, 0x89, 0x20, /* '\' 0x5C */
0xD5, 0x55, 0x57, /* ']' 0x5D */
0x46, 0xA9, /* '^' 0x5E */
0xFE, /* '_' 0x5F */
0x80, /* '`' 0x60 */
0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, /* 'a' 0x61 */
0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0, /* 'b' 0x62 */
0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, /* 'c' 0x63 */
0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, /* 'd' 0x64 */
0x39, 0x38, 0x7F, 0x81, 0x13, 0x80, /* 'e' 0x65 */
0x6B, 0xA4, 0x92, 0x40, /* 'f' 0x66 */
0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, /* 'g' 0x67 */
0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, /* 'h' 0x68 */
0xBF, 0x80, /* 'i' 0x69 */
0x45, 0x55, 0x57, /* 'j' 0x6A */
0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, /* 'k' 0x6B */
0xFF, 0x80, /* 'l' 0x6C */
0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, /* 'm' 0x6D */
0xF4, 0x63, 0x18, 0xC6, 0x20, /* 'n' 0x6E */
0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, /* 'o' 0x6F */
0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, /* 'p' 0x70 */
0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, /* 'q' 0x71 */
0xF2, 0x49, 0x20, /* 'r' 0x72 */
0x7A, 0x50, 0xE0, 0xE5, 0xE0, /* 's' 0x73 */
0x5D, 0x24, 0x93, /* 't' 0x74 */
0x8C, 0x63, 0x18, 0xCF, 0xA0, /* 'u' 0x75 */
0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, /* 'v' 0x76 */
0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26, /* 'w' 0x77 */
0x4A, 0x4C, 0x43, 0x27, 0x20, /* 'x' 0x78 */
0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00, /* 'y' 0x79 */
0x78, 0x44, 0x46, 0x23, 0xE0, /* 'z' 0x7A */
0x6A, 0xAA, 0xA9, /* '{' 0x7B */
0xFF, 0xE0, /* '|' 0x7C */
0x95, 0x55, 0x56, /* '}' 0x7D */
0x66, 0x60, /* '~' 0x7E */
0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0, /* 0x7F */
0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E, /* 0x80 */
/* 0x81 */
0xE0, /* 0x82 */
0x6B, 0xA4, 0x92, 0x49, 0x60, /* 0x83 */
0xB6, 0x80, /* 0x84 */
0xA8, /* 0x85 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, /* 0x86 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08, /* 0x87 */
0x54, /* 0x88 */
0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60, /* 0x89 */
0x28, 0x47, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80, /* 0x8A */
0x64, /* 0x8B */
0x3B, 0xE8, 0xC2, 0x08, 0x41, 0x08, 0x3F, 0x04, 0x20, 0x82, 0x30, 0x3B, 0xE0, /* 0x8C */
/* 0x8D */
0x14, 0x11, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0x8E */
/* 0x8F */
/* 0x90 */
0xE0, /* 0x91 */
0xE0, /* 0x92 */
0xB6, 0x80, /* 0x93 */
0xB6, 0x80, /* 0x94 */
0xFF, 0x80, /* 0x95 */
0xFC, /* 0x96 */
0xFF, 0xF0, /* 0x97 */
0xDB, /* 0x98 */
0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68, /* 0x99 */
0x52, 0x69, 0x8E, 0x19, 0x60, /* 0x9A */
0x98, /* 0x9B */
0x7B, 0xD9, 0xCE, 0x10, 0xC3, 0xF8, 0x41, 0x9C, 0x5E, 0xF0, /* 0x9C */
/* 0x9D */
0x51, 0x1E, 0x11, 0x11, 0x88, 0xF8, /* 0x9E */
0x29, 0x05, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20, /* 0x9F */
/* 0xA0 */
0xBF, 0x80, /* 0xA1 */
0x23, 0xAB, 0x4A, 0x52, 0xAE, 0x20, /* 0xA2 */
0x39, 0x14, 0x10, 0xF0, 0x82, 0x1C, 0x4C, /* 0xA3 */
0xFC, 0x63, 0xF0, /* 0xA4 */
0x8C, 0x54, 0xAF, 0x93, 0xE4, 0x20, /* 0xA5 */
0xF9, 0xF0, /* 0xA6 */
0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0, /* 0xA7 */
0xA0, /* 0xA8 */
0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00, /* 0xA9 */
0x61, 0x79, 0x60, /* 0xAA */
0x5A, 0xA5, /* 0xAB */
0xFC, 0x10, 0x40, /* 0xAC */
/* 0xAD */
0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00, /* 0xAE */
0xE0, /* 0xAF */
0x69, 0x96, /* 0xB0 */
0x21, 0x3E, 0x42, 0x03, 0xE0, /* 0xB1 */
0x69, 0x3C, 0xF0, /* 0xB2 */
0x79, 0x29, 0x70, /* 0xB3 */
0x80, /* 0xB4 */
0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80, /* 0xB5 */
0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0, /* 0xB6 */
0x80, /* 0xB7 */
0x67, 0x80, /* 0xB8 */
0x75, 0x50, /* 0xB9 */
0x69, 0x96, 0xF0, /* 0xBA */
0xA5, 0x5A, /* 0xBB */
0x42, 0x30, 0x84, 0x41, 0x10, 0x48, 0x82, 0x61, 0x28, 0x8F, 0x20, 0x80, /* 0xBC */
0x40, 0x63, 0x11, 0x09, 0x74, 0xA8, 0x84, 0x44, 0x44, 0x43, 0x80, /* 0xBD */
0x71, 0x24, 0x82, 0x20, 0x50, 0x98, 0x9A, 0x61, 0x28, 0x4F, 0x20, 0x80, /* 0xBE */
0x20, 0x08, 0x44, 0x42, 0x11, 0x70, /* 0xBF */
0x10, 0x08, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC0 */
0x08, 0x10, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC1 */
0x18, 0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC2 */
0x34, 0x2C, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC3 */
0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 0xC4 */
0x18, 0x24, 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC5 */
0x1F, 0xC5, 0x02, 0x40, 0x90, 0x47, 0xDF, 0x04, 0x42, 0x10, 0x87, 0xC0, /* 0xC6 */
0x3E, 0x61, 0xC0, 0x80, 0x80, 0x80, 0xC1, 0x63, 0x3E, 0x0C, 0x04, 0x1C, /* 0xC7 */
0x20, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xC8 */
0x08, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xC9 */
0x10, 0xA0, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xCA */
0x28, 0x0F, 0xE0, 0x83, 0xE8, 0x20, 0x83, 0xF0, /* 0xCB */
0x91, 0x55, 0x50, /* 0xCC */
0x62, 0xAA, 0xA0, /* 0xCD */
0x54, 0x24, 0x92, 0x48, /* 0xCE */
0xA1, 0x24, 0x92, 0x48, /* 0xCF */
0x7C, 0x42, 0x41, 0x41, 0xF1, 0x41, 0x41, 0x42, 0x7C, /* 0xD0 */
0x14, 0x53, 0x0F, 0x1B, 0x32, 0x66, 0xC7, 0x87, 0x04, /* 0xD1 */
0x10, 0x04, 0x0F, 0x8C, 0x6C, 0x1C, 0x06, 0x03, 0x83, 0x63, 0x1F, 0x00, /* 0xD2 */
0x04, 0x04, 0x0F, 0x8C, 0x6C, 0x1C, 0x06, 0x03, 0x83, 0x63, 0x1F, 0x00, /* 0xD3 */
0x08, 0x0A, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD4 */
0x1A, 0x0B, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD5 */
0x14, 0x00, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD6 */
0x8A, 0x88, 0xA8, 0x80, /* 0xD7 */
0x3E, 0xB1, 0xB0, 0xF0, 0x98, 0x8C, 0x87, 0x86, 0xC6, 0xBE, 0x00, /* 0xD8 */
0x20, 0x22, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xD9 */
0x08, 0x22, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDA */
0x10, 0x52, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDB */
0x29, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDC */
0x09, 0x25, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20, /* 0xDD */
0x83, 0xE8, 0x61, 0x87, 0xE8, 0x20, 0x80, /* 0xDE */
0x7A, 0x18, 0x61, 0x8A, 0x18, 0x61, 0xB8, /* 0xDF */
0x20, 0x20, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE0 */
0x10, 0x40, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE1 */
0x10, 0x50, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE2 */
0x68, 0xB0, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE3 */
0x28, 0x01, 0xE4, 0x20, 0x47, 0xB1, 0x46, 0x76, /* 0xE4 */
0x10, 0x50, 0x43, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE5 */
0x7B, 0xA1, 0x90, 0x45, 0xFF, 0x84, 0x23, 0x17, 0x38, /* 0xE6 */
0x7B, 0x18, 0x20, 0x83, 0x17, 0x8C, 0x11, 0xC0, /* 0xE7 */
0x20, 0x40, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xE8 */
0x10, 0x80, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xE9 */
0x10, 0xA0, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xEA */
0x28, 0x07, 0xB3, 0x87, 0xF8, 0x31, 0x78, /* 0xEB */
0x91, 0x55, 0x50, /* 0xEC */
0x62, 0xAA, 0xA0, /* 0xED */
0x54, 0x24, 0x92, 0x48, /* 0xEE */
0xA1, 0x24, 0x92, 0x40, /* 0xEF */
0x28, 0x42, 0x8F, 0x46, 0x18, 0x52, 0x30, /* 0xF0 */
0x6A, 0xC1, 0x6C, 0xC6, 0x31, 0x8C, 0x40, /* 0xF1 */
0x20, 0x40, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF2 */
0x10, 0x80, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF3 */
0x10, 0xA0, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF4 */
0x69, 0x60, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF5 */
0x28, 0x07, 0xB3, 0x86, 0x18, 0x73, 0x78, /* 0xF6 */
0x20, 0x3E, 0x02, 0x00, /* 0xF7 */
0x7F, 0x39, 0x69, 0xC7, 0x3F, 0x80, /* 0xF8 */
0x41, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xF9 */
0x11, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFA */
0x22, 0x81, 0x18, 0xC6, 0x31, 0x9B, 0x40, /* 0xFB */
0x50, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFC */
0x10, 0x88, 0x52, 0x49, 0x23, 0x0C, 0x30, 0x82, 0x18, /* 0xFD */
0x84, 0x3D, 0xB8, 0xC6, 0x3B, 0xF4, 0x20, /* 0xFE */
0x28, 0x08, 0x52, 0x49, 0x23, 0x0C, 0x30, 0x82, 0x18, /* 0xFF */
};
const GFXglyph FreeSans6pt_Win1252Glyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 3, 0, 0},
/* '!' 0x21 */ {0, 1, 9, 4, 2, -8},
/* '"' 0x22 */ {2, 3, 3, 4, 0, -8},
/* '#' 0x23 */ {4, 7, 8, 7, 0, -7},
/* '$' 0x24 */ {11, 6, 11, 7, 0, -9},
/* '%' 0x25 */ {20, 10, 9, 11, 0, -8},
/* '&' 0x26 */ {32, 6, 9, 8, 1, -8},
/* ''' 0x27 */ {39, 1, 3, 2, 1, -8},
/* '(' 0x28 */ {40, 2, 11, 4, 1, -8},
/* ')' 0x29 */ {43, 3, 11, 4, 0, -8},
/* '*' 0x2A */ {48, 3, 3, 5, 1, -8},
/* '+' 0x2B */ {50, 5, 5, 7, 1, -4},
/* ',' 0x2C */ {54, 1, 3, 3, 1, 0},
/* '-' 0x2D */ {55, 2, 1, 4, 1, -3},
/* '.' 0x2E */ {56, 1, 1, 3, 1, 0},
/* '/' 0x2F */ {57, 3, 9, 3, 0, -8},
/* '0' 0x30 */ {61, 5, 9, 7, 1, -8},
/* '1' 0x31 */ {67, 3, 9, 7, 1, -8},
/* '2' 0x32 */ {71, 6, 9, 7, 0, -8},
/* '3' 0x33 */ {78, 6, 9, 7, 0, -8},
/* '4' 0x34 */ {85, 6, 9, 7, 0, -8},
/* '5' 0x35 */ {92, 5, 9, 7, 1, -8},
/* '6' 0x36 */ {98, 5, 9, 7, 1, -8},
/* '7' 0x37 */ {104, 5, 9, 7, 1, -8},
/* '8' 0x38 */ {110, 6, 9, 7, 0, -8},
/* '9' 0x39 */ {117, 6, 9, 7, 0, -8},
/* ':' 0x3A */ {124, 1, 7, 3, 1, -6},
/* ';' 0x3B */ {125, 1, 8, 3, 1, -5},
/* '<' 0x3C */ {126, 5, 5, 7, 1, -4},
/* '=' 0x3D */ {130, 5, 3, 7, 1, -3},
/* '>' 0x3E */ {132, 5, 5, 7, 1, -4},
/* '?' 0x3F */ {136, 5, 9, 7, 1, -8},
/* '@' 0x40 */ {142, 11, 11, 12, 0, -8},
/* 'A' 0x41 */ {158, 8, 9, 8, 0, -8},
/* 'B' 0x42 */ {167, 6, 9, 8, 1, -8},
/* 'C' 0x43 */ {174, 8, 9, 9, 0, -8},
/* 'D' 0x44 */ {183, 7, 9, 8, 1, -8},
/* 'E' 0x45 */ {191, 6, 9, 8, 1, -8},
/* 'F' 0x46 */ {198, 6, 9, 7, 1, -8},
/* 'G' 0x47 */ {205, 8, 9, 9, 0, -8},
/* 'H' 0x48 */ {214, 7, 9, 9, 1, -8},
/* 'I' 0x49 */ {222, 1, 9, 3, 1, -8},
/* 'J' 0x4A */ {224, 5, 9, 6, 0, -8},
/* 'K' 0x4B */ {230, 7, 9, 8, 1, -8},
/* 'L' 0x4C */ {238, 5, 9, 7, 1, -8},
/* 'M' 0x4D */ {244, 8, 9, 10, 1, -8},
/* 'N' 0x4E */ {253, 7, 9, 9, 1, -8},
/* 'O' 0x4F */ {261, 9, 9, 9, 0, -8},
/* 'P' 0x50 */ {272, 6, 9, 8, 1, -8},
/* 'Q' 0x51 */ {279, 9, 10, 9, 0, -8},
/* 'R' 0x52 */ {291, 7, 9, 9, 1, -8},
/* 'S' 0x53 */ {299, 6, 9, 8, 1, -8},
/* 'T' 0x54 */ {306, 7, 9, 8, 0, -8},
/* 'U' 0x55 */ {314, 7, 9, 9, 1, -8},
/* 'V' 0x56 */ {322, 7, 9, 8, 0, -8},
/* 'W' 0x57 */ {330, 11, 9, 11, 0, -8},
/* 'X' 0x58 */ {343, 6, 9, 8, 1, -8},
/* 'Y' 0x59 */ {350, 8, 9, 8, 0, -8},
/* 'Z' 0x5A */ {359, 7, 9, 7, 0, -8},
/* '[' 0x5B */ {367, 2, 12, 3, 1, -8},
/* '\' 0x5C */ {370, 3, 9, 3, 0, -8},
/* ']' 0x5D */ {374, 2, 12, 3, 0, -8},
/* '^' 0x5E */ {377, 4, 4, 6, 1, -8},
/* '_' 0x5F */ {379, 7, 1, 7, 0, 2},
/* '`' 0x60 */ {380, 1, 1, 3, 1, -8},
/* 'a' 0x61 */ {381, 6, 7, 7, 0, -6},
/* 'b' 0x62 */ {387, 5, 9, 7, 1, -8},
/* 'c' 0x63 */ {393, 6, 7, 6, 0, -6},
/* 'd' 0x64 */ {399, 6, 9, 7, 0, -8},
/* 'e' 0x65 */ {406, 6, 7, 6, 0, -6},
/* 'f' 0x66 */ {412, 3, 9, 3, 0, -8},
/* 'g' 0x67 */ {416, 6, 10, 7, 0, -6},
/* 'h' 0x68 */ {424, 5, 9, 6, 1, -8},
/* 'i' 0x69 */ {430, 1, 9, 3, 1, -8},
/* 'j' 0x6A */ {432, 2, 12, 3, 0, -8},
/* 'k' 0x6B */ {435, 5, 9, 6, 1, -8},
/* 'l' 0x6C */ {441, 1, 9, 3, 1, -8},
/* 'm' 0x6D */ {443, 8, 7, 10, 1, -6},
/* 'n' 0x6E */ {450, 5, 7, 6, 1, -6},
/* 'o' 0x6F */ {455, 6, 7, 6, 0, -6},
/* 'p' 0x70 */ {461, 5, 9, 7, 1, -6},
/* 'q' 0x71 */ {467, 6, 9, 7, 0, -6},
/* 'r' 0x72 */ {474, 3, 7, 4, 1, -6},
/* 's' 0x73 */ {477, 5, 7, 6, 0, -6},
/* 't' 0x74 */ {482, 3, 8, 3, 0, -7},
/* 'u' 0x75 */ {485, 5, 7, 6, 1, -6},
/* 'v' 0x76 */ {490, 6, 7, 6, 0, -6},
/* 'w' 0x77 */ {496, 8, 7, 9, 0, -6},
/* 'x' 0x78 */ {503, 5, 7, 6, 0, -6},
/* 'y' 0x79 */ {508, 5, 10, 6, 0, -6},
/* 'z' 0x7A */ {515, 5, 7, 6, 0, -6},
/* '{' 0x7B */ {520, 2, 12, 4, 1, -8},
/* '|' 0x7C */ {523, 1, 11, 3, 1, -8},
/* '}' 0x7D */ {525, 2, 12, 4, 1, -8},
/* '~' 0x7E */ {528, 6, 2, 6, 0, -4},
/* 0x7F */ {530, 9, 10, 11, 1, -8},
/* 0x80 */ {542, 7, 9, 8, 0, -8},
/* 0x81 */ {550, 0, 0, 8, 0, 0},
/* 0x82 */ {550, 1, 3, 3, 1, 0},
/* 0x83 */ {551, 3, 12, 3, 0, -8},
/* 0x84 */ {556, 3, 3, 5, 1, 0},
/* 0x85 */ {558, 5, 1, 7, 1, 0},
/* 0x86 */ {559, 5, 11, 7, 1, -8},
/* 0x87 */ {566, 5, 11, 7, 1, -8},
/* 0x88 */ {573, 3, 2, 4, 0, -9},
/* 0x89 */ {574, 12, 9, 12, 0, -8},
/* 0x8A */ {588, 6, 11, 8, 1, -9},
/* 0x8B */ {597, 2, 3, 4, 1, -4},
/* 0x8C */ {598, 11, 9, 12, 0, -8},
/* 0x8D */ {611, 0, 0, 8, 0, 0},
/* 0x8E */ {611, 7, 10, 7, 0, -9},
/* 0x8F */ {620, 0, 0, 8, 0, 0},
/* 0x90 */ {620, 0, 0, 8, 0, 0},
/* 0x91 */ {620, 1, 3, 3, 1, -8},
/* 0x92 */ {621, 1, 3, 2, 1, -8},
/* 0x93 */ {622, 3, 3, 5, 1, -8},
/* 0x94 */ {624, 3, 3, 5, 1, -8},
/* 0x95 */ {626, 3, 3, 5, 1, -5},
/* 0x96 */ {628, 6, 1, 6, 0, -3},
/* 0x97 */ {629, 12, 1, 12, 0, -3},
/* 0x98 */ {631, 4, 2, 4, 0, -8},
/* 0x99 */ {632, 11, 7, 12, 1, -8},
/* 0x9A */ {642, 4, 9, 6, 1, -8},
/* 0x9B */ {647, 2, 3, 3, 1, -4},
/* 0x9C */ {648, 11, 7, 11, 0, -6},
/* 0x9D */ {658, 0, 0, 8, 0, 0},
/* 0x9E */ {658, 5, 9, 6, 0, -8},
/* 0x9F */ {664, 7, 10, 8, 1, -9},
/* 0xA0 */ {673, 0, 0, 3, 0, 0},
/* 0xA1 */ {673, 1, 9, 4, 1, -5},
/* 0xA2 */ {675, 5, 9, 7, 1, -7},
/* 0xA3 */ {681, 6, 9, 7, 0, -8},
/* 0xA4 */ {688, 5, 4, 7, 1, -5},
/* 0xA5 */ {691, 5, 9, 7, 1, -8},
/* 0xA6 */ {697, 1, 12, 3, 1, -8},
/* 0xA7 */ {699, 5, 12, 7, 1, -8},
/* 0xA8 */ {707, 3, 1, 4, 0, -7},
/* 0xA9 */ {708, 9, 9, 10, 0, -8},
/* 0xAA */ {719, 4, 5, 4, 0, -8},
/* 0xAB */ {722, 4, 4, 6, 1, -4},
/* 0xAC */ {724, 6, 3, 7, 1, -4},
/* 0xAD */ {727, 0, 0, 0, 0, 0},
/* 0xAE */ {727, 9, 9, 10, 0, -8},
/* 0xAF */ {738, 3, 1, 4, 0, -8},
/* 0xB0 */ {739, 4, 4, 7, 2, -8},
/* 0xB1 */ {741, 5, 7, 7, 1, -6},
/* 0xB2 */ {746, 4, 5, 4, 0, -9},
/* 0xB3 */ {749, 4, 5, 4, 0, -9},
/* 0xB4 */ {752, 1, 1, 4, 1, -8},
/* 0xB5 */ {753, 6, 9, 7, 1, -6},
/* 0xB6 */ {760, 6, 10, 6, 1, -8},
/* 0xB7 */ {768, 1, 1, 3, 1, -2},
/* 0xB8 */ {769, 3, 3, 4, 1, 1},
/* 0xB9 */ {771, 2, 6, 4, 1, -9},
/* 0xBA */ {773, 4, 5, 4, 0, -8},
/* 0xBB */ {776, 4, 4, 6, 1, -5},
/* 0xBC */ {778, 10, 9, 10, 1, -8},
/* 0xBD */ {790, 9, 9, 10, 1, -8},
/* 0xBE */ {801, 10, 9, 11, 0, -8},
/* 0xBF */ {813, 5, 9, 7, 1, -5},
/* 0xC0 */ {819, 8, 10, 8, 0, -9},
/* 0xC1 */ {829, 8, 10, 8, 0, -9},
/* 0xC2 */ {839, 8, 10, 8, 0, -9},
/* 0xC3 */ {849, 8, 10, 8, 0, -9},
/* 0xC4 */ {859, 8, 10, 8, 0, -9},
/* 0xC5 */ {869, 8, 10, 8, 0, -9},
/* 0xC6 */ {879, 10, 9, 12, 1, -8},
/* 0xC7 */ {891, 8, 12, 9, 0, -8},
/* 0xC8 */ {903, 6, 10, 8, 1, -9},
/* 0xC9 */ {911, 6, 10, 8, 1, -9},
/* 0xCA */ {919, 6, 10, 8, 1, -9},
/* 0xCB */ {927, 6, 10, 8, 1, -9},
/* 0xCC */ {935, 2, 10, 3, 0, -9},
/* 0xCD */ {938, 2, 10, 3, 1, -9},
/* 0xCE */ {941, 3, 10, 4, 0, -9},
/* 0xCF */ {945, 3, 10, 4, 0, -9},
/* 0xD0 */ {949, 8, 9, 8, 0, -8},
/* 0xD1 */ {958, 7, 10, 9, 1, -9},
/* 0xD2 */ {967, 9, 10, 9, 0, -9},
/* 0xD3 */ {979, 9, 10, 9, 0, -9},
/* 0xD4 */ {991, 9, 11, 9, 0, -10},
/* 0xD5 */ {1004, 9, 11, 9, 0, -10},
/* 0xD6 */ {1017, 9, 11, 9, 0, -10},
/* 0xD7 */ {1030, 5, 5, 7, 1, -5},
/* 0xD8 */ {1034, 9, 9, 9, 0, -8},
/* 0xD9 */ {1045, 7, 10, 9, 1, -9},
/* 0xDA */ {1054, 7, 10, 9, 1, -9},
/* 0xDB */ {1063, 7, 10, 9, 1, -9},
/* 0xDC */ {1072, 7, 10, 9, 1, -9},
/* 0xDD */ {1081, 7, 10, 8, 1, -9},
/* 0xDE */ {1090, 6, 9, 8, 1, -8},
/* 0xDF */ {1097, 6, 9, 7, 1, -8},
/* 0xE0 */ {1104, 7, 10, 7, 0, -9},
/* 0xE1 */ {1113, 7, 10, 7, 0, -9},
/* 0xE2 */ {1122, 7, 10, 7, 0, -9},
/* 0xE3 */ {1131, 7, 10, 7, 0, -9},
/* 0xE4 */ {1140, 7, 9, 7, 0, -8},
/* 0xE5 */ {1148, 7, 10, 7, 0, -9},
/* 0xE6 */ {1157, 10, 7, 10, 0, -6},
/* 0xE7 */ {1166, 6, 10, 6, 0, -6},
/* 0xE8 */ {1174, 6, 10, 6, 0, -9},
/* 0xE9 */ {1182, 6, 10, 6, 0, -9},
/* 0xEA */ {1190, 6, 10, 6, 0, -9},
/* 0xEB */ {1198, 6, 9, 6, 0, -8},
/* 0xEC */ {1205, 2, 10, 3, 0, -9},
/* 0xED */ {1208, 2, 10, 3, 1, -9},
/* 0xEE */ {1211, 3, 10, 3, 0, -9},
/* 0xEF */ {1215, 3, 9, 3, 0, -8},
/* 0xF0 */ {1219, 6, 9, 6, 0, -8},
/* 0xF1 */ {1226, 5, 10, 6, 1, -9},
/* 0xF2 */ {1233, 6, 10, 6, 0, -9},
/* 0xF3 */ {1241, 6, 10, 6, 0, -9},
/* 0xF4 */ {1249, 6, 10, 6, 0, -9},
/* 0xF5 */ {1257, 6, 10, 6, 0, -9},
/* 0xF6 */ {1265, 6, 9, 6, 0, -8},
/* 0xF7 */ {1272, 5, 5, 7, 1, -5},
/* 0xF8 */ {1276, 6, 7, 6, 0, -6},
/* 0xF9 */ {1282, 5, 9, 6, 1, -8},
/* 0xFA */ {1288, 5, 9, 6, 1, -8},
/* 0xFB */ {1294, 5, 10, 6, 1, -9},
/* 0xFC */ {1301, 5, 9, 6, 1, -8},
/* 0xFD */ {1307, 6, 12, 6, 0, -8},
/* 0xFE */ {1316, 5, 11, 7, 1, -8},
/* 0xFF */ {1323, 6, 12, 6, 0, -8},
};
const GFXfont FreeSans6pt_Win1252 PROGMEM = {(uint8_t *)FreeSans6pt_Win1252Bitmaps, (GFXglyph *)FreeSans6pt_Win1252Glyphs, 0x20,
0xFF, 14};

View File

@@ -0,0 +1,494 @@
#pragma once
const uint8_t FreeSans9pt_Win1250Bitmaps[] PROGMEM = {
/* ' ' 0x20 */
0xFF, 0xFF, 0xF0, 0xC0, /* '!' 0x21 */
0xDE, 0xF7, 0x20, /* '"' 0x22 */
0x09, 0x86, 0x41, 0x91, 0xFF, 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90, /* '#' 0x23 */
0x10, 0x1F, 0x14, 0xDA, 0x3D, 0x1E, 0x83, 0x40, 0x78, 0x17, 0x08, 0xF4, 0x7A, 0x35, 0x33, 0xF0, 0x40, 0x20, /* '$' 0x24 */
0x38, 0x10, 0xEC, 0x20, 0xC6, 0x20, 0xC6, 0x40, 0xC6, 0x40, 0x6C, 0x80, 0x39, 0x00, 0x01, 0x3C, 0x02, 0x77, 0x02, 0x63, 0x04,
0x63, 0x04, 0x77, 0x08, 0x3C, /* '%' 0x25 */
0x0E, 0x0C, 0xC3, 0x30, 0xCC, 0x1E, 0x03, 0x03, 0xC1, 0x9B, 0xC2, 0xF0, 0xEC, 0x19, 0x8F, 0x3C, 0x40, /* '&' 0x26 */
0xFE, /* ''' 0x27 */
0x13, 0x26, 0x6C, 0xCC, 0xCC, 0xC4, 0x66, 0x23, 0x10, /* '(' 0x28 */
0x8C, 0x46, 0x63, 0x33, 0x33, 0x32, 0x66, 0x4C, 0x80, /* ')' 0x29 */
0x25, 0x7E, 0xA5, 0x00, /* '*' 0x2A */
0x30, 0xC3, 0x3F, 0x30, 0xC3, 0x0C, /* '+' 0x2B */
0xD6, /* ',' 0x2C */
0xF0, /* '-' 0x2D */
0xC0, /* '.' 0x2E */
0x08, 0x44, 0x21, 0x10, 0x84, 0x42, 0x11, 0x08, 0x00, /* '/' 0x2F */
0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, /* '0' 0x30 */
0x11, 0x3F, 0x33, 0x33, 0x33, 0x33, 0x30, /* '1' 0x31 */
0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x1C, 0x1C, 0x1C, 0x18, 0x18, 0x10, 0x08, 0x07, 0xF8, /* '2' 0x32 */
0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x1C, 0x07, 0x03, 0xC3, 0xC3, 0x66, 0x3C, /* '3' 0x33 */
0x0C, 0x18, 0x71, 0x62, 0xC9, 0xA3, 0x46, 0xFE, 0x18, 0x30, 0x60, 0xC0, /* '4' 0x34 */
0x7F, 0x20, 0x10, 0x08, 0x08, 0x07, 0xF3, 0x8C, 0x03, 0x01, 0x80, 0xF0, 0x6C, 0x63, 0xE0, /* '5' 0x35 */
0x1E, 0x31, 0x98, 0x78, 0x0C, 0x06, 0xF3, 0x8D, 0x83, 0xC1, 0xE0, 0xD0, 0x6C, 0x63, 0xE0, /* '6' 0x36 */
0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30, /* '7' 0x37 */
0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1B, 0x18, 0xF8, 0xC6, 0xC1, 0xE0, 0xF0, 0x6C, 0x63, 0xE0, /* '8' 0x38 */
0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC2, 0x66, 0x3C, /* '9' 0x39 */
0xC0, 0x00, 0x30, /* ':' 0x3A */
0xC0, 0x00, 0x00, 0x64, 0xA0, /* ';' 0x3B */
0x00, 0x81, 0xC7, 0x8E, 0x0C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0x80, /* '<' 0x3C */
0xFF, 0x80, 0x00, 0x1F, 0xF0, /* '=' 0x3D */
0xE0, 0x1C, 0x03, 0x80, 0x30, 0x70, 0xE3, 0x81, 0x00, /* '>' 0x3E */
0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x18, 0x38, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x01, 0x80, /* '?' 0x3F */
0x03, 0xF0, 0x06, 0x0E, 0x06, 0x01, 0x86, 0x00, 0x66, 0x1D, 0xBB, 0x31, 0xCF, 0x18, 0xC7, 0x98, 0x63, 0xCC, 0x31, 0xE6, 0x11,
0xB3, 0x99, 0xCC, 0xF7, 0x86, 0x00, 0x01, 0x80, 0x00, 0x70, 0x40, 0x0F, 0xE0, /* '@' 0x40 */
0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0,
0x30, /* 'A' 0x41 */
0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 'B' 0x42 */
0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 'C' 0x43 */
0xFF, 0x18, 0x33, 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, 0x60, 0xCF, 0xF0, /* 'D' 0x44 */
0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, /* 'E' 0x45 */
0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 'F' 0x46 */
0x0F, 0x83, 0x0E, 0x60, 0x66, 0x03, 0xC0, 0x0C, 0x00, 0xC1, 0xFC, 0x03, 0xC0, 0x36, 0x03, 0x60, 0x73, 0x0F, 0x0F,
0x10, /* 'G' 0x47 */
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 'H' 0x48 */
0xFF, 0xFF, 0xFF, 0xC0, /* 'I' 0x49 */
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 0x8F, 0x1E, 0x27, 0x80, /* 'J' 0x4A */
0xC0, 0xF0, 0x6C, 0x33, 0x18, 0xCC, 0x37, 0x0F, 0xC3, 0x98, 0xC3, 0x30, 0xCC, 0x1B, 0x03, 0xC0, 0xC0, /* 'K' 0x4B */
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 'L' 0x4C */
0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71,
0x80, /* 'M' 0x4D */
0xE0, 0x7C, 0x0F, 0xC1, 0xE8, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, 0xE0, 0x7C, 0x0E, /* 'N' 0x4E */
0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8,
0x00, /* 'O' 0x4F */
0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 'P' 0x50 */
0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x6C, 0x60, 0xC0, 0xFB,
0x00, 0x08, /* 'Q' 0x51 */
0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0,
0x70, /* 'R' 0x52 */
0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 'S' 0x53 */
0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, /* 'T' 0x54 */
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xB0, 0x61, 0xF0, /* 'U' 0x55 */
0xC0, 0x6C, 0x0D, 0x81, 0x10, 0x63, 0x0C, 0x61, 0x04, 0x60, 0xCC, 0x19, 0x01, 0x60, 0x3C, 0x07, 0x00, 0x60, /* 'V' 0x56 */
0xC1, 0x81, 0x61, 0xC3, 0x61, 0xC3, 0x61, 0x43, 0x62, 0x62, 0x22, 0x66, 0x32, 0x26, 0x36, 0x26, 0x14, 0x34, 0x14, 0x34, 0x1C,
0x1C, 0x18, 0x1C, 0x08, 0x18, /* 'W' 0x57 */
0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E, 0x07, 0x00, 0xC0, 0x78, 0x32, 0x0C, 0xC6, 0x1B, 0x07, 0xC0, 0xC0, /* 'X' 0x58 */
0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06,
0x00, /* 'Y' 0x59 */
0xFF, 0xC0, 0x60, 0x30, 0x0C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x18, 0x06, 0x03, 0x00, 0xFF, 0xC0, /* 'Z' 0x5A */
0xFB, 0x6D, 0xB6, 0xDB, 0x6D, 0xB6, 0xE0, /* '[' 0x5B */
0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x80, /* '\' 0x5C */
0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xDB, 0xE0, /* ']' 0x5D */
0x30, 0x60, 0xA2, 0x44, 0xD8, 0xA1, 0x80, /* '^' 0x5E */
0xFF, 0xC0, /* '_' 0x5F */
0xC6, 0x30, /* '`' 0x60 */
0x7E, 0x71, 0xB0, 0xC0, 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, /* 'a' 0x61 */
0xC0, 0x60, 0x30, 0x1B, 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, /* 'b' 0x62 */
0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'c' 0x63 */
0x03, 0x03, 0x03, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, /* 'd' 0x64 */
0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'e' 0x65 */
0x36, 0x6F, 0x66, 0x66, 0x66, 0x66, 0x60, /* 'f' 0x66 */
0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC6, 0x7C, /* 'g' 0x67 */
0xC0, 0xC0, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'h' 0x68 */
0xC3, 0xFF, 0xFF, 0xC0, /* 'i' 0x69 */
0x30, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, /* 'j' 0x6A */
0xC0, 0xC0, 0xC0, 0xC2, 0xC4, 0xCC, 0xD8, 0xF8, 0xEC, 0xC4, 0xC6, 0xC3, 0xC3, /* 'k' 0x6B */
0xFF, 0xFF, 0xFF, 0xC0, /* 'l' 0x6C */
0xDE, 0xF7, 0x1C, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xC0, /* 'm' 0x6D */
0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'n' 0x6E */
0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 'o' 0x6F */
0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, /* 'p' 0x70 */
0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0x03, /* 'q' 0x71 */
0xDF, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, /* 'r' 0x72 */
0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 's' 0x73 */
0x66, 0xF6, 0x66, 0x66, 0x66, 0x67, /* 't' 0x74 */
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 'u' 0x75 */
0xC1, 0xA0, 0x98, 0xCC, 0x42, 0x21, 0xB0, 0xD0, 0x28, 0x1C, 0x0C, 0x00, /* 'v' 0x76 */
0xC6, 0x1E, 0x38, 0x91, 0xC4, 0xCA, 0x66, 0xD3, 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, 0x00, /* 'w' 0x77 */
0x87, 0x89, 0xB1, 0xC3, 0x07, 0x1E, 0x26, 0xC5, 0x0C, /* 'x' 0x78 */
0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 'y' 0x79 */
0xFE, 0x0C, 0x30, 0xC1, 0x86, 0x18, 0x20, 0xC1, 0xFC, /* 'z' 0x7A */
0x36, 0x66, 0x66, 0x6E, 0xCE, 0x66, 0x66, 0x66, 0x30, /* '{' 0x7B */
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, /* '|' 0x7C */
0xC6, 0x66, 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0xC0, /* '}' 0x7D */
0x61, 0x24, 0x38, /* '~' 0x7E */
0xFF, 0xFC, 0x00, 0x63, 0xE3, 0x31, 0x99, 0x04, 0xC8, 0x66, 0x06, 0x30, 0x61, 0x83, 0x0C, 0x18, 0x60, 0x03, 0x06, 0x18, 0x00,
0xFF, 0xFC, /* 0x7F */
0x07, 0xC6, 0x13, 0x00, 0xC0, 0x60, 0x3F, 0xE6, 0x03, 0xFC, 0x60, 0x0C, 0x03, 0x00, 0x61, 0x07, 0xC0, /* 0x80 */
/* 0x81 */
0xDC, /* 0x82 */
/* 0x83 */
0xDA, 0x76, /* 0x84 */
0xCC, 0xC0, /* 0x85 */
0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, /* 0x86 */
0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, /* 0x87 */
/* 0x88 */
0x70, 0x80, 0x22, 0x20, 0x08, 0x90, 0x02, 0x24, 0x00, 0x72, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x10, 0x00, 0x09, 0xC7, 0x84,
0x8B, 0x31, 0x22, 0x84, 0x88, 0xB3, 0x21, 0xC7, 0x80, /* 0x89 */
0x1B, 0x03, 0x83, 0xF1, 0x86, 0xC0, 0xF0, 0x3C, 0x01, 0xE0, 0x1F, 0x00, 0xE0, 0x0F, 0x03, 0xC0, 0xD8, 0x63, 0xF0, /* 0x8A */
0x69, /* 0x8B */
0x06, 0x03, 0x03, 0xF1, 0x86, 0xC0, 0xF0, 0x3C, 0x01, 0xE0, 0x1F, 0x00, 0xE0, 0x0F, 0x03, 0xC0, 0xD8, 0x63, 0xF0, /* 0x8C */
0x33, 0x0F, 0x3F, 0xE1, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, /* 0x8D */
0x1B, 0x03, 0x8F, 0xFC, 0x06, 0x03, 0x00, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x03, 0x01, 0x80, 0x60, 0x30, 0x0F, 0xFC, /* 0x8E */
0x0C, 0x06, 0x0F, 0xFC, 0x06, 0x03, 0x00, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x03, 0x01, 0x80, 0x60, 0x30, 0x0F, 0xFC, /* 0x8F */
/* 0x90 */
0x6B, /* 0x91 */
0xD6, /* 0x92 */
0x4C, 0xA5, 0xB0, /* 0x93 */
0xDA, 0x53, 0x20, /* 0x94 */
0x6F, 0xFF, 0x60, /* 0x95 */
0xFE, /* 0x96 */
0xFF, 0xFF, /* 0x97 */
/* 0x98 */
0xFC, 0xE1, 0xCC, 0x38, 0x73, 0x0E, 0x1C, 0xC3, 0x8F, 0x30, 0xD2, 0xCC, 0x34, 0xB3, 0x0D, 0x6C, 0xC3, 0x53, 0x30, 0xCC, 0xCC,
0x33, 0x30, /* 0x99 */
0x24, 0x3C, 0x18, 0x7E, 0xE3, 0xC0, 0xC0, 0x60, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 0x9A */
0x96, /* 0x9B */
0x0C, 0x18, 0x10, 0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 0x9C */
0x0D, 0xA7, 0x3C, 0x61, 0x86, 0x18, 0x61, 0x86, 0x18, 0x70, /* 0x9D */
0x48, 0xF0, 0xC7, 0xF0, 0x61, 0x86, 0x0C, 0x30, 0xC1, 0x06, 0x0F, 0xE0, /* 0x9E */
0x0C, 0x10, 0x47, 0xF0, 0x61, 0x86, 0x0C, 0x30, 0xC1, 0x06, 0x0F, 0xE0, /* 0x9F */
/* 0xA0 */
0x8A, 0x9C, /* 0xA1 */
0x85, 0xE0, /* 0xA2 */
0x60, 0x30, 0x18, 0x0C, 0x86, 0xC3, 0xC1, 0xC1, 0xC0, 0xE0, 0x30, 0x18, 0x0C, 0x07, 0xF8, /* 0xA3 */
0xFF, 0xDF, 0x1E, 0x3E, 0xFF, 0xC0, /* 0xA4 */
0x06, 0x00, 0xF0, 0x0F, 0x01, 0x30, 0x13, 0x81, 0x38, 0x21, 0x82, 0x1C, 0x3F, 0xC6, 0x04, 0x60, 0x66, 0x06, 0xC0, 0x30, 0x06,
0x00, 0xC0, 0x0C, 0x00, 0x70, /* 0xA5 */
0xFF, 0xFC, 0x0F, 0xFF, 0xC0, /* 0xA6 */
0x0C, 0x09, 0x0C, 0xC6, 0x63, 0x81, 0xE3, 0x19, 0x87, 0xE1, 0xB8, 0xC6, 0x41, 0xC0, 0x73, 0x19, 0x8C, 0x66, 0x1E,
0x00, /* 0xA7 */
0xCC, /* 0xA8 */
0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9B, 0xC6, 0xD9, 0x8F, 0x60, 0x3D, 0x00, 0xF4, 0x03, 0xD8, 0x0D, 0xE6, 0x67, 0xF3, 0x86, 0x18,
0x0F, 0xC0, /* 0xA9 */
0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x02, 0x00, 0xE0, 0x18, 0x1C,
0x00, /* 0xAA */
0x22, 0xCF, 0x26, 0x46, 0x64, 0x40, /* 0xAB */
0xFF, 0x80, 0xC0, 0x60, 0x30, 0x18, /* 0xAC */
/* 0xAD */
0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9F, 0xE6, 0xD0, 0x8F, 0x42, 0x3D, 0xF0, 0xF4, 0x23, 0xD0, 0x8D, 0xC2, 0x67, 0x0B, 0x86, 0x18,
0x0F, 0xC0, /* 0xAE */
0x0C, 0x00, 0x0F, 0xFC, 0x06, 0x03, 0x00, 0xC0, 0x60, 0x30, 0x1C, 0x06, 0x03, 0x01, 0x80, 0x60, 0x30, 0x0F, 0xFC, /* 0xAF */
0x74, 0x63, 0x17, 0x00, /* 0xB0 */
0x0C, 0x06, 0x03, 0x07, 0xE0, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x3F, 0xE0, /* 0xB1 */
0x6C, 0xC7, /* 0xB2 */
0x66, 0x66, 0x67, 0x6E, 0x66, 0x66, 0x60, /* 0xB3 */
0x36, 0xC0, /* 0xB4 */
0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0x86, 0xE7, 0x7D, 0xF0, 0x18, 0x0C, 0x00, /* 0xB5 */
0x3F, 0x7E, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0x72, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, /* 0xB6 */
0xE0, /* 0xB7 */
0x21, 0xC7, 0xE0, /* 0xB8 */
0x7E, 0x38, 0xCC, 0x30, 0x0C, 0x0F, 0x1E, 0xCC, 0x33, 0x0C, 0xC7, 0x1E, 0xE0, 0x10, 0x0C, 0x03, 0x00, 0x70, /* 0xB9 */
0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xC3, 0x7E, 0x10, 0x1C, 0x0C, 0x38, /* 0xBA */
0x89, 0x98, 0x99, 0x3C, 0xD1, 0x00, /* 0xBB */
0xC6, 0xC4, 0xC8, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 0xBC */
0x6F, 0x69, 0x00, /* 0xBD */
0xDE, 0xB9, 0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00, /* 0xBE */
0x30, 0x03, 0xF8, 0x30, 0xC3, 0x06, 0x18, 0x60, 0x83, 0x07, 0xF0, /* 0xBF */
0x06, 0x00, 0xC0, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06,
0xC0, 0x70, /* 0xC0 */
0x06, 0x03, 0x00, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC1 */
0x0C, 0x04, 0x80, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC2 */
0x21, 0x07, 0x80, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC3 */
0x33, 0x00, 0x00, 0xC0, 0x78, 0x1E, 0x04, 0x83, 0x30, 0xCC, 0x33, 0x1F, 0xE6, 0x19, 0x02, 0xC0, 0xF0, 0x30, /* 0xC4 */
0x30, 0x60, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 0xC5 */
0x06, 0x01, 0x80, 0x00, 0x0F, 0xC3, 0x0C, 0xC0, 0xD0, 0x1E, 0x00, 0xC0, 0x18, 0x03, 0x01, 0xA0, 0x36, 0x0C, 0x61, 0x87,
0xC0, /* 0xC6 */
0x1F, 0x06, 0x19, 0x83, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0xE1, 0xF0, 0x08, 0x01, 0xC0,
0x18, 0x0E, 0x00, /* 0xC7 */
0x19, 0x81, 0xE0, 0x00, 0x0F, 0xC3, 0x0C, 0xC0, 0xF0, 0x1E, 0x00, 0xC0, 0x18, 0x03, 0x01, 0xA0, 0x36, 0x0C, 0x61, 0x87,
0xC0, /* 0xC8 */
0x0C, 0x0C, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xC9 */
0xFF, 0xD8, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x3F, 0xF6, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0F, 0xFC, 0x01, 0x80, 0x60,
0x0C, 0x00, 0xE0, /* 0xCA */
0x33, 0x00, 0x3F, 0xF8, 0x0C, 0x06, 0x03, 0x01, 0xFE, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xCB */
0x33, 0x0F, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFE, /* 0xCC */
0x78, 0x36, 0xDB, 0x6D, 0xB6, 0xC0, /* 0xCD */
0x76, 0xC0, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, /* 0xCE */
0x66, 0x0F, 0x00, 0x03, 0xF8, 0xC3, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC1, 0xB0, 0xEF, 0xE0, /* 0xCF */
0x7F, 0x0C, 0x31, 0x83, 0x30, 0x36, 0x06, 0xC0, 0xFE, 0x1B, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x30, 0xE7, 0xF0, /* 0xD0 */
0x03, 0x01, 0x83, 0x81, 0xF0, 0x3F, 0x07, 0xA0, 0xF6, 0x1E, 0x63, 0xC4, 0x78, 0xCF, 0x0D, 0xE1, 0xBC, 0x1F, 0x81,
0xC0, /* 0xD1 */
0x19, 0x81, 0xE3, 0x81, 0xF0, 0x3F, 0x07, 0xA0, 0xF6, 0x1E, 0x63, 0xC4, 0x78, 0xCF, 0x0D, 0xE1, 0xBC, 0x1F, 0x81,
0xC0, /* 0xD2 */
0x03, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C,
0x0F, 0x00, /* 0xD3 */
0x0F, 0x01, 0x98, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C,
0x0F, 0x00, /* 0xD4 */
0x0D, 0x81, 0xB0, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C,
0x0F, 0x00, /* 0xD5 */
0x19, 0x81, 0x98, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C,
0x0F, 0x00, /* 0xD6 */
0x83, 0x89, 0xA1, 0x83, 0x89, 0xA1, 0x80, /* 0xD7 */
0x33, 0x01, 0xE0, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06,
0xC0, 0x70, /* 0xD8 */
0x04, 0x01, 0x43, 0x11, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E,
0x00, /* 0xD9 */
0x06, 0x01, 0x83, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E,
0x00, /* 0xDA */
0x0D, 0x83, 0x63, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E,
0x00, /* 0xDB */
0x1B, 0x00, 0x03, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E,
0x00, /* 0xDC */
0x03, 0x0C, 0x63, 0x60, 0x63, 0x0C, 0x30, 0xC1, 0x98, 0x1D, 0x80, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
0x60, /* 0xDD */
0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x40, 0x3C, 0x06, 0x1E,
0x00, /* 0xDE */
0x3C, 0x33, 0x30, 0xD8, 0x6C, 0x36, 0x33, 0x39, 0x86, 0xC1, 0xE0, 0xF0, 0x78, 0x6D, 0xE0, /* 0xDF */
0x19, 0x89, 0xBE, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00, /* 0xE0 */
0x0C, 0x04, 0x04, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE1 */
0x10, 0x14, 0x1B, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE2 */
0x66, 0x1E, 0x00, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE3 */
0x66, 0x00, 0x1F, 0x9C, 0x6C, 0x30, 0x18, 0x3C, 0xF6, 0xC3, 0x61, 0xB1, 0xCF, 0x70, /* 0xE4 */
0x78, 0x36, 0xDB, 0x6D, 0xB6, 0xD8, /* 0xE5 */
0x0C, 0x08, 0x10, 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE6 */
0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, 0x10, 0x1C, 0x0C, 0x38, /* 0xE7 */
0x44, 0x28, 0x38, 0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE8 */
0x0C, 0x08, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE9 */
0x3C, 0x62, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3E, 0x04, 0x0C, 0x0C, 0x06, /* 0xEA */
0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xEB */
0x64, 0x2C, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xEC */
0x7A, 0x6D, 0xB6, 0xDB, 0x6C, /* 0xED */
0x69, 0x06, 0x66, 0x66, 0x66, 0x66, 0x60, /* 0xEE */
0x03, 0x30, 0x32, 0x03, 0x43, 0xB0, 0x67, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x06, 0x70, 0x3B,
0x00, /* 0xEF */
0x03, 0x07, 0xC0, 0xC7, 0x66, 0x76, 0x1B, 0x0D, 0x86, 0xC3, 0x61, 0xB0, 0xCC, 0xE3, 0xB0, /* 0xF0 */
0x0C, 0x18, 0x00, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xF1 */
0x66, 0x3C, 0x00, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xF2 */
0x0C, 0x18, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF3 */
0x18, 0x24, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF4 */
0x36, 0x6C, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF5 */
0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF6 */
0x18, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x30, /* 0xF7 */
0xDB, 0x81, 0xBE, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00, /* 0xF8 */
0x10, 0x28, 0x10, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xF9 */
0x06, 0x0C, 0x18, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFA */
0x36, 0x6C, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFB */
0x66, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFC */
0x06, 0x04, 0x08, 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xFD */
0x63, 0x3C, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xE2, 0x1C, 0x6F, /* 0xFE */
0xC0, /* 0xFF */
};
const GFXglyph FreeSans9pt_Win1250Glyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 5, 0, 0},
/* '!' 0x21 */ {0, 2, 13, 6, 2, -12},
/* '"' 0x22 */ {4, 5, 4, 6, 1, -12},
/* '#' 0x23 */ {7, 10, 12, 10, 0, -11},
/* '$' 0x24 */ {22, 9, 16, 10, 1, -13},
/* '%' 0x25 */ {40, 16, 13, 16, 1, -12},
/* '&' 0x26 */ {66, 10, 13, 12, 1, -12},
/* ''' 0x27 */ {83, 2, 4, 4, 1, -12},
/* '(' 0x28 */ {84, 4, 17, 6, 1, -12},
/* ')' 0x29 */ {93, 4, 17, 6, 1, -12},
/* '*' 0x2A */ {102, 5, 5, 7, 1, -12},
/* '+' 0x2B */ {106, 6, 8, 11, 3, -7},
/* ',' 0x2C */ {112, 2, 4, 5, 2, 0},
/* '-' 0x2D */ {113, 4, 1, 6, 1, -4},
/* '.' 0x2E */ {114, 2, 1, 5, 1, 0},
/* '/' 0x2F */ {115, 5, 13, 5, 0, -12},
/* '0' 0x30 */ {124, 8, 13, 10, 1, -12},
/* '1' 0x31 */ {137, 4, 13, 10, 3, -12},
/* '2' 0x32 */ {144, 9, 13, 10, 1, -12},
/* '3' 0x33 */ {159, 8, 13, 10, 1, -12},
/* '4' 0x34 */ {172, 7, 13, 10, 2, -12},
/* '5' 0x35 */ {184, 9, 13, 10, 1, -12},
/* '6' 0x36 */ {199, 9, 13, 10, 1, -12},
/* '7' 0x37 */ {214, 8, 13, 10, 0, -12},
/* '8' 0x38 */ {227, 9, 13, 10, 1, -12},
/* '9' 0x39 */ {242, 8, 13, 10, 1, -12},
/* ':' 0x3A */ {255, 2, 10, 5, 1, -9},
/* ';' 0x3B */ {258, 3, 12, 5, 1, -8},
/* '<' 0x3C */ {263, 9, 9, 11, 1, -8},
/* '=' 0x3D */ {274, 9, 4, 11, 1, -5},
/* '>' 0x3E */ {279, 9, 8, 11, 1, -7},
/* '?' 0x3F */ {288, 9, 13, 10, 1, -12},
/* '@' 0x40 */ {303, 17, 16, 18, 1, -12},
/* 'A' 0x41 */ {337, 12, 13, 12, 0, -12},
/* 'B' 0x42 */ {357, 11, 13, 12, 1, -12},
/* 'C' 0x43 */ {375, 11, 13, 13, 1, -12},
/* 'D' 0x44 */ {393, 11, 13, 13, 1, -12},
/* 'E' 0x45 */ {411, 9, 13, 11, 1, -12},
/* 'F' 0x46 */ {426, 8, 13, 11, 1, -12},
/* 'G' 0x47 */ {439, 12, 13, 14, 1, -12},
/* 'H' 0x48 */ {459, 11, 13, 13, 1, -12},
/* 'I' 0x49 */ {477, 2, 13, 5, 2, -12},
/* 'J' 0x4A */ {481, 7, 13, 10, 1, -12},
/* 'K' 0x4B */ {493, 10, 13, 12, 1, -12},
/* 'L' 0x4C */ {510, 8, 13, 10, 1, -12},
/* 'M' 0x4D */ {523, 13, 13, 15, 1, -12},
/* 'N' 0x4E */ {545, 11, 13, 13, 1, -12},
/* 'O' 0x4F */ {563, 13, 13, 14, 1, -12},
/* 'P' 0x50 */ {585, 10, 13, 12, 1, -12},
/* 'Q' 0x51 */ {602, 13, 14, 14, 1, -12},
/* 'R' 0x52 */ {625, 12, 13, 13, 1, -12},
/* 'S' 0x53 */ {645, 10, 13, 12, 1, -12},
/* 'T' 0x54 */ {662, 9, 13, 11, 1, -12},
/* 'U' 0x55 */ {677, 11, 13, 13, 1, -12},
/* 'V' 0x56 */ {695, 11, 13, 11, 0, -12},
/* 'W' 0x57 */ {713, 16, 13, 17, 0, -12},
/* 'X' 0x58 */ {739, 10, 13, 12, 1, -12},
/* 'Y' 0x59 */ {756, 12, 13, 12, 0, -12},
/* 'Z' 0x5A */ {776, 10, 13, 11, 1, -12},
/* '[' 0x5B */ {793, 3, 17, 5, 1, -12},
/* '\' 0x5C */ {800, 5, 13, 5, 0, -12},
/* ']' 0x5D */ {809, 3, 17, 5, 0, -12},
/* '^' 0x5E */ {816, 7, 7, 8, 1, -12},
/* '_' 0x5F */ {823, 10, 1, 10, 0, 3},
/* '`' 0x60 */ {825, 4, 3, 5, 0, -12},
/* 'a' 0x61 */ {827, 9, 10, 10, 1, -9},
/* 'b' 0x62 */ {839, 9, 13, 10, 1, -12},
/* 'c' 0x63 */ {854, 8, 10, 9, 1, -9},
/* 'd' 0x64 */ {864, 8, 13, 10, 1, -12},
/* 'e' 0x65 */ {877, 8, 10, 10, 1, -9},
/* 'f' 0x66 */ {887, 4, 13, 5, 1, -12},
/* 'g' 0x67 */ {894, 8, 14, 10, 1, -9},
/* 'h' 0x68 */ {908, 8, 13, 10, 1, -12},
/* 'i' 0x69 */ {921, 2, 13, 4, 1, -12},
/* 'j' 0x6A */ {925, 4, 17, 4, 0, -12},
/* 'k' 0x6B */ {934, 8, 13, 9, 1, -12},
/* 'l' 0x6C */ {947, 2, 13, 4, 1, -12},
/* 'm' 0x6D */ {951, 13, 10, 15, 1, -9},
/* 'n' 0x6E */ {968, 8, 10, 10, 1, -9},
/* 'o' 0x6F */ {978, 8, 10, 10, 1, -9},
/* 'p' 0x70 */ {988, 9, 13, 10, 1, -9},
/* 'q' 0x71 */ {1003, 8, 13, 10, 1, -9},
/* 'r' 0x72 */ {1016, 5, 10, 6, 1, -9},
/* 's' 0x73 */ {1023, 8, 10, 9, 1, -9},
/* 't' 0x74 */ {1033, 4, 12, 5, 1, -11},
/* 'u' 0x75 */ {1039, 8, 10, 10, 1, -9},
/* 'v' 0x76 */ {1049, 9, 10, 9, 0, -9},
/* 'w' 0x77 */ {1061, 13, 10, 13, 0, -9},
/* 'x' 0x78 */ {1078, 7, 10, 9, 1, -9},
/* 'y' 0x79 */ {1087, 8, 14, 9, 0, -9},
/* 'z' 0x7A */ {1101, 7, 10, 9, 1, -9},
/* '{' 0x7B */ {1110, 4, 17, 6, 1, -12},
/* '|' 0x7C */ {1119, 2, 17, 4, 2, -12},
/* '}' 0x7D */ {1124, 4, 17, 6, 1, -12},
/* '~' 0x7E */ {1133, 7, 3, 9, 1, -7},
/* 0x7F */ {1136, 13, 14, 15, 1, -12},
/* 0x80 */ {1159, 10, 13, 12, 1, -12},
/* 0x81 */ {1176, 0, 0, 0, 0, 0},
/* 0x82 */ {1176, 2, 3, 5, 1, 0},
/* 0x83 */ {1177, 0, 0, 0, 0, 0},
/* 0x84 */ {1177, 5, 3, 7, 1, 0},
/* 0x85 */ {1179, 10, 1, 12, 1, 0},
/* 0x86 */ {1181, 8, 16, 10, 1, -12},
/* 0x87 */ {1197, 8, 16, 10, 1, -12},
/* 0x88 */ {1213, 0, 0, 0, 0, 0},
/* 0x89 */ {1213, 18, 13, 18, 0, -12},
/* 0x8A */ {1243, 10, 15, 12, 1, -14},
/* 0x8B */ {1262, 2, 4, 4, 1, -6},
/* 0x8C */ {1263, 10, 15, 12, 1, -14},
/* 0x8D */ {1282, 9, 15, 11, 1, -14},
/* 0x8E */ {1299, 10, 15, 11, 1, -14},
/* 0x8F */ {1318, 10, 15, 11, 1, -14},
/* 0x90 */ {1337, 0, 0, 0, 0, 0},
/* 0x91 */ {1337, 2, 4, 4, 2, -12},
/* 0x92 */ {1338, 2, 4, 4, 1, -12},
/* 0x93 */ {1339, 5, 4, 7, 2, -12},
/* 0x94 */ {1342, 5, 4, 7, 1, -12},
/* 0x95 */ {1345, 4, 5, 7, 1, -8},
/* 0x96 */ {1348, 7, 1, 9, 1, -4},
/* 0x97 */ {1349, 16, 1, 18, 1, -4},
/* 0x98 */ {1351, 0, 0, 0, 0, 0},
/* 0x99 */ {1351, 18, 10, 18, 1, -13},
/* 0x9A */ {1374, 8, 13, 9, 1, -12},
/* 0x9B */ {1387, 2, 4, 5, 2, -6},
/* 0x9C */ {1388, 8, 13, 9, 1, -12},
/* 0x9D */ {1401, 6, 13, 8, 1, -12},
/* 0x9E */ {1411, 7, 13, 9, 1, -12},
/* 0x9F */ {1423, 7, 13, 9, 1, -12},
/* 0xA0 */ {1435, 0, 0, 5, 0, 0},
/* 0xA1 */ {1435, 5, 3, 6, 0, -12},
/* 0xA2 */ {1437, 6, 2, 6, 0, -12},
/* 0xA3 */ {1439, 9, 13, 11, 1, -12},
/* 0xA4 */ {1454, 7, 6, 10, 2, -8},
/* 0xA5 */ {1460, 12, 17, 12, 1, -12},
/* 0xA6 */ {1486, 2, 17, 5, 2, -12},
/* 0xA7 */ {1491, 9, 17, 10, 1, -12},
/* 0xA8 */ {1511, 6, 1, 6, 0, -11},
/* 0xA9 */ {1512, 14, 13, 14, 1, -12},
/* 0xAA */ {1535, 10, 17, 12, 1, -12},
/* 0xAB */ {1557, 7, 6, 9, 1, -7},
/* 0xAC */ {1563, 9, 5, 11, 2, -5},
/* 0xAD */ {1569, 0, 0, 0, 0, 0},
/* 0xAE */ {1569, 14, 13, 14, 1, -12},
/* 0xAF */ {1592, 10, 15, 11, 1, -14},
/* 0xB0 */ {1611, 5, 5, 11, 3, -11},
/* 0xB1 */ {1615, 9, 11, 11, 1, -10},
/* 0xB2 */ {1628, 4, 4, 6, 1, 1},
/* 0xB3 */ {1630, 4, 13, 5, 1, -12},
/* 0xB4 */ {1637, 4, 3, 6, 2, -12},
/* 0xB5 */ {1639, 9, 13, 10, 1, -9},
/* 0xB6 */ {1654, 8, 16, 10, 2, -12},
/* 0xB7 */ {1670, 3, 1, 5, 1, -4},
/* 0xB8 */ {1671, 5, 4, 6, 1, 1},
/* 0xB9 */ {1674, 10, 14, 10, 1, -9},
/* 0xBA */ {1692, 8, 14, 9, 1, -9},
/* 0xBB */ {1706, 7, 6, 9, 1, -7},
/* 0xBC */ {1712, 8, 13, 10, 1, -12},
/* 0xBD */ {1725, 6, 3, 6, 0, -12},
/* 0xBE */ {1728, 5, 13, 7, 1, -12},
/* 0xBF */ {1737, 7, 12, 9, 1, -11},
/* 0xC0 */ {1748, 12, 15, 13, 1, -14},
/* 0xC1 */ {1771, 10, 14, 12, 1, -13},
/* 0xC2 */ {1789, 10, 14, 12, 1, -13},
/* 0xC3 */ {1807, 10, 14, 12, 1, -13},
/* 0xC4 */ {1825, 10, 14, 12, 1, -13},
/* 0xC5 */ {1843, 8, 14, 10, 1, -13},
/* 0xC6 */ {1857, 11, 15, 13, 1, -14},
/* 0xC7 */ {1878, 11, 17, 13, 1, -12},
/* 0xC8 */ {1902, 11, 15, 13, 1, -14},
/* 0xC9 */ {1923, 9, 14, 11, 1, -13},
/* 0xCA */ {1939, 11, 17, 12, 1, -12},
/* 0xCB */ {1963, 9, 14, 11, 1, -13},
/* 0xCC */ {1979, 9, 15, 11, 1, -14},
/* 0xCD */ {1996, 3, 14, 5, 1, -13},
/* 0xCE */ {2002, 5, 14, 5, 0, -13},
/* 0xCF */ {2011, 10, 15, 13, 2, -14},
/* 0xD0 */ {2030, 11, 13, 13, 1, -12},
/* 0xD1 */ {2048, 11, 14, 13, 1, -13},
/* 0xD2 */ {2068, 11, 14, 13, 1, -13},
/* 0xD3 */ {2088, 12, 15, 13, 1, -14},
/* 0xD4 */ {2111, 12, 15, 13, 1, -14},
/* 0xD5 */ {2134, 12, 15, 13, 1, -14},
/* 0xD6 */ {2157, 12, 15, 13, 1, -14},
/* 0xD7 */ {2180, 7, 7, 11, 2, -7},
/* 0xD8 */ {2187, 12, 15, 13, 1, -14},
/* 0xD9 */ {2210, 11, 14, 13, 1, -13},
/* 0xDA */ {2230, 11, 14, 13, 1, -13},
/* 0xDB */ {2250, 11, 14, 13, 1, -13},
/* 0xDC */ {2270, 11, 14, 13, 1, -13},
/* 0xDD */ {2290, 12, 14, 12, 0, -13},
/* 0xDE */ {2311, 9, 17, 11, 1, -12},
/* 0xDF */ {2331, 9, 13, 11, 1, -12},
/* 0xE0 */ {2346, 5, 13, 6, 1, -12},
/* 0xE1 */ {2355, 9, 13, 10, 1, -12},
/* 0xE2 */ {2370, 9, 13, 10, 1, -12},
/* 0xE3 */ {2385, 9, 13, 10, 1, -12},
/* 0xE4 */ {2400, 9, 12, 10, 1, -11},
/* 0xE5 */ {2414, 3, 15, 4, 0, -14},
/* 0xE6 */ {2420, 8, 13, 9, 1, -12},
/* 0xE7 */ {2433, 8, 14, 9, 1, -9},
/* 0xE8 */ {2447, 8, 13, 9, 1, -12},
/* 0xE9 */ {2460, 8, 13, 10, 1, -12},
/* 0xEA */ {2473, 8, 14, 10, 1, -9},
/* 0xEB */ {2487, 8, 12, 10, 1, -11},
/* 0xEC */ {2499, 8, 13, 10, 1, -12},
/* 0xED */ {2512, 3, 13, 4, 1, -12},
/* 0xEE */ {2517, 4, 13, 5, 0, -12},
/* 0xEF */ {2524, 12, 13, 12, 1, -12},
/* 0xF0 */ {2544, 9, 13, 10, 1, -12},
/* 0xF1 */ {2559, 8, 13, 10, 1, -12},
/* 0xF2 */ {2572, 8, 13, 10, 1, -12},
/* 0xF3 */ {2585, 8, 13, 10, 1, -12},
/* 0xF4 */ {2598, 8, 13, 10, 1, -12},
/* 0xF5 */ {2611, 8, 13, 10, 1, -12},
/* 0xF6 */ {2624, 8, 12, 10, 1, -11},
/* 0xF7 */ {2636, 9, 8, 11, 1, -7},
/* 0xF8 */ {2645, 5, 13, 6, 1, -12},
/* 0xF9 */ {2654, 8, 13, 10, 1, -12},
/* 0xFA */ {2667, 8, 13, 10, 1, -12},
/* 0xFB */ {2680, 8, 13, 10, 1, -12},
/* 0xFC */ {2693, 8, 12, 10, 1, -11},
/* 0xFD */ {2705, 8, 17, 9, 0, -12},
/* 0xFE */ {2722, 5, 16, 5, 1, -11},
/* 0xFF */ {2732, 2, 1, 6, 2, -11},
};
const GFXfont FreeSans9pt_Win1250 PROGMEM = {(uint8_t *)FreeSans9pt_Win1250Bitmaps, (GFXglyph *)FreeSans9pt_Win1250Glyphs, 0x20,
0xFF, 21};

View File

@@ -0,0 +1,493 @@
#pragma once
const uint8_t FreeSans9pt_Win1251Bitmaps[] PROGMEM = {
/* ' ' 0x20 */
0xFF, 0xFF, 0xF0, 0xC0, /* '!' 0x21 */
0xDE, 0xF7, 0x20, /* '"' 0x22 */
0x09, 0x86, 0x41, 0x91, 0xFF, 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90, /* '#' 0x23 */
0x10, 0x1F, 0x14, 0xDA, 0x3D, 0x1E, 0x83, 0x40, 0x78, 0x17, 0x08, 0xF4, 0x7A, 0x35, 0x33, 0xF0, 0x40, 0x20, /* '$' 0x24 */
0x38, 0x10, 0xEC, 0x20, 0xC6, 0x20, 0xC6, 0x40, 0xC6, 0x40, 0x6C, 0x80, 0x39, 0x00, 0x01, 0x3C, 0x02, 0x77, 0x02, 0x63, 0x04,
0x63, 0x04, 0x77, 0x08, 0x3C, /* '%' 0x25 */
0x0E, 0x0C, 0xC3, 0x30, 0xCC, 0x1E, 0x03, 0x03, 0xC1, 0x9B, 0xC2, 0xF0, 0xEC, 0x19, 0x8F, 0x3C, 0x40, /* '&' 0x26 */
0xFE, /* ''' 0x27 */
0x13, 0x26, 0x6C, 0xCC, 0xCC, 0xC4, 0x66, 0x23, 0x10, /* '(' 0x28 */
0x8C, 0x46, 0x63, 0x33, 0x33, 0x32, 0x66, 0x4C, 0x80, /* ')' 0x29 */
0x25, 0x7E, 0xA5, 0x00, /* '*' 0x2A */
0x30, 0xC3, 0x3F, 0x30, 0xC3, 0x0C, /* '+' 0x2B */
0xD6, /* ',' 0x2C */
0xF0, /* '-' 0x2D */
0xC0, /* '.' 0x2E */
0x08, 0x44, 0x21, 0x10, 0x84, 0x42, 0x11, 0x08, 0x00, /* '/' 0x2F */
0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, /* '0' 0x30 */
0x11, 0x3F, 0x33, 0x33, 0x33, 0x33, 0x30, /* '1' 0x31 */
0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x1C, 0x1C, 0x1C, 0x18, 0x18, 0x10, 0x08, 0x07, 0xF8, /* '2' 0x32 */
0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x1C, 0x07, 0x03, 0xC3, 0xC3, 0x66, 0x3C, /* '3' 0x33 */
0x0C, 0x18, 0x71, 0x62, 0xC9, 0xA3, 0x46, 0xFE, 0x18, 0x30, 0x60, 0xC0, /* '4' 0x34 */
0x7F, 0x20, 0x10, 0x08, 0x08, 0x07, 0xF3, 0x8C, 0x03, 0x01, 0x80, 0xF0, 0x6C, 0x63, 0xE0, /* '5' 0x35 */
0x1E, 0x31, 0x98, 0x78, 0x0C, 0x06, 0xF3, 0x8D, 0x83, 0xC1, 0xE0, 0xD0, 0x6C, 0x63, 0xE0, /* '6' 0x36 */
0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30, /* '7' 0x37 */
0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1B, 0x18, 0xF8, 0xC6, 0xC1, 0xE0, 0xF0, 0x6C, 0x63, 0xE0, /* '8' 0x38 */
0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC2, 0x66, 0x3C, /* '9' 0x39 */
0xC0, 0x00, 0x30, /* ':' 0x3A */
0xC0, 0x00, 0x00, 0x64, 0xA0, /* ';' 0x3B */
0x00, 0x81, 0xC7, 0x8E, 0x0C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0x80, /* '<' 0x3C */
0xFF, 0x80, 0x00, 0x1F, 0xF0, /* '=' 0x3D */
0xE0, 0x1C, 0x03, 0x80, 0x30, 0x70, 0xE3, 0x81, 0x00, /* '>' 0x3E */
0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x18, 0x38, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x01, 0x80, /* '?' 0x3F */
0x03, 0xF0, 0x06, 0x0E, 0x06, 0x01, 0x86, 0x00, 0x66, 0x1D, 0xBB, 0x31, 0xCF, 0x18, 0xC7, 0x98, 0x63, 0xCC, 0x31, 0xE6, 0x11,
0xB3, 0x99, 0xCC, 0xF7, 0x86, 0x00, 0x01, 0x80, 0x00, 0x70, 0x40, 0x0F, 0xE0, /* '@' 0x40 */
0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0,
0x30, /* 'A' 0x41 */
0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 'B' 0x42 */
0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 'C' 0x43 */
0xFF, 0x18, 0x33, 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, 0x60, 0xCF, 0xF0, /* 'D' 0x44 */
0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, /* 'E' 0x45 */
0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 'F' 0x46 */
0x0F, 0x83, 0x0E, 0x60, 0x66, 0x03, 0xC0, 0x0C, 0x00, 0xC1, 0xFC, 0x03, 0xC0, 0x36, 0x03, 0x60, 0x73, 0x0F, 0x0F,
0x10, /* 'G' 0x47 */
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 'H' 0x48 */
0xFF, 0xFF, 0xFF, 0xC0, /* 'I' 0x49 */
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 0x8F, 0x1E, 0x27, 0x80, /* 'J' 0x4A */
0xC0, 0xF0, 0x6C, 0x33, 0x18, 0xCC, 0x37, 0x0F, 0xC3, 0x98, 0xC3, 0x30, 0xCC, 0x1B, 0x03, 0xC0, 0xC0, /* 'K' 0x4B */
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 'L' 0x4C */
0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71,
0x80, /* 'M' 0x4D */
0xE0, 0x7C, 0x0F, 0xC1, 0xE8, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, 0xE0, 0x7C, 0x0E, /* 'N' 0x4E */
0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8,
0x00, /* 'O' 0x4F */
0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 'P' 0x50 */
0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x6C, 0x60, 0xC0, 0xFB,
0x00, 0x08, /* 'Q' 0x51 */
0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0,
0x70, /* 'R' 0x52 */
0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 'S' 0x53 */
0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, /* 'T' 0x54 */
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xB0, 0x61, 0xF0, /* 'U' 0x55 */
0xC0, 0x6C, 0x0D, 0x81, 0x10, 0x63, 0x0C, 0x61, 0x04, 0x60, 0xCC, 0x19, 0x01, 0x60, 0x3C, 0x07, 0x00, 0x60, /* 'V' 0x56 */
0xC1, 0x81, 0x61, 0xC3, 0x61, 0xC3, 0x61, 0x43, 0x62, 0x62, 0x22, 0x66, 0x32, 0x26, 0x36, 0x26, 0x14, 0x34, 0x14, 0x34, 0x1C,
0x1C, 0x18, 0x1C, 0x08, 0x18, /* 'W' 0x57 */
0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E, 0x07, 0x00, 0xC0, 0x78, 0x32, 0x0C, 0xC6, 0x1B, 0x07, 0xC0, 0xC0, /* 'X' 0x58 */
0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06,
0x00, /* 'Y' 0x59 */
0xFF, 0xC0, 0x60, 0x30, 0x0C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x18, 0x06, 0x03, 0x00, 0xFF, 0xC0, /* 'Z' 0x5A */
0xFB, 0x6D, 0xB6, 0xDB, 0x6D, 0xB6, 0xE0, /* '[' 0x5B */
0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x80, /* '\' 0x5C */
0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xDB, 0xE0, /* ']' 0x5D */
0x30, 0x60, 0xA2, 0x44, 0xD8, 0xA1, 0x80, /* '^' 0x5E */
0xFF, 0xC0, /* '_' 0x5F */
0xC6, 0x30, /* '`' 0x60 */
0x7E, 0x71, 0xB0, 0xC0, 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, /* 'a' 0x61 */
0xC0, 0x60, 0x30, 0x1B, 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, /* 'b' 0x62 */
0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'c' 0x63 */
0x03, 0x03, 0x03, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, /* 'd' 0x64 */
0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'e' 0x65 */
0x36, 0x6F, 0x66, 0x66, 0x66, 0x66, 0x60, /* 'f' 0x66 */
0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC6, 0x7C, /* 'g' 0x67 */
0xC0, 0xC0, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'h' 0x68 */
0xC3, 0xFF, 0xFF, 0xC0, /* 'i' 0x69 */
0x30, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, /* 'j' 0x6A */
0xC0, 0xC0, 0xC0, 0xC2, 0xC4, 0xCC, 0xD8, 0xF8, 0xEC, 0xC4, 0xC6, 0xC3, 0xC3, /* 'k' 0x6B */
0xFF, 0xFF, 0xFF, 0xC0, /* 'l' 0x6C */
0xDE, 0xF7, 0x1C, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xC0, /* 'm' 0x6D */
0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'n' 0x6E */
0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 'o' 0x6F */
0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, /* 'p' 0x70 */
0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0x03, /* 'q' 0x71 */
0xDF, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, /* 'r' 0x72 */
0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 's' 0x73 */
0x66, 0xF6, 0x66, 0x66, 0x66, 0x67, /* 't' 0x74 */
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 'u' 0x75 */
0xC1, 0xA0, 0x98, 0xCC, 0x42, 0x21, 0xB0, 0xD0, 0x28, 0x1C, 0x0C, 0x00, /* 'v' 0x76 */
0xC6, 0x1E, 0x38, 0x91, 0xC4, 0xCA, 0x66, 0xD3, 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, 0x00, /* 'w' 0x77 */
0x87, 0x89, 0xB1, 0xC3, 0x07, 0x1E, 0x26, 0xC5, 0x0C, /* 'x' 0x78 */
0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 'y' 0x79 */
0xFE, 0x0C, 0x30, 0xC1, 0x86, 0x18, 0x20, 0xC1, 0xFC, /* 'z' 0x7A */
0x36, 0x66, 0x66, 0x6E, 0xCE, 0x66, 0x66, 0x66, 0x30, /* '{' 0x7B */
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, /* '|' 0x7C */
0xC6, 0x66, 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0xC0, /* '}' 0x7D */
0x61, 0x24, 0x38, /* '~' 0x7E */
0xFF, 0xFC, 0x00, 0x63, 0xE3, 0x31, 0x99, 0x04, 0xC8, 0x66, 0x06, 0x30, 0x61, 0x83, 0x0C, 0x18, 0x60, 0x03, 0x06, 0x18, 0x00,
0xFF, 0xFC, /* 0x7F */
0xFF, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0xFE, 0x18, 0x31, 0x83, 0x18, 0x31, 0x83, 0x18, 0x31, 0x83, 0x18, 0x30, 0x03,
0x00, 0x30, 0x0E, /* 0x80 */
0x0C, 0x18, 0x00, 0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 0x81 */
0xDC, /* 0x82 */
0x18, 0x89, 0xFC, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x00, /* 0x83 */
0xDA, 0x76, /* 0x84 */
0xCC, 0xC0, /* 0x85 */
0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, /* 0x86 */
0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, /* 0x87 */
0x07, 0xC6, 0x13, 0x00, 0xC0, 0x60, 0x3F, 0xE6, 0x03, 0xFC, 0x60, 0x0C, 0x03, 0x00, 0x61, 0x07, 0xC0, /* 0x88 */
0x70, 0x80, 0x22, 0x20, 0x08, 0x90, 0x02, 0x24, 0x00, 0x72, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x10, 0x00, 0x09, 0xC7, 0x84,
0x8B, 0x31, 0x22, 0x84, 0x88, 0xB3, 0x21, 0xC7, 0x80, /* 0x89 */
0x3F, 0x80, 0x18, 0xC0, 0x0C, 0x60, 0x06, 0x30, 0x03, 0x18, 0x01, 0x8C, 0x00, 0xC7, 0xF8, 0x63, 0x06, 0x31, 0x81, 0x90, 0xC0,
0xD8, 0x60, 0x6C, 0x30, 0x6C, 0x1F, 0xE0, /* 0x8A */
0x69, /* 0x8B */
0xC0, 0xC0, 0x60, 0x60, 0x30, 0x30, 0x18, 0x18, 0x0C, 0x0C, 0x06, 0x06, 0x03, 0xFF, 0xF9, 0x81, 0x86, 0xC0, 0xC1, 0xE0, 0x60,
0xF0, 0x30, 0x78, 0x18, 0x6C, 0x0F, 0xE0, /* 0x8C */
0x0C, 0x06, 0x0C, 0x1B, 0x0C, 0xC6, 0x33, 0x0D, 0x83, 0xC0, 0xF0, 0x3E, 0x0D, 0xC3, 0x38, 0xC7, 0x30, 0xEC, 0x1C, /* 0x8D */
0xFF, 0x01, 0x80, 0x18, 0x01, 0x80, 0x18, 0x01, 0xFE, 0x18, 0x31, 0x83, 0x18, 0x31, 0x83, 0x18, 0x31, 0x83, 0x18,
0x30, /* 0x8E */
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3F, 0xFE, 0x0C, 0x01,
0x80, /* 0x8F */
0x60, 0x7C, 0x18, 0x0D, 0xE7, 0x1B, 0x0D, 0x86, 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x18, 0x18, 0x08, 0x08, /* 0x90 */
0x6B, /* 0x91 */
0xD6, /* 0x92 */
0x4C, 0xA5, 0xB0, /* 0x93 */
0xDA, 0x53, 0x20, /* 0x94 */
0x6F, 0xFF, 0x60, /* 0x95 */
0xFE, /* 0x96 */
0xFF, 0xFF, /* 0x97 */
/* 0x98 */
0xFC, 0xE1, 0xCC, 0x38, 0x73, 0x0E, 0x1C, 0xC3, 0x8F, 0x30, 0xD2, 0xCC, 0x34, 0xB3, 0x0D, 0x6C, 0xC3, 0x53, 0x30, 0xCC, 0xCC,
0x33, 0x30, /* 0x99 */
0x7E, 0x03, 0x30, 0x19, 0x80, 0xCC, 0x06, 0x60, 0x33, 0xF9, 0x98, 0x6C, 0xC3, 0x46, 0x1E, 0x3F, 0x80, /* 0x9A */
0x96, /* 0x9B */
0xC3, 0x03, 0x0C, 0x0C, 0x30, 0x30, 0xC0, 0xC3, 0x03, 0xFF, 0xEC, 0x30, 0xF0, 0xC3, 0xC3, 0x0F, 0x0F, 0xE0, /* 0x9C */
0x0C, 0x30, 0x46, 0x3C, 0xDB, 0x34, 0x70, 0xF1, 0xB3, 0x36, 0x3C, 0x20, /* 0x9D */
0x60, 0x7C, 0x18, 0x0D, 0xE7, 0x3B, 0x0D, 0x86, 0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x18, /* 0x9E */
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0x18, 0x18, /* 0x9F */
/* 0xA0 */
0x21, 0x07, 0x8C, 0x0F, 0x06, 0x61, 0x98, 0xC3, 0x30, 0xD8, 0x1E, 0x07, 0x00, 0xC0, 0x60, 0x18, 0x0C, 0x03, 0x00, /* 0xA1 */
0x66, 0x18, 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xA2 */
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 0x8F, 0x1E, 0x27, 0x80, /* 0xA3 */
0xFF, 0xDF, 0x1E, 0x3E, 0xFF, 0xC0, /* 0xA4 */
0x00, 0xC0, 0x3F, 0xFF, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x00, /* 0xA5 */
0xFF, 0xFC, 0x0F, 0xFF, 0xC0, /* 0xA6 */
0x0C, 0x09, 0x0C, 0xC6, 0x63, 0x81, 0xE3, 0x19, 0x87, 0xE1, 0xB8, 0xC6, 0x41, 0xC0, 0x73, 0x19, 0x8C, 0x66, 0x1E,
0x00, /* 0xA7 */
0x33, 0x00, 0x3F, 0xF8, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFE, /* 0xA8 */
0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9B, 0xC6, 0xD9, 0x8F, 0x60, 0x3D, 0x00, 0xF4, 0x03, 0xD8, 0x0D, 0xE6, 0x67, 0xF3, 0x86, 0x18,
0x0F, 0xC0, /* 0xA9 */
0x1F, 0x86, 0x19, 0x81, 0xB0, 0x3C, 0x01, 0x80, 0x3F, 0xC6, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 0xAA */
0x22, 0xCF, 0x26, 0x46, 0x64, 0x40, /* 0xAB */
0xFF, 0x80, 0xC0, 0x60, 0x30, 0x18, /* 0xAC */
/* 0xAD */
0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9F, 0xE6, 0xD0, 0x8F, 0x42, 0x3D, 0xF0, 0xF4, 0x23, 0xD0, 0x8D, 0xC2, 0x67, 0x0B, 0x86, 0x18,
0x0F, 0xC0, /* 0xAE */
0xCC, 0x03, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x00, /* 0xAF */
0x74, 0x63, 0x17, 0x00, /* 0xB0 */
0x0C, 0x06, 0x03, 0x07, 0xE0, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x3F, 0xE0, /* 0xB1 */
0xFF, 0xFF, 0xFF, 0xC0, /* 0xB2 */
0xC3, 0xFF, 0xFF, 0xC0, /* 0xB3 */
0x0C, 0x3F, 0xF0, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, /* 0xB4 */
0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0x86, 0xE7, 0x7D, 0xF0, 0x18, 0x0C, 0x00, /* 0xB5 */
0x3F, 0x7E, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0x72, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, /* 0xB6 */
0xE0, /* 0xB7 */
0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xB8 */
0xC1, 0x81, 0x83, 0x03, 0x86, 0x05, 0x0C, 0xEB, 0x1A, 0x32, 0x34, 0x66, 0x68, 0xC4, 0xD1, 0x8D, 0xB3, 0x0B, 0x3A, 0x1E, 0x04,
0x1C, 0x08, 0x1B, 0xC0, /* 0xB9 */
0x3C, 0x46, 0xC3, 0x80, 0xF8, 0x80, 0x80, 0xC3, 0x46, 0x3C, /* 0xBA */
0x89, 0x98, 0x99, 0x3C, 0xD1, 0x00, /* 0xBB */
0x30, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, /* 0xBC */
0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 0xBD */
0x3E, 0xE3, 0xC0, 0xC0, 0x60, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 0xBE */
0xCC, 0x03, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, /* 0xBF */
0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0,
0x30, /* 0xC0 */
0xFF, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x80, 0x3F, 0xE6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 0xC1 */
0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 0xC2 */
0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 0xC3 */
0x1F, 0xF0, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x03, 0x0C, 0x0C,
0xFF, 0xFF, 0x00, 0x3C, 0x00, 0xF0, 0x03, /* 0xC4 */
0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, /* 0xC5 */
0x61, 0x86, 0x31, 0x8C, 0x19, 0x98, 0x19, 0x98, 0x0D, 0xB0, 0x07, 0xE0, 0x03, 0xC0, 0x07, 0xE0, 0x0D, 0xB0, 0x19, 0x98, 0x31,
0x8C, 0x61, 0x86, 0xC1, 0x83, /* 0xC6 */
0x3F, 0x18, 0x6C, 0x0F, 0x03, 0x00, 0xC0, 0x60, 0xF0, 0x06, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 0xC7 */
0xC0, 0xF8, 0x1F, 0x07, 0xE0, 0xBC, 0x37, 0x8C, 0xF1, 0x1E, 0x63, 0xD8, 0x7A, 0x0F, 0xC1, 0xF0, 0x3E, 0x06, /* 0xC8 */
0x11, 0x03, 0xE0, 0x00, 0x60, 0x7C, 0x0F, 0x83, 0xF0, 0x5E, 0x1B, 0xC6, 0x78, 0x8F, 0x31, 0xEC, 0x3D, 0x07, 0xE0, 0xF8, 0x1F,
0x03, /* 0xC9 */
0xC1, 0xB0, 0xCC, 0x63, 0x30, 0xD8, 0x3C, 0x0F, 0x03, 0xE0, 0xDC, 0x33, 0x8C, 0x73, 0x0E, 0xC1, 0xC0, /* 0xCA */
0x3F, 0xCC, 0x33, 0x0C, 0xC3, 0x30, 0xCC, 0x33, 0x0C, 0xC3, 0x30, 0xC8, 0x36, 0x0D, 0x83, 0xC0, 0xC0, /* 0xCB */
0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71,
0x80, /* 0xCC */
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 0xCD */
0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8,
0x00, /* 0xCE */
0xFF, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 0xCF */
0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 0xD0 */
0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 0xD1 */
0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, /* 0xD2 */
0xC0, 0xF0, 0x66, 0x19, 0x8C, 0x33, 0x0D, 0x81, 0xE0, 0x70, 0x0C, 0x06, 0x01, 0x80, 0xC0, 0x30, 0x00, /* 0xD3 */
0x03, 0x00, 0x0C, 0x01, 0xFE, 0x1C, 0xCE, 0xE3, 0x1F, 0x0C, 0x3C, 0x30, 0xF0, 0xC3, 0xE3, 0x1D, 0xCC, 0xE3, 0xFF, 0x00, 0xC0,
0x03, 0x00, /* 0xD4 */
0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E, 0x07, 0x00, 0xC0, 0x78, 0x32, 0x0C, 0xC6, 0x1B, 0x07, 0xC0, 0xC0, /* 0xD5 */
0xC0, 0x66, 0x03, 0x30, 0x19, 0x80, 0xCC, 0x06, 0x60, 0x33, 0x01, 0x98, 0x0C, 0xC0, 0x66, 0x03, 0x30, 0x19, 0x80, 0xCF, 0xFF,
0x80, 0x0C, 0x00, 0x60, /* 0xD6 */
0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F, 0x06, 0xFF, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, /* 0xD7 */
0xC3, 0x1E, 0x18, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xF0, 0xC7, 0x86, 0x3F, 0xFF,
0x80, /* 0xD8 */
0xC3, 0x19, 0x86, 0x33, 0x0C, 0x66, 0x18, 0xCC, 0x31, 0x98, 0x63, 0x30, 0xC6, 0x61, 0x8C, 0xC3, 0x19, 0x86, 0x33, 0x0C, 0x66,
0x18, 0xCF, 0xFF, 0xE0, 0x00, 0xC0, 0x01, 0x80, /* 0xD9 */
0xF8, 0x00, 0xC0, 0x06, 0x00, 0x30, 0x01, 0x80, 0x0F, 0xF0, 0x60, 0xC3, 0x03, 0x18, 0x18, 0xC0, 0xC6, 0x06, 0x30, 0x61, 0xFE,
0x00, /* 0xDA */
0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0, 0x0F, 0xFE, 0x3C, 0x0C, 0xF0, 0x1B, 0xC0, 0x6F, 0x01, 0xBC, 0x06, 0xF0, 0x33,
0xFF, 0x8C, /* 0xDB */
0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0xFF, 0x30, 0x36, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 0xDC */
0x3F, 0x0C, 0x33, 0x83, 0x60, 0x20, 0x06, 0x00, 0x47, 0xF8, 0x01, 0xC0, 0x78, 0x0D, 0x81, 0x30, 0xC1, 0xF0, /* 0xDD */
0xC0, 0xF8, 0x61, 0x83, 0x31, 0x80, 0xD8, 0xC0, 0x6C, 0xC0, 0x1E, 0x60, 0x0F, 0xF0, 0x07, 0x98, 0x03, 0xCC, 0x01, 0xE3, 0x01,
0xB1, 0x80, 0xD8, 0x60, 0xCC, 0x0F, 0x80, /* 0xDE */
0x3F, 0xD8, 0x3C, 0x0F, 0x03, 0xC0, 0xD8, 0x33, 0xFC, 0x33, 0x18, 0xCC, 0x36, 0x0D, 0x83, 0xC0, 0xC0, /* 0xDF */
0x7E, 0x71, 0xB0, 0xC0, 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, /* 0xE0 */
0x03, 0x1F, 0x78, 0x40, 0xFC, 0xE6, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xE1 */
0xFD, 0x8F, 0x0E, 0x3F, 0xDF, 0xB1, 0xE1, 0xC7, 0xF8, /* 0xE2 */
0xFE, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, /* 0xE3 */
0x1F, 0x83, 0x30, 0x66, 0x0C, 0xC1, 0x98, 0x33, 0x06, 0x61, 0x8C, 0x31, 0x9F, 0xFF, 0x01, 0xE0, 0x30, /* 0xE4 */
0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE5 */
0xC6, 0x36, 0x66, 0x36, 0xC1, 0xF8, 0x0F, 0x01, 0xF8, 0x36, 0xC6, 0x66, 0xC6, 0x38, 0x61, /* 0xE6 */
0x79, 0x8C, 0x18, 0x30, 0x43, 0x01, 0xE3, 0xC6, 0xF8, /* 0xE7 */
0xC7, 0xC7, 0xCF, 0xCB, 0xCB, 0xD3, 0xD3, 0xF3, 0xE3, 0xE3, /* 0xE8 */
0x66, 0x18, 0xC7, 0xC7, 0xCF, 0xCB, 0xCB, 0xD3, 0xD3, 0xF3, 0xE3, 0xE3, /* 0xE9 */
0xC7, 0x9B, 0x66, 0x8E, 0x1E, 0x36, 0x66, 0xC7, 0x84, /* 0xEA */
0x7E, 0xCD, 0x9B, 0x36, 0x6C, 0xD9, 0xA3, 0xC7, 0x0C, /* 0xEB */
0xE3, 0xF1, 0xF8, 0xFE, 0xFF, 0x7E, 0xAF, 0x77, 0x93, 0xC9, 0xE0, 0xC0, /* 0xEC */
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xFF, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xED */
0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xEE */
0xFF, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xEF */
0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, /* 0xF0 */
0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xF1 */
0xFC, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0, /* 0xF2 */
0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xF3 */
0x03, 0x00, 0x0C, 0x03, 0xB7, 0x19, 0xE6, 0xC3, 0x0F, 0x0C, 0x3C, 0x30, 0xF0, 0xC3, 0xC3, 0x0F, 0x0C, 0x36, 0x79, 0x8E, 0xDC,
0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, /* 0xF4 */
0x87, 0x89, 0xB1, 0xC3, 0x07, 0x1E, 0x26, 0xC5, 0x0C, /* 0xF5 */
0xC3, 0x30, 0xCC, 0x33, 0x0C, 0xC3, 0x30, 0xCC, 0x33, 0x0C, 0xC3, 0x3F, 0xF0, 0x0C, 0x03, /* 0xF6 */
0xC7, 0x8F, 0x1E, 0x3C, 0x6F, 0xC1, 0x83, 0x06, 0x0C, /* 0xF7 */
0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0xCC, 0xFF, 0xF0, /* 0xF8 */
0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCF, 0xFF, 0x00, 0x30, 0x03, /* 0xF9 */
0xF0, 0x18, 0x0C, 0x06, 0x03, 0xF1, 0x8C, 0xC6, 0x63, 0x31, 0x9F, 0x80, /* 0xFA */
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xFE, 0xF0, 0xFC, 0x3F, 0x0F, 0xC3, 0xFF, 0xB0, /* 0xFB */
0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xC3, 0xC3, 0xC3, 0xC3, 0xFE, /* 0xFC */
0x3C, 0x62, 0xC3, 0x01, 0x1F, 0x01, 0x01, 0xC3, 0x62, 0x3C, /* 0xFD */
0xC7, 0xCC, 0xC6, 0xD8, 0x3D, 0x83, 0xF8, 0x3D, 0x83, 0xD8, 0x3C, 0xC2, 0xCC, 0x6C, 0x7C, /* 0xFE */
0x7F, 0xC3, 0xC3, 0xC3, 0x7F, 0x13, 0x33, 0x63, 0xC3, 0x83, /* 0xFF */
};
const GFXglyph FreeSans9pt_Win1251Glyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 5, 0, 0},
/* '!' 0x21 */ {0, 2, 13, 6, 2, -12},
/* '"' 0x22 */ {4, 5, 4, 6, 1, -12},
/* '#' 0x23 */ {7, 10, 12, 10, 0, -11},
/* '$' 0x24 */ {22, 9, 16, 10, 1, -13},
/* '%' 0x25 */ {40, 16, 13, 16, 1, -12},
/* '&' 0x26 */ {66, 10, 13, 12, 1, -12},
/* ''' 0x27 */ {83, 2, 4, 4, 1, -12},
/* '(' 0x28 */ {84, 4, 17, 6, 1, -12},
/* ')' 0x29 */ {93, 4, 17, 6, 1, -12},
/* '*' 0x2A */ {102, 5, 5, 7, 1, -12},
/* '+' 0x2B */ {106, 6, 8, 11, 3, -7},
/* ',' 0x2C */ {112, 2, 4, 5, 2, 0},
/* '-' 0x2D */ {113, 4, 1, 6, 1, -4},
/* '.' 0x2E */ {114, 2, 1, 5, 1, 0},
/* '/' 0x2F */ {115, 5, 13, 5, 0, -12},
/* '0' 0x30 */ {124, 8, 13, 10, 1, -12},
/* '1' 0x31 */ {137, 4, 13, 10, 3, -12},
/* '2' 0x32 */ {144, 9, 13, 10, 1, -12},
/* '3' 0x33 */ {159, 8, 13, 10, 1, -12},
/* '4' 0x34 */ {172, 7, 13, 10, 2, -12},
/* '5' 0x35 */ {184, 9, 13, 10, 1, -12},
/* '6' 0x36 */ {199, 9, 13, 10, 1, -12},
/* '7' 0x37 */ {214, 8, 13, 10, 0, -12},
/* '8' 0x38 */ {227, 9, 13, 10, 1, -12},
/* '9' 0x39 */ {242, 8, 13, 10, 1, -12},
/* ':' 0x3A */ {255, 2, 10, 5, 1, -9},
/* ';' 0x3B */ {258, 3, 12, 5, 1, -8},
/* '<' 0x3C */ {263, 9, 9, 11, 1, -8},
/* '=' 0x3D */ {274, 9, 4, 11, 1, -5},
/* '>' 0x3E */ {279, 9, 8, 11, 1, -7},
/* '?' 0x3F */ {288, 9, 13, 10, 1, -12},
/* '@' 0x40 */ {303, 17, 16, 18, 1, -12},
/* 'A' 0x41 */ {337, 12, 13, 12, 0, -12},
/* 'B' 0x42 */ {357, 11, 13, 12, 1, -12},
/* 'C' 0x43 */ {375, 11, 13, 13, 1, -12},
/* 'D' 0x44 */ {393, 11, 13, 13, 1, -12},
/* 'E' 0x45 */ {411, 9, 13, 11, 1, -12},
/* 'F' 0x46 */ {426, 8, 13, 11, 1, -12},
/* 'G' 0x47 */ {439, 12, 13, 14, 1, -12},
/* 'H' 0x48 */ {459, 11, 13, 13, 1, -12},
/* 'I' 0x49 */ {477, 2, 13, 5, 2, -12},
/* 'J' 0x4A */ {481, 7, 13, 10, 1, -12},
/* 'K' 0x4B */ {493, 10, 13, 12, 1, -12},
/* 'L' 0x4C */ {510, 8, 13, 10, 1, -12},
/* 'M' 0x4D */ {523, 13, 13, 15, 1, -12},
/* 'N' 0x4E */ {545, 11, 13, 13, 1, -12},
/* 'O' 0x4F */ {563, 13, 13, 14, 1, -12},
/* 'P' 0x50 */ {585, 10, 13, 12, 1, -12},
/* 'Q' 0x51 */ {602, 13, 14, 14, 1, -12},
/* 'R' 0x52 */ {625, 12, 13, 13, 1, -12},
/* 'S' 0x53 */ {645, 10, 13, 12, 1, -12},
/* 'T' 0x54 */ {662, 9, 13, 11, 1, -12},
/* 'U' 0x55 */ {677, 11, 13, 13, 1, -12},
/* 'V' 0x56 */ {695, 11, 13, 11, 0, -12},
/* 'W' 0x57 */ {713, 16, 13, 17, 0, -12},
/* 'X' 0x58 */ {739, 10, 13, 12, 1, -12},
/* 'Y' 0x59 */ {756, 12, 13, 12, 0, -12},
/* 'Z' 0x5A */ {776, 10, 13, 11, 1, -12},
/* '[' 0x5B */ {793, 3, 17, 5, 1, -12},
/* '\' 0x5C */ {800, 5, 13, 5, 0, -12},
/* ']' 0x5D */ {809, 3, 17, 5, 0, -12},
/* '^' 0x5E */ {816, 7, 7, 8, 1, -12},
/* '_' 0x5F */ {823, 10, 1, 10, 0, 3},
/* '`' 0x60 */ {825, 4, 3, 5, 0, -12},
/* 'a' 0x61 */ {827, 9, 10, 10, 1, -9},
/* 'b' 0x62 */ {839, 9, 13, 10, 1, -12},
/* 'c' 0x63 */ {854, 8, 10, 9, 1, -9},
/* 'd' 0x64 */ {864, 8, 13, 10, 1, -12},
/* 'e' 0x65 */ {877, 8, 10, 10, 1, -9},
/* 'f' 0x66 */ {887, 4, 13, 5, 1, -12},
/* 'g' 0x67 */ {894, 8, 14, 10, 1, -9},
/* 'h' 0x68 */ {908, 8, 13, 10, 1, -12},
/* 'i' 0x69 */ {921, 2, 13, 4, 1, -12},
/* 'j' 0x6A */ {925, 4, 17, 4, 0, -12},
/* 'k' 0x6B */ {934, 8, 13, 9, 1, -12},
/* 'l' 0x6C */ {947, 2, 13, 4, 1, -12},
/* 'm' 0x6D */ {951, 13, 10, 15, 1, -9},
/* 'n' 0x6E */ {968, 8, 10, 10, 1, -9},
/* 'o' 0x6F */ {978, 8, 10, 10, 1, -9},
/* 'p' 0x70 */ {988, 9, 13, 10, 1, -9},
/* 'q' 0x71 */ {1003, 8, 13, 10, 1, -9},
/* 'r' 0x72 */ {1016, 5, 10, 6, 1, -9},
/* 's' 0x73 */ {1023, 8, 10, 9, 1, -9},
/* 't' 0x74 */ {1033, 4, 12, 5, 1, -11},
/* 'u' 0x75 */ {1039, 8, 10, 10, 1, -9},
/* 'v' 0x76 */ {1049, 9, 10, 9, 0, -9},
/* 'w' 0x77 */ {1061, 13, 10, 13, 0, -9},
/* 'x' 0x78 */ {1078, 7, 10, 9, 1, -9},
/* 'y' 0x79 */ {1087, 8, 14, 9, 0, -9},
/* 'z' 0x7A */ {1101, 7, 10, 9, 1, -9},
/* '{' 0x7B */ {1110, 4, 17, 6, 1, -12},
/* '|' 0x7C */ {1119, 2, 17, 4, 2, -12},
/* '}' 0x7D */ {1124, 4, 17, 6, 1, -12},
/* '~' 0x7E */ {1133, 7, 3, 9, 1, -7},
/* 0x7F */ {1136, 13, 14, 15, 1, -12},
/* 0x80 */ {1159, 12, 16, 14, 1, -12},
/* 0x81 */ {1183, 8, 15, 11, 1, -14},
/* 0x82 */ {1198, 2, 3, 5, 1, 0},
/* 0x83 */ {1199, 5, 13, 7, 1, -12},
/* 0x84 */ {1208, 5, 3, 7, 1, 0},
/* 0x85 */ {1210, 10, 1, 12, 1, 0},
/* 0x86 */ {1212, 8, 16, 10, 1, -12},
/* 0x87 */ {1228, 8, 16, 10, 1, -12},
/* 0x88 */ {1244, 10, 13, 12, 1, -12},
/* 0x89 */ {1261, 18, 13, 18, 0, -12},
/* 0x8A */ {1291, 17, 13, 18, 1, -12},
/* 0x8B */ {1319, 2, 4, 4, 1, -6},
/* 0x8C */ {1320, 17, 13, 18, 1, -12},
/* 0x8D */ {1348, 10, 15, 11, 1, -14},
/* 0x8E */ {1367, 12, 13, 14, 1, -12},
/* 0x8F */ {1387, 11, 15, 13, 1, -12},
/* 0x90 */ {1408, 9, 16, 10, 1, -12},
/* 0x91 */ {1426, 2, 4, 4, 2, -12},
/* 0x92 */ {1427, 2, 4, 4, 1, -12},
/* 0x93 */ {1428, 5, 4, 7, 2, -12},
/* 0x94 */ {1431, 5, 4, 7, 1, -12},
/* 0x95 */ {1434, 4, 5, 7, 1, -8},
/* 0x96 */ {1437, 7, 1, 9, 1, -4},
/* 0x97 */ {1438, 16, 1, 18, 1, -4},
/* 0x98 */ {1440, 0, 0, 0, 0, 0},
/* 0x99 */ {1440, 18, 10, 18, 1, -13},
/* 0x9A */ {1463, 13, 10, 14, 1, -9},
/* 0x9B */ {1480, 2, 4, 5, 2, -6},
/* 0x9C */ {1481, 14, 10, 15, 1, -9},
/* 0x9D */ {1499, 7, 13, 9, 1, -12},
/* 0x9E */ {1511, 9, 13, 10, 1, -12},
/* 0x9F */ {1526, 8, 12, 10, 1, -9},
/* 0xA0 */ {1538, 0, 0, 5, 0, 0},
/* 0xA1 */ {1538, 10, 15, 11, 1, -14},
/* 0xA2 */ {1557, 8, 16, 9, 0, -11},
/* 0xA3 */ {1573, 7, 13, 10, 1, -12},
/* 0xA4 */ {1585, 7, 6, 10, 2, -8},
/* 0xA5 */ {1591, 10, 14, 11, 1, -13},
/* 0xA6 */ {1609, 2, 17, 5, 2, -12},
/* 0xA7 */ {1614, 9, 17, 10, 1, -12},
/* 0xA8 */ {1634, 9, 15, 12, 1, -14},
/* 0xA9 */ {1651, 14, 13, 14, 1, -12},
/* 0xAA */ {1674, 11, 13, 13, 1, -12},
/* 0xAB */ {1692, 7, 6, 9, 1, -7},
/* 0xAC */ {1698, 9, 5, 11, 2, -5},
/* 0xAD */ {1704, 0, 0, 0, 0, 0},
/* 0xAE */ {1704, 14, 13, 14, 1, -12},
/* 0xAF */ {1727, 6, 15, 5, 0, -14},
/* 0xB0 */ {1739, 5, 5, 11, 3, -11},
/* 0xB1 */ {1743, 9, 11, 11, 1, -10},
/* 0xB2 */ {1756, 2, 13, 4, 1, -12},
/* 0xB3 */ {1760, 2, 13, 4, 1, -12},
/* 0xB4 */ {1764, 6, 12, 7, 1, -11},
/* 0xB5 */ {1773, 9, 13, 10, 1, -9},
/* 0xB6 */ {1788, 8, 16, 10, 2, -12},
/* 0xB7 */ {1804, 3, 1, 5, 1, -4},
/* 0xB8 */ {1805, 8, 12, 10, 1, -11},
/* 0xB9 */ {1817, 15, 13, 17, 1, -12},
/* 0xBA */ {1842, 8, 10, 9, 1, -9},
/* 0xBB */ {1852, 7, 6, 9, 1, -7},
/* 0xBC */ {1858, 4, 17, 4, 0, -12},
/* 0xBD */ {1867, 10, 13, 12, 1, -12},
/* 0xBE */ {1884, 8, 10, 9, 1, -9},
/* 0xBF */ {1894, 6, 12, 5, -1, -11},
/* 0xC0 */ {1903, 12, 13, 12, 0, -12},
/* 0xC1 */ {1923, 11, 13, 12, 1, -12},
/* 0xC2 */ {1941, 11, 13, 12, 1, -12},
/* 0xC3 */ {1959, 8, 13, 8, 1, -12},
/* 0xC4 */ {1972, 14, 16, 15, 1, -12},
/* 0xC5 */ {2000, 9, 13, 12, 1, -12},
/* 0xC6 */ {2015, 16, 13, 16, 0, -12},
/* 0xC7 */ {2041, 10, 13, 12, 1, -12},
/* 0xC8 */ {2058, 11, 13, 13, 1, -12},
/* 0xC9 */ {2076, 11, 16, 13, 1, -15},
/* 0xCA */ {2098, 10, 13, 11, 1, -12},
/* 0xCB */ {2115, 10, 13, 12, 1, -12},
/* 0xCC */ {2132, 13, 13, 15, 1, -12},
/* 0xCD */ {2154, 11, 13, 13, 1, -12},
/* 0xCE */ {2172, 13, 13, 14, 1, -12},
/* 0xCF */ {2194, 11, 13, 13, 1, -12},
/* 0xD0 */ {2212, 10, 13, 12, 1, -12},
/* 0xD1 */ {2229, 11, 13, 13, 1, -12},
/* 0xD2 */ {2247, 9, 13, 11, 1, -12},
/* 0xD3 */ {2262, 10, 13, 11, 1, -12},
/* 0xD4 */ {2279, 14, 13, 15, 1, -12},
/* 0xD5 */ {2302, 10, 13, 12, 1, -12},
/* 0xD6 */ {2319, 13, 15, 13, 1, -12},
/* 0xD7 */ {2344, 9, 13, 11, 1, -12},
/* 0xD8 */ {2359, 13, 13, 15, 1, -12},
/* 0xD9 */ {2381, 15, 15, 15, 1, -12},
/* 0xDA */ {2410, 13, 13, 15, 2, -12},
/* 0xDB */ {2432, 14, 13, 16, 1, -12},
/* 0xDC */ {2455, 11, 13, 12, 1, -12},
/* 0xDD */ {2473, 11, 13, 13, 1, -12},
/* 0xDE */ {2491, 17, 13, 18, 1, -12},
/* 0xDF */ {2519, 10, 13, 12, 1, -12},
/* 0xE0 */ {2536, 9, 10, 10, 1, -9},
/* 0xE1 */ {2548, 8, 14, 10, 1, -13},
/* 0xE2 */ {2562, 7, 10, 9, 1, -9},
/* 0xE3 */ {2571, 5, 10, 7, 1, -9},
/* 0xE4 */ {2578, 11, 12, 10, 0, -9},
/* 0xE5 */ {2595, 8, 10, 10, 1, -9},
/* 0xE6 */ {2605, 12, 10, 14, 1, -9},
/* 0xE7 */ {2620, 7, 10, 9, 1, -9},
/* 0xE8 */ {2629, 8, 10, 10, 1, -9},
/* 0xE9 */ {2639, 8, 12, 10, 1, -11},
/* 0xEA */ {2651, 7, 10, 9, 1, -9},
/* 0xEB */ {2660, 7, 10, 8, 0, -9},
/* 0xEC */ {2669, 9, 10, 11, 1, -9},
/* 0xED */ {2681, 8, 10, 10, 1, -9},
/* 0xEE */ {2691, 8, 10, 10, 1, -9},
/* 0xEF */ {2701, 8, 10, 10, 1, -9},
/* 0xF0 */ {2711, 9, 13, 10, 1, -9},
/* 0xF1 */ {2726, 8, 10, 9, 1, -9},
/* 0xF2 */ {2736, 6, 10, 7, 1, -9},
/* 0xF3 */ {2744, 8, 14, 9, 0, -9},
/* 0xF4 */ {2758, 14, 15, 15, 1, -11},
/* 0xF5 */ {2785, 7, 10, 9, 1, -9},
/* 0xF6 */ {2794, 10, 12, 10, 1, -9},
/* 0xF7 */ {2809, 7, 10, 9, 1, -9},
/* 0xF8 */ {2818, 10, 10, 12, 1, -9},
/* 0xF9 */ {2831, 12, 12, 13, 1, -9},
/* 0xFA */ {2849, 9, 10, 12, 2, -9},
/* 0xFB */ {2861, 10, 10, 12, 1, -9},
/* 0xFC */ {2874, 8, 10, 9, 1, -9},
/* 0xFD */ {2884, 8, 10, 9, 1, -9},
/* 0xFE */ {2894, 12, 10, 13, 1, -9},
/* 0xFF */ {2909, 8, 10, 10, 1, -9},
};
const GFXfont FreeSans9pt_Win1251 PROGMEM = {(uint8_t *)FreeSans9pt_Win1251Bitmaps, (GFXglyph *)FreeSans9pt_Win1251Glyphs, 0x20,
0xFF, 21};

View File

@@ -0,0 +1,494 @@
#pragma once
const uint8_t FreeSans9pt_Win1252Bitmaps[] PROGMEM = {
/* ' ' 0x20 */
0xFF, 0xFF, 0xF0, 0xC0, /* '!' 0x21 */
0xDE, 0xF7, 0x20, /* '"' 0x22 */
0x09, 0x86, 0x41, 0x91, 0xFF, 0x13, 0x04, 0xC3, 0x20, 0xC8, 0xFF, 0x89, 0x82, 0x61, 0x90, /* '#' 0x23 */
0x10, 0x1F, 0x14, 0xDA, 0x3D, 0x1E, 0x83, 0x40, 0x78, 0x17, 0x08, 0xF4, 0x7A, 0x35, 0x33, 0xF0, 0x40, 0x20, /* '$' 0x24 */
0x38, 0x10, 0xEC, 0x20, 0xC6, 0x20, 0xC6, 0x40, 0xC6, 0x40, 0x6C, 0x80, 0x39, 0x00, 0x01, 0x3C, 0x02, 0x77, 0x02, 0x63, 0x04,
0x63, 0x04, 0x77, 0x08, 0x3C, /* '%' 0x25 */
0x0E, 0x0C, 0xC3, 0x30, 0xCC, 0x1E, 0x03, 0x03, 0xC1, 0x9B, 0xC2, 0xF0, 0xEC, 0x19, 0x8F, 0x3C, 0x40, /* '&' 0x26 */
0xFE, /* ''' 0x27 */
0x13, 0x26, 0x6C, 0xCC, 0xCC, 0xC4, 0x66, 0x23, 0x10, /* '(' 0x28 */
0x8C, 0x46, 0x63, 0x33, 0x33, 0x32, 0x66, 0x4C, 0x80, /* ')' 0x29 */
0x25, 0x7E, 0xA5, 0x00, /* '*' 0x2A */
0x30, 0xC3, 0x3F, 0x30, 0xC3, 0x0C, /* '+' 0x2B */
0xD6, /* ',' 0x2C */
0xF0, /* '-' 0x2D */
0xC0, /* '.' 0x2E */
0x08, 0x44, 0x21, 0x10, 0x84, 0x42, 0x11, 0x08, 0x00, /* '/' 0x2F */
0x3C, 0x66, 0x42, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, /* '0' 0x30 */
0x11, 0x3F, 0x33, 0x33, 0x33, 0x33, 0x30, /* '1' 0x31 */
0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x1C, 0x1C, 0x1C, 0x18, 0x18, 0x10, 0x08, 0x07, 0xF8, /* '2' 0x32 */
0x3C, 0x66, 0xC3, 0xC3, 0x03, 0x06, 0x1C, 0x07, 0x03, 0xC3, 0xC3, 0x66, 0x3C, /* '3' 0x33 */
0x0C, 0x18, 0x71, 0x62, 0xC9, 0xA3, 0x46, 0xFE, 0x18, 0x30, 0x60, 0xC0, /* '4' 0x34 */
0x7F, 0x20, 0x10, 0x08, 0x08, 0x07, 0xF3, 0x8C, 0x03, 0x01, 0x80, 0xF0, 0x6C, 0x63, 0xE0, /* '5' 0x35 */
0x1E, 0x31, 0x98, 0x78, 0x0C, 0x06, 0xF3, 0x8D, 0x83, 0xC1, 0xE0, 0xD0, 0x6C, 0x63, 0xE0, /* '6' 0x36 */
0xFF, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x08, 0x18, 0x18, 0x18, 0x10, 0x30, 0x30, /* '7' 0x37 */
0x3E, 0x31, 0xB0, 0x78, 0x3C, 0x1B, 0x18, 0xF8, 0xC6, 0xC1, 0xE0, 0xF0, 0x6C, 0x63, 0xE0, /* '8' 0x38 */
0x3C, 0x66, 0xC2, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC2, 0x66, 0x3C, /* '9' 0x39 */
0xC0, 0x00, 0x30, /* ':' 0x3A */
0xC0, 0x00, 0x00, 0x64, 0xA0, /* ';' 0x3B */
0x00, 0x81, 0xC7, 0x8E, 0x0C, 0x07, 0x80, 0x70, 0x0E, 0x01, 0x80, /* '<' 0x3C */
0xFF, 0x80, 0x00, 0x1F, 0xF0, /* '=' 0x3D */
0xE0, 0x1C, 0x03, 0x80, 0x30, 0x70, 0xE3, 0x81, 0x00, /* '>' 0x3E */
0x3E, 0x31, 0xB0, 0x78, 0x30, 0x18, 0x18, 0x38, 0x18, 0x18, 0x0C, 0x00, 0x00, 0x01, 0x80, /* '?' 0x3F */
0x03, 0xF0, 0x06, 0x0E, 0x06, 0x01, 0x86, 0x00, 0x66, 0x1D, 0xBB, 0x31, 0xCF, 0x18, 0xC7, 0x98, 0x63, 0xCC, 0x31, 0xE6, 0x11,
0xB3, 0x99, 0xCC, 0xF7, 0x86, 0x00, 0x01, 0x80, 0x00, 0x70, 0x40, 0x0F, 0xE0, /* '@' 0x40 */
0x06, 0x00, 0xF0, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC2, 0x04, 0x60, 0x66, 0x06, 0xC0,
0x30, /* 'A' 0x41 */
0xFF, 0x18, 0x33, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x3F, 0xC6, 0x06, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x6F, 0xF8, /* 'B' 0x42 */
0x1F, 0x86, 0x19, 0x81, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0x61, 0xF0, /* 'C' 0x43 */
0xFF, 0x18, 0x33, 0x03, 0x60, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x03, 0x60, 0xCF, 0xF0, /* 'D' 0x44 */
0xFF, 0xE0, 0x30, 0x18, 0x0C, 0x06, 0x03, 0xFD, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xF8, /* 'E' 0x45 */
0xFF, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFE, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, /* 'F' 0x46 */
0x0F, 0x83, 0x0E, 0x60, 0x66, 0x03, 0xC0, 0x0C, 0x00, 0xC1, 0xFC, 0x03, 0xC0, 0x36, 0x03, 0x60, 0x73, 0x0F, 0x0F,
0x10, /* 'G' 0x47 */
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xFF, 0xFE, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x06, /* 'H' 0x48 */
0xFF, 0xFF, 0xFF, 0xC0, /* 'I' 0x49 */
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x07, 0x8F, 0x1E, 0x27, 0x80, /* 'J' 0x4A */
0xC0, 0xF0, 0x6C, 0x33, 0x18, 0xCC, 0x37, 0x0F, 0xC3, 0x98, 0xC3, 0x30, 0xCC, 0x1B, 0x03, 0xC0, 0xC0, /* 'K' 0x4B */
0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 'L' 0x4C */
0xE0, 0x3F, 0x01, 0xFC, 0x1F, 0xE0, 0xFD, 0x05, 0xEC, 0x6F, 0x63, 0x79, 0x13, 0xCD, 0x9E, 0x6C, 0xF1, 0x47, 0x8E, 0x3C, 0x71,
0x80, /* 'M' 0x4D */
0xE0, 0x7C, 0x0F, 0xC1, 0xE8, 0x3D, 0x87, 0x98, 0xF1, 0x1E, 0x33, 0xC3, 0x78, 0x6F, 0x07, 0xE0, 0x7C, 0x0E, /* 'N' 0x4E */
0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x0C, 0x60, 0xC0, 0xF8,
0x00, /* 'O' 0x4F */
0xFF, 0x30, 0x6C, 0x0F, 0x03, 0xC0, 0xF0, 0x6F, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 'P' 0x50 */
0x0F, 0x81, 0x83, 0x18, 0x0C, 0xC0, 0x6C, 0x01, 0xE0, 0x0F, 0x00, 0x78, 0x03, 0xC0, 0x1B, 0x01, 0x98, 0x6C, 0x60, 0xC0, 0xFB,
0x00, 0x08, /* 'Q' 0x51 */
0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x0C, 0xFF, 0x8C, 0x0E, 0xC0, 0x6C, 0x06, 0xC0, 0x6C, 0x06, 0xC0,
0x70, /* 'R' 0x52 */
0x3F, 0x18, 0x6C, 0x0F, 0x03, 0xC0, 0x1E, 0x01, 0xF0, 0x0E, 0x00, 0xF0, 0x3C, 0x0D, 0x86, 0x3F, 0x00, /* 'S' 0x53 */
0xFF, 0x86, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, /* 'T' 0x54 */
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xB0, 0x61, 0xF0, /* 'U' 0x55 */
0xC0, 0x6C, 0x0D, 0x81, 0x10, 0x63, 0x0C, 0x61, 0x04, 0x60, 0xCC, 0x19, 0x01, 0x60, 0x3C, 0x07, 0x00, 0x60, /* 'V' 0x56 */
0xC1, 0x81, 0x61, 0xC3, 0x61, 0xC3, 0x61, 0x43, 0x62, 0x62, 0x22, 0x66, 0x32, 0x26, 0x36, 0x26, 0x14, 0x34, 0x14, 0x34, 0x1C,
0x1C, 0x18, 0x1C, 0x08, 0x18, /* 'W' 0x57 */
0xC0, 0xD8, 0x66, 0x18, 0xCC, 0x1E, 0x07, 0x00, 0xC0, 0x78, 0x32, 0x0C, 0xC6, 0x1B, 0x07, 0xC0, 0xC0, /* 'X' 0x58 */
0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06,
0x00, /* 'Y' 0x59 */
0xFF, 0xC0, 0x60, 0x30, 0x0C, 0x06, 0x03, 0x01, 0xC0, 0x60, 0x30, 0x18, 0x06, 0x03, 0x00, 0xFF, 0xC0, /* 'Z' 0x5A */
0xFB, 0x6D, 0xB6, 0xDB, 0x6D, 0xB6, 0xE0, /* '[' 0x5B */
0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x84, 0x10, 0x80, /* '\' 0x5C */
0xED, 0xB6, 0xDB, 0x6D, 0xB6, 0xDB, 0xE0, /* ']' 0x5D */
0x30, 0x60, 0xA2, 0x44, 0xD8, 0xA1, 0x80, /* '^' 0x5E */
0xFF, 0xC0, /* '_' 0x5F */
0xC6, 0x30, /* '`' 0x60 */
0x7E, 0x71, 0xB0, 0xC0, 0x60, 0xF3, 0xDB, 0x0D, 0x86, 0xC7, 0x3D, 0xC0, /* 'a' 0x61 */
0xC0, 0x60, 0x30, 0x1B, 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE0, /* 'b' 0x62 */
0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'c' 0x63 */
0x03, 0x03, 0x03, 0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, /* 'd' 0x64 */
0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 'e' 0x65 */
0x36, 0x6F, 0x66, 0x66, 0x66, 0x66, 0x60, /* 'f' 0x66 */
0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0xC6, 0x7C, /* 'g' 0x67 */
0xC0, 0xC0, 0xC0, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'h' 0x68 */
0xC3, 0xFF, 0xFF, 0xC0, /* 'i' 0x69 */
0x30, 0x03, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0xE0, /* 'j' 0x6A */
0xC0, 0xC0, 0xC0, 0xC2, 0xC4, 0xCC, 0xD8, 0xF8, 0xEC, 0xC4, 0xC6, 0xC3, 0xC3, /* 'k' 0x6B */
0xFF, 0xFF, 0xFF, 0xC0, /* 'l' 0x6C */
0xDE, 0xF7, 0x1C, 0xF0, 0xC7, 0x86, 0x3C, 0x31, 0xE1, 0x8F, 0x0C, 0x78, 0x63, 0xC3, 0x1E, 0x18, 0xC0, /* 'm' 0x6D */
0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 'n' 0x6E */
0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 'o' 0x6F */
0xDE, 0x71, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xE3, 0x6F, 0x30, 0x18, 0x0C, 0x00, /* 'p' 0x70 */
0x3B, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x67, 0x3B, 0x03, 0x03, 0x03, /* 'q' 0x71 */
0xDF, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0x00, /* 'r' 0x72 */
0x3E, 0xE3, 0xC0, 0xC0, 0xE0, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 's' 0x73 */
0x66, 0xF6, 0x66, 0x66, 0x66, 0x67, /* 't' 0x74 */
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 'u' 0x75 */
0xC1, 0xA0, 0x98, 0xCC, 0x42, 0x21, 0xB0, 0xD0, 0x28, 0x1C, 0x0C, 0x00, /* 'v' 0x76 */
0xC6, 0x1E, 0x38, 0x91, 0xC4, 0xCA, 0x66, 0xD3, 0x16, 0xD0, 0xA6, 0x87, 0x1C, 0x38, 0xC0, 0xC6, 0x00, /* 'w' 0x77 */
0x87, 0x89, 0xB1, 0xC3, 0x07, 0x1E, 0x26, 0xC5, 0x0C, /* 'x' 0x78 */
0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 'y' 0x79 */
0xFE, 0x0C, 0x30, 0xC1, 0x86, 0x18, 0x20, 0xC1, 0xFC, /* 'z' 0x7A */
0x36, 0x66, 0x66, 0x6E, 0xCE, 0x66, 0x66, 0x66, 0x30, /* '{' 0x7B */
0xFF, 0xFF, 0xFF, 0xFF, 0xC0, /* '|' 0x7C */
0xC6, 0x66, 0x66, 0x67, 0x37, 0x66, 0x66, 0x66, 0xC0, /* '}' 0x7D */
0x61, 0x24, 0x38, /* '~' 0x7E */
0xFF, 0xFC, 0x00, 0x63, 0xE3, 0x31, 0x99, 0x04, 0xC8, 0x66, 0x06, 0x30, 0x61, 0x83, 0x0C, 0x18, 0x60, 0x03, 0x06, 0x18, 0x00,
0xFF, 0xFC, /* 0x7F */
0x07, 0xC6, 0x13, 0x00, 0xC0, 0x60, 0x3F, 0xE6, 0x03, 0xFC, 0x60, 0x0C, 0x03, 0x00, 0x61, 0x07, 0xC0, /* 0x80 */
/* 0x81 */
0xDC, /* 0x82 */
0x19, 0x8C, 0xF3, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, 0xC6, 0xE0, /* 0x83 */
0xDA, 0x76, /* 0x84 */
0xCC, 0xC0, /* 0x85 */
0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, /* 0x86 */
0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x18, 0x18, 0x18, 0x18, /* 0x87 */
0x72, 0xA2, /* 0x88 */
0x70, 0x80, 0x22, 0x20, 0x08, 0x90, 0x02, 0x24, 0x00, 0x72, 0x00, 0x00, 0x80, 0x00, 0x40, 0x00, 0x10, 0x00, 0x09, 0xC7, 0x84,
0x8B, 0x31, 0x22, 0x84, 0x88, 0xB3, 0x21, 0xC7, 0x80, /* 0x89 */
0x1B, 0x03, 0x80, 0x00, 0xFC, 0x61, 0xB0, 0x3C, 0x0F, 0x00, 0x78, 0x07, 0xC0, 0x38, 0x03, 0xC0, 0xF0, 0x36, 0x18,
0xFC, /* 0x8A */
0x69, /* 0x8B */
0x1E, 0xFE, 0x43, 0x81, 0x83, 0x06, 0x06, 0x0C, 0x0C, 0x18, 0x18, 0x30, 0x3F, 0xE0, 0x60, 0xC0, 0xC1, 0x81, 0x81, 0x83, 0x01,
0x8E, 0x01, 0xEF, 0xE0, /* 0x8C */
/* 0x8D */
0x1B, 0x03, 0x80, 0x03, 0xFF, 0x01, 0x80, 0xC0, 0x30, 0x18, 0x0C, 0x07, 0x01, 0x80, 0xC0, 0x60, 0x18, 0x0C, 0x03,
0xFF, /* 0x8E */
/* 0x8F */
/* 0x90 */
0x6B, /* 0x91 */
0xD6, /* 0x92 */
0x4C, 0xA5, 0xB0, /* 0x93 */
0xDA, 0x53, 0x20, /* 0x94 */
0x6F, 0xFF, 0x60, /* 0x95 */
0xFE, /* 0x96 */
0xFF, 0xFF, /* 0x97 */
0x4D, 0xC0, /* 0x98 */
0xFC, 0xE1, 0xCC, 0x38, 0x73, 0x0E, 0x1C, 0xC3, 0x8F, 0x30, 0xD2, 0xCC, 0x34, 0xB3, 0x0D, 0x6C, 0xC3, 0x53, 0x30, 0xCC, 0xCC,
0x33, 0x30, /* 0x99 */
0x24, 0x3C, 0x18, 0x7E, 0xE3, 0xC0, 0xC0, 0x60, 0x3C, 0x07, 0xC3, 0xE3, 0x7E, /* 0x9A */
0x96, /* 0x9B */
0x3C, 0xF8, 0xCF, 0x1B, 0x0C, 0x1E, 0x18, 0x3C, 0x3F, 0xF8, 0x60, 0x30, 0xC0, 0x61, 0x83, 0x67, 0x8C, 0x79, 0xF0, /* 0x9C */
/* 0x9D */
0x48, 0xF0, 0xC7, 0xF0, 0x61, 0x86, 0x0C, 0x30, 0xC1, 0x06, 0x0F, 0xE0, /* 0x9E */
0x19, 0x80, 0x00, 0xC0, 0x36, 0x06, 0x30, 0xC3, 0x0C, 0x19, 0x81, 0xD8, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
0x60, /* 0x9F */
/* 0xA0 */
0xCF, 0xFF, 0xFF, 0xC0, /* 0xA1 */
0x08, 0x04, 0x0F, 0x8D, 0x6C, 0x9E, 0x43, 0x21, 0x90, 0xC8, 0x64, 0xDA, 0xC7, 0xC0, 0x80, 0x40, /* 0xA2 */
0x1F, 0x0C, 0x66, 0x0D, 0x83, 0x60, 0x0C, 0x0F, 0xC0, 0x60, 0x18, 0x06, 0x03, 0x01, 0xF1, 0x43, 0xC0, /* 0xA3 */
0xFF, 0xDF, 0x1E, 0x3E, 0xFF, 0xC0, /* 0xA4 */
0xC3, 0x42, 0x42, 0x24, 0x24, 0x3C, 0x18, 0x7E, 0x18, 0x7E, 0x18, 0x18, 0x18, /* 0xA5 */
0xFF, 0xFC, 0x0F, 0xFF, 0xC0, /* 0xA6 */
0x0C, 0x09, 0x0C, 0xC6, 0x63, 0x81, 0xE3, 0x19, 0x87, 0xE1, 0xB8, 0xC6, 0x41, 0xC0, 0x73, 0x19, 0x8C, 0x66, 0x1E,
0x00, /* 0xA7 */
0xCC, /* 0xA8 */
0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9B, 0xC6, 0xD9, 0x8F, 0x60, 0x3D, 0x00, 0xF4, 0x03, 0xD8, 0x0D, 0xE6, 0x67, 0xF3, 0x86, 0x18,
0x0F, 0xC0, /* 0xA9 */
0x74, 0x8D, 0xA9, 0x7C, 0x1F, /* 0xAA */
0x22, 0xCF, 0x26, 0x46, 0x64, 0x40, /* 0xAB */
0xFF, 0x80, 0xC0, 0x60, 0x30, 0x18, /* 0xAC */
/* 0xAD */
0x0F, 0xC0, 0x61, 0x87, 0x03, 0x9F, 0xE6, 0xD0, 0x8F, 0x42, 0x3D, 0xF0, 0xF4, 0x23, 0xD0, 0x8D, 0xC2, 0x67, 0x0B, 0x86, 0x18,
0x0F, 0xC0, /* 0xAE */
0xF8, /* 0xAF */
0x74, 0x63, 0x17, 0x00, /* 0xB0 */
0x0C, 0x06, 0x03, 0x07, 0xE0, 0xC0, 0x60, 0x30, 0x18, 0x00, 0x00, 0x3F, 0xE0, /* 0xB1 */
0x7B, 0x30, 0xC3, 0x11, 0x84, 0x3F, /* 0xB2 */
0x7D, 0x8C, 0x18, 0xC0, 0x60, 0xF1, 0xBE, /* 0xB3 */
0x36, 0xC0, /* 0xB4 */
0xC3, 0x61, 0xB0, 0xD8, 0x6C, 0x36, 0x1B, 0x0D, 0x86, 0xE7, 0x7D, 0xF0, 0x18, 0x0C, 0x00, /* 0xB5 */
0x3F, 0x7E, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0x72, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, /* 0xB6 */
0xE0, /* 0xB7 */
0x21, 0xC7, 0xE0, /* 0xB8 */
0x3D, 0xB6, 0xD8, /* 0xB9 */
0x74, 0x63, 0x18, 0xB8, 0x1F, /* 0xBA */
0x89, 0x98, 0x99, 0x3C, 0xD1, 0x00, /* 0xBB */
0x20, 0x43, 0x81, 0x06, 0x08, 0x18, 0x20, 0x61, 0x01, 0x84, 0x06, 0x21, 0x80, 0x86, 0x04, 0x78, 0x32, 0x60, 0x87, 0xC4, 0x06,
0x10, 0x18, /* 0xBC */
0x20, 0x43, 0x81, 0x06, 0x08, 0x18, 0x20, 0x61, 0x01, 0x8D, 0xE6, 0x2C, 0xC1, 0x03, 0x0C, 0x0C, 0x20, 0x41, 0x86, 0x0C, 0x30,
0x20, 0xFC, /* 0xBD */
0x78, 0x11, 0x98, 0x40, 0x31, 0x00, 0x82, 0x00, 0xC8, 0x01, 0x90, 0x33, 0x43, 0x3D, 0x06, 0x02, 0x3C, 0x08, 0x98, 0x10, 0xF8,
0x40, 0x61, 0x00, 0xC0, /* 0xBE */
0x0C, 0x00, 0x00, 0x01, 0x80, 0xC0, 0xC0, 0xE0, 0xC0, 0xC0, 0x60, 0xF0, 0x6C, 0x63, 0xE0, /* 0xBF */
0x18, 0x03, 0x00, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC0 */
0x06, 0x03, 0x00, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC1 */
0x0C, 0x04, 0x80, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC2 */
0x19, 0x09, 0x80, 0x00, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC3 */
0x33, 0x00, 0x00, 0xC0, 0x78, 0x1E, 0x04, 0x83, 0x30, 0xCC, 0x33, 0x1F, 0xE6, 0x19, 0x02, 0xC0, 0xF0, 0x30, /* 0xC4 */
0x0C, 0x04, 0x81, 0x20, 0x30, 0x1E, 0x07, 0x81, 0x20, 0xCC, 0x33, 0x0F, 0xC6, 0x19, 0x86, 0x40, 0xB0, 0x30, /* 0xC5 */
0x07, 0xFF, 0x04, 0xC0, 0x0C, 0xC0, 0x08, 0xC0, 0x18, 0xC0, 0x18, 0xC0, 0x30, 0xFF, 0x30, 0xC0, 0x3F, 0xC0, 0x60, 0xC0, 0x60,
0xC0, 0xC0, 0xC0, 0xC0, 0xFF, /* 0xC6 */
0x1F, 0x06, 0x19, 0x83, 0xA0, 0x3C, 0x01, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x68, 0x0D, 0x83, 0x18, 0xE1, 0xF0, 0x08, 0x01, 0xC0,
0x18, 0x0E, 0x00, /* 0xC7 */
0x18, 0x06, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xC8 */
0x0C, 0x0C, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xC9 */
0x1C, 0x1B, 0x00, 0x1F, 0xFC, 0x06, 0x03, 0x01, 0x80, 0xFF, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xCA */
0x33, 0x00, 0x3F, 0xF8, 0x0C, 0x06, 0x03, 0x01, 0xFE, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x07, 0xFC, /* 0xCB */
0xCC, 0x36, 0xDB, 0x6D, 0xB6, 0xD8, /* 0xCC */
0x78, 0x36, 0xDB, 0x6D, 0xB6, 0xC0, /* 0xCD */
0x76, 0xC0, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x63, 0x18, /* 0xCE */
0xCC, 0x03, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC0, /* 0xCF */
0x7F, 0x0C, 0x31, 0x83, 0x30, 0x36, 0x06, 0xC0, 0xFE, 0x1B, 0x03, 0x60, 0x6C, 0x0D, 0x83, 0x30, 0xE7, 0xF0, /* 0xD0 */
0x19, 0x02, 0xC3, 0x81, 0xF0, 0x3F, 0x07, 0xA0, 0xF6, 0x1E, 0x63, 0xC4, 0x78, 0xCF, 0x0D, 0xE1, 0xBC, 0x1F, 0x81,
0xC0, /* 0xD1 */
0x0C, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C,
0x0F, 0x00, /* 0xD2 */
0x03, 0x00, 0x60, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C,
0x0F, 0x00, /* 0xD3 */
0x0F, 0x01, 0x98, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C,
0x0F, 0x00, /* 0xD4 */
0x1C, 0x81, 0x38, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C,
0x0F, 0x00, /* 0xD5 */
0x19, 0x81, 0x98, 0x00, 0x00, 0xF0, 0x39, 0xC6, 0x06, 0x60, 0x6C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x9C,
0x0F, 0x00, /* 0xD6 */
0x83, 0x89, 0xA1, 0x83, 0x89, 0xA1, 0x80, /* 0xD7 */
0x0F, 0xD9, 0x83, 0x18, 0x1C, 0xC1, 0xEC, 0x19, 0xE0, 0x8F, 0x08, 0x78, 0x83, 0xC8, 0x1B, 0x81, 0x98, 0x0C, 0xE0, 0xC8, 0xF8,
0x00, /* 0xD8 */
0x0C, 0x00, 0xC3, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E,
0x00, /* 0xD9 */
0x06, 0x01, 0x83, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E,
0x00, /* 0xDA */
0x0E, 0x03, 0x63, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E,
0x00, /* 0xDB */
0x1B, 0x00, 0x03, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x36, 0x0C, 0x3E,
0x00, /* 0xDC */
0x03, 0x0C, 0x63, 0x60, 0x63, 0x0C, 0x30, 0xC1, 0x98, 0x1D, 0x80, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
0x60, /* 0xDD */
0xC0, 0x30, 0x0F, 0xF3, 0x06, 0xC0, 0xF0, 0x3C, 0x0F, 0x06, 0xFF, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, /* 0xDE */
0x3C, 0x33, 0x30, 0xD8, 0x6C, 0x36, 0x33, 0x39, 0x86, 0xC1, 0xE0, 0xF0, 0x78, 0x6D, 0xE0, /* 0xDF */
0x60, 0x18, 0x06, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE0 */
0x0C, 0x04, 0x04, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE1 */
0x10, 0x14, 0x1B, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE2 */
0x24, 0x2E, 0x00, 0x0F, 0xCE, 0x36, 0x18, 0x0C, 0x1E, 0x7B, 0x61, 0xB0, 0xD8, 0xE7, 0xB8, /* 0xE3 */
0x66, 0x00, 0x1F, 0x9C, 0x6C, 0x30, 0x18, 0x3C, 0xF6, 0xC3, 0x61, 0xB1, 0xCF, 0x70, /* 0xE4 */
0x1C, 0x1B, 0x0D, 0x83, 0x87, 0xE7, 0x1B, 0x0C, 0x06, 0x0F, 0x3D, 0xB0, 0xD8, 0x6C, 0x73, 0xDC, /* 0xE5 */
0x7E, 0xF9, 0xC7, 0x1B, 0x0C, 0x18, 0x18, 0x33, 0xFF, 0xFC, 0x60, 0x30, 0xC0, 0x61, 0x83, 0xC7, 0x8C, 0xF1, 0xF0, /* 0xE6 */
0x3C, 0x66, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, 0x10, 0x1C, 0x0C, 0x38, /* 0xE7 */
0x60, 0x30, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE8 */
0x0C, 0x08, 0x18, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xE9 */
0x10, 0x28, 0x6C, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xEA */
0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xFF, 0xC0, 0xC0, 0xC3, 0x66, 0x3C, /* 0xEB */
0xCC, 0xB6, 0xDB, 0x6D, 0xB6, /* 0xEC */
0x7A, 0x6D, 0xB6, 0xDB, 0x6C, /* 0xED */
0x6E, 0x96, 0x66, 0x66, 0x66, 0x66, 0x60, /* 0xEE */
0xCC, 0x03, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, /* 0xEF */
0x34, 0x0C, 0x16, 0x03, 0x3F, 0x67, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF0 */
0x24, 0x5C, 0x00, 0xDE, 0xE3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, /* 0xF1 */
0x30, 0x18, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF2 */
0x0C, 0x18, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF3 */
0x18, 0x24, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF4 */
0x34, 0x2C, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF5 */
0x66, 0x00, 0x3C, 0x66, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x66, 0x3C, /* 0xF6 */
0x18, 0x00, 0x00, 0x1F, 0xF0, 0x00, 0x00, 0x00, 0x30, /* 0xF7 */
0x3D, 0x66, 0xC7, 0xCB, 0xCB, 0xD3, 0xD3, 0xE3, 0x66, 0xBC, /* 0xF8 */
0x60, 0x30, 0x18, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xF9 */
0x06, 0x0C, 0x18, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFA */
0x3C, 0x66, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFB */
0x66, 0x00, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC7, 0x7B, /* 0xFC */
0x06, 0x04, 0x08, 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xFD */
0xC0, 0x60, 0x30, 0x1B, 0xCE, 0x36, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x7C, 0x6D, 0xE6, 0x03, 0x01, 0x80, /* 0xFE */
0x33, 0x00, 0xC1, 0x43, 0x63, 0x62, 0x26, 0x36, 0x34, 0x1C, 0x1C, 0x18, 0x18, 0x18, 0x10, 0x60, /* 0xFF */
};
const GFXglyph FreeSans9pt_Win1252Glyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 5, 0, 0},
/* '!' 0x21 */ {0, 2, 13, 6, 2, -12},
/* '"' 0x22 */ {4, 5, 4, 6, 1, -12},
/* '#' 0x23 */ {7, 10, 12, 10, 0, -11},
/* '$' 0x24 */ {22, 9, 16, 10, 1, -13},
/* '%' 0x25 */ {40, 16, 13, 16, 1, -12},
/* '&' 0x26 */ {66, 10, 13, 12, 1, -12},
/* ''' 0x27 */ {83, 2, 4, 4, 1, -12},
/* '(' 0x28 */ {84, 4, 17, 6, 1, -12},
/* ')' 0x29 */ {93, 4, 17, 6, 1, -12},
/* '*' 0x2A */ {102, 5, 5, 7, 1, -12},
/* '+' 0x2B */ {106, 6, 8, 11, 3, -7},
/* ',' 0x2C */ {112, 2, 4, 5, 2, 0},
/* '-' 0x2D */ {113, 4, 1, 6, 1, -4},
/* '.' 0x2E */ {114, 2, 1, 5, 1, 0},
/* '/' 0x2F */ {115, 5, 13, 5, 0, -12},
/* '0' 0x30 */ {124, 8, 13, 10, 1, -12},
/* '1' 0x31 */ {137, 4, 13, 10, 3, -12},
/* '2' 0x32 */ {144, 9, 13, 10, 1, -12},
/* '3' 0x33 */ {159, 8, 13, 10, 1, -12},
/* '4' 0x34 */ {172, 7, 13, 10, 2, -12},
/* '5' 0x35 */ {184, 9, 13, 10, 1, -12},
/* '6' 0x36 */ {199, 9, 13, 10, 1, -12},
/* '7' 0x37 */ {214, 8, 13, 10, 0, -12},
/* '8' 0x38 */ {227, 9, 13, 10, 1, -12},
/* '9' 0x39 */ {242, 8, 13, 10, 1, -12},
/* ':' 0x3A */ {255, 2, 10, 5, 1, -9},
/* ';' 0x3B */ {258, 3, 12, 5, 1, -8},
/* '<' 0x3C */ {263, 9, 9, 11, 1, -8},
/* '=' 0x3D */ {274, 9, 4, 11, 1, -5},
/* '>' 0x3E */ {279, 9, 8, 11, 1, -7},
/* '?' 0x3F */ {288, 9, 13, 10, 1, -12},
/* '@' 0x40 */ {303, 17, 16, 18, 1, -12},
/* 'A' 0x41 */ {337, 12, 13, 12, 0, -12},
/* 'B' 0x42 */ {357, 11, 13, 12, 1, -12},
/* 'C' 0x43 */ {375, 11, 13, 13, 1, -12},
/* 'D' 0x44 */ {393, 11, 13, 13, 1, -12},
/* 'E' 0x45 */ {411, 9, 13, 11, 1, -12},
/* 'F' 0x46 */ {426, 8, 13, 11, 1, -12},
/* 'G' 0x47 */ {439, 12, 13, 14, 1, -12},
/* 'H' 0x48 */ {459, 11, 13, 13, 1, -12},
/* 'I' 0x49 */ {477, 2, 13, 5, 2, -12},
/* 'J' 0x4A */ {481, 7, 13, 10, 1, -12},
/* 'K' 0x4B */ {493, 10, 13, 12, 1, -12},
/* 'L' 0x4C */ {510, 8, 13, 10, 1, -12},
/* 'M' 0x4D */ {523, 13, 13, 15, 1, -12},
/* 'N' 0x4E */ {545, 11, 13, 13, 1, -12},
/* 'O' 0x4F */ {563, 13, 13, 14, 1, -12},
/* 'P' 0x50 */ {585, 10, 13, 12, 1, -12},
/* 'Q' 0x51 */ {602, 13, 14, 14, 1, -12},
/* 'R' 0x52 */ {625, 12, 13, 13, 1, -12},
/* 'S' 0x53 */ {645, 10, 13, 12, 1, -12},
/* 'T' 0x54 */ {662, 9, 13, 11, 1, -12},
/* 'U' 0x55 */ {677, 11, 13, 13, 1, -12},
/* 'V' 0x56 */ {695, 11, 13, 11, 0, -12},
/* 'W' 0x57 */ {713, 16, 13, 17, 0, -12},
/* 'X' 0x58 */ {739, 10, 13, 12, 1, -12},
/* 'Y' 0x59 */ {756, 12, 13, 12, 0, -12},
/* 'Z' 0x5A */ {776, 10, 13, 11, 1, -12},
/* '[' 0x5B */ {793, 3, 17, 5, 1, -12},
/* '\' 0x5C */ {800, 5, 13, 5, 0, -12},
/* ']' 0x5D */ {809, 3, 17, 5, 0, -12},
/* '^' 0x5E */ {816, 7, 7, 8, 1, -12},
/* '_' 0x5F */ {823, 10, 1, 10, 0, 3},
/* '`' 0x60 */ {825, 4, 3, 5, 0, -12},
/* 'a' 0x61 */ {827, 9, 10, 10, 1, -9},
/* 'b' 0x62 */ {839, 9, 13, 10, 1, -12},
/* 'c' 0x63 */ {854, 8, 10, 9, 1, -9},
/* 'd' 0x64 */ {864, 8, 13, 10, 1, -12},
/* 'e' 0x65 */ {877, 8, 10, 10, 1, -9},
/* 'f' 0x66 */ {887, 4, 13, 5, 1, -12},
/* 'g' 0x67 */ {894, 8, 14, 10, 1, -9},
/* 'h' 0x68 */ {908, 8, 13, 10, 1, -12},
/* 'i' 0x69 */ {921, 2, 13, 4, 1, -12},
/* 'j' 0x6A */ {925, 4, 17, 4, 0, -12},
/* 'k' 0x6B */ {934, 8, 13, 9, 1, -12},
/* 'l' 0x6C */ {947, 2, 13, 4, 1, -12},
/* 'm' 0x6D */ {951, 13, 10, 15, 1, -9},
/* 'n' 0x6E */ {968, 8, 10, 10, 1, -9},
/* 'o' 0x6F */ {978, 8, 10, 10, 1, -9},
/* 'p' 0x70 */ {988, 9, 13, 10, 1, -9},
/* 'q' 0x71 */ {1003, 8, 13, 10, 1, -9},
/* 'r' 0x72 */ {1016, 5, 10, 6, 1, -9},
/* 's' 0x73 */ {1023, 8, 10, 9, 1, -9},
/* 't' 0x74 */ {1033, 4, 12, 5, 1, -11},
/* 'u' 0x75 */ {1039, 8, 10, 10, 1, -9},
/* 'v' 0x76 */ {1049, 9, 10, 9, 0, -9},
/* 'w' 0x77 */ {1061, 13, 10, 13, 0, -9},
/* 'x' 0x78 */ {1078, 7, 10, 9, 1, -9},
/* 'y' 0x79 */ {1087, 8, 14, 9, 0, -9},
/* 'z' 0x7A */ {1101, 7, 10, 9, 1, -9},
/* '{' 0x7B */ {1110, 4, 17, 6, 1, -12},
/* '|' 0x7C */ {1119, 2, 17, 4, 2, -12},
/* '}' 0x7D */ {1124, 4, 17, 6, 1, -12},
/* '~' 0x7E */ {1133, 7, 3, 9, 1, -7},
/* 0x7F */ {1136, 13, 14, 15, 1, -12},
/* 0x80 */ {1159, 10, 13, 12, 1, -12},
/* 0x81 */ {1176, 0, 0, 8, 0, 0},
/* 0x82 */ {1176, 2, 3, 5, 1, 0},
/* 0x83 */ {1177, 5, 17, 5, 0, -12},
/* 0x84 */ {1188, 5, 3, 7, 1, 0},
/* 0x85 */ {1190, 10, 1, 12, 1, 0},
/* 0x86 */ {1192, 8, 16, 10, 1, -12},
/* 0x87 */ {1208, 8, 16, 10, 1, -12},
/* 0x88 */ {1224, 5, 3, 6, 0, -12},
/* 0x89 */ {1226, 18, 13, 18, 0, -12},
/* 0x8A */ {1256, 10, 16, 12, 1, -15},
/* 0x8B */ {1276, 2, 4, 4, 1, -6},
/* 0x8C */ {1277, 15, 13, 18, 1, -12},
/* 0x8D */ {1302, 0, 0, 8, 0, 0},
/* 0x8E */ {1302, 10, 16, 11, 1, -15},
/* 0x8F */ {1322, 0, 0, 8, 0, 0},
/* 0x90 */ {1322, 0, 0, 8, 0, 0},
/* 0x91 */ {1322, 2, 4, 4, 2, -12},
/* 0x92 */ {1323, 2, 4, 4, 1, -12},
/* 0x93 */ {1324, 5, 4, 7, 2, -12},
/* 0x94 */ {1327, 5, 4, 7, 1, -12},
/* 0x95 */ {1330, 4, 5, 7, 1, -8},
/* 0x96 */ {1333, 7, 1, 9, 1, -4},
/* 0x97 */ {1334, 16, 1, 18, 1, -4},
/* 0x98 */ {1336, 5, 2, 6, 0, -12},
/* 0x99 */ {1338, 18, 10, 18, 1, -13},
/* 0x9A */ {1361, 8, 13, 9, 1, -12},
/* 0x9B */ {1374, 2, 4, 5, 2, -6},
/* 0x9C */ {1375, 15, 10, 17, 1, -9},
/* 0x9D */ {1394, 0, 0, 8, 0, 0},
/* 0x9E */ {1394, 7, 13, 9, 1, -12},
/* 0x9F */ {1406, 12, 14, 12, 0, -13},
/* 0xA0 */ {1427, 0, 0, 5, 0, 0},
/* 0xA1 */ {1427, 2, 13, 6, 2, -8},
/* 0xA2 */ {1431, 9, 14, 10, 1, -11},
/* 0xA3 */ {1447, 10, 13, 10, 0, -12},
/* 0xA4 */ {1464, 7, 6, 10, 2, -8},
/* 0xA5 */ {1470, 8, 13, 10, 1, -12},
/* 0xA6 */ {1483, 2, 17, 5, 2, -12},
/* 0xA7 */ {1488, 9, 17, 10, 1, -12},
/* 0xA8 */ {1508, 6, 1, 6, 0, -11},
/* 0xA9 */ {1509, 14, 13, 14, 1, -12},
/* 0xAA */ {1532, 5, 8, 7, 1, -12},
/* 0xAB */ {1537, 7, 6, 9, 1, -7},
/* 0xAC */ {1543, 9, 5, 11, 2, -5},
/* 0xAD */ {1549, 0, 0, 0, 0, 0},
/* 0xAE */ {1549, 14, 13, 14, 1, -12},
/* 0xAF */ {1572, 5, 1, 6, 0, -12},
/* 0xB0 */ {1573, 5, 5, 11, 3, -11},
/* 0xB1 */ {1577, 9, 11, 11, 1, -10},
/* 0xB2 */ {1590, 6, 8, 6, 1, -13},
/* 0xB3 */ {1596, 7, 8, 6, 0, -13},
/* 0xB4 */ {1603, 4, 3, 6, 2, -12},
/* 0xB5 */ {1605, 9, 13, 10, 1, -9},
/* 0xB6 */ {1620, 8, 16, 10, 2, -12},
/* 0xB7 */ {1636, 3, 1, 5, 1, -4},
/* 0xB8 */ {1637, 5, 4, 6, 1, 1},
/* 0xB9 */ {1640, 3, 7, 6, 2, -13},
/* 0xBA */ {1643, 5, 8, 7, 1, -12},
/* 0xBB */ {1648, 7, 6, 9, 1, -7},
/* 0xBC */ {1654, 14, 13, 16, 2, -12},
/* 0xBD */ {1677, 14, 13, 16, 2, -12},
/* 0xBE */ {1700, 15, 13, 16, 1, -12},
/* 0xBF */ {1725, 9, 13, 10, 1, -8},
/* 0xC0 */ {1740, 10, 14, 12, 1, -13},
/* 0xC1 */ {1758, 10, 14, 12, 1, -13},
/* 0xC2 */ {1776, 10, 14, 12, 1, -13},
/* 0xC3 */ {1794, 10, 14, 12, 1, -13},
/* 0xC4 */ {1812, 10, 14, 12, 1, -13},
/* 0xC5 */ {1830, 10, 14, 12, 1, -13},
/* 0xC6 */ {1848, 16, 13, 18, 1, -12},
/* 0xC7 */ {1874, 11, 17, 13, 1, -12},
/* 0xC8 */ {1898, 9, 14, 11, 1, -13},
/* 0xC9 */ {1914, 9, 14, 11, 1, -13},
/* 0xCA */ {1930, 9, 14, 11, 1, -13},
/* 0xCB */ {1946, 9, 14, 11, 1, -13},
/* 0xCC */ {1962, 3, 15, 5, 1, -13},
/* 0xCD */ {1968, 3, 14, 5, 1, -13},
/* 0xCE */ {1974, 5, 14, 5, 0, -13},
/* 0xCF */ {1983, 6, 14, 5, 0, -13},
/* 0xD0 */ {1994, 11, 13, 13, 1, -12},
/* 0xD1 */ {2012, 11, 14, 13, 1, -13},
/* 0xD2 */ {2032, 12, 15, 13, 1, -14},
/* 0xD3 */ {2055, 12, 15, 13, 1, -14},
/* 0xD4 */ {2078, 12, 15, 13, 1, -14},
/* 0xD5 */ {2101, 12, 15, 13, 1, -14},
/* 0xD6 */ {2124, 12, 15, 13, 1, -14},
/* 0xD7 */ {2147, 7, 7, 11, 2, -7},
/* 0xD8 */ {2154, 13, 13, 14, 1, -12},
/* 0xD9 */ {2176, 11, 14, 13, 1, -13},
/* 0xDA */ {2196, 11, 14, 13, 1, -13},
/* 0xDB */ {2216, 11, 14, 13, 1, -13},
/* 0xDC */ {2236, 11, 14, 13, 1, -13},
/* 0xDD */ {2256, 12, 14, 12, 0, -13},
/* 0xDE */ {2277, 10, 13, 12, 1, -12},
/* 0xDF */ {2294, 9, 13, 11, 1, -12},
/* 0xE0 */ {2309, 9, 13, 10, 1, -12},
/* 0xE1 */ {2324, 9, 13, 10, 1, -12},
/* 0xE2 */ {2339, 9, 13, 10, 1, -12},
/* 0xE3 */ {2354, 9, 13, 10, 1, -12},
/* 0xE4 */ {2369, 9, 12, 10, 1, -11},
/* 0xE5 */ {2383, 9, 14, 10, 1, -13},
/* 0xE6 */ {2399, 15, 10, 16, 1, -9},
/* 0xE7 */ {2418, 8, 14, 9, 1, -9},
/* 0xE8 */ {2432, 8, 13, 10, 1, -12},
/* 0xE9 */ {2445, 8, 13, 10, 1, -12},
/* 0xEA */ {2458, 8, 13, 10, 1, -12},
/* 0xEB */ {2471, 8, 12, 10, 1, -11},
/* 0xEC */ {2483, 3, 13, 4, 0, -12},
/* 0xED */ {2488, 3, 13, 4, 1, -12},
/* 0xEE */ {2493, 4, 13, 5, 0, -12},
/* 0xEF */ {2500, 6, 12, 5, -1, -11},
/* 0xF0 */ {2509, 8, 13, 10, 1, -12},
/* 0xF1 */ {2522, 8, 13, 10, 1, -12},
/* 0xF2 */ {2535, 8, 13, 10, 1, -12},
/* 0xF3 */ {2548, 8, 13, 10, 1, -12},
/* 0xF4 */ {2561, 8, 13, 10, 1, -12},
/* 0xF5 */ {2574, 8, 13, 10, 1, -12},
/* 0xF6 */ {2587, 8, 12, 10, 1, -11},
/* 0xF7 */ {2599, 9, 8, 11, 1, -7},
/* 0xF8 */ {2608, 8, 10, 10, 1, -9},
/* 0xF9 */ {2618, 8, 13, 10, 1, -12},
/* 0xFA */ {2631, 8, 13, 10, 1, -12},
/* 0xFB */ {2644, 8, 13, 10, 1, -12},
/* 0xFC */ {2657, 8, 12, 10, 1, -11},
/* 0xFD */ {2669, 8, 17, 9, 0, -12},
/* 0xFE */ {2686, 9, 16, 10, 1, -12},
/* 0xFF */ {2704, 8, 16, 9, 0, -11},
};
const GFXfont FreeSans9pt_Win1252 PROGMEM = {(uint8_t *)FreeSans9pt_Win1252Bitmaps, (GFXglyph *)FreeSans9pt_Win1252Glyphs, 0x20,
0xFF, 21};

View File

@@ -263,22 +263,10 @@ uint16_t InkHUD::Applet::Y(float f)
// Print text, specifying the position of any edge / corner of the textbox
void InkHUD::Applet::printAt(int16_t x, int16_t y, const char *text, HorizontalAlignment ha, VerticalAlignment va)
{
printAt(x, y, std::string(text), ha, va);
}
// Print text, specifying the position of any edge / corner of the textbox
void InkHUD::Applet::printAt(int16_t x, int16_t y, std::string text, HorizontalAlignment ha, VerticalAlignment va)
{
// Custom font
// - set with AppletFont::addSubstitution
// - find certain UTF8 chars
// - replace with glyph from custom font (or suitable ASCII addSubstitution?)
getFont().applySubstitutions(&text);
// We do still have to run getTextBounds to find the width
int16_t textOffsetX, textOffsetY;
uint16_t textWidth, textHeight;
getTextBounds(text.c_str(), 0, 0, &textOffsetX, &textOffsetY, &textWidth, &textHeight);
getTextBounds(text, 0, 0, &textOffsetX, &textOffsetY, &textWidth, &textHeight);
int16_t cursorX = 0;
int16_t cursorY = 0;
@@ -310,7 +298,13 @@ void InkHUD::Applet::printAt(int16_t x, int16_t y, std::string text, HorizontalA
}
setCursor(cursorX, cursorY);
print(text.c_str());
print(text);
}
// Print text, specifying the position of any edge / corner of the textbox
void InkHUD::Applet::printAt(int16_t x, int16_t y, std::string text, HorizontalAlignment ha, VerticalAlignment va)
{
printAt(x, y, text.c_str(), ha, va);
}
// Set which font should be used for subsequent drawing
@@ -328,11 +322,52 @@ InkHUD::AppletFont InkHUD::Applet::getFont()
return currentFont;
}
// Parse any text which might have "special characters"
// Re-encodes UTF-8 characters to match our 8-bit encoded fonts
std::string InkHUD::Applet::parse(std::string text)
{
return getFont().decodeUTF8(text);
}
// Get the best version of a node's short name available to us
// Parses any non-ascii chars
// Swaps for last-four of node-id if the real short name is unknown or can't be rendered (emoji)
std::string InkHUD::Applet::parseShortName(meshtastic_NodeInfoLite *node)
{
assert(node);
// Use the true shortname if known, and doesn't contain any unprintable characters (emoji, etc.)
if (node->has_user) {
std::string parsed = parse(node->user.short_name);
if (isPrintable(parsed))
return parsed;
}
// Otherwise, use the "last 4" of node id
// - if short name unknown, or
// - if short name is emoji (we can't render this)
std::string nodeID = hexifyNodeNum(node->num);
return nodeID.substr(nodeID.length() - 4);
}
// Determine if all characters of a string are printable using the current font
bool InkHUD::Applet::isPrintable(std::string text)
{
// Scan for DEL (0x7F), which is the value assigned by AppletFont::applyEncoding if a unicode character is not handled
// Todo: move this to from DEL to SUB, once the fonts have been changed for this
for (char &c : text) {
if (c == '\x7F')
return false;
}
// No unprintable characters found
return true;
}
// Gets rendered width of a string
// Wrapper for getTextBounds
uint16_t InkHUD::Applet::getTextWidth(const char *text)
{
// We do still have to run getTextBounds to find the width
int16_t textOffsetX, textOffsetY;
uint16_t textWidth, textHeight;
@@ -345,8 +380,6 @@ uint16_t InkHUD::Applet::getTextWidth(const char *text)
// Wrapper for getTextBounds
uint16_t InkHUD::Applet::getTextWidth(std::string text)
{
getFont().applySubstitutions(&text);
return getTextWidth(text.c_str());
}
@@ -395,12 +428,6 @@ std::string InkHUD::Applet::hexifyNodeNum(NodeNum num)
// Avoids splitting words in half, instead moving the entire word to a new line wherever possible
void InkHUD::Applet::printWrapped(int16_t left, int16_t top, uint16_t width, std::string text)
{
// Custom font glyphs
// - set with AppletFont::addSubstitution
// - find certain UTF8 chars
// - replace with glyph from custom font (or suitable ASCII addSubstitution?)
getFont().applySubstitutions(&text);
// Place the AdafruitGFX cursor to suit our "top" coord
setCursor(left, top + getFont().heightAboveCursor());

View File

@@ -133,12 +133,15 @@ class Applet : public GFX
void drawLogo(int16_t centerX, int16_t centerY, uint16_t width, uint16_t height,
Color color = BLACK); // Draw the Meshtastic logo
std::string hexifyNodeNum(NodeNum num); // Style as !0123abdc
SignalStrength getSignalStrength(float snr, float rssi); // Interpret SNR and RSSI, as an easy to understand value
std::string getTimeString(uint32_t epochSeconds); // Human readable
std::string getTimeString(); // Current time, human readable
uint16_t getActiveNodeCount(); // Duration determined by user, in onscreen menu
std::string localizeDistance(uint32_t meters); // Human readable distance, imperial or metric
std::string hexifyNodeNum(NodeNum num); // Style as !0123abdc
SignalStrength getSignalStrength(float snr, float rssi); // Interpret SNR and RSSI, as an easy to understand value
std::string getTimeString(uint32_t epochSeconds); // Human readable
std::string getTimeString(); // Current time, human readable
uint16_t getActiveNodeCount(); // Duration determined by user, in onscreen menu
std::string localizeDistance(uint32_t meters); // Human readable distance, imperial or metric
std::string parse(std::string text); // Handle text which might contain special chars
std::string parseShortName(meshtastic_NodeInfoLite *node); // Get the shortname, or a substitute if has unprintable chars
bool isPrintable(std::string); // Check for characters which the font can't print
// Convenient references

View File

@@ -2,14 +2,17 @@
#include "./AppletFont.h"
#include <assert.h>
using namespace NicheGraphics;
InkHUD::AppletFont::AppletFont()
{
// Default constructor uses the in-built AdafruitGFX font
// Default constructor uses the in-built AdafruitGFX font (not recommended)
}
InkHUD::AppletFont::AppletFont(const GFXfont &adafruitGFXFont) : gfxFont(&adafruitGFXFont)
InkHUD::AppletFont::AppletFont(const GFXfont &adafruitGFXFont, Encoding encoding, int8_t paddingTop, int8_t paddingBottom)
: gfxFont(&adafruitGFXFont), encoding(encoding)
{
// AdafruitGFX fonts are drawn relative to a "cursor line";
// they print as if the glyphs are resting on the line of piece of ruled paper.
@@ -22,6 +25,10 @@ InkHUD::AppletFont::AppletFont(const GFXfont &adafruitGFXFont) : gfxFont(&adafru
// AdafruitGFX fonts do declare a line-height, but this seems to include a certain amount of padding,
// which we'd rather not deal with. If we want padding, we'll add it manually.
this->ascenderHeight = 0;
this->descenderHeight = 0;
this->height = 0;
// Scan each glyph in the AdafruitGFX font
for (uint16_t i = 0; i <= (gfxFont->last - gfxFont->first); i++) {
uint8_t glyphHeight = gfxFont->glyph[i].height; // Height of glyph
@@ -33,10 +40,16 @@ InkHUD::AppletFont::AppletFont(const GFXfont &adafruitGFXFont) : gfxFont(&adafru
int8_t glyphAscender = 0 - gfxFont->glyph[i].yOffset;
if (glyphAscender > 0)
this->ascenderHeight = max(this->ascenderHeight, (uint8_t)glyphAscender);
int8_t glyphDescender = gfxFont->glyph[i].height + gfxFont->glyph[i].yOffset;
if (glyphDescender > 0)
this->descenderHeight = max(this->descenderHeight, (uint8_t)glyphDescender);
}
// Determine how far characters may hang "below the line"
descenderHeight = height - ascenderHeight;
// Apply any manual padding to grow or shrink the line size
// Helpful if a font has one or two exceptionally large characters, which would make the lines ridiculously tall
ascenderHeight += paddingTop;
descenderHeight += paddingBottom;
// Find how far the cursor advances when we "print" a space character
spaceCharWidth = gfxFont->glyph[(uint8_t)' ' - gfxFont->first].xAdvance;
@@ -83,139 +96,533 @@ uint8_t InkHUD::AppletFont::widthBetweenWords()
return this->spaceCharWidth;
}
// Add to the list of substituted glyphs
// This "find and replace" operation will be run before text is printed
// Used to swap out UTF8 special characters, either with a custom font, or with a suitable ASCII approximation
void InkHUD::AppletFont::addSubstitution(const char *from, const char *to)
// Convert a unicode char from set of UTF-8 bytes to UTF-32
// Used by AppletFont::applyEncoding, which remaps unicode chars for extended ASCII fonts, based on their UTF-32 value
uint32_t InkHUD::AppletFont::toUtf32(std::string utf8)
{
substitutions.push_back({.from = from, .to = to});
uint32_t utf32 = 0;
switch (utf8.length()) {
case 2:
// 5 bits + 6 bits
utf32 |= (utf8.at(0) & 0b00011111) << 6;
utf32 |= (utf8.at(1) & 0b00111111);
break;
case 3:
// 4 bits + 6 bits + 6 bits
utf32 |= (utf8.at(0) & 0b00001111) << (6 + 6);
utf32 |= (utf8.at(1) & 0b00111111) << 6;
utf32 |= (utf8.at(2) & 0b00111111);
break;
case 4:
// 3 bits + 6 bits + 6 bits + 6 bits
utf32 |= (utf8.at(0) & 0b00000111) << (6 + 6 + 6);
utf32 |= (utf8.at(1) & 0b00111111) << (6 + 6);
utf32 |= (utf8.at(2) & 0b00111111) << 6;
utf32 |= (utf8.at(3) & 0b00111111);
break;
default:
assert(false);
}
return utf32;
}
// Run all registered substitutions on a string
// Used to swap out UTF8 special chars
void InkHUD::AppletFont::applySubstitutions(std::string *text)
// Process a string, collating UTF-8 bytes, and sending them off for re-encoding to extended ASCII
// Not all InkHUD text is passed through here, only text which could potentially contain non-ASCII chars
std::string InkHUD::AppletFont::decodeUTF8(std::string encoded)
{
// For each substitution
for (Substitution s : substitutions) {
// Final processed output
std::string decoded;
// Find and replace
// - search for Substitution::from
// - replace with Substitution::to
size_t i = text->find(s.from);
while (i != std::string::npos) {
text->replace(i, strlen(s.from), s.to);
i = text->find(s.from, i); // Continue looking from last position
// Holds bytes for one UTF-8 char during parsing
std::string utf8Char;
uint8_t utf8CharSize = 0;
for (char &c : encoded) {
// If first byte
if (utf8Char.empty()) {
// If MSB is unset, byte is an ASCII char
// If MSB is set, byte is part of a UTF-8 char. Counting number of higher-order bits tells how many bytes in char
if ((c & 0x80)) {
char c1 = c;
while (c1 & 0x80) {
c1 <<= 1;
utf8CharSize++;
}
}
}
// Append the byte to the UTF-8 char we're building
utf8Char += c;
// More bytes left to collect. Iterate.
if (utf8Char.length() < utf8CharSize)
continue;
// Now collected all bytes for this char
// Remap the value to match the encoding of our 8-bit AppletFont
decoded += applyEncoding(utf8Char);
// Reset, ready to build next UTF-8 char from the encoded bytes
utf8Char.clear();
utf8CharSize = 0;
} // For each char
// All chars processed, return result
return decoded;
}
// Re-encode a single UTF-8 character to extended ASCII
// Target encoding depends on the font
char InkHUD::AppletFont::applyEncoding(std::string utf8)
{
// ##################################################### Syntactic Sugar #####################################################
#define REMAP(in, out) \
case in: \
return out;
// ###########################################################################################################################
// Latin - Central Europe
// https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1250.TXT
if (encoding == WINDOWS_1250) {
// 1-Byte chars: no remapping
if (utf8.length() == 1)
return utf8.at(0);
// Multi-byte chars:
switch (toUtf32(utf8)) {
REMAP(0x20AC, 0x80); // EURO SIGN
REMAP(0x201A, 0x82); // SINGLE LOW-9 QUOTATION MARK
REMAP(0x201E, 0x84); // DOUBLE LOW-9 QUOTATION MARK
REMAP(0x2026, 0x85); // HORIZONTAL ELLIPSIS
REMAP(0x2020, 0x86); // DAGGER
REMAP(0x2021, 0x87); // DOUBLE DAGGER
REMAP(0x2030, 0x89); // PER MILLE SIGN
REMAP(0x0160, 0x8A); // LATIN CAPITAL LETTER S WITH CARON
REMAP(0x2039, 0x8B); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
REMAP(0x015A, 0x8C); // LATIN CAPITAL LETTER S WITH ACUTE
REMAP(0x0164, 0x8D); // LATIN CAPITAL LETTER T WITH CARON
REMAP(0x017D, 0x8E); // LATIN CAPITAL LETTER Z WITH CARON
REMAP(0x0179, 0x8F); // LATIN CAPITAL LETTER Z WITH ACUTE
REMAP(0x2018, 0x91); // LEFT SINGLE QUOTATION MARK
REMAP(0x2019, 0x92); // RIGHT SINGLE QUOTATION MARK
REMAP(0x201C, 0x93); // LEFT DOUBLE QUOTATION MARK
REMAP(0x201D, 0x94); // RIGHT DOUBLE QUOTATION MARK
REMAP(0x2022, 0x95); // BULLET
REMAP(0x2013, 0x96); // EN DASH
REMAP(0x2014, 0x97); // EM DASH
REMAP(0x2122, 0x99); // TRADE MARK SIGN
REMAP(0x0161, 0x9A); // LATIN SMALL LETTER S WITH CARON
REMAP(0x203A, 0x9B); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
REMAP(0x015B, 0x9C); // LATIN SMALL LETTER S WITH ACUTE
REMAP(0x0165, 0x9D); // LATIN SMALL LETTER T WITH CARON
REMAP(0x017E, 0x9E); // LATIN SMALL LETTER Z WITH CARON
REMAP(0x017A, 0x9F); // LATIN SMALL LETTER Z WITH ACUTE
REMAP(0x00A0, 0xA0); // NO-BREAK SPACE
REMAP(0x02C7, 0xA1); // CARON
REMAP(0x02D8, 0xA2); // BREVE
REMAP(0x0141, 0xA3); // LATIN CAPITAL LETTER L WITH STROKE
REMAP(0x00A4, 0xA4); // CURRENCY SIGN
REMAP(0x0104, 0xA5); // LATIN CAPITAL LETTER A WITH OGONEK
REMAP(0x00A6, 0xA6); // BROKEN BAR
REMAP(0x00A7, 0xA7); // SECTION SIGN
REMAP(0x00A8, 0xA8); // DIAERESIS
REMAP(0x00A9, 0xA9); // COPYRIGHT SIGN
REMAP(0x015E, 0xAA); // LATIN CAPITAL LETTER S WITH CEDILLA
REMAP(0x00AB, 0xAB); // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
REMAP(0x00AC, 0xAC); // NOT SIGN
REMAP(0x00AD, 0xAD); // SOFT HYPHEN
REMAP(0x00AE, 0xAE); // REGISTERED SIGN
REMAP(0x017B, 0xAF); // LATIN CAPITAL LETTER Z WITH DOT ABOVE
REMAP(0x00B0, 0xB0); // DEGREE SIGN
REMAP(0x00B1, 0xB1); // PLUS-MINUS SIGN
REMAP(0x02DB, 0xB2); // OGONEK
REMAP(0x0142, 0xB3); // LATIN SMALL LETTER L WITH STROKE
REMAP(0x00B4, 0xB4); // ACUTE ACCENT
REMAP(0x00B5, 0xB5); // MICRO SIGN
REMAP(0x00B6, 0xB6); // PILCROW SIGN
REMAP(0x00B7, 0xB7); // MIDDLE DOT
REMAP(0x00B8, 0xB8); // CEDILLA
REMAP(0x0105, 0xB9); // LATIN SMALL LETTER A WITH OGONEK
REMAP(0x015F, 0xBA); // LATIN SMALL LETTER S WITH CEDILLA
REMAP(0x00BB, 0xBB); // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
REMAP(0x013D, 0xBC); // LATIN CAPITAL LETTER L WITH CARON
REMAP(0x02DD, 0xBD); // DOUBLE ACUTE ACCENT
REMAP(0x013E, 0xBE); // LATIN SMALL LETTER L WITH CARON
REMAP(0x017C, 0xBF); // LATIN SMALL LETTER Z WITH DOT ABOVE
REMAP(0x0154, 0xC0); // LATIN CAPITAL LETTER R WITH ACUTE
REMAP(0x00C1, 0xC1); // LATIN CAPITAL LETTER A WITH ACUTE
REMAP(0x00C2, 0xC2); // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
REMAP(0x0102, 0xC3); // LATIN CAPITAL LETTER A WITH BREVE
REMAP(0x00C4, 0xC4); // LATIN CAPITAL LETTER A WITH DIAERESIS
REMAP(0x0139, 0xC5); // LATIN CAPITAL LETTER L WITH ACUTE
REMAP(0x0106, 0xC6); // LATIN CAPITAL LETTER C WITH ACUTE
REMAP(0x00C7, 0xC7); // LATIN CAPITAL LETTER C WITH CEDILLA
REMAP(0x010C, 0xC8); // LATIN CAPITAL LETTER C WITH CARON
REMAP(0x00C9, 0xC9); // LATIN CAPITAL LETTER E WITH ACUTE
REMAP(0x0118, 0xCA); // LATIN CAPITAL LETTER E WITH OGONEK
REMAP(0x00CB, 0xCB); // LATIN CAPITAL LETTER E WITH DIAERESIS
REMAP(0x011A, 0xCC); // LATIN CAPITAL LETTER E WITH CARON
REMAP(0x00CD, 0xCD); // LATIN CAPITAL LETTER I WITH ACUTE
REMAP(0x00CE, 0xCE); // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
REMAP(0x010E, 0xCF); // LATIN CAPITAL LETTER D WITH CARON
REMAP(0x0110, 0xD0); // LATIN CAPITAL LETTER D WITH STROKE
REMAP(0x0143, 0xD1); // LATIN CAPITAL LETTER N WITH ACUTE
REMAP(0x0147, 0xD2); // LATIN CAPITAL LETTER N WITH CARON
REMAP(0x00D3, 0xD3); // LATIN CAPITAL LETTER O WITH ACUTE
REMAP(0x00D4, 0xD4); // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
REMAP(0x0150, 0xD5); // LATIN CAPITAL LETTER O WITH DOUBLE ACUTE
REMAP(0x00D6, 0xD6); // LATIN CAPITAL LETTER O WITH DIAERESIS
REMAP(0x00D7, 0xD7); // MULTIPLICATION SIGN
REMAP(0x0158, 0xD8); // LATIN CAPITAL LETTER R WITH CARON
REMAP(0x016E, 0xD9); // LATIN CAPITAL LETTER U WITH RING ABOVE
REMAP(0x00DA, 0xDA); // LATIN CAPITAL LETTER U WITH ACUTE
REMAP(0x0170, 0xDB); // LATIN CAPITAL LETTER U WITH DOUBLE ACUTE
REMAP(0x00DC, 0xDC); // LATIN CAPITAL LETTER U WITH DIAERESIS
REMAP(0x00DD, 0xDD); // LATIN CAPITAL LETTER Y WITH ACUTE
REMAP(0x0162, 0xDE); // LATIN CAPITAL LETTER T WITH CEDILLA
REMAP(0x00DF, 0xDF); // LATIN SMALL LETTER SHARP S
REMAP(0x0155, 0xE0); // LATIN SMALL LETTER R WITH ACUTE
REMAP(0x00E1, 0xE1); // LATIN SMALL LETTER A WITH ACUTE
REMAP(0x00E2, 0xE2); // LATIN SMALL LETTER A WITH CIRCUMFLEX
REMAP(0x0103, 0xE3); // LATIN SMALL LETTER A WITH BREVE
REMAP(0x00E4, 0xE4); // LATIN SMALL LETTER A WITH DIAERESIS
REMAP(0x013A, 0xE5); // LATIN SMALL LETTER L WITH ACUTE
REMAP(0x0107, 0xE6); // LATIN SMALL LETTER C WITH ACUTE
REMAP(0x00E7, 0xE7); // LATIN SMALL LETTER C WITH CEDILLA
REMAP(0x010D, 0xE8); // LATIN SMALL LETTER C WITH CARON
REMAP(0x00E9, 0xE9); // LATIN SMALL LETTER E WITH ACUTE
REMAP(0x0119, 0xEA); // LATIN SMALL LETTER E WITH OGONEK
REMAP(0x00EB, 0xEB); // LATIN SMALL LETTER E WITH DIAERESIS
REMAP(0x011B, 0xEC); // LATIN SMALL LETTER E WITH CARON
REMAP(0x00ED, 0xED); // LATIN SMALL LETTER I WITH ACUTE
REMAP(0x00EE, 0xEE); // LATIN SMALL LETTER I WITH CIRCUMFLEX
REMAP(0x010F, 0xEF); // LATIN SMALL LETTER D WITH CARON
REMAP(0x0111, 0xF0); // LATIN SMALL LETTER D WITH STROKE
REMAP(0x0144, 0xF1); // LATIN SMALL LETTER N WITH ACUTE
REMAP(0x0148, 0xF2); // LATIN SMALL LETTER N WITH CARON
REMAP(0x00F3, 0xF3); // LATIN SMALL LETTER O WITH ACUTE
REMAP(0x00F4, 0xF4); // LATIN SMALL LETTER O WITH CIRCUMFLEX
REMAP(0x0151, 0xF5); // LATIN SMALL LETTER O WITH DOUBLE ACUTE
REMAP(0x00F6, 0xF6); // LATIN SMALL LETTER O WITH DIAERESIS
REMAP(0x00F7, 0xF7); // DIVISION SIGN
REMAP(0x0159, 0xF8); // LATIN SMALL LETTER R WITH CARON
REMAP(0x016F, 0xF9); // LATIN SMALL LETTER U WITH RING ABOVE
REMAP(0x00FA, 0xFA); // LATIN SMALL LETTER U WITH ACUTE
REMAP(0x0171, 0xFB); // LATIN SMALL LETTER U WITH DOUBLE ACUTE
REMAP(0x00FC, 0xFC); // LATIN SMALL LETTER U WITH DIAERESIS
REMAP(0x00FD, 0xFD); // LATIN SMALL LETTER Y WITH ACUTE
REMAP(0x0163, 0xFE); // LATIN SMALL LETTER T WITH CEDILLA
REMAP(0x02D9, 0xFF); // DOT ABOVE
}
}
}
// Apply a set of substitutions which remap UTF8 for a Windows-1251 font
// Windows-1251 is an 8-bit character encoding, suitable for several languages which use the Cyrillic script
void InkHUD::AppletFont::addSubstitutionsWin1251()
{
addSubstitution("Ђ", "\x80");
addSubstitution("Ѓ", "\x81");
addSubstitution("ѓ", "\x83");
addSubstitution("", "\x88");
addSubstitution("Љ", "\x8A");
addSubstitution("Њ", "\x8C");
addSubstitution("Ќ", "\x8D");
addSubstitution("Ћ", "\x8E");
addSubstitution("Џ", "\x8F");
// Latin - Cyrillic
// https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1251.TXT
else if (encoding == WINDOWS_1251) {
// 1-Byte chars: no remapping
if (utf8.length() == 1)
return utf8.at(0);
addSubstitution("ђ", "\x90");
addSubstitution("љ", "\x9A");
addSubstitution("њ", "\x9C");
addSubstitution("ќ", "\x9D");
addSubstitution("ћ", "\x9E");
addSubstitution("џ", "\x9F");
// Multi-byte chars:
switch (toUtf32(utf8)) {
REMAP(0x0402, 0x80); // CYRILLIC CAPITAL LETTER DJE
REMAP(0x0403, 0x81); // CYRILLIC CAPITAL LETTER GJE
REMAP(0x201A, 0x82); // SINGLE LOW-9 QUOTATION MARK
REMAP(0x0453, 0x83); // CYRILLIC SMALL LETTER GJE
REMAP(0x201E, 0x84); // DOUBLE LOW-9 QUOTATION MARK
REMAP(0x2026, 0x85); // HORIZONTAL ELLIPSIS
REMAP(0x2020, 0x86); // DAGGER
REMAP(0x2021, 0x87); // DOUBLE DAGGER
REMAP(0x20AC, 0x88); // EURO SIGN
REMAP(0x2030, 0x89); // PER MILLE SIGN
REMAP(0x0409, 0x8A); // CYRILLIC CAPITAL LETTER LJE
REMAP(0x2039, 0x8B); // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
REMAP(0x040A, 0x8C); // CYRILLIC CAPITAL LETTER NJE
REMAP(0x040C, 0x8D); // CYRILLIC CAPITAL LETTER KJE
REMAP(0x040B, 0x8E); // CYRILLIC CAPITAL LETTER TSHE
REMAP(0x040F, 0x8F); // CYRILLIC CAPITAL LETTER DZHE
addSubstitution("Ў", "\xA1");
addSubstitution("ў", "\xA2");
addSubstitution("Ј", "\xA3");
addSubstitution("Ґ", "\xA5");
addSubstitution("Ё", "\xA8");
addSubstitution("Є", "\xAA");
addSubstitution("Ї", "\xAF");
REMAP(0x0452, 0x90); // CYRILLIC SMALL LETTER DJE
REMAP(0x2018, 0x91); // LEFT SINGLE QUOTATION MARK
REMAP(0x2019, 0x92); // RIGHT SINGLE QUOTATION MARK
REMAP(0x201C, 0x93); // LEFT DOUBLE QUOTATION MARK
REMAP(0x201D, 0x94); // RIGHT DOUBLE QUOTATION MARK
REMAP(0x2022, 0x95); // BULLET
REMAP(0x2013, 0x96); // EN DASH
REMAP(0x2014, 0x97); // EM DASH
REMAP(0x2122, 0x99); // TRADE MARK SIGN
REMAP(0x0459, 0x9A); // CYRILLIC SMALL LETTER LJE
REMAP(0x203A, 0x9B); // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
REMAP(0x045A, 0x9C); // CYRILLIC SMALL LETTER NJE
REMAP(0x045C, 0x9D); // CYRILLIC SMALL LETTER KJE
REMAP(0x045B, 0x9E); // CYRILLIC SMALL LETTER TSHE
REMAP(0x045F, 0x9F); // CYRILLIC SMALL LETTER DZHE
addSubstitution("І", "\xB2");
addSubstitution("і", "\xB3");
addSubstitution("ґ", "\xB4");
addSubstitution("ё", "\xB8");
addSubstitution("", "\xB9");
addSubstitution("є", "\xBA");
addSubstitution("ј", "\xBC");
addSubstitution("Ѕ", "\xBD");
addSubstitution("ѕ", "\xBE");
addSubstitution("ї", "\xBF");
REMAP(0x00A0, 0xA0); // NO-BREAK SPACE
REMAP(0x040E, 0xA1); // CYRILLIC CAPITAL LETTER SHORT U
REMAP(0x045E, 0xA2); // CYRILLIC SMALL LETTER SHORT U
REMAP(0x0408, 0xA3); // CYRILLIC CAPITAL LETTER JE
REMAP(0x00A4, 0xA4); // CURRENCY SIGN
REMAP(0x0490, 0xA5); // CYRILLIC CAPITAL LETTER GHE WITH UPTURN
REMAP(0x00A6, 0xA6); // BROKEN BAR
REMAP(0x00A7, 0xA7); // SECTION SIGN
REMAP(0x0401, 0xA8); // CYRILLIC CAPITAL LETTER IO
REMAP(0x00A9, 0xA9); // COPYRIGHT SIGN
REMAP(0x0404, 0xAA); // CYRILLIC CAPITAL LETTER UKRAINIAN IE
REMAP(0x00AB, 0xAB); // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
REMAP(0x00AC, 0xAC); // NOT SIGN
REMAP(0x00AD, 0xAD); // SOFT HYPHEN
REMAP(0x00AE, 0xAE); // REGISTERED SIGN
REMAP(0x0407, 0xAF); // CYRILLIC CAPITAL LETTER YI
addSubstitution("А", "\xC0");
addSubstitution("Б", "\xC1");
addSubstitution("В", "\xC2");
addSubstitution("Г", "\xC3");
addSubstitution("Д", "\xC4");
addSubstitution("Е", "\xC5");
addSubstitution("Ж", "\xC6");
addSubstitution("З", "\xC7");
addSubstitution("И", "\xC8");
addSubstitution("Й", "\xC9");
addSubstitution("К", "\xCA");
addSubstitution("Л", "\xCB");
addSubstitution("М", "\xCC");
addSubstitution("Н", "\xCD");
addSubstitution("О", "\xCE");
addSubstitution("П", "\xCF");
REMAP(0x00B0, 0xB0); // DEGREE SIGN
REMAP(0x00B1, 0xB1); // PLUS-MINUS SIGN
REMAP(0x0406, 0xB2); // CYRILLIC CAPITAL LETTER BYELORUSSIAN-UKRAINIAN I
REMAP(0x0456, 0xB3); // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
REMAP(0x0491, 0xB4); // CYRILLIC SMALL LETTER GHE WITH UPTURN
REMAP(0x00B5, 0xB5); // MICRO SIGN
REMAP(0x00B6, 0xB6); // PILCROW SIGN
REMAP(0x00B7, 0xB7); // MIDDLE DOT
REMAP(0x0451, 0xB8); // CYRILLIC SMALL LETTER IO
REMAP(0x2116, 0xB9); // NUMERO SIGN
REMAP(0x0454, 0xBA); // CYRILLIC SMALL LETTER UKRAINIAN IE
REMAP(0x00BB, 0xBB); // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
REMAP(0x0458, 0xBC); // CYRILLIC SMALL LETTER JE
REMAP(0x0405, 0xBD); // CYRILLIC CAPITAL LETTER DZE
REMAP(0x0455, 0xBE); // CYRILLIC SMALL LETTER DZE
REMAP(0x0457, 0xBF); // CYRILLIC SMALL LETTER YI
addSubstitution("Р", "\xD0");
addSubstitution("С", "\xD1");
addSubstitution("Т", "\xD2");
addSubstitution("У", "\xD3");
addSubstitution("Ф", "\xD4");
addSubstitution("Х", "\xD5");
addSubstitution("Ц", "\xD6");
addSubstitution("Ч", "\xD7");
addSubstitution("Ш", "\xD8");
addSubstitution("Щ", "\xD9");
addSubstitution("Ъ", "\xDA");
addSubstitution("Ы", "\xDB");
addSubstitution("Ь", "\xDC");
addSubstitution("Э", "\xDD");
addSubstitution("Ю", "\xDE");
addSubstitution("Я", "\xDF");
REMAP(0x0410, 0xC0); // CYRILLIC CAPITAL LETTER A
REMAP(0x0411, 0xC1); // CYRILLIC CAPITAL LETTER BE
REMAP(0x0412, 0xC2); // CYRILLIC CAPITAL LETTER VE
REMAP(0x0413, 0xC3); // CYRILLIC CAPITAL LETTER GHE
REMAP(0x0414, 0xC4); // CYRILLIC CAPITAL LETTER DE
REMAP(0x0415, 0xC5); // CYRILLIC CAPITAL LETTER IE
REMAP(0x0416, 0xC6); // CYRILLIC CAPITAL LETTER ZHE
REMAP(0x0417, 0xC7); // CYRILLIC CAPITAL LETTER ZE
REMAP(0x0418, 0xC8); // CYRILLIC CAPITAL LETTER I
REMAP(0x0419, 0xC9); // CYRILLIC CAPITAL LETTER SHORT I
REMAP(0x041A, 0xCA); // CYRILLIC CAPITAL LETTER KA
REMAP(0x041B, 0xCB); // CYRILLIC CAPITAL LETTER EL
REMAP(0x041C, 0xCC); // CYRILLIC CAPITAL LETTER EM
REMAP(0x041D, 0xCD); // CYRILLIC CAPITAL LETTER EN
REMAP(0x041E, 0xCE); // CYRILLIC CAPITAL LETTER O
REMAP(0x041F, 0xCF); // CYRILLIC CAPITAL LETTER PE
addSubstitution("а", "\xE0");
addSubstitution("б", "\xE1");
addSubstitution("в", "\xE2");
addSubstitution("г", "\xE3");
addSubstitution("д", "\xE4");
addSubstitution("е", "\xE5");
addSubstitution("ж", "\xE6");
addSubstitution("з", "\xE7");
addSubstitution("и", "\xE8");
addSubstitution("й", "\xE9");
addSubstitution("к", "\xEA");
addSubstitution("л", "\xEB");
addSubstitution("м", "\xEC");
addSubstitution("н", "\xED");
addSubstitution("о", "\xEE");
addSubstitution("п", "\xEF");
REMAP(0x0420, 0xD0); // CYRILLIC CAPITAL LETTER ER
REMAP(0x0421, 0xD1); // CYRILLIC CAPITAL LETTER ES
REMAP(0x0422, 0xD2); // CYRILLIC CAPITAL LETTER TE
REMAP(0x0423, 0xD3); // CYRILLIC CAPITAL LETTER U
REMAP(0x0424, 0xD4); // CYRILLIC CAPITAL LETTER EF
REMAP(0x0425, 0xD5); // CYRILLIC CAPITAL LETTER HA
REMAP(0x0426, 0xD6); // CYRILLIC CAPITAL LETTER TSE
REMAP(0x0427, 0xD7); // CYRILLIC CAPITAL LETTER CHE
REMAP(0x0428, 0xD8); // CYRILLIC CAPITAL LETTER SHA
REMAP(0x0429, 0xD9); // CYRILLIC CAPITAL LETTER SHCHA
REMAP(0x042A, 0xDA); // CYRILLIC CAPITAL LETTER HARD SIGN
REMAP(0x042B, 0xDB); // CYRILLIC CAPITAL LETTER YERU
REMAP(0x042C, 0xDC); // CYRILLIC CAPITAL LETTER SOFT SIGN
REMAP(0x042D, 0xDD); // CYRILLIC CAPITAL LETTER E
REMAP(0x042E, 0xDE); // CYRILLIC CAPITAL LETTER YU
REMAP(0x042F, 0xDF); // CYRILLIC CAPITAL LETTER YA
addSubstitution("р", "\xF0");
addSubstitution("с", "\xF1");
addSubstitution("т", "\xF2");
addSubstitution("у", "\xF3");
addSubstitution("ф", "\xF4");
addSubstitution("х", "\xF5");
addSubstitution("ц", "\xF6");
addSubstitution("ч", "\xF7");
addSubstitution("ш", "\xF8");
addSubstitution("щ", "\xF9");
addSubstitution("ъ", "\xFA");
addSubstitution("ы", "\xFB");
addSubstitution("ь", "\xFC");
addSubstitution("э", "\xFD");
addSubstitution("ю", "\xFE");
addSubstitution("я", "\xFF");
REMAP(0x0430, 0xE0); // CYRILLIC SMALL LETTER A
REMAP(0x0431, 0xE1); // CYRILLIC SMALL LETTER BE
REMAP(0x0432, 0xE2); // CYRILLIC SMALL LETTER VE
REMAP(0x0433, 0xE3); // CYRILLIC SMALL LETTER GHE
REMAP(0x0434, 0xE4); // CYRILLIC SMALL LETTER DE
REMAP(0x0435, 0xE5); // CYRILLIC SMALL LETTER IE
REMAP(0x0436, 0xE6); // CYRILLIC SMALL LETTER ZHE
REMAP(0x0437, 0xE7); // CYRILLIC SMALL LETTER ZE
REMAP(0x0438, 0xE8); // CYRILLIC SMALL LETTER I
REMAP(0x0439, 0xE9); // CYRILLIC SMALL LETTER SHORT I
REMAP(0x043A, 0xEA); // CYRILLIC SMALL LETTER KA
REMAP(0x043B, 0xEB); // CYRILLIC SMALL LETTER EL
REMAP(0x043C, 0xEC); // CYRILLIC SMALL LETTER EM
REMAP(0x043D, 0xED); // CYRILLIC SMALL LETTER EN
REMAP(0x043E, 0xEE); // CYRILLIC SMALL LETTER O
REMAP(0x043F, 0xEF); // CYRILLIC SMALL LETTER PE
REMAP(0x0440, 0xF0); // CYRILLIC SMALL LETTER ER
REMAP(0x0441, 0xF1); // CYRILLIC SMALL LETTER ES
REMAP(0x0442, 0xF2); // CYRILLIC SMALL LETTER TE
REMAP(0x0443, 0xF3); // CYRILLIC SMALL LETTER U
REMAP(0x0444, 0xF4); // CYRILLIC SMALL LETTER EF
REMAP(0x0445, 0xF5); // CYRILLIC SMALL LETTER HA
REMAP(0x0446, 0xF6); // CYRILLIC SMALL LETTER TSE
REMAP(0x0447, 0xF7); // CYRILLIC SMALL LETTER CHE
REMAP(0x0448, 0xF8); // CYRILLIC SMALL LETTER SHA
REMAP(0x0449, 0xF9); // CYRILLIC SMALL LETTER SHCHA
REMAP(0x044A, 0xFA); // CYRILLIC SMALL LETTER HARD SIGN
REMAP(0x044B, 0xFB); // CYRILLIC SMALL LETTER YERU
REMAP(0x044C, 0xFC); // CYRILLIC SMALL LETTER SOFT SIGN
REMAP(0x044D, 0xFD); // CYRILLIC SMALL LETTER E
REMAP(0x044E, 0xFE); // CYRILLIC SMALL LETTER YU
REMAP(0x044F, 0xFF); // CYRILLIC SMALL LETTER YA
}
}
// Latin - Western Europe
// https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT
else if (encoding == WINDOWS_1252) {
// 1-Byte chars: no remapping
if (utf8.length() == 1)
return utf8.at(0);
// Multi-byte chars:
switch (toUtf32(utf8)) {
REMAP(0x20AC, 0x80) // EURO SIGN
REMAP(0x201A, 0x82) // SINGLE LOW-9 QUOTATION MARK
REMAP(0x0192, 0x83) // LATIN SMALL LETTER F WITH HOOK
REMAP(0x201E, 0x84) // DOUBLE LOW-9 QUOTATION MARK
REMAP(0x2026, 0x85) // HORIZONTAL ELLIPSIS
REMAP(0x2020, 0x86) // DAGGER
REMAP(0x2021, 0x87) // DOUBLE DAGGER
REMAP(0x02C6, 0x88) // MODIFIER LETTER CIRCUMFLEX ACCENT
REMAP(0x2030, 0x89) // PER MILLE SIGN
REMAP(0x0160, 0x8A) // LATIN CAPITAL LETTER S WITH CARON
REMAP(0x2039, 0x8B) // SINGLE LEFT-POINTING ANGLE QUOTATION MARK
REMAP(0x0152, 0x8C) // LATIN CAPITAL LIGATURE OE
REMAP(0x017D, 0x8E) // LATIN CAPITAL LETTER Z WITH CARON
REMAP(0x2018, 0x91) // LEFT SINGLE QUOTATION MARK
REMAP(0x2019, 0x92) // RIGHT SINGLE QUOTATION MARK
REMAP(0x201C, 0x93) // LEFT DOUBLE QUOTATION MARK
REMAP(0x201D, 0x94) // RIGHT DOUBLE QUOTATION MARK
REMAP(0x2022, 0x95) // BULLET
REMAP(0x2013, 0x96) // EN DASH
REMAP(0x2014, 0x97) // EM DASH
REMAP(0x02DC, 0x98) // SMALL TILDE
REMAP(0x2122, 0x99) // TRADE MARK SIGN
REMAP(0x0161, 0x9A) // LATIN SMALL LETTER S WITH CARON
REMAP(0x203A, 0x9B) // SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
REMAP(0x0153, 0x9C) // LATIN SMALL LIGATURE OE
REMAP(0x017E, 0x9E) // LATIN SMALL LETTER Z WITH CARON
REMAP(0x0178, 0x9F) // LATIN CAPITAL LETTER Y WITH DIAERESIS
REMAP(0x00A0, 0xA0) // NO-BREAK SPACE
REMAP(0x00A1, 0xA1) // INVERTED EXCLAMATION MARK
REMAP(0x00A2, 0xA2) // CENT SIGN
REMAP(0x00A3, 0xA3) // POUND SIGN
REMAP(0x00A4, 0xA4) // CURRENCY SIGN
REMAP(0x00A5, 0xA5) // YEN SIGN
REMAP(0x00A6, 0xA6) // BROKEN BAR
REMAP(0x00A7, 0xA7) // SECTION SIGN
REMAP(0x00A8, 0xA8) // DIAERESIS
REMAP(0x00A9, 0xA9) // COPYRIGHT SIGN
REMAP(0x00AA, 0xAA) // FEMININE ORDINAL INDICATOR
REMAP(0x00AB, 0xAB) // LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
REMAP(0x00AC, 0xAC) // NOT SIGN
REMAP(0x00AD, 0xAD) // SOFT HYPHEN
REMAP(0x00AE, 0xAE) // REGISTERED SIGN
REMAP(0x00AF, 0xAF) // MACRON
REMAP(0x00B0, 0xB0) // DEGREE SIGN
REMAP(0x00B1, 0xB1) // PLUS-MINUS SIGN
REMAP(0x00B2, 0xB2) // SUPERSCRIPT TWO
REMAP(0x00B3, 0xB3) // SUPERSCRIPT THREE
REMAP(0x00B4, 0xB4) // ACUTE ACCENT
REMAP(0x00B5, 0xB5) // MICRO SIGN
REMAP(0x00B6, 0xB6) // PILCROW SIGN
REMAP(0x00B7, 0xB7) // MIDDLE DOT
REMAP(0x00B8, 0xB8) // CEDILLA
REMAP(0x00B9, 0xB9) // SUPERSCRIPT ONE
REMAP(0x00BA, 0xBA) // MASCULINE ORDINAL INDICATOR
REMAP(0x00BB, 0xBB) // RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
REMAP(0x00BC, 0xBC) // VULGAR FRACTION ONE QUARTER
REMAP(0x00BD, 0xBD) // VULGAR FRACTION ONE HALF
REMAP(0x00BE, 0xBE) // VULGAR FRACTION THREE QUARTERS
REMAP(0x00BF, 0xBF) // INVERTED QUESTION MARK
REMAP(0x00C0, 0xC0) // LATIN CAPITAL LETTER A WITH GRAVE
REMAP(0x00C1, 0xC1) // LATIN CAPITAL LETTER A WITH ACUTE
REMAP(0x00C2, 0xC2) // LATIN CAPITAL LETTER A WITH CIRCUMFLEX
REMAP(0x00C3, 0xC3) // LATIN CAPITAL LETTER A WITH TILDE
REMAP(0x00C4, 0xC4) // LATIN CAPITAL LETTER A WITH DIAERESIS
REMAP(0x00C5, 0xC5) // LATIN CAPITAL LETTER A WITH RING ABOVE
REMAP(0x00C6, 0xC6) // LATIN CAPITAL LETTER AE
REMAP(0x00C7, 0xC7) // LATIN CAPITAL LETTER C WITH CEDILLA
REMAP(0x00C8, 0xC8) // LATIN CAPITAL LETTER E WITH GRAVE
REMAP(0x00C9, 0xC9) // LATIN CAPITAL LETTER E WITH ACUTE
REMAP(0x00CA, 0xCA) // LATIN CAPITAL LETTER E WITH CIRCUMFLEX
REMAP(0x00CB, 0xCB) // LATIN CAPITAL LETTER E WITH DIAERESIS
REMAP(0x00CC, 0xCC) // LATIN CAPITAL LETTER I WITH GRAVE
REMAP(0x00CD, 0xCD) // LATIN CAPITAL LETTER I WITH ACUTE
REMAP(0x00CE, 0xCE) // LATIN CAPITAL LETTER I WITH CIRCUMFLEX
REMAP(0x00CF, 0xCF) // LATIN CAPITAL LETTER I WITH DIAERESIS
REMAP(0x00D0, 0xD0) // LATIN CAPITAL LETTER ETH
REMAP(0x00D1, 0xD1) // LATIN CAPITAL LETTER N WITH TILDE
REMAP(0x00D2, 0xD2) // LATIN CAPITAL LETTER O WITH GRAVE
REMAP(0x00D3, 0xD3) // LATIN CAPITAL LETTER O WITH ACUTE
REMAP(0x00D4, 0xD4) // LATIN CAPITAL LETTER O WITH CIRCUMFLEX
REMAP(0x00D5, 0xD5) // LATIN CAPITAL LETTER O WITH TILDE
REMAP(0x00D6, 0xD6) // LATIN CAPITAL LETTER O WITH DIAERESIS
REMAP(0x00D7, 0xD7) // MULTIPLICATION SIGN
REMAP(0x00D8, 0xD8) // LATIN CAPITAL LETTER O WITH STROKE
REMAP(0x00D9, 0xD9) // LATIN CAPITAL LETTER U WITH GRAVE
REMAP(0x00DA, 0xDA) // LATIN CAPITAL LETTER U WITH ACUTE
REMAP(0x00DB, 0xDB) // LATIN CAPITAL LETTER U WITH CIRCUMFLEX
REMAP(0x00DC, 0xDC) // LATIN CAPITAL LETTER U WITH DIAERESIS
REMAP(0x00DD, 0xDD) // LATIN CAPITAL LETTER Y WITH ACUTE
REMAP(0x00DE, 0xDE) // LATIN CAPITAL LETTER THORN
REMAP(0x00DF, 0xDF) // LATIN SMALL LETTER SHARP S
REMAP(0x00E0, 0xE0) // LATIN SMALL LETTER A WITH GRAVE
REMAP(0x00E1, 0xE1) // LATIN SMALL LETTER A WITH ACUTE
REMAP(0x00E2, 0xE2) // LATIN SMALL LETTER A WITH CIRCUMFLEX
REMAP(0x00E3, 0xE3) // LATIN SMALL LETTER A WITH TILDE
REMAP(0x00E4, 0xE4) // LATIN SMALL LETTER A WITH DIAERESIS
REMAP(0x00E5, 0xE5) // LATIN SMALL LETTER A WITH RING ABOVE
REMAP(0x00E6, 0xE6) // LATIN SMALL LETTER AE
REMAP(0x00E7, 0xE7) // LATIN SMALL LETTER C WITH CEDILLA
REMAP(0x00E8, 0xE8) // LATIN SMALL LETTER E WITH GRAVE
REMAP(0x00E9, 0xE9) // LATIN SMALL LETTER E WITH ACUTE
REMAP(0x00EA, 0xEA) // LATIN SMALL LETTER E WITH CIRCUMFLEX
REMAP(0x00EB, 0xEB) // LATIN SMALL LETTER E WITH DIAERESIS
REMAP(0x00EC, 0xEC) // LATIN SMALL LETTER I WITH GRAVE
REMAP(0x00ED, 0xED) // LATIN SMALL LETTER I WITH ACUTE
REMAP(0x00EE, 0xEE) // LATIN SMALL LETTER I WITH CIRCUMFLEX
REMAP(0x00EF, 0xEF) // LATIN SMALL LETTER I WITH DIAERESIS
REMAP(0x00F0, 0xF0) // LATIN SMALL LETTER ETH
REMAP(0x00F1, 0xF1) // LATIN SMALL LETTER N WITH TILDE
REMAP(0x00F2, 0xF2) // LATIN SMALL LETTER O WITH GRAVE
REMAP(0x00F3, 0xF3) // LATIN SMALL LETTER O WITH ACUTE
REMAP(0x00F4, 0xF4) // LATIN SMALL LETTER O WITH CIRCUMFLEX
REMAP(0x00F5, 0xF5) // LATIN SMALL LETTER O WITH TILDE
REMAP(0x00F6, 0xF6) // LATIN SMALL LETTER O WITH DIAERESIS
REMAP(0x00F7, 0xF7) // DIVISION SIGN
REMAP(0x00F8, 0xF8) // LATIN SMALL LETTER O WITH STROKE
REMAP(0x00F9, 0xF9) // LATIN SMALL LETTER U WITH GRAVE
REMAP(0x00FA, 0xFA) // LATIN SMALL LETTER U WITH ACUTE
REMAP(0x00FB, 0xFB) // LATIN SMALL LETTER U WITH CIRCUMFLEX
REMAP(0x00FC, 0xFC) // LATIN SMALL LETTER U WITH DIAERESIS
REMAP(0x00FD, 0xFD) // LATIN SMALL LETTER Y WITH ACUTE
REMAP(0x00FE, 0xFE) // LATIN SMALL LETTER THORN
REMAP(0x00FF, 0xFF) // LATIN SMALL LETTER Y WITH DIAERESIS
}
}
// If not handled, return DEL
// Todo: swap this to SUB, and modify the fonts
return '\x7F';
// Sweep up the syntactic sugar
// Don't want ants in the house
#undef REMAP
}
#endif

View File

@@ -4,10 +4,7 @@
Wrapper class for an AdafruitGFX font
Pre-calculates some font dimension info which InkHUD uses repeatedly
Also contains an optional set of "substitutions".
These can be used to detect special UTF8 chars, and replace occurrences with a remapped char val to suit a custom font
These can also be used to swap UTF8 chars for a suitable ASCII substitution (e.g. German ö -> oe, etc)
Re-encodes UTF-8 characters to suit extended ASCII AdafruitGFX fonts
*/
@@ -24,36 +21,61 @@ namespace NicheGraphics::InkHUD
class AppletFont
{
public:
enum Encoding {
ASCII,
WINDOWS_1250,
WINDOWS_1251,
WINDOWS_1252,
};
AppletFont();
explicit AppletFont(const GFXfont &adafruitGFXFont);
AppletFont(const GFXfont &adafruitGFXFont, Encoding encoding = ASCII, int8_t paddingTop = 0, int8_t paddingBottom = 0);
uint8_t lineHeight();
uint8_t heightAboveCursor();
uint8_t heightBelowCursor();
uint8_t widthBetweenWords(); // Width of the space character
void applySubstitutions(std::string *text); // Run all char-substitution operations, prior to printing
void addSubstitution(const char *from, const char *to); // Register a find-replace action, for remapping UTF8 chars
void addSubstitutionsWin1251(); // Cyrillic fonts: remap UTF8 values to their Win-1251 equivalent
// Todo: Polish font
std::string decodeUTF8(std::string encoded);
const GFXfont *gfxFont = NULL; // Default value: in-built AdafruitGFX font
private:
uint32_t toUtf32(std::string utf8);
char applyEncoding(std::string utf8);
uint8_t height = 8; // Default value: in-built AdafruitGFX font
uint8_t ascenderHeight = 0; // Default value: in-built AdafruitGFX font
uint8_t descenderHeight = 8; // Default value: in-built AdafruitGFX font
uint8_t spaceCharWidth = 8; // Default value: in-built AdafruitGFX font
// One pair of find-replace values, for substituting or remapping UTF8 chars
struct Substitution {
const char *from;
const char *to;
};
std::vector<Substitution> substitutions; // List of all character substitutions to run, prior to printing a string
Encoding encoding = ASCII;
};
} // namespace NicheGraphics::InkHUD
// Macros for InkHUD's standard fonts
// --------------------------------------
// Use these once only, passing them to InkHUD::Applet::fontLarge and InkHUD::Applet:fontSmall
// Line padding has been adjusted manually, to compensate for a few *extra tall* diacritics
// Central European
#include "graphics/niche/Fonts/FreeSans6pt_Win1250.h"
#include "graphics/niche/Fonts/FreeSans9pt_Win1250.h"
#define FREESANS_9PT_WIN1250 InkHUD::AppletFont(FreeSans9pt_Win1250, InkHUD::AppletFont::WINDOWS_1250, -1, -1)
#define FREESANS_6PT_WIN1250 InkHUD::AppletFont(FreeSans6pt_Win1250, InkHUD::AppletFont::WINDOWS_1250, -1, -2)
// Cyrillic
#include "graphics/niche/Fonts/FreeSans6pt_Win1251.h"
#include "graphics/niche/Fonts/FreeSans9pt_Win1251.h"
#define FREESANS_9PT_WIN1251 InkHUD::AppletFont(FreeSans9pt_Win1251, InkHUD::AppletFont::WINDOWS_1251, -2, -1)
#define FREESANS_6PT_WIN1251 InkHUD::AppletFont(FreeSans6pt_Win1251, InkHUD::AppletFont::WINDOWS_1251, -1, -2)
// Western European
#include "graphics/niche/Fonts/FreeSans6pt_Win1252.h"
#include "graphics/niche/Fonts/FreeSans9pt_Win1252.h"
#define FREESANS_9PT_WIN1252 InkHUD::AppletFont(FreeSans9pt_Win1252, InkHUD::AppletFont::WINDOWS_1252, -2, -1)
#define FREESANS_6PT_WIN1252 InkHUD::AppletFont(FreeSans6pt_Win1252, InkHUD::AppletFont::WINDOWS_1252, -1, -2)
#endif

View File

@@ -286,6 +286,10 @@ void InkHUD::MapApplet::drawLabeledMarker(meshtastic_NodeInfoLite *node)
bool isOurNode = node->num == nodeDB->getNodeNum();
bool unknownHops = !node->has_hops_away && !isOurNode;
// Parse any non-ascii chars in the short name,
// and use last 4 instead if unknown / can't render
std::string shortName = parseShortName(node);
// We will draw a left or right hand variant, to place text towards screen center
// Hopefully avoid text spilling off screen
// Most values are the same, regardless of left-right handedness
@@ -299,7 +303,7 @@ void InkHUD::MapApplet::drawLabeledMarker(meshtastic_NodeInfoLite *node)
markerSize = map(node->hops_away, 0, config.lora.hop_limit, markerSizeMax, markerSizeMin);
// Common dimensions (left or right variant)
textW = getTextWidth(node->user.short_name);
textW = getTextWidth(shortName);
if (textW == 0)
paddingInnerW = 0; // If no text, no padding for text
textH = fontSmall.lineHeight();
@@ -325,7 +329,7 @@ void InkHUD::MapApplet::drawLabeledMarker(meshtastic_NodeInfoLite *node)
drawRect(labelX, labelY, labelW, labelH, BLACK);
// Short name
printAt(textX, textY, node->user.short_name, LEFT, MIDDLE);
printAt(textX, textY, shortName, LEFT, MIDDLE);
// If the label is for our own node,
// fade it by overdrawing partially with white

View File

@@ -142,16 +142,18 @@ void InkHUD::NodeListApplet::onRender()
meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeNum);
// -- Shortname --
// use "?" if unknown
if (node && node->has_user)
shortName = node->user.short_name;
// Parse special chars in the short name
// Use "?" if unknown
if (node)
shortName = parseShortName(node);
else
shortName = "?";
// -- Longname --
// use node id if unknown
// Parse special chars in long name
// Use node id if unknown
if (node && node->has_user)
longName = node->user.long_name; // Found in nodeDB
longName = parse(node->user.long_name); // Found in nodeDB
else {
// Not found in nodeDB, show a hex nodeid instead
longName = hexifyNodeNum(nodeNum);

View File

@@ -9,6 +9,12 @@ using namespace NicheGraphics;
void InkHUD::BasicExampleApplet::onRender()
{
printAt(0, 0, "Hello, World!");
// If text might contain "special characters", is needs parsing first
// This applies to data such as text-messages and and node names
// std::string greeting = parse("Grüezi mitenand!");
// printAt(0, 0, greeting);
}
#endif

View File

@@ -5,7 +5,7 @@
An example of an InkHUD applet.
Tells us when a new text message arrives.
This applet makes use of the MeshModule API to detect new messages,
This applet makes use of the Module API to detect new messages,
which is a general part of the Meshtastic firmware, and not part of InkHUD.
In variants/<your device>/nicheGraphics.h:

View File

@@ -111,9 +111,10 @@ void InkHUD::LogoApplet::onShutdown()
// Prepare for the powered-off screen now
// We can change these values because the initial "shutting down" screen has already rendered at this point
meshtastic_NodeInfoLite *ourNode = nodeDB->getMeshNode(nodeDB->getNodeNum());
textLeft = "";
textRight = "";
textTitle = owner.short_name;
textTitle = parseShortName(ourNode);
fontTitle = fontLarge;
// This is then drawn by InkHUD::Events::onShutdown, with a blocking FULL update, after InkHUD's flash write is complete

View File

@@ -244,6 +244,7 @@ void InkHUD::MenuApplet::execute(MenuItem item)
void InkHUD::MenuApplet::showPage(MenuPage page)
{
items.clear();
items.shrink_to_fit();
switch (page) {
case ROOT:

View File

@@ -33,11 +33,6 @@ int InkHUD::NotificationApplet::onReceiveTextMessage(const meshtastic_MeshPacket
if (getFrom(p) == nodeDB->getNodeNum())
return 0;
// Abort if message was only an "emoji reaction"
// Possibly some implementation of this in future?
if (p->decoded.emoji)
return 0;
Notification n;
n.timestamp = getValidTime(RTCQuality::RTCQualityDevice, true); // Current RTC time
@@ -122,7 +117,7 @@ void InkHUD::NotificationApplet::onRender()
int16_t textM = divX + padW + (getTextWidth(text) / 2);
// Restrict area for printing
// - don't overlap border, or diveder
// - don't overlap border, or divider
setCrop(divX + 1, 1, (width() - (divX + 1) - 1), height() - 2);
// Drop shadow
@@ -218,7 +213,7 @@ std::string InkHUD::NotificationApplet::getNotificationText(uint16_t widthAvaila
// Sender id
if (node && node->has_user)
text += node->user.short_name;
text += parseShortName(node);
else
text += hexifyNodeNum(message->sender);
@@ -232,7 +227,7 @@ std::string InkHUD::NotificationApplet::getNotificationText(uint16_t widthAvaila
// Sender id
if (node && node->has_user)
text += node->user.short_name;
text += parseShortName(node);
else
text += hexifyNodeNum(message->sender);
@@ -241,7 +236,8 @@ std::string InkHUD::NotificationApplet::getNotificationText(uint16_t widthAvaila
}
}
return text;
// Parse any non-ascii characters and return
return parse(text);
}
#endif

View File

@@ -23,9 +23,9 @@ void InkHUD::PairingApplet::onRender()
// Device's bluetooth name, if it will fit
setFont(fontSmall);
std::string name = "Name: " + std::string(getDeviceName());
std::string name = "Name: " + parse(getDeviceName());
if (getTextWidth(name) > width()) // Too wide, try without the leading "Name: "
name = std::string(getDeviceName());
name = parse(getDeviceName());
if (getTextWidth(name) < width()) // Does it fit?
printAt(X(0.5), Y(0.75), name, CENTER, MIDDLE);
}

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