diff --git a/.github/workflows/build_native.yml b/.github/workflows/build_native.yml index 1fb44a717..d4b0c8d58 100644 --- a/.github/workflows/build_native.yml +++ b/.github/workflows/build_native.yml @@ -14,7 +14,7 @@ jobs: shell: bash run: | sudo apt-get update --fix-missing - sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev + sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev - name: Checkout code uses: actions/checkout@v4 diff --git a/.github/workflows/build_raspbian.yml b/.github/workflows/build_raspbian.yml index e857ae635..1826504f0 100644 --- a/.github/workflows/build_raspbian.yml +++ b/.github/workflows/build_raspbian.yml @@ -14,7 +14,7 @@ jobs: shell: bash run: | sudo apt-get update -y --fix-missing - sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev + sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev - name: Checkout code uses: actions/checkout@v4 diff --git a/.github/workflows/build_raspbian_armv7l.yml b/.github/workflows/build_raspbian_armv7l.yml index f7fddd038..fd53585a5 100644 --- a/.github/workflows/build_raspbian_armv7l.yml +++ b/.github/workflows/build_raspbian_armv7l.yml @@ -14,7 +14,7 @@ jobs: shell: bash run: | sudo apt-get update -y --fix-missing - sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev + sudo apt-get install -y libbluetooth-dev libgpiod-dev libyaml-cpp-dev openssl libssl-dev libulfius-dev liborcania-dev libusb-1.0-0-dev - name: Checkout code uses: actions/checkout@v4 diff --git a/.github/workflows/package_amd64.yml b/.github/workflows/package_amd64.yml index 4f6636712..ce2c85d54 100644 --- a/.github/workflows/package_amd64.yml +++ b/.github/workflows/package_amd64.yml @@ -57,11 +57,11 @@ jobs: shopt -s dotglob nullglob if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then mv .debpkg/usr/share/doc/meshtasticd/web/build/* .debpkg/usr/share/doc/meshtasticd/web/; fi if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/doc/meshtasticd/web/build; fi - if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi - gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz + if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi + gunzip .debpkg/usr/share/doc/meshtasticd/web/ -r cp release/meshtasticd_linux_x86_64 .debpkg/usr/sbin/meshtasticd cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml - cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ + cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r chmod +x .debpkg/usr/sbin/meshtasticd cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles @@ -82,4 +82,4 @@ jobs: name: meshtasticd_${{ steps.version.outputs.version }}_amd64.deb overwrite: true path: | - ./*.deb + ./*.deb \ No newline at end of file diff --git a/.github/workflows/package_raspbian.yml b/.github/workflows/package_raspbian.yml index d9b12d6da..46039b6ea 100644 --- a/.github/workflows/package_raspbian.yml +++ b/.github/workflows/package_raspbian.yml @@ -57,11 +57,11 @@ jobs: shopt -s dotglob nullglob if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then mv .debpkg/usr/share/doc/meshtasticd/web/build/* .debpkg/usr/share/doc/meshtasticd/web/; fi if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/doc/meshtasticd/web/build; fi - if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi - gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz + if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi + gunzip .debpkg/usr/share/doc/meshtasticd/web/ -r cp release/meshtasticd_linux_aarch64 .debpkg/usr/sbin/meshtasticd cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml - cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ + cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r chmod +x .debpkg/usr/sbin/meshtasticd cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles @@ -82,4 +82,4 @@ jobs: name: meshtasticd_${{ steps.version.outputs.version }}_arm64.deb overwrite: true path: | - ./*.deb + ./*.deb \ No newline at end of file diff --git a/.github/workflows/package_raspbian_armv7l.yml b/.github/workflows/package_raspbian_armv7l.yml index e19df9d17..2eda103ca 100644 --- a/.github/workflows/package_raspbian_armv7l.yml +++ b/.github/workflows/package_raspbian_armv7l.yml @@ -57,11 +57,11 @@ jobs: shopt -s dotglob nullglob if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then mv .debpkg/usr/share/doc/meshtasticd/web/build/* .debpkg/usr/share/doc/meshtasticd/web/; fi if [ -d .debpkg/usr/share/doc/meshtasticd/web/build ]; then rmdir .debpkg/usr/share/doc/meshtasticd/web/build; fi - if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi - gunzip .debpkg/usr/share/doc/meshtasticd/web/*.gz + if [ -d .debpkg/usr/share/doc/meshtasticd/web/.DS_Store ]; then rm -f .debpkg/usr/share/doc/meshtasticd/web/.DS_Store; fi + gunzip .debpkg/usr/share/doc/meshtasticd/web/ -r cp release/meshtasticd_linux_armv7l .debpkg/usr/sbin/meshtasticd cp bin/config-dist.yaml .debpkg/etc/meshtasticd/config.yaml - cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ + cp bin/config.d/* .debpkg/etc/meshtasticd/available.d/ -r chmod +x .debpkg/usr/sbin/meshtasticd cp bin/meshtasticd.service .debpkg/usr/lib/systemd/system/meshtasticd.service echo "/etc/meshtasticd/config.yaml" > .debpkg/DEBIAN/conffiles @@ -82,4 +82,4 @@ jobs: name: meshtasticd_${{ steps.version.outputs.version }}_armhf.deb overwrite: true path: | - ./*.deb + ./*.deb \ No newline at end of file diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml index 040712e1d..743f4214d 100644 --- a/.trunk/trunk.yaml +++ b/.trunk/trunk.yaml @@ -30,7 +30,7 @@ lint: - git-diff-check - gitleaks@8.21.1 - clang-format@16.0.3 - - prettier@3.3.3 + #- prettier@3.3.3 ignore: - linters: [ALL] paths: @@ -46,4 +46,4 @@ actions: enabled: - trunk-fmt-pre-commit - trunk-check-pre-push - - trunk-upgrade-available + - trunk-upgrade-available \ No newline at end of file diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 1e23cdf4d..6843fc85d 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,4 +1,4 @@ # Contributor Covenant Code of Conduct -The Meshtastic Firmware project is subject to the code of conduct for the parent project, which can be found here: +The Meshtastic Firmware project is subject to the code of conduct for the parent project, which can be found here: https://meshtastic.org/docs/legal/conduct/ diff --git a/arch/portduino/portduino.ini b/arch/portduino/portduino.ini index 04fd6db09..946a1489b 100644 --- a/arch/portduino/portduino.ini +++ b/arch/portduino/portduino.ini @@ -1,6 +1,6 @@ ; The Portduino based sim environment on top of any host OS, all hardware will be simulated [portduino_base] -platform = https://github.com/meshtastic/platform-native.git#bcd02436cfca91f7d28ad0f7dab977c6aaa781af +platform = https://github.com/meshtastic/platform-native.git#7fcee253a928535ff8b142704035b4b982f7e2d2 framework = arduino build_src_filter = diff --git a/arch/rp2xx0/rp2040.ini b/arch/rp2xx0/rp2040.ini index 85efa583c..5cfa678d5 100644 --- a/arch/rp2xx0/rp2040.ini +++ b/arch/rp2xx0/rp2040.ini @@ -1,8 +1,8 @@ ; Common settings for rp2040 Processor based targets [rp2040_base] -platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico 4.2.1 +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico >=4.2.1 extends = arduino_base -platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#996c3bfab9758f12c07aa20cc6d352e630c16987 ; 4.2.1 with fix for sporadic hangs +platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#6024e9a7e82a72e38dd90f42029ba3748835eb2e ; 4.3.0 with fix MDNS board_build.core = earlephilhower board_build.filesystem_size = 0.5m diff --git a/arch/rp2xx0/rp2350.ini b/arch/rp2xx0/rp2350.ini index 6daf59bdf..c5849ff2a 100644 --- a/arch/rp2xx0/rp2350.ini +++ b/arch/rp2xx0/rp2350.ini @@ -1,8 +1,8 @@ ; Common settings for rp2040 Processor based targets [rp2350_base] -platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico 4.2.1 +platform = https://github.com/maxgerhardt/platform-raspberrypi.git#19e30129fb1428b823be585c787dcb4ac0d9014c ; For arduino-pico >=4.2.1 extends = arduino_base -platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#96c3bfab9758f12c07aa20cc6d352e630c16987 ; 4.2.1 with fix for sporadic hangs +platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico.git#6024e9a7e82a72e38dd90f42029ba3748835eb2e ; 4.3.0 with fix MDNS board_build.core = earlephilhower board_build.filesystem_size = 0.5m diff --git a/bin/build-userprefs-json.py b/bin/build-userprefs-json.py index 58f460bcf..d155bae01 100644 --- a/bin/build-userprefs-json.py +++ b/bin/build-userprefs-json.py @@ -24,7 +24,7 @@ def write_macros_to_json(macros, output_file): def main(): header_file = 'userPrefs.h' - output_file = 'userPrefs.json' + output_file = 'userPrefs.jsonc' # Uncomment all macros in the header file with open(header_file, 'r') as file: lines = file.readlines() diff --git a/bin/config-dist.yaml b/bin/config-dist.yaml index 77680cc63..cb25b36e7 100644 --- a/bin/config-dist.yaml +++ b/bin/config-dist.yaml @@ -160,4 +160,6 @@ Webserver: General: MaxNodes: 200 MaxMessageQueue: 100 - ConfigDirectory: /etc/meshtasticd/config.d/ \ No newline at end of file + ConfigDirectory: /etc/meshtasticd/config.d/ +# MACAddress: AA:BB:CC:DD:EE:FF +# MACAddressSource: eth0 \ No newline at end of file diff --git a/bin/config.d/OpenWRT_One_mikroBUS_sx1262.yaml b/bin/config.d/OpenWRT_One_mikroBUS_sx1262.yaml new file mode 100644 index 000000000..f31411a51 --- /dev/null +++ b/bin/config.d/OpenWRT_One_mikroBUS_sx1262.yaml @@ -0,0 +1,8 @@ +Lora: + Module: sx1262 + IRQ: 10 + Busy: 12 + Reset: 2 + spidev: spidev2.0 + DIO2_AS_RF_SWITCH: true + DIO3_TCXO_VOLTAGE: true diff --git a/bin/config.d/femtofox/femtofox_EByte-E22-900M30S_Ebyte-E22-900M22S.yaml b/bin/config.d/femtofox/femtofox_EByte-E22-900M30S_Ebyte-E22-900M22S.yaml new file mode 100644 index 000000000..6c88b1eb2 --- /dev/null +++ b/bin/config.d/femtofox/femtofox_EByte-E22-900M30S_Ebyte-E22-900M22S.yaml @@ -0,0 +1,16 @@ +--- +Lora: +## Ebyte E22-900M30S, E22-900M22S with no external RF switching setup +## Will work with any module without RF switching, and with TCXO + Module: sx1262 + gpiochip: 1 # subtract 32 from the gpio numbers + DIO2_AS_RF_SWITCH: true + DIO3_TCXO_VOLTAGE: true + CS: 16 #pin6 / GPIO48 1C0 + IRQ: 23 #pin17 / GPIO55 1C7 + Busy: 22 #pin16 / GPIO54 1C6 + Reset: 25 #pin13 / GPIO57 1D1 + RXen: 24 #pin12 / GPIO56 1D0 + #TXen: bridge to DIO2 on E22 module + spidev: spidev0.0 + spiSpeed: 2000000 \ No newline at end of file diff --git a/bin/config.d/femtofox/femtofox_EByte-E22-900MM22S.yaml b/bin/config.d/femtofox/femtofox_EByte-E22-900MM22S.yaml new file mode 100644 index 000000000..451d5d3f4 --- /dev/null +++ b/bin/config.d/femtofox/femtofox_EByte-E22-900MM22S.yaml @@ -0,0 +1,16 @@ +--- +Lora: +## Ebyte E22-900MM22S with no external RF switching setup +## Will work with any module without RF switching and no TCXO + Module: sx1262 + gpiochip: 1 # subtract 32 from the gpio numbers + DIO2_AS_RF_SWITCH: true + DIO3_TCXO_VOLTAGE: true + CS: 16 #pin6 / GPIO48 1C0 + IRQ: 23 #pin17 / GPIO55 1C7 + Busy: 22 #pin16 / GPIO54 1C6 + Reset: 25 #pin13 / GPIO57 1D1 + RXen: 24 #pin12 / GPIO56 1D0 + #TXen: bridge to DIO2 on E22 module + spidev: spidev0.0 + spiSpeed: 2000000 \ No newline at end of file diff --git a/bin/config.d/femtofox/femtofox_Heltec-HT-RA62_Seeed-WIO-SX1262.yaml b/bin/config.d/femtofox/femtofox_Heltec-HT-RA62_Seeed-WIO-SX1262.yaml new file mode 100644 index 000000000..d5f02b42c --- /dev/null +++ b/bin/config.d/femtofox/femtofox_Heltec-HT-RA62_Seeed-WIO-SX1262.yaml @@ -0,0 +1,14 @@ +--- +Lora: +## Heltec HT-RA62, Seeed WIO SX1262 +## Will work with any module with automatic RF switching, and with TCXO + Module: sx1262 + gpiochip: 1 # subtract 32 from the gpio numbers + DIO2_AS_RF_SWITCH: true + DIO3_TCXO_VOLTAGE: true + CS: 16 #pin6 (GPIO pin 48 1C0) + IRQ: 23 #pin17 (GPIO pin 55 1C7) + Reset: 25 #pin13 (GPIO pin 57 1D1) + Busy: 22 #pin16 (GPIO pin 54 1C6) + spidev: spidev0.0 #pins are (CS=6, CLK=7, MOSI=8, MISO=9) + spiSpeed: 2000000 \ No newline at end of file diff --git a/bin/config.d/femtofox/femtofox_Waveshare-SX126X-XXXM_AI-Thinker-RA-01SH.yaml b/bin/config.d/femtofox/femtofox_Waveshare-SX126X-XXXM_AI-Thinker-RA-01SH.yaml new file mode 100644 index 000000000..23834adec --- /dev/null +++ b/bin/config.d/femtofox/femtofox_Waveshare-SX126X-XXXM_AI-Thinker-RA-01SH.yaml @@ -0,0 +1,13 @@ +--- +Lora: +## Waveshare SX126X XXXM, AI Thinker RA-01SH +## Will work with any module with automatic RF switching, and with no TCXO + Module: sx1262 + gpiochip: 1 # subtract 32 from the gpio numbers + DIO2_AS_RF_SWITCH: true + CS: 16 #pin6 (GPIO pin 48 1C0) + IRQ: 23 #pin17 (GPIO pin 55 1C7) + Reset: 25 #pin13 (GPIO pin 57 1D1) + Busy: 22 #pin16 (GPIO pin 54 1C6) + spidev: spidev0.0 #pins are (CS=6, CLK=7, MOSI=8, MISO=9) + spiSpeed: 2000000 diff --git a/bin/platformio-custom.py b/bin/platformio-custom.py index 701f6b5d8..acfeae10c 100644 --- a/bin/platformio-custom.py +++ b/bin/platformio-custom.py @@ -3,6 +3,8 @@ # trunk-ignore-all(flake8/F821): For SConstruct imports import sys from os.path import join +import json +import re from readprops import readProps @@ -90,11 +92,37 @@ prefsLoc = projenv["PROJECT_DIR"] + "/version.properties" verObj = readProps(prefsLoc) print("Using meshtastic platformio-custom.py, firmware version " + verObj["long"] + " on " + env.get("PIOENV")) +jsonLoc = env["PROJECT_DIR"] + "/userPrefs.jsonc" +with open(jsonLoc) as f: + jsonStr = re.sub("//.*","", f.read(), flags=re.MULTILINE) + userPrefs = json.loads(jsonStr) + +pref_flags = [] +# Pre-process the userPrefs +for pref in userPrefs: + if userPrefs[pref].startswith("{"): + pref_flags.append("-D" + pref + "=" + userPrefs[pref]) + elif userPrefs[pref].replace(".", "").isdigit(): + pref_flags.append("-D" + pref + "=" + userPrefs[pref]) + elif userPrefs[pref] == "true" or userPrefs[pref] == "false": + pref_flags.append("-D" + pref + "=" + userPrefs[pref]) + elif userPrefs[pref].startswith("meshtastic_"): + pref_flags.append("-D" + pref + "=" + userPrefs[pref]) + # If the value is a string, we need to wrap it in quotes + else: + pref_flags.append("-D" + pref + "=" + env.StringifyMacro(userPrefs[pref]) + "") + # General options that are passed to the C and C++ compilers -projenv.Append( - CCFLAGS=[ +flags = [ "-DAPP_VERSION=" + verObj["long"], "-DAPP_VERSION_SHORT=" + verObj["short"], "-DAPP_ENV=" + env.get("PIOENV"), - ] -) + ] + pref_flags + +print ("Using flags:") +for flag in flags: + print(flag) + +projenv.Append( + CCFLAGS=flags, +) \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 982848f41..cc08b33a0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -34,7 +34,6 @@ default_envs = tbeam ;default_envs = radiomaster_900_bandit_nano ;default_envs = radiomaster_900_bandit_micro ;default_envs = radiomaster_900_bandit -;default_envs = heltec_capsule_sensor_v3 ;default_envs = heltec_vision_master_t190 ;default_envs = heltec_vision_master_e213 ;default_envs = heltec_vision_master_e290 @@ -110,7 +109,6 @@ framework = arduino lib_deps = ${env.lib_deps} end2endzone/NonBlockingRTTTL@1.3.0 - https://github.com/meshtastic/SparkFun_ATECCX08a_Arduino_Library.git#5cf62b36c6f30bc72a07bdb2c11fc9a22d1e31da build_flags = ${env.build_flags} -Os build_src_filter = ${env.build_src_filter} - @@ -161,4 +159,4 @@ lib_deps = https://github.com/KodinLanewave/INA3221@1.0.1 mprograms/QMC5883LCompass@1.2.3 dfrobot/DFRobot_RTU@1.0.3 - https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d + https://github.com/meshtastic/DFRobot_LarkWeatherStation#4de3a9cadef0f6a5220a8a906cf9775b02b0040d \ No newline at end of file diff --git a/protobufs b/protobufs index c952f8a4c..00c9c9932 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit c952f8a4c1c30f724743ee322dd3ec3ec2f934c4 +Subproject commit 00c9c9932ea50c14cdc44d497d2672a0031641ce diff --git a/src/ButtonThread.cpp b/src/ButtonThread.cpp index 238359952..3f64b3b3e 100644 --- a/src/ButtonThread.cpp +++ b/src/ButtonThread.cpp @@ -1,5 +1,5 @@ #include "ButtonThread.h" -#include "../userPrefs.h" + #include "configuration.h" #if !MESHTASTIC_EXCLUDE_GPS #include "GPS.h" diff --git a/src/PowerFSM.cpp b/src/PowerFSM.cpp index 00dd6c942..4c4d203c2 100644 --- a/src/PowerFSM.cpp +++ b/src/PowerFSM.cpp @@ -19,6 +19,10 @@ #include "sleep.h" #include "target_specific.h" +#if HAS_WIFI && !defined(ARCH_PORTDUINO) +#include "mesh/wifi/WiFiAPClient.h" +#endif + #ifndef SLEEP_TIME #define SLEEP_TIME 30 #endif @@ -377,9 +381,9 @@ void PowerFSM_setup() // We never enter light-sleep or NB states on NRF52 (because the CPU uses so little power normally) #ifdef ARCH_ESP32 // See: https://github.com/meshtastic/firmware/issues/1071 - // Don't add power saving transitions if we are a power saving tracker or sensor. Sleep will be initiated through the - // modules - if ((isRouter || config.power.is_power_saving) && !isTrackerOrSensor) { + // Don't add power saving transitions if we are a power saving tracker or sensor or have Wifi enabled. Sleep will be initiated + // through the modules + if ((isRouter || config.power.is_power_saving) && !isWifiAvailable() && !isTrackerOrSensor) { powerFSM.add_timed_transition(&stateNB, &stateLS, Default::getConfiguredOrDefaultMs(config.power.min_wake_secs, default_min_wake_secs), NULL, "Min wake timeout"); diff --git a/src/configuration.h b/src/configuration.h index 2e81557b1..b5727508d 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -171,7 +171,6 @@ along with this program. If not, see . // ----------------------------------------------------------------------------- // Security // ----------------------------------------------------------------------------- -#define ATECC608B_ADDR 0x35 // ----------------------------------------------------------------------------- // IO Expander @@ -362,4 +361,4 @@ along with this program. If not, see . #endif #include "DebugConfiguration.h" -#include "RF95Configuration.h" +#include "RF95Configuration.h" \ No newline at end of file diff --git a/src/detect/ScanI2C.h b/src/detect/ScanI2C.h index f4516458b..7fe3aac89 100644 --- a/src/detect/ScanI2C.h +++ b/src/detect/ScanI2C.h @@ -12,7 +12,6 @@ class ScanI2C SCREEN_SH1106, SCREEN_UNKNOWN, // has the same address as the two above but does not respond to the same commands SCREEN_ST7567, - ATECC608B, RTC_RV3028, RTC_PCF8563, CARDKB, diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 55f13c5a0..d29e5be8e 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -7,7 +7,6 @@ #include "linux/LinuxHardwareI2C.h" #endif #if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) -#include "main.h" // atecc #include "meshUtils.h" // vformat #endif @@ -72,10 +71,10 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const r &= 0x0f; if (r == 0x08 || r == 0x00) { - LOG_INFO("sh1106 display found"); + logFoundDevice("SH1106", (uint8_t)addr.address); o_probe = SCREEN_SH1106; // SH1106 } else if (r == 0x03 || r == 0x04 || r == 0x06 || r == 0x07) { - LOG_INFO("ssd1306 display found"); + logFoundDevice("SSD1306", (uint8_t)addr.address); o_probe = SCREEN_SSD1306; // SSD1306 } c++; @@ -84,40 +83,6 @@ ScanI2C::DeviceType ScanI2CTwoWire::probeOLED(ScanI2C::DeviceAddress addr) const return o_probe; } -void ScanI2CTwoWire::printATECCInfo() const -{ -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) - atecc.readConfigZone(false); - - std::string atecc_numbers = "ATECC608B Serial Number: "; - for (int i = 0; i < 9; i++) { - atecc_numbers += vformat("%02x", atecc.serialNumber[i]); - } - - atecc_numbers += ", Rev Number: "; - for (int i = 0; i < 4; i++) { - atecc_numbers += vformat("%02x", atecc.revisionNumber[i]); - } - LOG_DEBUG(atecc_numbers.c_str()); - - LOG_DEBUG("ATECC608B Config %s, Data %s, Slot 0 %s", atecc.configLockStatus ? "Locked" : "Unlocked", - atecc.dataOTPLockStatus ? "Locked" : "Unlocked", atecc.slot0LockStatus ? "Locked" : "Unlocked"); - - std::string atecc_publickey = ""; - if (atecc.configLockStatus && atecc.dataOTPLockStatus && atecc.slot0LockStatus) { - if (atecc.generatePublicKey() == false) { - atecc_publickey += "ATECC608B Error generating public key"; - } else { - atecc_publickey += "ATECC608B Public Key: "; - for (int i = 0; i < 64; i++) { - atecc_publickey += vformat("%02x", atecc.publicKey64Bytes[i]); - } - } - LOG_DEBUG(atecc_publickey.c_str()); - } -#endif -} - uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation ®isterLocation, ScanI2CTwoWire::ResponseWidth responseWidth) const { @@ -129,7 +94,6 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation i2cBus->endTransmission(); delay(20); i2cBus->requestFrom(registerLocation.i2cAddress.address, responseWidth); - LOG_DEBUG("Wire.available() = %d", i2cBus->available()); if (i2cBus->available() == 2) { // Read MSB, then LSB value = (uint16_t)i2cBus->read() << 8; @@ -142,7 +106,7 @@ uint16_t ScanI2CTwoWire::getRegisterValue(const ScanI2CTwoWire::RegisterLocation #define SCAN_SIMPLE_CASE(ADDR, T, ...) \ case ADDR: \ - LOG_INFO(__VA_ARGS__); \ + logFoundDevice(__VA_ARGS__); \ type = T; \ break; @@ -184,9 +148,9 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) for (addr.address = 8; addr.address < 120; addr.address++) { if (asize != 0) { - if (!in_array(address, asize, addr.address)) + if (!in_array(address, asize, (uint8_t)addr.address)) continue; - LOG_DEBUG("Scan address 0x%x", addr.address); + LOG_DEBUG("Scan address 0x%x", (uint8_t)addr.address); } i2cBus->beginTransmission(addr.address); #ifdef ARCH_PORTDUINO @@ -199,35 +163,16 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) #endif type = NONE; if (err == 0) { - LOG_DEBUG("I2C device found at address 0x%x", addr.address); - switch (addr.address) { case SSD1306_ADDRESS: type = probeOLED(addr); break; -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) - case ATECC608B_ADDR: -#ifdef RP2040_SLOW_CLOCK - if (atecc.begin(addr.address, Wire, Serial2) == true) -#else - if (atecc.begin(addr.address) == true) -#endif - - { - LOG_INFO("ATECC608B initialized"); - } else { - LOG_WARN("ATECC608B initialization failed"); - } - printATECCInfo(); - break; -#endif - #ifdef RV3028_RTC case RV3028_RTC: // foundDevices[addr] = RTC_RV3028; type = RTC_RV3028; - LOG_INFO("RV3028 RTC found"); + logFoundDevice("RV3028", (uint8_t)addr.address); rtc.initI2C(*i2cBus); rtc.writeToRegister(0x35, 0x07); // no Clkout rtc.writeToRegister(0x37, 0xB4); @@ -235,7 +180,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) #endif #ifdef PCF8563_RTC - SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563 RTC found") + SCAN_SIMPLE_CASE(PCF8563_RTC, RTC_PCF8563, "PCF8563", (uint8_t)addr.address) #endif case CARDKB_ADDR: @@ -243,50 +188,50 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x04), 1); if (registerValue == 0x02) { // KEYPAD_VERSION - LOG_INFO("RAK14004 found"); + logFoundDevice("RAK14004", (uint8_t)addr.address); type = RAK14004; } else { - LOG_INFO("m5 cardKB found"); + logFoundDevice("M5 cardKB", (uint8_t)addr.address); type = CARDKB; } break; - SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard found"); - SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10 keyboard found"); + SCAN_SIMPLE_CASE(TDECK_KB_ADDR, TDECKKB, "T-Deck keyboard", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(BBQ10_KB_ADDR, BBQ10KB, "BB Q10", (uint8_t)addr.address); - SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "st7567 display found"); + SCAN_SIMPLE_CASE(ST7567_ADDRESS, SCREEN_ST7567, "ST7567", (uint8_t)addr.address); #ifdef HAS_NCP5623 - SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623 RGB LED found"); + SCAN_SIMPLE_CASE(NCP5623_ADDR, NCP5623, "NCP5623", (uint8_t)addr.address); #endif #ifdef HAS_PMU - SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "axp192/axp2101 PMU found") + SCAN_SIMPLE_CASE(XPOWERS_AXP192_AXP2101_ADDRESS, PMU_AXP192_AXP2101, "AXP192/AXP2101", (uint8_t)addr.address) #endif case BME_ADDR: case BME_ADDR_ALTERNATE: registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID switch (registerValue) { case 0x61: - LOG_INFO("BME-680 sensor found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("BME680", (uint8_t)addr.address); type = BME_680; break; case 0x60: - LOG_INFO("BME-280 sensor found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("BME280", (uint8_t)addr.address); type = BME_280; break; case 0x55: - LOG_INFO("BMP-085 or BMP-180 sensor found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("BMP085/BMP180", (uint8_t)addr.address); type = BMP_085; break; default: registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); // GET_ID switch (registerValue) { case 0x50: // BMP-388 should be 0x50 - LOG_INFO("BMP-388 sensor found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("BMP-388", (uint8_t)addr.address); type = BMP_3XX; break; case 0x58: // BMP-280 should be 0x58 default: - LOG_INFO("BMP-280 sensor found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("BMP-280", (uint8_t)addr.address); type = BMP_280; break; } @@ -295,7 +240,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) break; #ifndef HAS_NCP5623 case AHT10_ADDR: - LOG_INFO("AHT10 sensor found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("AHT10", (uint8_t)addr.address); type = AHT10; break; #endif @@ -305,10 +250,10 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2); LOG_DEBUG("Register MFG_UID: 0x%x", registerValue); if (registerValue == 0x5449) { - LOG_INFO("INA260 sensor found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("INA260", (uint8_t)addr.address); type = INA260; } else { // Assume INA219 if INA260 ID is not found - LOG_INFO("INA219 sensor found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("INA219", (uint8_t)addr.address); type = INA219; } break; @@ -316,7 +261,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFE), 2); LOG_DEBUG("Register MFG_UID FE: 0x%x", registerValue); if (registerValue == 0x5449) { - LOG_INFO("INA3221 sensor found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("INA3221", (uint8_t)addr.address); type = INA3221; } else { /* check the first 2 bytes of the 6 byte response register @@ -331,7 +276,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x05), 2); LOG_DEBUG("Register MFG_UID 05: 0x%x", registerValue); if (registerValue == 0x5305) { - LOG_INFO("DFRobot Lark weather station found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("DFRobot Lark", (uint8_t)addr.address); type = DFROBOT_LARK; } // else: probably a RAK12500/UBLOX GPS on I2C @@ -346,7 +291,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 2); if (registerValue == 0x8700) { type = STK8BAXX; - LOG_INFO("STK8BAXX accelerometer found"); + logFoundDevice("STK8BAXX", (uint8_t)addr.address); break; } #endif @@ -355,7 +300,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x07), 2); if (registerValue == 0x0400) { type = MCP9808; - LOG_INFO("MCP9808 sensor found"); + logFoundDevice("MCP9808", (uint8_t)addr.address); break; } @@ -363,7 +308,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2); if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333 type = LIS3DH; - LOG_INFO("LIS3DH accelerometer found"); + logFoundDevice("LIS3DH", (uint8_t)addr.address); } break; } @@ -371,93 +316,92 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x89), 2); if (registerValue == 0x11a2 || registerValue == 0x11da || registerValue == 0xe9c) { type = SHT4X; - LOG_INFO("SHT4X sensor found"); + logFoundDevice("SHT4X", (uint8_t)addr.address); } else if (getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x7E), 2) == 0x5449) { type = OPT3001; - LOG_INFO("OPT3001 light sensor found"); + logFoundDevice("OPT3001", (uint8_t)addr.address); } else { type = SHT31; - LOG_INFO("SHT31 sensor found"); + logFoundDevice("SHT31", (uint8_t)addr.address); } break; - SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3 sensor found") + SCAN_SIMPLE_CASE(SHTC3_ADDR, SHTC3, "SHTC3", (uint8_t)addr.address) case RCWL9620_ADDR: // get MAX30102 PARTID registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xFF), 1); if (registerValue == 0x15) { type = MAX30102; - LOG_INFO("MAX30102 Health sensor found"); + logFoundDevice("MAX30102", (uint8_t)addr.address); break; } else { type = RCWL9620; - LOG_INFO("RCWL9620 sensor found"); + logFoundDevice("RCWL9620", (uint8_t)addr.address); } break; case LPS22HB_ADDR_ALT: - SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB sensor found") - - SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310 Highrate 3-Axis magnetic sensor found") + SCAN_SIMPLE_CASE(LPS22HB_ADDR, LPS22HB, "LPS22HB", (uint8_t)addr.address) + SCAN_SIMPLE_CASE(QMC6310_ADDR, QMC6310, "QMC6310", (uint8_t)addr.address) case QMI8658_ADDR: registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0A), 1); // get ID if (registerValue == 0xC0) { type = BQ24295; - LOG_INFO("BQ24295 PMU found"); + logFoundDevice("BQ24295", (uint8_t)addr.address); break; } registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 1); // get ID if (registerValue == 0x6A) { type = LSM6DS3; - LOG_INFO("LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address); + logFoundDevice("LSM6DS3", (uint8_t)addr.address); } else { type = QMI8658; - LOG_INFO("QMI8658 Highrate 6-Axis inertial measurement sensor found"); + logFoundDevice("QMI8658", (uint8_t)addr.address); } break; - SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L Highrate 3-Axis magnetic sensor found") - SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L 3-Axis digital compass found") + SCAN_SIMPLE_CASE(QMC5883L_ADDR, QMC5883L, "QMC5883L", (uint8_t)addr.address) + SCAN_SIMPLE_CASE(HMC5883L_ADDR, HMC5883L, "HMC5883L", (uint8_t)addr.address) #ifdef HAS_QMA6100P - SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P accelerometer found") + SCAN_SIMPLE_CASE(QMA6100P_ADDR, QMA6100P, "QMA6100P", (uint8_t)addr.address) #else - SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031 air quality sensor found") + SCAN_SIMPLE_CASE(PMSA0031_ADDR, PMSA0031, "PMSA0031", (uint8_t)addr.address) #endif case BMA423_ADDR: // this can also be LIS3DH_ADDR_ALT registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0F), 2); if (registerValue == 0x3300 || registerValue == 0x3333) { // RAK4631 WisBlock has LIS3DH register at 0x3333 type = LIS3DH; - LOG_INFO("LIS3DH accelerometer found"); + logFoundDevice("LIS3DH", (uint8_t)addr.address); } else { type = BMA423; - LOG_INFO("BMA423 accelerometer found"); + logFoundDevice("BMA423", (uint8_t)addr.address); } break; - SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3 accelerometer found at address 0x%x", (uint8_t)addr.address); - SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535 I2C expander found"); - SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555 I2C expander found"); - SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700 light sensor found"); - SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591 light sensor found"); - SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001 light sensor found"); - SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632 IR temp sensor found"); - SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802 based scale found"); - SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U touchscreen found"); - SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048 lipo fuel gauge found"); + SCAN_SIMPLE_CASE(LSM6DS3_ADDR, LSM6DS3, "LSM6DS3", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(TCA9535_ADDR, TCA9535, "TCA9535", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(TCA9555_ADDR, TCA9555, "TCA9555", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(VEML7700_ADDR, VEML7700, "VEML7700", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(TSL25911_ADDR, TSL2591, "TSL2591", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(OPT3001_ADDR, OPT3001, "OPT3001", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(MLX90632_ADDR, MLX90632, "MLX90632", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(NAU7802_ADDR, NAU7802, "NAU7802", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(FT6336U_ADDR, FT6336U, "FT6336U", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(MAX1704X_ADDR, MAX17048, "MAX17048", (uint8_t)addr.address); #ifdef HAS_TPS65233 - SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233 BIAS-T found"); + SCAN_SIMPLE_CASE(TPS65233_ADDR, TPS65233, "TPS65233", (uint8_t)addr.address); #endif case MLX90614_ADDR_DEF: registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x0e), 1); if (registerValue == 0x5a) { type = MLX90614; - LOG_INFO("MLX90614 IR temp sensor found"); + logFoundDevice("MLX90614", (uint8_t)addr.address); } else { type = MPR121KB; - LOG_INFO("MPR121KB keyboard found"); + logFoundDevice("MPR121KB", (uint8_t)addr.address); } break; @@ -466,15 +410,15 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); if (registerValue == 0xEA) { type = ICM20948; - LOG_INFO("ICM20948 9-dof motion processor found"); + logFoundDevice("ICM20948", (uint8_t)addr.address); break; } else if (addr.address == BMX160_ADDR) { type = BMX160; - LOG_INFO("BMX160 accelerometer found"); + logFoundDevice("BMX160", (uint8_t)addr.address); break; } else { type = MPU6050; - LOG_INFO("MPU6050 accelerometer found"); + logFoundDevice("MPU6050", (uint8_t)addr.address); break; } break; @@ -484,16 +428,16 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x00), 1); if (registerValue == 0x7D) { type = CGRADSENS; - LOG_INFO("ClimateGuard RadSens Geiger-Muller Sensor found"); + logFoundDevice("ClimateGuard RadSens", (uint8_t)addr.address); break; } break; default: - LOG_INFO("Device found at address 0x%x was not able to be enumerated", addr.address); + LOG_INFO("Device found at address 0x%x was not able to be enumerated", (uint8_t)addr.address); } } else if (err == 4) { - LOG_ERROR("Unknown error at address 0x%x", addr.address); + LOG_ERROR("Unknown error at address 0x%x", (uint8_t)addr.address); } // Check if a type was found for the enumerated device - save, if so @@ -526,4 +470,9 @@ size_t ScanI2CTwoWire::countDevices() const { return foundDevices.size(); } + +void ScanI2CTwoWire::logFoundDevice(const char *device, uint8_t address) +{ + LOG_INFO("%s found at address 0x%x", device, address); +} #endif \ No newline at end of file diff --git a/src/detect/ScanI2CTwoWire.h b/src/detect/ScanI2CTwoWire.h index c8dd96469..d0af7cde6 100644 --- a/src/detect/ScanI2CTwoWire.h +++ b/src/detect/ScanI2CTwoWire.h @@ -53,10 +53,10 @@ class ScanI2CTwoWire : public ScanI2C concurrency::Lock lock; - void printATECCInfo() const; - uint16_t getRegisterValue(const RegisterLocation &, ResponseWidth) const; DeviceType probeOLED(ScanI2C::DeviceAddress) const; + + static void logFoundDevice(const char *device, uint8_t address); }; #endif \ No newline at end of file diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index a6db85950..dcece305a 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -28,29 +28,43 @@ #define GPS_RESET_MODE HIGH #endif +// Not all platforms have std::size(). +template std::size_t array_count(const T (&)[N]) +{ + return N; +} + #if defined(NRF52840_XXAA) || defined(NRF52833_XXAA) || defined(ARCH_ESP32) || defined(ARCH_PORTDUINO) HardwareSerial *GPS::_serial_gps = &Serial1; #elif defined(ARCH_RP2040) SerialUART *GPS::_serial_gps = &Serial1; #else -HardwareSerial *GPS::_serial_gps = NULL; +HardwareSerial *GPS::_serial_gps = nullptr; #endif GPS *gps = nullptr; -GPSUpdateScheduling scheduling; +static const char *ACK_SUCCESS_MESSAGE = "Get ack success!"; + +static GPSUpdateScheduling scheduling; /// Multiple GPS instances might use the same serial port (in sequence), but we can /// only init that port once. static bool didSerialInit; -struct uBloxGnssModelInfo info; -uint8_t uBloxProtocolVersion; +static struct uBloxGnssModelInfo { + char swVersion[30]; + char hwVersion[10]; + uint8_t extensionNo; + char extension[10][30]; + uint8_t protocol_version; +} ublox_info; + #define GPS_SOL_EXPIRY_MS 5000 // in millis. give 1 second time to combine different sentences. NMEA Frequency isn't higher anyway #define NMEA_MSG_GXGSA "GNGSA" // GSA message (GPGSA, GNGSA etc) // For logging -const char *getGPSPowerStateString(GPSPowerState state) +static const char *getGPSPowerStateString(GPSPowerState state) { switch (state) { case GPS_ACTIVE: @@ -69,7 +83,7 @@ const char *getGPSPowerStateString(GPSPowerState state) } } -void GPS::UBXChecksum(uint8_t *message, size_t length) +static void UBXChecksum(uint8_t *message, size_t length) { uint8_t CK_A = 0, CK_B = 0; @@ -85,7 +99,7 @@ void GPS::UBXChecksum(uint8_t *message, size_t length) } // Calculate the checksum for a CAS packet -void GPS::CASChecksum(uint8_t *message, size_t length) +static void CASChecksum(uint8_t *message, size_t length) { uint32_t cksum = ((uint32_t)message[5] << 24); // Message ID cksum += ((uint32_t)message[4]) << 16; // Class @@ -410,6 +424,15 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t return 0; } +#if GPS_BAUDRATE_FIXED +// if GPS_BAUDRATE is specified in variant, only try that. +static const int serialSpeeds[1] = {GPS_BAUDRATE}; +static const int rareSerialSpeeds[1] = {GPS_BAUDRATE}; +#else +static const int serialSpeeds[3] = {9600, 115200, 38400}; +static const int rareSerialSpeeds[3] = {4800, 57600, GPS_BAUDRATE}; +#endif + /** * @brief Setup the GPS based on the model detected. * We detect the GPS by cycling through a set of baud rates, first common then rare. @@ -419,7 +442,6 @@ int GPS::getACK(uint8_t *buffer, uint16_t size, uint8_t requestedClass, uint8_t */ bool GPS::setup() { - if (!didSerialInit) { int msglen = 0; if (tx_gpio && gnssModel == GNSS_MODEL_UNKNOWN) { @@ -427,7 +449,7 @@ bool GPS::setup() LOG_DEBUG("Probe for GPS at %d", serialSpeeds[speedSelect]); gnssModel = probe(serialSpeeds[speedSelect]); if (gnssModel == GNSS_MODEL_UNKNOWN) { - if (++speedSelect == sizeof(serialSpeeds) / sizeof(int)) { + if (++speedSelect == array_count(serialSpeeds)) { speedSelect = 0; ++probeTries; } @@ -438,7 +460,7 @@ bool GPS::setup() LOG_DEBUG("Probe for GPS at %d", rareSerialSpeeds[speedSelect]); gnssModel = probe(rareSerialSpeeds[speedSelect]); if (gnssModel == GNSS_MODEL_UNKNOWN) { - if (++speedSelect == sizeof(rareSerialSpeeds) / sizeof(int)) { + if (++speedSelect == array_count(rareSerialSpeeds)) { LOG_WARN("Give up on GPS probe and set to %d", GPS_BAUDRATE); return true; } @@ -634,7 +656,7 @@ bool GPS::setup() SEND_UBX_PACKET(0x06, 0x01, _message_RMC, "enable NMEA RMC", 500); SEND_UBX_PACKET(0x06, 0x01, _message_GGA, "enable NMEA GGA", 500); - if (uBloxProtocolVersion >= 18) { + if (ublox_info.protocol_version >= 18) { clearBuffer(); SEND_UBX_PACKET(0x06, 0x86, _message_PMS, "enable powersave for GPS", 500); SEND_UBX_PACKET(0x06, 0x3B, _message_CFG_PM2, "enable powersave details for GPS", 500); @@ -718,6 +740,7 @@ GPS::~GPS() // we really should unregister our sleep observer notifyDeepSleepObserver.unobserve(¬ifyDeepSleep); } + // Put the GPS hardware into a specified state void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime) { @@ -882,17 +905,17 @@ void GPS::setPowerUBLOX(bool on, uint32_t sleepMs) if (gnssModel != GNSS_MODEL_UBLOX10) { // Encode the sleep time in millis into the packet for (int i = 0; i < 4; i++) - gps->_message_PMREQ[0 + i] = sleepMs >> (i * 8); + _message_PMREQ[0 + i] = sleepMs >> (i * 8); // Record the message length - msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ), gps->_message_PMREQ); + msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ), _message_PMREQ); } else { // Encode the sleep time in millis into the packet for (int i = 0; i < 4; i++) - gps->_message_PMREQ_10[4 + i] = sleepMs >> (i * 8); + _message_PMREQ_10[4 + i] = sleepMs >> (i * 8); // Record the message length - msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ_10), gps->_message_PMREQ_10); + msglen = gps->makeUBXPacket(0x02, 0x41, sizeof(_message_PMREQ_10), _message_PMREQ_10); } // Send the UBX packet @@ -1099,17 +1122,19 @@ int GPS::prepareDeepSleep(void *unused) return 0; } -const char *PROBE_MESSAGE = "Trying %s (%s)..."; -const char *DETECTED_MESSAGE = "%s detected, using %s Module"; +static const char *PROBE_MESSAGE = "Trying %s (%s)..."; +static const char *DETECTED_MESSAGE = "%s detected, using %s Module"; #define PROBE_SIMPLE(CHIP, TOWRITE, RESPONSE, DRIVER, TIMEOUT, ...) \ - LOG_DEBUG(PROBE_MESSAGE, TOWRITE, CHIP); \ - clearBuffer(); \ - _serial_gps->write(TOWRITE "\r\n"); \ - if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \ - LOG_INFO(DETECTED_MESSAGE, CHIP, #DRIVER); \ - return DRIVER; \ - } + do { \ + LOG_DEBUG(PROBE_MESSAGE, TOWRITE, CHIP); \ + clearBuffer(); \ + _serial_gps->write(TOWRITE "\r\n"); \ + if (getACK(RESPONSE, TIMEOUT) == GNSS_RESPONSE_OK) { \ + LOG_INFO(DETECTED_MESSAGE, CHIP, #DRIVER); \ + return DRIVER; \ + } \ + } while (0) GnssModel_t GPS::probe(int serialSpeed) { @@ -1127,7 +1152,7 @@ GnssModel_t GPS::probe(int serialSpeed) } #endif - memset(&info, 0, sizeof(struct uBloxGnssModelInfo)); + memset(&ublox_info, 0, sizeof(ublox_info)); uint8_t buffer[768] = {0}; delay(100); @@ -1194,64 +1219,64 @@ GnssModel_t GPS::probe(int serialSpeed) if (len) { uint16_t position = 0; for (int i = 0; i < 30; i++) { - info.swVersion[i] = buffer[position]; + ublox_info.swVersion[i] = buffer[position]; position++; } for (int i = 0; i < 10; i++) { - info.hwVersion[i] = buffer[position]; + ublox_info.hwVersion[i] = buffer[position]; position++; } while (len >= position + 30) { for (int i = 0; i < 30; i++) { - info.extension[info.extensionNo][i] = buffer[position]; + ublox_info.extension[ublox_info.extensionNo][i] = buffer[position]; position++; } - info.extensionNo++; - if (info.extensionNo > 9) + ublox_info.extensionNo++; + if (ublox_info.extensionNo > 9) break; } LOG_DEBUG("Module Info : "); - LOG_DEBUG("Soft version: %s", info.swVersion); - LOG_DEBUG("Hard version: %s", info.hwVersion); - LOG_DEBUG("Extensions:%d", info.extensionNo); - for (int i = 0; i < info.extensionNo; i++) { - LOG_DEBUG(" %s", info.extension[i]); + LOG_DEBUG("Soft version: %s", ublox_info.swVersion); + LOG_DEBUG("Hard version: %s", ublox_info.hwVersion); + LOG_DEBUG("Extensions:%d", ublox_info.extensionNo); + for (int i = 0; i < ublox_info.extensionNo; i++) { + LOG_DEBUG(" %s", ublox_info.extension[i]); } memset(buffer, 0, sizeof(buffer)); // tips: extensionNo field is 0 on some 6M GNSS modules - for (int i = 0; i < info.extensionNo; ++i) { - if (!strncmp(info.extension[i], "MOD=", 4)) { - strncpy((char *)buffer, &(info.extension[i][4]), sizeof(buffer)); - } else if (!strncmp(info.extension[i], "PROTVER", 7)) { + for (int i = 0; i < ublox_info.extensionNo; ++i) { + if (!strncmp(ublox_info.extension[i], "MOD=", 4)) { + strncpy((char *)buffer, &(ublox_info.extension[i][4]), sizeof(buffer)); + } else if (!strncmp(ublox_info.extension[i], "PROTVER", 7)) { char *ptr = nullptr; memset(buffer, 0, sizeof(buffer)); - strncpy((char *)buffer, &(info.extension[i][8]), sizeof(buffer)); + strncpy((char *)buffer, &(ublox_info.extension[i][8]), sizeof(buffer)); LOG_DEBUG("Protocol Version:%s", (char *)buffer); if (strlen((char *)buffer)) { - uBloxProtocolVersion = strtoul((char *)buffer, &ptr, 10); - LOG_DEBUG("ProtVer=%d", uBloxProtocolVersion); + ublox_info.protocol_version = strtoul((char *)buffer, &ptr, 10); + LOG_DEBUG("ProtVer=%d", ublox_info.protocol_version); } else { - uBloxProtocolVersion = 0; + ublox_info.protocol_version = 0; } } } - if (strncmp(info.hwVersion, "00040007", 8) == 0) { + if (strncmp(ublox_info.hwVersion, "00040007", 8) == 0) { LOG_INFO(DETECTED_MESSAGE, "U-blox 6", "6"); return GNSS_MODEL_UBLOX6; - } else if (strncmp(info.hwVersion, "00070000", 8) == 0) { + } else if (strncmp(ublox_info.hwVersion, "00070000", 8) == 0) { LOG_INFO(DETECTED_MESSAGE, "U-blox 7", "7"); return GNSS_MODEL_UBLOX7; - } else if (strncmp(info.hwVersion, "00080000", 8) == 0) { + } else if (strncmp(ublox_info.hwVersion, "00080000", 8) == 0) { LOG_INFO(DETECTED_MESSAGE, "U-blox 8", "8"); return GNSS_MODEL_UBLOX8; - } else if (strncmp(info.hwVersion, "00190000", 8) == 0) { + } else if (strncmp(ublox_info.hwVersion, "00190000", 8) == 0) { LOG_INFO(DETECTED_MESSAGE, "U-blox 9", "9"); return GNSS_MODEL_UBLOX9; - } else if (strncmp(info.hwVersion, "000A0000", 8) == 0) { + } else if (strncmp(ublox_info.hwVersion, "000A0000", 8) == 0) { LOG_INFO(DETECTED_MESSAGE, "U-blox 10", "10"); return GNSS_MODEL_UBLOX10; } @@ -1725,4 +1750,4 @@ void GPS::toggleGpsMode() enable(); } } -#endif // Exclude GPS +#endif // Exclude GPS \ No newline at end of file diff --git a/src/gps/GPS.h b/src/gps/GPS.h index cb970f7db..15fc50fe7 100644 --- a/src/gps/GPS.h +++ b/src/gps/GPS.h @@ -16,13 +16,6 @@ #define GPS_EN_ACTIVE 1 #endif -struct uBloxGnssModelInfo { - char swVersion[30]; - char hwVersion[10]; - uint8_t extensionNo; - char extension[10][30]; -}; - typedef enum { GNSS_MODEL_ATGM336H, GNSS_MODEL_MTK, @@ -54,9 +47,6 @@ enum GPSPowerState : uint8_t { GPS_OFF // Powered off indefinitely }; -// Generate a string representation of DOP -const char *getDOPString(uint32_t dop); - /** * A gps class that only reads from the GPS periodically and keeps the gps powered down except when reading * @@ -122,7 +112,9 @@ class GPS : private concurrency::OSThread // Let the GPS hardware save power between updates void down(); - protected: + private: + GPS() : concurrency::OSThread("GPS") {} + /// Record that we have a GPS void setConnected(); @@ -150,9 +142,6 @@ class GPS : private concurrency::OSThread GnssModel_t gnssModel = GNSS_MODEL_UNKNOWN; - private: - GPS() : concurrency::OSThread("GPS") {} - TinyGPSPlus reader; uint8_t fixQual = 0; // fix quality from GPGGA uint32_t lastChecksumFailCount = 0; @@ -164,21 +153,13 @@ class GPS : private concurrency::OSThread TinyGPSCustom gsapdop; // custom extract PDOP from GPGSA uint8_t fixType = 0; // fix type from GPGSA #endif -#if GPS_BAUDRATE_FIXED - // if GPS_BAUDRATE is specified in variant, only try that. - const int serialSpeeds[1] = {GPS_BAUDRATE}; - const int rareSerialSpeeds[1] = {GPS_BAUDRATE}; -#else - const int serialSpeeds[3] = {9600, 115200, 38400}; - const int rareSerialSpeeds[3] = {4800, 57600, GPS_BAUDRATE}; -#endif uint32_t lastWakeStartMsec = 0, lastSleepStartMsec = 0, lastFixStartMsec = 0; uint32_t rx_gpio = 0; uint32_t tx_gpio = 0; - int speedSelect = 0; - int probeTries = 0; + uint8_t speedSelect = 0; + uint8_t probeTries = 0; /** * hasValidLocation - indicates that the position variables contain a complete @@ -207,52 +188,6 @@ class GPS : private concurrency::OSThread #else static HardwareSerial *_serial_gps; #endif - static uint8_t _message_PMREQ[]; - static uint8_t _message_PMREQ_10[]; - static const uint8_t _message_CFG_RXM_PSM[]; - static const uint8_t _message_CFG_RXM_ECO[]; - static const uint8_t _message_CFG_PM2[]; - static const uint8_t _message_GNSS_7[]; - static const uint8_t _message_GNSS_8[]; - static const uint8_t _message_JAM_6_7[]; - static const uint8_t _message_JAM_8[]; - static const uint8_t _message_NAVX5[]; - static const uint8_t _message_NAVX5_8[]; - static const uint8_t _message_NMEA[]; - static const uint8_t _message_DISABLE_TXT_INFO[]; - static const uint8_t _message_1HZ[]; - static const uint8_t _message_GLL[]; - static const uint8_t _message_GSA[]; - static const uint8_t _message_GSV[]; - static const uint8_t _message_VTG[]; - static const uint8_t _message_RMC[]; - static const uint8_t _message_AID[]; - static const uint8_t _message_GGA[]; - static const uint8_t _message_PMS[]; - static const uint8_t _message_SAVE[]; - static const uint8_t _message_SAVE_10[]; - - // VALSET Commands for M10 - static const uint8_t _message_VALSET_PM[]; - static const uint8_t _message_VALSET_PM_RAM[]; - static const uint8_t _message_VALSET_PM_BBR[]; - static const uint8_t _message_VALSET_ITFM_RAM[]; - static const uint8_t _message_VALSET_ITFM_BBR[]; - static const uint8_t _message_VALSET_DISABLE_NMEA_RAM[]; - static const uint8_t _message_VALSET_DISABLE_NMEA_BBR[]; - static const uint8_t _message_VALSET_DISABLE_TXT_INFO_RAM[]; - static const uint8_t _message_VALSET_DISABLE_TXT_INFO_BBR[]; - static const uint8_t _message_VALSET_ENABLE_NMEA_RAM[]; - static const uint8_t _message_VALSET_ENABLE_NMEA_BBR[]; - static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[]; - static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[]; - - // CASIC commands for ATGM336H - static const uint8_t _message_CAS_CFG_RST_FACTORY[]; - static const uint8_t _message_CAS_CFG_NAVX_CONF[]; - static const uint8_t _message_CAS_CFG_RATE_1HZ[]; - - const char *ACK_SUCCESS_MESSAGE = "Get ack success!"; // Create a ublox packet for editing in memory uint8_t makeUBXPacket(uint8_t class_id, uint8_t msg_id, uint8_t payload_size, const uint8_t *msg); @@ -273,10 +208,6 @@ class GPS : private concurrency::OSThread /// always returns 0 to indicate okay to sleep int prepareDeepSleep(void *unused); - // Calculate checksum - void UBXChecksum(uint8_t *message, size_t length); - void CASChecksum(uint8_t *message, size_t length); - /** Set power with EN pin, if relevant */ void writePinEN(bool on); @@ -305,9 +236,7 @@ class GPS : private concurrency::OSThread // delay counter to allow more sats before fixed position stops GPS thread uint8_t fixeddelayCtr = 0; - - const char *powerStateToString(); }; extern GPS *gps; -#endif // Exclude GPS +#endif // Exclude GPS \ No newline at end of file diff --git a/src/gps/GeoCoord.cpp b/src/gps/GeoCoord.cpp index 5abb25a06..6d1f2da6d 100644 --- a/src/gps/GeoCoord.cpp +++ b/src/gps/GeoCoord.cpp @@ -574,3 +574,23 @@ const char *GeoCoord::degreesToBearing(unsigned int degrees) else return "N"; } + +double GeoCoord::pow_neg(double base, double exponent) +{ + if (exponent == 0) { + return 1; + } else if (exponent > 0) { + return pow(base, exponent); + } + return 1 / pow(base, -exponent); +} + +double GeoCoord::toRadians(double deg) +{ + return deg * PI / 180; +} + +double GeoCoord::toDegrees(double r) +{ + return r * 180 / PI; +} \ No newline at end of file diff --git a/src/gps/GeoCoord.h b/src/gps/GeoCoord.h index ecdaf0ec7..658c177b3 100644 --- a/src/gps/GeoCoord.h +++ b/src/gps/GeoCoord.h @@ -13,28 +13,6 @@ #define OLC_CODE_LEN 11 #define DEG_CONVERT (180 / PI) -// Helper functions -// Raises a number to an exponent, handling negative exponents. -static inline double pow_neg(double base, double exponent) -{ - if (exponent == 0) { - return 1; - } else if (exponent > 0) { - return pow(base, exponent); - } - return 1 / pow(base, -exponent); -} - -static inline double toRadians(double deg) -{ - return deg * PI / 180; -} - -static inline double toDegrees(double r) -{ - return r * 180 / PI; -} - // GeoCoord structs/classes // A struct to hold the data for a DMS coordinate. struct DMS { @@ -120,6 +98,11 @@ class GeoCoord static unsigned int bearingToDegrees(const char *bearing); static const char *degreesToBearing(unsigned int degrees); + // Raises a number to an exponent, handling negative exponents. + static double pow_neg(double base, double exponent); + static double toRadians(double deg); + static double toDegrees(double r); + // Point to point conversions int32_t distanceTo(const GeoCoord &pointB); int32_t bearingTo(const GeoCoord &pointB); @@ -162,4 +145,4 @@ class GeoCoord // OLC getter void getOLCCode(char *code) { strncpy(code, _olc.code, OLC_CODE_LEN + 1); } // +1 for null termination -}; +}; \ No newline at end of file diff --git a/src/gps/cas.h b/src/gps/cas.h index 53d75cda9..725fd07b3 100644 --- a/src/gps/cas.h +++ b/src/gps/cas.h @@ -21,7 +21,7 @@ // CFG-RST (0x06, 0x02) // Factory reset -const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = { +static const uint8_t _message_CAS_CFG_RST_FACTORY[] = { 0xFF, 0x03, // Fields to clear 0x01, // Reset Mode: Controlled Software reset 0x03 // Startup Mode: Factory @@ -30,7 +30,7 @@ const uint8_t GPS::_message_CAS_CFG_RST_FACTORY[] = { // CFG_RATE (0x06, 0x01) // 1HZ update rate, this should always be the case after // factory reset but update it regardless -const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = { +static const uint8_t _message_CAS_CFG_RATE_1HZ[] = { 0xE8, 0x03, // Update Rate: 0x03E8 = 1000ms 0x00, 0x00 // Reserved }; @@ -39,7 +39,7 @@ const uint8_t GPS::_message_CAS_CFG_RATE_1HZ[] = { // Initial ATGM33H-5N configuration, Updates for Dynamic Mode, Fix Mode, and SV system // Qwirk: The ATGM33H-5N-31 should only support GPS+BDS, however it will happily enable // and use GPS+BDS+GLONASS iff the correct CFG_NAVX command is used. -const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = { +static const uint8_t _message_CAS_CFG_NAVX_CONF[] = { 0x03, 0x01, 0x00, 0x00, // Update Mask: Dynamic Mode, Fix Mode, Nav Settings 0x03, // Dynamic Mode: Automotive 0x03, // Fix Mode: Auto 2D/3D @@ -60,4 +60,4 @@ const uint8_t GPS::_message_CAS_CFG_NAVX_CONF[] = { 0x00, 0x00, 0x00, 0x00, // Position Accuracy Max 0x00, 0x00, 0x00, 0x00, // Time Accuracy Max 0x00, 0x00, 0x00, 0x00 // Static Hold Threshold -}; \ No newline at end of file +}; diff --git a/src/gps/ubx.h b/src/gps/ubx.h index 551921384..d674bed51 100644 --- a/src/gps/ubx.h +++ b/src/gps/ubx.h @@ -1,20 +1,22 @@ -const char *failMessage = "Unable to %s"; +static const char *failMessage = "Unable to %s"; #define SEND_UBX_PACKET(TYPE, ID, DATA, ERRMSG, TIMEOUT) \ - msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \ - _serial_gps->write(UBXscratch, msglen); \ - if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \ - LOG_WARN(failMessage, #ERRMSG); \ - } + do { \ + msglen = makeUBXPacket(TYPE, ID, sizeof(DATA), DATA); \ + _serial_gps->write(UBXscratch, msglen); \ + if (getACK(TYPE, ID, TIMEOUT) != GNSS_RESPONSE_OK) { \ + LOG_WARN(failMessage, #ERRMSG); \ + } \ + } while (0) // Power Management -uint8_t GPS::_message_PMREQ[] PROGMEM = { +static uint8_t _message_PMREQ[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds) 0x02, 0x00, 0x00, 0x00 // Bitfield, set backup = 1 }; -uint8_t GPS::_message_PMREQ_10[] PROGMEM = { +static uint8_t _message_PMREQ_10[] PROGMEM = { 0x00, // version (0 for this version) 0x00, 0x00, 0x00, // Reserved 1 0x00, 0x00, 0x00, 0x00, // 4 bytes duration of request task (milliseconds) @@ -22,18 +24,18 @@ uint8_t GPS::_message_PMREQ_10[] PROGMEM = { 0x08, 0x00, 0x00, 0x00 // wakeupSources Wake on uartrx }; -const uint8_t GPS::_message_CFG_RXM_PSM[] PROGMEM = { +static const uint8_t _message_CFG_RXM_PSM[] PROGMEM = { 0x08, // Reserved 0x01 // Power save mode }; // only for Neo-6 -const uint8_t GPS::_message_CFG_RXM_ECO[] PROGMEM = { +static const uint8_t _message_CFG_RXM_ECO[] PROGMEM = { 0x08, // Reserved 0x04 // eco mode }; -const uint8_t GPS::_message_CFG_PM2[] PROGMEM = { +static const uint8_t _message_CFG_PM2[] PROGMEM = { 0x01, // version 0x00, // Reserved 1, set to 0x06 by u-Center 0x00, // Reserved 2 @@ -58,7 +60,7 @@ const uint8_t GPS::_message_CFG_PM2[] PROGMEM = { // Constallation setup, none required for Neo-6 // For Neo-7 GPS & SBAS -const uint8_t GPS::_message_GNSS_7[] = { +static const uint8_t _message_GNSS_7[] = { 0x00, // msgVer (0 for this version) 0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0) 0xff, // numTrkChUse (max number of channels to use, 0xff = max available) @@ -76,7 +78,7 @@ const uint8_t GPS::_message_GNSS_7[] = { // There is also a possibility that the module may be GPS-only. // For M8 GPS, GLONASS, Galileo, SBAS, QZSS -const uint8_t GPS::_message_GNSS_8[] = { +static const uint8_t _message_GNSS_8[] = { 0x00, // msgVer (0 for this version) 0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0) 0xff, // numTrkChUse (max number of channels to use, 0xff = max available) @@ -90,7 +92,7 @@ const uint8_t GPS::_message_GNSS_8[] = { }; /* // For M8 GPS, GLONASS, BeiDou, SBAS, QZSS -const uint8_t GPS::_message_GNSS_8_B[] = { +static const uint8_t _message_GNSS_8_B[] = { 0x00, // msgVer (0 for this version) 0x00, // numTrkChHw (max number of hardware channels, read only, so it's always 0) 0xff, // numTrkChUse (max number of channels to use, 0xff = max available) read only for protocol >23 @@ -105,7 +107,7 @@ const uint8_t GPS::_message_GNSS_8_B[] = { */ // For M8 we want to enable NMEA version 4.10 messages to allow for Galileo and or BeiDou -const uint8_t GPS::_message_NMEA[]{ +static const uint8_t _message_NMEA[]{ 0x00, // filter flags 0x41, // NMEA Version 0x00, // Max number of SVs to report per TaklerId @@ -121,13 +123,13 @@ const uint8_t GPS::_message_NMEA[]{ // Enable jamming/interference monitor // For Neo-6, Max-7 and Neo-7 -const uint8_t GPS::_message_JAM_6_7[] = { +static const uint8_t _message_JAM_6_7[] = { 0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable = 1, reserved bits 0x16B156 0x1e, 0x03, 0x00, 0x00 // config2 antennaSetting Unknown = 0, reserved 3, = 0x00,0x00, reserved 2 = 0x31E }; // For M8 -const uint8_t GPS::_message_JAM_8[] = { +static const uint8_t _message_JAM_8[] = { 0xf3, 0xac, 0x62, 0xad, // config1 bbThreshold = 3, cwThreshold = 15, enable1 = 1, reserved bits 0x16B156 0x1e, 0x43, 0x00, 0x00 // config2 antennaSetting Unknown = 0, enable2 = 1, generalBits = 0x31E }; @@ -137,7 +139,7 @@ const uint8_t GPS::_message_JAM_8[] = { // ToDo: check UBX-MON-VER for module type and protocol version // For the Neo-6 -const uint8_t GPS::_message_NAVX5[] = { +static const uint8_t _message_NAVX5[] = { 0x00, 0x00, // msgVer (0 for this version) 0x4c, 0x66, // mask1 0x00, 0x00, 0x00, 0x00, // Reserved 0 @@ -166,7 +168,7 @@ const uint8_t GPS::_message_NAVX5[] = { 0x00, 0x00, 0x00, 0x00 // Reserved 4 }; // For the M8 -const uint8_t GPS::_message_NAVX5_8[] = { +static const uint8_t _message_NAVX5_8[] = { 0x02, 0x00, // msgVer (2 for this version) 0x4c, 0x66, // mask1 0x00, 0x00, 0x00, 0x00, // mask2 @@ -197,7 +199,7 @@ const uint8_t GPS::_message_NAVX5_8[] = { // Additionally, for some new modules like the M9/M10, an update rate lower than 5Hz // is recommended to avoid a known issue with satellites disappearing. // The module defaults for M8, M9, M10 are the same as we use here so no update is necessary -const uint8_t GPS::_message_1HZ[] = { +static const uint8_t _message_1HZ[] = { 0xE8, 0x03, // Measurement Rate (1000ms for 1Hz) 0x01, 0x00, // Navigation rate, always 1 in GPS mode 0x01, 0x00 // Time reference @@ -205,7 +207,7 @@ const uint8_t GPS::_message_1HZ[] = { // Disable GLL. GLL - Geographic position (latitude and longitude), which provides the current geographical // coordinates. -const uint8_t GPS::_message_GLL[] = { +static const uint8_t _message_GLL[] = { 0xF0, 0x01, // NMEA ID for GLL 0x00, // Rate for DDC 0x00, // Rate for UART1 @@ -217,7 +219,7 @@ const uint8_t GPS::_message_GLL[] = { // Disable GSA. GSA - GPS DOP and active satellites, used for detailing the satellites used in the positioning and // the DOP (Dilution of Precision) -const uint8_t GPS::_message_GSA[] = { +static const uint8_t _message_GSA[] = { 0xF0, 0x02, // NMEA ID for GSA 0x00, // Rate for DDC 0x00, // Rate for UART1 @@ -228,7 +230,7 @@ const uint8_t GPS::_message_GSA[] = { }; // Disable GSV. GSV - Satellites in view, details the number and location of satellites in view. -const uint8_t GPS::_message_GSV[] = { +static const uint8_t _message_GSV[] = { 0xF0, 0x03, // NMEA ID for GSV 0x00, // Rate for DDC 0x00, // Rate for UART1 @@ -240,7 +242,7 @@ const uint8_t GPS::_message_GSV[] = { // Disable VTG. VTG - Track made good and ground speed, which provides course and speed information relative to // the ground. -const uint8_t GPS::_message_VTG[] = { +static const uint8_t _message_VTG[] = { 0xF0, 0x05, // NMEA ID for VTG 0x00, // Rate for DDC 0x00, // Rate for UART1 @@ -251,7 +253,7 @@ const uint8_t GPS::_message_VTG[] = { }; // Enable RMC. RMC - Recommended Minimum data, the essential gps pvt (position, velocity, time) data. -const uint8_t GPS::_message_RMC[] = { +static const uint8_t _message_RMC[] = { 0xF0, 0x04, // NMEA ID for RMC 0x00, // Rate for DDC 0x01, // Rate for UART1 @@ -262,7 +264,7 @@ const uint8_t GPS::_message_RMC[] = { }; // Enable GGA. GGA - Global Positioning System Fix Data, which provides 3D location and accuracy data. -const uint8_t GPS::_message_GGA[] = { +static const uint8_t _message_GGA[] = { 0xF0, 0x00, // NMEA ID for GGA 0x00, // Rate for DDC 0x01, // Rate for UART1 @@ -274,7 +276,7 @@ const uint8_t GPS::_message_GGA[] = { // Disable UBX-AID-ALPSRV as it may confuse TinyGPS. The Neo-6 seems to send this message // whether the AID Autonomous is enabled or not -const uint8_t GPS::_message_AID[] = { +static const uint8_t _message_AID[] = { 0x0B, 0x32, // NMEA ID for UBX-AID-ALPSRV 0x00, // Rate for DDC 0x00, // Rate for UART1 @@ -287,7 +289,7 @@ const uint8_t GPS::_message_AID[] = { // Turn off TEXT INFO Messages for all but M10 series // B5 62 06 02 0A 00 01 00 00 00 03 03 00 03 03 00 1F 20 -const uint8_t GPS::_message_DISABLE_TXT_INFO[] = { +static const uint8_t _message_DISABLE_TXT_INFO[] = { 0x01, // Protocol ID for NMEA 0x00, 0x00, 0x00, // Reserved 0x03, // I2C @@ -310,7 +312,7 @@ const uint8_t GPS::_message_DISABLE_TXT_INFO[] = { // and must be smaller than the period. It is only valid when the powerSetupValue is set to Interval; otherwise, // it must be set to '0'. // This command applies to M8 products -const uint8_t GPS::_message_PMS[] = { +static const uint8_t _message_PMS[] = { 0x00, // Version (0) 0x03, // Power setup value 3 = Agresssive 1Hz 0x00, 0x00, // period: not applicable, set to 0 @@ -318,14 +320,14 @@ const uint8_t GPS::_message_PMS[] = { 0x00, 0x00 // reserved, generated by u-center }; -const uint8_t GPS::_message_SAVE[] = { +static const uint8_t _message_SAVE[] = { 0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared 0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections 0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded 0x17 // deviceMask: BBR, Flash, EEPROM, and SPI Flash }; -const uint8_t GPS::_message_SAVE_10[] = { +static const uint8_t _message_SAVE_10[] = { 0x00, 0x00, 0x00, 0x00, // clearMask: no sections cleared 0xFF, 0xFF, 0x00, 0x00, // saveMask: save all sections 0x00, 0x00, 0x00, 0x00, // loadMask: no sections loaded @@ -375,12 +377,12 @@ LIMITPEAKCURRENT L 1 // b5 62 06 8a 26 00 00 02 00 00 01 00 d0 20 02 02 00 d0 40 05 00 00 00 05 00 d0 30 01 00 08 00 d0 10 01 09 00 d0 10 01 10 00 d0 // 10 01 8c 03 */ -const uint8_t GPS::_message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0, - 0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01}; -const uint8_t GPS::_message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40, - 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0, - 0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01}; +static const uint8_t _message_VALSET_PM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0, + 0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01}; +static const uint8_t _message_VALSET_PM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0xd0, 0x20, 0x02, 0x02, 0x00, 0xd0, 0x40, + 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0xd0, 0x30, 0x01, 0x00, 0x08, 0x00, 0xd0, + 0x10, 0x01, 0x09, 0x00, 0xd0, 0x10, 0x01, 0x10, 0x00, 0xd0, 0x10, 0x01}; /* CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM and one for BBR @@ -394,10 +396,10 @@ CFG-ITFM replaced by 5 valset messages which can be combined into one for RAM an b5 62 06 8a 0e 00 00 01 00 00 0d 00 41 10 01 13 00 41 10 01 63 c6 */ -const uint8_t GPS::_message_VALSET_ITFM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x41, - 0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01}; -const uint8_t GPS::_message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x41, - 0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01}; +static const uint8_t _message_VALSET_ITFM_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x0d, 0x00, 0x41, + 0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01}; +static const uint8_t _message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0x00, 0x41, + 0x10, 0x01, 0x13, 0x00, 0x41, 0x10, 0x01}; // Turn off all NMEA messages: // Ram layer config message: @@ -407,13 +409,13 @@ const uint8_t GPS::_message_VALSET_ITFM_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x0d, 0 // BBR layer config message: // b5 62 06 8a 13 00 00 02 00 00 ca 00 91 20 00 c5 00 91 20 00 b1 00 91 20 00 f8 4e -const uint8_t GPS::_message_VALSET_DISABLE_NMEA_RAM[] = { +static const uint8_t _message_VALSET_DISABLE_NMEA_RAM[] = { /*0x00, 0x01, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00 */ 0x00, 0x01, 0x00, 0x00, 0xc0, 0x00, 0x91, 0x20, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, 0x00, 0x91, 0x20, 0x00, 0xac, 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00, 0xbb, 0x00, 0x91, 0x20, 0x00}; -const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, - 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00}; +static const uint8_t _message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xca, 0x00, 0x91, 0x20, 0x00, 0xc5, + 0x00, 0x91, 0x20, 0x00, 0xb1, 0x00, 0x91, 0x20, 0x00}; // Turn off text info messages: // Ram layer config message: @@ -432,17 +434,17 @@ const uint8_t GPS::_message_VALSET_DISABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, // b5 62 06 8a 0e 00 00 04 00 00 bb 00 91 20 01 ac 00 91 20 01 6d b6 // Doing this for the FLASH layer isn't really required since we save the config to flash later -const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03}; -const uint8_t GPS::_message_VALSET_DISABLE_TXT_INFO_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03}; +static const uint8_t _message_VALSET_DISABLE_TXT_INFO_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03}; +static const uint8_t _message_VALSET_DISABLE_TXT_INFO_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x07, 0x00, 0x92, 0x20, 0x03}; -const uint8_t GPS::_message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xbb, 0x00, 0x91, - 0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01}; -const uint8_t GPS::_message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xbb, 0x00, 0x91, - 0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01}; -const uint8_t GPS::_message_VALSET_DISABLE_SBAS_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x31, - 0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00}; -const uint8_t GPS::_message_VALSET_DISABLE_SBAS_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31, - 0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00}; +static const uint8_t _message_VALSET_ENABLE_NMEA_RAM[] = {0x00, 0x01, 0x00, 0x00, 0xbb, 0x00, 0x91, + 0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01}; +static const uint8_t _message_VALSET_ENABLE_NMEA_BBR[] = {0x00, 0x02, 0x00, 0x00, 0xbb, 0x00, 0x91, + 0x20, 0x01, 0xac, 0x00, 0x91, 0x20, 0x01}; +static const uint8_t _message_VALSET_DISABLE_SBAS_RAM[] = {0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x31, + 0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00}; +static const uint8_t _message_VALSET_DISABLE_SBAS_BBR[] = {0x00, 0x02, 0x00, 0x00, 0x20, 0x00, 0x31, + 0x10, 0x00, 0x05, 0x00, 0x31, 0x10, 0x00}; /* Operational issues with the M10: @@ -475,4 +477,4 @@ b5 62 06 8a 0e 00 00 01 00 00 20 00 31 10 00 05 00 31 10 00 46 87 BBR layer config message: b5 62 06 8a 0e 00 00 02 00 00 20 00 31 10 00 05 00 31 10 00 47 94 -*/ \ No newline at end of file +*/ diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index b575bfe2c..d41bbda44 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -20,7 +20,6 @@ along with this program. If not, see . */ #include "Screen.h" -#include "../userPrefs.h" #include "PowerMon.h" #include "Throttle.h" #include "configuration.h" @@ -1421,7 +1420,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ } bool hasNodeHeading = false; - if (ourNode && (hasValidPosition(ourNode) || screen->hasHeading())) { + if (ourNode && (nodeDB->hasValidPosition(ourNode) || screen->hasHeading())) { const meshtastic_PositionLite &op = ourNode->position; float myHeading; if (screen->hasHeading()) @@ -1430,7 +1429,7 @@ static void drawNodeInfo(OLEDDisplay *display, OLEDDisplayUiState *state, int16_ myHeading = screen->estimatedHeading(DegD(op.latitude_i), DegD(op.longitude_i)); screen->drawCompassNorth(display, compassX, compassY, myHeading); - if (hasValidPosition(node)) { + if (nodeDB->hasValidPosition(node)) { // display direction toward node hasNodeHeading = true; const meshtastic_PositionLite &p = node->position; diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 2a77ca575..00884c5af 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -605,4 +605,4 @@ class Screen : public concurrency::OSThread } // namespace graphics -#endif +#endif \ No newline at end of file diff --git a/src/graphics/ScreenFonts.h b/src/graphics/ScreenFonts.h index c9ce961fa..032348d54 100644 --- a/src/graphics/ScreenFonts.h +++ b/src/graphics/ScreenFonts.h @@ -27,14 +27,22 @@ #define FONT_SMALL ArialMT_Plain_10_RU #else #ifdef OLED_UA -#define FONT_SMALL ArialMT_Plain_10_UA +#define FONT_SMALL ArialMT_Plain_10_UA // Height: 13 #else #define FONT_SMALL ArialMT_Plain_10 // Height: 13 #endif #endif #endif +#ifdef OLED_UA +#define FONT_MEDIUM ArialMT_Plain_16_UA // Height: 19 +#else #define FONT_MEDIUM ArialMT_Plain_16 // Height: 19 -#define FONT_LARGE ArialMT_Plain_24 // Height: 28 +#endif +#ifdef OLED_UA +#define FONT_LARGE ArialMT_Plain_24_UA // Height: 28 +#else +#define FONT_LARGE ArialMT_Plain_24 // Height: 28 +#endif #endif #define _fontHeight(font) ((font)[1] + 1) // height is position 1 diff --git a/src/graphics/fonts/OLEDDisplayFontsUA.cpp b/src/graphics/fonts/OLEDDisplayFontsUA.cpp index 0295ee6ba..2a97526ef 100644 --- a/src/graphics/fonts/OLEDDisplayFontsUA.cpp +++ b/src/graphics/fonts/OLEDDisplayFontsUA.cpp @@ -166,71 +166,71 @@ const uint8_t ArialMT_Plain_10_UA[] PROGMEM = { 0x04, 0x6F, 0x10, 0x09, // 188 0x04, 0x7F, 0x10, 0x09, // 189 0x04, 0x8F, 0x10, 0x09, // 190 - 0x04, 0x9F, 0x0A, 0x06, // 191 - 0x04, 0xA9, 0x0C, 0x07, // 192 - 0x04, 0xB5, 0x0C, 0x07, // 193 - 0x04, 0xC1, 0x0C, 0x07, // 194 - 0x04, 0xCD, 0x0B, 0x07, // 195 - 0x04, 0xD8, 0x0C, 0x07, // 196 - 0x04, 0xE4, 0x0C, 0x07, // 197 - 0x04, 0xF0, 0x0C, 0x07, // 198 - 0x04, 0xFC, 0x0C, 0x07, // 199 - 0x05, 0x08, 0x0C, 0x07, // 200 - 0x05, 0x14, 0x0C, 0x07, // 201 - 0x05, 0x20, 0x0C, 0x07, // 202 - 0x05, 0x2C, 0x0C, 0x07, // 203 - 0x05, 0x38, 0x0C, 0x07, // 204 - 0x05, 0x44, 0x0C, 0x07, // 205 - 0x05, 0x50, 0x0C, 0x07, // 206 - 0x05, 0x5C, 0x0C, 0x07, // 207 - 0x05, 0x68, 0x0B, 0x07, // 208 - 0x05, 0x73, 0x0C, 0x07, // 209 - 0x05, 0x7F, 0x0B, 0x07, // 210 - 0x05, 0x8A, 0x0C, 0x07, // 211 - 0x05, 0x96, 0x0B, 0x07, // 212 - 0x05, 0xA1, 0x0C, 0x07, // 213 - 0x05, 0xAD, 0x0C, 0x07, // 214 - 0x05, 0xB9, 0x0C, 0x07, // 215 - 0x05, 0xC5, 0x0C, 0x07, // 216 - 0x05, 0xD1, 0x0E, 0x08, // 217 - 0x05, 0xDF, 0x0C, 0x07, // 218 - 0x05, 0xEB, 0x0C, 0x07, // 219 - 0x05, 0xF7, 0x0C, 0x07, // 220 - 0x06, 0x03, 0x0C, 0x07, // 221 - 0x06, 0x0F, 0x0C, 0x07, // 222 - 0x06, 0x1B, 0x0C, 0x07, // 223 - 0x06, 0x27, 0x0C, 0x07, // 224 - 0x06, 0x33, 0x0C, 0x07, // 225 - 0x06, 0x3F, 0x0C, 0x07, // 226 - 0x06, 0x4B, 0x0B, 0x07, // 227 - 0x06, 0x56, 0x0C, 0x07, // 228 - 0x06, 0x62, 0x0B, 0x07, // 229 - 0x06, 0x6D, 0x0C, 0x07, // 230 - 0x06, 0x79, 0x0C, 0x07, // 231 - 0x06, 0x85, 0x0C, 0x07, // 232 - 0x06, 0x91, 0x0C, 0x07, // 233 - 0x06, 0x9D, 0x0C, 0x07, // 234 - 0x06, 0xA9, 0x0C, 0x07, // 235 - 0x06, 0xB5, 0x0C, 0x07, // 236 - 0x06, 0xC1, 0x0C, 0x07, // 237 - 0x06, 0xCD, 0x0C, 0x07, // 238 - 0x06, 0xD9, 0x0C, 0x07, // 239 - 0x06, 0xE5, 0x0B, 0x07, // 240 - 0x06, 0xF0, 0x0C, 0x07, // 241 - 0x06, 0xFC, 0x0B, 0x07, // 242 - 0x07, 0x07, 0x0C, 0x07, // 243 - 0x07, 0x13, 0x0B, 0x07, // 244 - 0x07, 0x1E, 0x0C, 0x07, // 245 - 0x07, 0x2A, 0x0C, 0x07, // 246 - 0x07, 0x36, 0x0C, 0x07, // 247 - 0x07, 0x42, 0x0C, 0x07, // 248 - 0x07, 0x4E, 0x0E, 0x08, // 249 - 0x07, 0x5C, 0x0C, 0x07, // 250 - 0x07, 0x68, 0x0C, 0x07, // 251 - 0x07, 0x74, 0x0C, 0x07, // 252 - 0x07, 0x80, 0x0C, 0x07, // 253 - 0x07, 0x8C, 0x0C, 0x07, // 254 - 0x07, 0x98, 0x0C, 0x07, // 255 + 0x04, 0x9F, 0x06, 0x04, // 191 + 0x04, 0xA5, 0x0A, 0x06, // 192 + 0x04, 0xAF, 0x0A, 0x06, // 193 + 0x04, 0xB9, 0x0A, 0x06, // 194 + 0x04, 0xC3, 0x09, 0x06, // 195 + 0x04, 0xCC, 0x0A, 0x06, // 196 + 0x04, 0xD6, 0x0A, 0x06, // 197 + 0x04, 0xE0, 0x0A, 0x06, // 198 + 0x04, 0xEA, 0x08, 0x05, // 199 + 0x04, 0xF2, 0x0A, 0x06, // 200 + 0x04, 0xFC, 0x0A, 0x06, // 201 + 0x05, 0x06, 0x0A, 0x06, // 202 + 0x05, 0x10, 0x0A, 0x06, // 203 + 0x05, 0x1A, 0x0A, 0x06, // 204 + 0x05, 0x24, 0x0A, 0x06, // 205 + 0x05, 0x2E, 0x0A, 0x06, // 206 + 0x05, 0x38, 0x0A, 0x06, // 207 + 0x05, 0x42, 0x09, 0x06, // 208 + 0x05, 0x4B, 0x0A, 0x06, // 209 + 0x05, 0x55, 0x09, 0x06, // 210 + 0x05, 0x5E, 0x0A, 0x06, // 211 + 0x05, 0x68, 0x09, 0x06, // 212 + 0x05, 0x71, 0x0A, 0x06, // 213 + 0x05, 0x7B, 0x0A, 0x06, // 214 + 0x05, 0x85, 0x08, 0x05, // 215 + 0x05, 0x8D, 0x0A, 0x06, // 216 + 0x05, 0x97, 0x0C, 0x07, // 217 + 0x05, 0xA3, 0x0A, 0x06, // 218 + 0x05, 0xAD, 0x0A, 0x06, // 219 + 0x05, 0xB7, 0x08, 0x05, // 220 + 0x05, 0xBF, 0x0A, 0x06, // 221 + 0x05, 0xC9, 0x0A, 0x06, // 222 + 0x05, 0xD3, 0x0A, 0x06, // 223 + 0x05, 0xDD, 0x08, 0x05, // 224 + 0x05, 0xE5, 0x08, 0x05, // 225 + 0x05, 0xED, 0x08, 0x05, // 226 + 0x05, 0xF5, 0x07, 0x05, // 227 + 0x05, 0xFC, 0x0A, 0x06, // 228 + 0x06, 0x06, 0x09, 0x06, // 229 + 0x06, 0x0F, 0x0A, 0x06, // 230 + 0x06, 0x19, 0x08, 0x05, // 231 + 0x06, 0x21, 0x0A, 0x06, // 232 + 0x06, 0x2B, 0x0A, 0x06, // 233 + 0x06, 0x35, 0x06, 0x04, // 234 + 0x06, 0x3B, 0x08, 0x05, // 235 + 0x06, 0x43, 0x0A, 0x06, // 236 + 0x06, 0x4D, 0x08, 0x05, // 237 + 0x06, 0x55, 0x08, 0x05, // 238 + 0x06, 0x5D, 0x08, 0x05, // 239 + 0x06, 0x65, 0x05, 0x04, // 240 + 0x06, 0x6A, 0x08, 0x05, // 241 + 0x06, 0x72, 0x05, 0x04, // 242 + 0x06, 0x77, 0x08, 0x05, // 243 + 0x06, 0x7F, 0x09, 0x06, // 244 + 0x06, 0x88, 0x0A, 0x06, // 245 + 0x06, 0x92, 0x08, 0x05, // 246 + 0x06, 0x9A, 0x08, 0x05, // 247 + 0x06, 0xA2, 0x0A, 0x06, // 248 + 0x06, 0xAC, 0x0C, 0x07, // 249 + 0x06, 0xB8, 0x08, 0x05, // 250 + 0x06, 0xC0, 0x08, 0x05, // 251 + 0x06, 0xC8, 0x08, 0x05, // 252 + 0x06, 0xD0, 0x08, 0x05, // 253 + 0x06, 0xD8, 0x0A, 0x06, // 254 + 0x06, 0xE2, 0x08, 0x05, // 255 // Font Data: 0x00, 0x00, 0xF8, 0x02, // 33 0x38, 0x00, 0x00, 0x00, 0x38, // 34 @@ -356,69 +356,1568 @@ const uint8_t ArialMT_Plain_10_UA[] PROGMEM = { 0x00, 0x00, 0x10, 0x02, 0x78, 0x01, 0xC0, 0x00, 0x20, 0x01, 0x90, 0x01, 0xC8, 0x03, 0x00, 0x01, // 188 0x00, 0x00, 0x10, 0x02, 0x78, 0x01, 0x80, 0x00, 0x60, 0x00, 0x50, 0x02, 0x48, 0x03, 0xC0, 0x02, // 189 0x48, 0x00, 0x58, 0x00, 0x68, 0x03, 0x80, 0x00, 0x60, 0x01, 0x90, 0x01, 0xC8, 0x03, 0x00, 0x01, // 190 - 0x00, 0x00, 0x00, 0x00, 0x28, 0x02, 0xE0, 0x03, 0x28, 0x02, // 191 - 0x00, 0x00, 0xF0, 0x03, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xF0, 0x03, // 192 - 0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x88, 0x01, // 193 - 0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 194 - 0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x18, // 195 - 0x00, 0x00, 0x00, 0x02, 0xFC, 0x03, 0x04, 0x02, 0xFC, 0x03, 0x00, 0x02, // 196 - 0x00, 0x00, 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x08, 0x02, // 197 - 0x00, 0x00, 0xB8, 0x03, 0x40, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xB8, 0x03, // 198 - 0x00, 0x00, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 199 - 0x00, 0x00, 0xF8, 0x03, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0xF8, 0x03, // 200 - 0x00, 0x00, 0xE0, 0x03, 0x08, 0x01, 0x90, 0x00, 0x48, 0x00, 0xE0, 0x03, // 201 - 0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xA0, 0x00, 0x10, 0x01, 0x08, 0x02, // 202 - 0x00, 0x00, 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 203 - 0x00, 0x00, 0xF8, 0x03, 0x10, 0x00, 0x60, 0x00, 0x10, 0x00, 0xF8, 0x03, // 204 - 0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 205 - 0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 206 - 0x00, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 207 - 0x00, 0x00, 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 208 - 0x00, 0x00, 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 209 - 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 210 - 0x00, 0x00, 0x38, 0x00, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0xF8, 0x01, // 211 - 0x00, 0x00, 0x70, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x88, 0x00, 0x70, // 212 - 0x00, 0x00, 0x18, 0x03, 0xA0, 0x00, 0x40, 0x00, 0xA0, 0x00, 0x18, 0x03, // 213 - 0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, // 214 - 0x00, 0x00, 0x38, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 215 - 0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, // 216 - 0x00, 0x00, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x06, // 217 - 0x00, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 218 - 0x00, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0xF8, 0x03, // 219 - 0x00, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 220 - 0x00, 0x00, 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 221 - 0x00, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xF0, 0x01, 0x08, 0x02, 0xF0, 0x01, // 222 - 0x00, 0x00, 0x30, 0x02, 0x48, 0x01, 0xC8, 0x00, 0x48, 0x00, 0xF8, 0x03, // 223 - 0x00, 0x00, 0x00, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x03, // 224 - 0x00, 0x00, 0xE0, 0x01, 0x50, 0x02, 0x50, 0x02, 0x48, 0x02, 0x88, 0x01, // 225 - 0x00, 0x00, 0xE0, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 226 - 0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, // 227 - 0x00, 0x00, 0x00, 0x02, 0xC0, 0x03, 0x20, 0x02, 0xE0, 0x03, 0x00, 0x02, // 228 - 0x00, 0x00, 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, // 229 - 0x00, 0x00, 0x60, 0x03, 0x80, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x60, 0x03, // 230 - 0x00, 0x00, 0x20, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 231 - 0x00, 0x00, 0xE0, 0x03, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 232 - 0x00, 0x00, 0xE0, 0x03, 0x00, 0x01, 0x98, 0x00, 0x40, 0x00, 0xE0, 0x03, // 233 - 0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 234 - 0x00, 0x00, 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // 235 - 0x00, 0x00, 0xE0, 0x03, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 236 - 0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 237 - 0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 238 - 0x00, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // 239 - 0x00, 0x00, 0xE0, 0x03, 0xA0, 0x00, 0xA0, 0x00, 0xA0, 0x00, 0x40, // 240 - 0x00, 0x00, 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x20, 0x02, 0x40, 0x02, // 241 - 0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x20, 0x00, 0x20, // 242 - 0x00, 0x00, 0x60, 0x00, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0xE0, 0x01, // 243 - 0x00, 0x00, 0xC0, 0x00, 0x20, 0x01, 0xE0, 0x03, 0x20, 0x01, 0xC0, // 244 - 0x00, 0x00, 0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 245 - 0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, // 246 - 0x00, 0x00, 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 247 - 0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, // 248 - 0x00, 0x00, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x06, // 249 - 0x00, 0x00, 0x20, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, // 250 - 0x00, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, 0xE0, 0x03, // 251 - 0x00, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, // 252 - 0x00, 0x00, 0x40, 0x01, 0x20, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, 0x01, // 253 - 0x00, 0x00, 0xE0, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, 0xC0, 0x01, // 254 - 0x00, 0x00, 0x40, 0x02, 0xA0, 0x01, 0xA0, 0x00, 0xA0, 0x00, 0xE0, 0x03, // 255 + 0x28, 0x02, 0xE0, 0x03, 0x28, 0x02, // 191 + 0xF0, 0x03, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xF0, 0x03, // 192 + 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x88, 0x01, // 193 + 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 194 + 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0x18, // 195 + 0x00, 0x02, 0xFC, 0x03, 0x04, 0x02, 0xFC, 0x03, 0x00, 0x02, // 196 + 0xF8, 0x03, 0x48, 0x02, 0x48, 0x02, 0x48, 0x02, 0x08, 0x02, // 197 + 0xB8, 0x03, 0x40, 0x00, 0xF8, 0x03, 0x40, 0x00, 0xB8, 0x03, // 198 + 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xB0, 0x01, // 199 + 0xF8, 0x03, 0x80, 0x00, 0x40, 0x00, 0x20, 0x00, 0xF8, 0x03, // 200 + 0xE0, 0x03, 0x08, 0x01, 0x90, 0x00, 0x48, 0x00, 0xE0, 0x03, // 201 + 0xF8, 0x03, 0x40, 0x00, 0xA0, 0x00, 0x10, 0x01, 0x08, 0x02, // 202 + 0x00, 0x02, 0xF0, 0x01, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 203 + 0xF8, 0x03, 0x10, 0x00, 0x60, 0x00, 0x10, 0x00, 0xF8, 0x03, // 204 + 0xF8, 0x03, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 205 + 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0xF0, 0x01, // 206 + 0xF8, 0x03, 0x08, 0x00, 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, // 207 + 0xF8, 0x03, 0x48, 0x00, 0x48, 0x00, 0x48, 0x00, 0x30, // 208 + 0xF0, 0x01, 0x08, 0x02, 0x08, 0x02, 0x08, 0x02, 0x10, 0x01, // 209 + 0x08, 0x00, 0x08, 0x00, 0xF8, 0x03, 0x08, 0x00, 0x08, // 210 + 0x38, 0x00, 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0xF8, 0x01, // 211 + 0x70, 0x00, 0x88, 0x00, 0xF8, 0x03, 0x88, 0x00, 0x70, // 212 + 0x18, 0x03, 0xA0, 0x00, 0x40, 0x00, 0xA0, 0x00, 0x18, 0x03, // 213 + 0xF8, 0x03, 0x00, 0x02, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, // 214 + 0x38, 0x00, 0x40, 0x00, 0x40, 0x00, 0xF8, 0x03, // 215 + 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, // 216 + 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x02, 0xF8, 0x03, 0x00, 0x06, // 217 + 0x08, 0x00, 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 218 + 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, 0xF8, 0x03, // 219 + 0xF8, 0x03, 0x40, 0x02, 0x40, 0x02, 0x80, 0x01, // 220 + 0x10, 0x01, 0x08, 0x02, 0x48, 0x02, 0x48, 0x02, 0xF0, 0x01, // 221 + 0xF8, 0x03, 0x40, 0x00, 0xF0, 0x01, 0x08, 0x02, 0xF0, 0x01, // 222 + 0x30, 0x02, 0x48, 0x01, 0xC8, 0x00, 0x48, 0x00, 0xF8, 0x03, // 223 + 0x00, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xE0, 0x01, // 224 + 0xE0, 0x01, 0x50, 0x02, 0x48, 0x02, 0x88, 0x01, // 225 + 0xE0, 0x03, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 226 + 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0x60, // 227 + 0x00, 0x02, 0xC0, 0x03, 0x20, 0x02, 0xE0, 0x03, 0x00, 0x02, // 228 + 0xC0, 0x01, 0xA0, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0xC0, // 229 + 0x60, 0x03, 0x80, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x60, 0x03, // 230 + 0x20, 0x02, 0xA0, 0x02, 0xA0, 0x02, 0x40, 0x01, // 231 + 0xE0, 0x03, 0x00, 0x01, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 232 + 0xE0, 0x03, 0x08, 0x01, 0x88, 0x00, 0x48, 0x00, 0xE0, 0x03, // 233 + 0xE0, 0x03, 0x80, 0x00, 0x60, 0x03, // 234 + 0x00, 0x02, 0xC0, 0x01, 0x20, 0x00, 0xE0, 0x03, // 235 + 0xE0, 0x03, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0xE0, 0x03, // 236 + 0xE0, 0x03, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 237 + 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0xC0, 0x01, // 238 + 0xE0, 0x03, 0x20, 0x00, 0x20, 0x00, 0xE0, 0x03, // 239 + 0xE0, 0x03, 0xA0, 0x00, 0x40, // 240 + 0xC0, 0x01, 0x20, 0x02, 0x20, 0x02, 0x40, 0x01, // 241 + 0x20, 0x00, 0xE0, 0x03, 0x20, // 242 + 0x60, 0x00, 0x80, 0x02, 0x80, 0x02, 0xE0, 0x01, // 243 + 0xC0, 0x00, 0x20, 0x01, 0xE0, 0x03, 0x20, 0x01, 0xC0, // 244 + 0x20, 0x02, 0x40, 0x01, 0x80, 0x00, 0x40, 0x01, 0x20, 0x02, // 245 + 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x06, // 246 + 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0xE0, 0x03, // 247 + 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, // 248 + 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x02, 0xE0, 0x03, 0x00, 0x06, // 249 + 0x20, 0x00, 0xE0, 0x03, 0x80, 0x02, 0x00, 0x01, // 250 + 0xE0, 0x03, 0x80, 0x02, 0x00, 0x01, 0xE0, 0x03, // 251 + 0xE0, 0x03, 0x80, 0x02, 0x80, 0x02, 0x00, 0x01, // 252 + 0x40, 0x01, 0x20, 0x02, 0xA0, 0x02, 0xC0, 0x01, // 253 + 0xE0, 0x03, 0x80, 0x00, 0xC0, 0x01, 0x20, 0x02, 0xC0, 0x01, // 254 + 0x40, 0x02, 0xA0, 0x01, 0xA0, 0x00, 0xE0, 0x03, // 255 +}; + +const uint8_t ArialMT_Plain_16_UA[] PROGMEM = { + 0x10, // Width: 16 + 0x13, // Height: 19 + 0x20, // First Char: 32 + 0xE0, // Numbers of Chars: 224 + // Jump Table: + 0xFF, 0xFF, 0x00, 0x04, // 32= :65535 + 0x00, 0x00, 0x08, 0x05, // 33=!:0 + 0x00, 0x08, 0x0D, 0x06, // 34=":8 + 0x00, 0x15, 0x1A, 0x09, // 35=#:21 + 0x00, 0x2F, 0x17, 0x09, // 36=$:47 + 0x00, 0x46, 0x26, 0x0E, // 37=%:70 + 0x00, 0x6C, 0x1D, 0x0B, // 38=&:108 + 0x00, 0x89, 0x04, 0x03, // 39=':137 + 0x00, 0x8D, 0x0C, 0x05, // 40=(:141 + 0x00, 0x99, 0x0B, 0x05, // 41=):153 + 0x00, 0xA4, 0x0D, 0x06, // 42=*:164 + 0x00, 0xB1, 0x17, 0x09, // 43=+:177 + 0x00, 0xC8, 0x09, 0x04, // 44=,:200 + 0x00, 0xD1, 0x0B, 0x05, // 45=-:209 + 0x00, 0xDC, 0x08, 0x04, // 46=.:220 + 0x00, 0xE4, 0x0A, 0x04, // 47=/:228 + 0x00, 0xEE, 0x17, 0x09, // 48=0:238 + 0x01, 0x05, 0x11, 0x09, // 49=1:261 + 0x01, 0x16, 0x17, 0x09, // 50=2:278 + 0x01, 0x2D, 0x17, 0x09, // 51=3:301 + 0x01, 0x44, 0x17, 0x09, // 52=4:324 + 0x01, 0x5B, 0x17, 0x09, // 53=5:347 + 0x01, 0x72, 0x17, 0x09, // 54=6:370 + 0x01, 0x89, 0x16, 0x09, // 55=7:393 + 0x01, 0x9F, 0x17, 0x09, // 56=8:415 + 0x01, 0xB6, 0x17, 0x09, // 57=9:438 + 0x01, 0xCD, 0x05, 0x04, // 58=::461 + 0x01, 0xD2, 0x06, 0x04, // 59=;:466 + 0x01, 0xD8, 0x17, 0x09, // 60=<:472 + 0x01, 0xEF, 0x17, 0x09, // 61==:495 + 0x02, 0x06, 0x17, 0x09, // 62=>:518 + 0x02, 0x1D, 0x16, 0x09, // 63=?:541 + 0x02, 0x33, 0x2F, 0x10, // 64=@:563 + 0x02, 0x62, 0x1D, 0x0B, // 65=A:610 + 0x02, 0x7F, 0x1D, 0x0B, // 66=B:639 + 0x02, 0x9C, 0x20, 0x0C, // 67=C:668 + 0x02, 0xBC, 0x20, 0x0C, // 68=D:700 + 0x02, 0xDC, 0x1D, 0x0B, // 69=E:732 + 0x02, 0xF9, 0x19, 0x0A, // 70=F:761 + 0x03, 0x12, 0x20, 0x0C, // 71=G:786 + 0x03, 0x32, 0x1D, 0x0B, // 72=H:818 + 0x03, 0x4F, 0x05, 0x03, // 73=I:847 + 0x03, 0x54, 0x14, 0x08, // 74=J:852 + 0x03, 0x68, 0x1D, 0x0B, // 75=K:872 + 0x03, 0x85, 0x17, 0x09, // 76=L:901 + 0x03, 0x9C, 0x23, 0x0D, // 77=M:924 + 0x03, 0xBF, 0x1D, 0x0B, // 78=N:959 + 0x03, 0xDC, 0x20, 0x0C, // 79=O:988 + 0x03, 0xFC, 0x1C, 0x0B, // 80=P:1020 + 0x04, 0x18, 0x20, 0x0C, // 81=Q:1048 + 0x04, 0x38, 0x1D, 0x0B, // 82=R:1080 + 0x04, 0x55, 0x1D, 0x0B, // 83=S:1109 + 0x04, 0x72, 0x19, 0x09, // 84=T:1138 + 0x04, 0x8B, 0x1D, 0x0B, // 85=U:1163 + 0x04, 0xA8, 0x1C, 0x0B, // 86=V:1192 + 0x04, 0xC4, 0x2B, 0x0F, // 87=W:1220 + 0x04, 0xEF, 0x20, 0x0B, // 88=X:1263 + 0x05, 0x0F, 0x19, 0x09, // 89=Y:1295 + 0x05, 0x28, 0x1A, 0x09, // 90=Z:1320 + 0x05, 0x42, 0x0C, 0x04, // 91=[:1346 + 0x05, 0x4E, 0x0B, 0x04, // 92=\:1358 + 0x05, 0x59, 0x09, 0x04, // 93=]:1369 + 0x05, 0x62, 0x14, 0x07, // 94=^:1378 + 0x05, 0x76, 0x1B, 0x09, // 95=_:1398 + 0x05, 0x91, 0x07, 0x05, // 96=`:1425 + 0x05, 0x98, 0x17, 0x09, // 97=a:1432 + 0x05, 0xAF, 0x17, 0x09, // 98=b:1455 + 0x05, 0xC6, 0x14, 0x08, // 99=c:1478 + 0x05, 0xDA, 0x17, 0x09, // 100=d:1498 + 0x05, 0xF1, 0x17, 0x09, // 101=e:1521 + 0x06, 0x08, 0x0A, 0x04, // 102=f:1544 + 0x06, 0x12, 0x17, 0x09, // 103=g:1554 + 0x06, 0x29, 0x14, 0x08, // 104=h:1577 + 0x06, 0x3D, 0x05, 0x04, // 105=i:1597 + 0x06, 0x42, 0x06, 0x03, // 106=j:1602 + 0x06, 0x48, 0x17, 0x08, // 107=k:1608 + 0x06, 0x5F, 0x05, 0x03, // 108=l:1631 + 0x06, 0x64, 0x23, 0x0D, // 109=m:1636 + 0x06, 0x87, 0x14, 0x08, // 110=n:1671 + 0x06, 0x9B, 0x17, 0x09, // 111=o:1691 + 0x06, 0xB2, 0x17, 0x09, // 112=p:1714 + 0x06, 0xC9, 0x18, 0x09, // 113=q:1737 + 0x06, 0xE1, 0x0D, 0x05, // 114=r:1761 + 0x06, 0xEE, 0x14, 0x08, // 115=s:1774 + 0x07, 0x02, 0x0B, 0x04, // 116=t:1794 + 0x07, 0x0D, 0x14, 0x08, // 117=u:1805 + 0x07, 0x21, 0x13, 0x07, // 118=v:1825 + 0x07, 0x34, 0x1F, 0x0B, // 119=w:1844 + 0x07, 0x53, 0x14, 0x07, // 120=x:1875 + 0x07, 0x67, 0x13, 0x07, // 121=y:1895 + 0x07, 0x7A, 0x14, 0x07, // 122=z:1914 + 0x07, 0x8E, 0x0F, 0x05, // 123={:1934 + 0x07, 0x9D, 0x06, 0x03, // 124=|:1949 + 0x07, 0xA3, 0x0E, 0x05, // 125=}:1955 + 0x07, 0xB1, 0x17, 0x09, // 126=~:1969 + 0x07, 0xC8, 0x1D, 0x0C, // 127=:1992 + 0x07, 0xE5, 0x26, 0x0E, // 1026=Ђ:2021 + 0x08, 0x0B, 0x19, 0x09, // 1027=Ѓ:2059 + 0x08, 0x24, 0x06, 0x04, // 8218=‚:2084 + 0x08, 0x2A, 0x10, 0x06, // 1107=ѓ:2090 + 0x08, 0x3A, 0x09, 0x05, // 8222=„:2106 + 0x08, 0x43, 0x26, 0x10, // 8230=…:2115 + 0x08, 0x69, 0x16, 0x09, // 8224=†:2153 + 0x08, 0x7F, 0x17, 0x09, // 8225=‡:2175 + 0x08, 0x96, 0x17, 0x09, // 8364=€:2198 + 0x08, 0xAD, 0x32, 0x11, // 8240=‰:2221 + 0x08, 0xDF, 0x2F, 0x11, // 1033=Љ:2271 + 0x09, 0x0E, 0x0B, 0x05, // 8249=‹:2318 + 0x09, 0x19, 0x2C, 0x10, // 1034=Њ:2329 + 0x09, 0x45, 0x1A, 0x09, // 1036=Ќ:2373 + 0x09, 0x5F, 0x23, 0x0D, // 1035=Ћ:2399 + 0x09, 0x82, 0x1D, 0x0C, // 1039=Џ:2434 + 0x09, 0x9F, 0x15, 0x08, // 1106=ђ:2463 + 0x09, 0xB4, 0x04, 0x04, // 8216=‘:2484 + 0x09, 0xB8, 0x04, 0x04, // 8217=’:2488 + 0x09, 0xBC, 0x07, 0x05, // 8220=“:2492 + 0x09, 0xC3, 0x0A, 0x05, // 8221=”:2499 + 0x09, 0xCD, 0x0E, 0x06, // 8226=•:2509 + 0x09, 0xDB, 0x1A, 0x09, // 8211=–:2523 + 0x09, 0xF5, 0x2F, 0x10, // 8212=—:2549 + 0x0A, 0x24, 0x1D, 0x0C, // 65533=�:2596 + 0x0A, 0x41, 0x2C, 0x10, // 8482=™:2625 + 0x0A, 0x6D, 0x29, 0x0F, // 1113=љ:2669 + 0x0A, 0x96, 0x0B, 0x05, // 8250=›:2710 + 0x0A, 0xA1, 0x23, 0x0D, // 1114=њ:2721 + 0x0A, 0xC4, 0x14, 0x07, // 1116=ќ:2756 + 0x0A, 0xD8, 0x14, 0x08, // 1115=ћ:2776 + 0x0A, 0xEC, 0x14, 0x08, // 1119=џ:2796 + 0xFF, 0xFF, 0x00, 0x04, // 160= :65535 + 0x0B, 0x00, 0x1C, 0x0A, // 1038=Ў:2816 + 0x0B, 0x1C, 0x13, 0x07, // 1118=ў:2844 + 0x0B, 0x2F, 0x14, 0x08, // 1032=Ј:2863 + 0x0B, 0x43, 0x14, 0x09, // 164=¤:2883 + 0x0B, 0x57, 0x16, 0x08, // 1168=Ґ:2903 + 0x0B, 0x6D, 0x06, 0x03, // 166=¦:2925 + 0x0B, 0x73, 0x17, 0x09, // 167=§:2931 + 0x0B, 0x8A, 0x1D, 0x0B, // 1025=Ё:2954 + 0x0B, 0xA7, 0x23, 0x0C, // 169=©:2983 + 0x0B, 0xCA, 0x20, 0x0C, // 1028=Є:3018 + 0x0B, 0xEA, 0x14, 0x09, // 171=«:3050 + 0x0B, 0xFE, 0x17, 0x09, // 172=¬:3070 + 0x0C, 0x15, 0x0B, 0x05, // 173=­:3093 + 0x0C, 0x20, 0x23, 0x0C, // 174=®:3104 + 0x0C, 0x43, 0x07, 0x03, // 1031=Ї:3139 + 0x0C, 0x4A, 0x0D, 0x06, // 176=°:3146 + 0x0C, 0x57, 0x17, 0x09, // 177=±:3159 + 0x0C, 0x6E, 0x05, 0x03, // 1030=І:3182 + 0x0C, 0x73, 0x05, 0x04, // 1110=і:3187 + 0x0C, 0x78, 0x10, 0x07, // 1169=ґ:3192 + 0x0C, 0x88, 0x17, 0x09, // 181=µ:3208 + 0x0C, 0x9F, 0x19, 0x09, // 182=¶:3231 + 0x0C, 0xB8, 0x08, 0x05, // 183=·:3256 + 0x0C, 0xC0, 0x17, 0x09, // 1105=ё:3264 + 0x0C, 0xD7, 0x2F, 0x11, // 8470=№:3287 + 0x0D, 0x06, 0x14, 0x08, // 1108=є:3334 + 0x0D, 0x1A, 0x17, 0x09, // 187=»:3354 + 0x0D, 0x31, 0x06, 0x03, // 1112=ј:3377 + 0x0D, 0x37, 0x1D, 0x0B, // 1029=Ѕ:3383 + 0x0D, 0x54, 0x14, 0x08, // 1109=ѕ:3412 + 0x0D, 0x68, 0x07, 0x03, // 1111=ї:3432 + 0x0D, 0x6F, 0x1D, 0x0B, // 1040=А:3439 + 0x0D, 0x8C, 0x1D, 0x0B, // 1041=Б:3468 + 0x0D, 0xA9, 0x1D, 0x0B, // 1042=В:3497 + 0x0D, 0xC6, 0x19, 0x09, // 1043=Г:3526 + 0x0D, 0xDF, 0x1E, 0x0B, // 1044=Д:3551 + 0x0D, 0xFD, 0x1D, 0x0B, // 1045=Е:3581 + 0x0E, 0x1A, 0x29, 0x0E, // 1046=Ж:3610 + 0x0E, 0x43, 0x1A, 0x0A, // 1047=З:3651 + 0x0E, 0x5D, 0x20, 0x0C, // 1048=И:3677 + 0x0E, 0x7D, 0x20, 0x0C, // 1049=Й:3709 + 0x0E, 0x9D, 0x1A, 0x09, // 1050=К:3741 + 0x0E, 0xB7, 0x1D, 0x0B, // 1051=Л:3767 + 0x0E, 0xD4, 0x23, 0x0D, // 1052=М:3796 + 0x0E, 0xF7, 0x1D, 0x0B, // 1053=Н:3831 + 0x0F, 0x14, 0x20, 0x0C, // 1054=О:3860 + 0x0F, 0x34, 0x1D, 0x0B, // 1055=П:3892 + 0x0F, 0x51, 0x1C, 0x0B, // 1056=Р:3921 + 0x0F, 0x6D, 0x20, 0x0C, // 1057=С:3949 + 0x0F, 0x8D, 0x19, 0x09, // 1058=Т:3981 + 0x0F, 0xA6, 0x1C, 0x0A, // 1059=У:4006 + 0x0F, 0xC2, 0x1D, 0x0B, // 1060=Ф:4034 + 0x0F, 0xDF, 0x20, 0x0B, // 1061=Х:4063 + 0x0F, 0xFF, 0x21, 0x0C, // 1062=Ц:4095 + 0x10, 0x20, 0x1A, 0x0A, // 1063=Ч:4128 + 0x10, 0x3A, 0x23, 0x0D, // 1064=Ш:4154 + 0x10, 0x5D, 0x27, 0x0E, // 1065=Щ:4189 + 0x10, 0x84, 0x23, 0x0D, // 1066=Ъ:4228 + 0x10, 0xA7, 0x26, 0x0E, // 1067=Ы:4263 + 0x10, 0xCD, 0x1D, 0x0B, // 1068=Ь:4301 + 0x10, 0xEA, 0x20, 0x0C, // 1069=Э:4330 + 0x11, 0x0A, 0x2C, 0x10, // 1070=Ю:4362 + 0x11, 0x36, 0x20, 0x0C, // 1071=Я:4406 + 0x11, 0x56, 0x17, 0x09, // 1072=а:4438 + 0x11, 0x6D, 0x17, 0x09, // 1073=б:4461 + 0x11, 0x84, 0x17, 0x09, // 1074=в:4484 + 0x11, 0x9B, 0x10, 0x06, // 1075=г:4507 + 0x11, 0xAB, 0x18, 0x09, // 1076=д:4523 + 0x11, 0xC3, 0x17, 0x09, // 1077=е:4547 + 0x11, 0xDA, 0x1D, 0x0A, // 1078=ж:4570 + 0x11, 0xF7, 0x11, 0x07, // 1079=з:4599 + 0x12, 0x08, 0x14, 0x08, // 1080=и:4616 + 0x12, 0x1C, 0x14, 0x08, // 1081=й:4636 + 0x12, 0x30, 0x14, 0x07, // 1082=к:4656 + 0x12, 0x44, 0x14, 0x08, // 1083=л:4676 + 0x12, 0x58, 0x1D, 0x0B, // 1084=м:4696 + 0x12, 0x75, 0x14, 0x08, // 1085=н:4725 + 0x12, 0x89, 0x17, 0x09, // 1086=о:4745 + 0x12, 0xA0, 0x14, 0x08, // 1087=п:4768 + 0x12, 0xB4, 0x17, 0x09, // 1088=р:4788 + 0x12, 0xCB, 0x14, 0x08, // 1089=с:4811 + 0x12, 0xDF, 0x13, 0x07, // 1090=т:4831 + 0x12, 0xF2, 0x13, 0x07, // 1091=у:4850 + 0x13, 0x05, 0x23, 0x0D, // 1092=ф:4869 + 0x13, 0x28, 0x14, 0x07, // 1093=х:4904 + 0x13, 0x3C, 0x1B, 0x09, // 1094=ц:4924 + 0x13, 0x57, 0x14, 0x08, // 1095=ч:4951 + 0x13, 0x6B, 0x1D, 0x0B, // 1096=ш:4971 + 0x13, 0x88, 0x21, 0x0B, // 1097=щ:5000 + 0x13, 0xA9, 0x1A, 0x0A, // 1098=ъ:5033 + 0x13, 0xC3, 0x20, 0x0C, // 1099=ы:5059 + 0x13, 0xE3, 0x17, 0x09, // 1100=ь:5091 + 0x13, 0xFA, 0x14, 0x08, // 1101=э:5114 + 0x14, 0x0E, 0x20, 0x0C, // 1102=ю:5134 + 0x14, 0x2E, 0x17, 0x09, // 1103=я:5166 + // Font Data: + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x5F, // 33 + 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, // 34 + 0x80, 0x08, 0x00, 0x80, 0x78, 0x00, 0xC0, 0x0F, 0x00, 0xB8, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80, 0x78, 0x00, 0xC0, 0x0F, 0x00, + 0xB8, 0x08, 0x00, 0x80, 0x08, // 35 + 0x00, 0x00, 0x00, 0xE0, 0x10, 0x00, 0x10, 0x21, 0x00, 0x08, 0x43, 0x00, 0xFC, 0xFF, 0x00, 0x08, 0x42, 0x00, 0x18, 0x22, 0x00, + 0x20, 0x1C, // 36 + 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x08, 0x01, 0x00, 0x08, 0x01, 0x00, 0x08, 0x61, 0x00, 0xF0, 0x18, 0x00, 0x00, 0x06, 0x00, + 0xC0, 0x01, 0x00, 0x30, 0x3C, 0x00, 0x08, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x3C, // 37 + 0x00, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x70, 0x22, 0x00, 0x88, 0x41, 0x00, 0x08, 0x43, 0x00, 0x88, 0x44, 0x00, 0x70, 0x28, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x28, 0x00, 0x00, 0x44, // 38 + 0x00, 0x00, 0x00, 0x78, // 39 + 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x70, 0xC0, 0x01, 0x08, 0x00, 0x02, // 40 + 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x70, 0xC0, 0x01, 0x80, 0x3F, // 41 + 0x10, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x38, 0x00, 0x00, 0xD0, 0x00, 0x00, 0x10, // 42 + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x02, // 43 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, // 44 + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, // 45 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, // 46 + 0x00, 0x60, 0x00, 0x00, 0x1E, 0x00, 0xE0, 0x01, 0x00, 0x18, // 47 + 0x00, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x10, 0x20, 0x00, + 0xE0, 0x1F, // 48 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0x00, 0x10, 0x00, 0x00, 0xF8, 0x7F, // 49 + 0x00, 0x00, 0x00, 0x20, 0x40, 0x00, 0x10, 0x60, 0x00, 0x08, 0x50, 0x00, 0x08, 0x48, 0x00, 0x08, 0x44, 0x00, 0x10, 0x43, 0x00, + 0xE0, 0x40, // 50 + 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x88, 0x41, 0x00, 0xF0, 0x22, 0x00, + 0x00, 0x1C, // 51 + 0x00, 0x0C, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x09, 0x00, 0xC0, 0x08, 0x00, 0x20, 0x08, 0x00, 0x10, 0x08, 0x00, 0xF8, 0x7F, 0x00, + 0x00, 0x08, // 52 + 0x00, 0x00, 0x00, 0xC0, 0x11, 0x00, 0xB8, 0x20, 0x00, 0x88, 0x40, 0x00, 0x88, 0x40, 0x00, 0x88, 0x40, 0x00, 0x08, 0x21, 0x00, + 0x08, 0x1E, // 53 + 0x00, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x10, 0x21, 0x00, 0x88, 0x40, 0x00, 0x88, 0x40, 0x00, 0x88, 0x40, 0x00, 0x10, 0x21, 0x00, + 0x20, 0x1E, // 54 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x78, 0x00, 0x88, 0x07, 0x00, 0x68, 0x00, 0x00, + 0x18, // 55 + 0x00, 0x00, 0x00, 0x60, 0x1C, 0x00, 0x90, 0x22, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x90, 0x22, 0x00, + 0x60, 0x1C, // 56 + 0x00, 0x00, 0x00, 0xE0, 0x11, 0x00, 0x10, 0x22, 0x00, 0x08, 0x44, 0x00, 0x08, 0x44, 0x00, 0x08, 0x44, 0x00, 0x10, 0x22, 0x00, + 0xE0, 0x1F, // 57 + 0x00, 0x00, 0x00, 0x40, 0x40, // 58 + 0x00, 0x00, 0x00, 0x40, 0xC0, 0x01, // 59 + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, + 0x40, 0x10, // 60 + 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, + 0x80, 0x08, // 61 + 0x00, 0x00, 0x00, 0x40, 0x10, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, 0x80, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x05, 0x00, + 0x00, 0x02, // 62 + 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x10, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x5C, 0x00, 0x08, 0x02, 0x00, 0x10, 0x01, 0x00, + 0xE0, // 63 + 0x00, 0x00, 0x00, 0x00, 0x3F, 0x00, 0xC0, 0x40, 0x00, 0x20, 0x80, 0x00, 0x10, 0x1E, 0x01, 0x10, 0x21, 0x01, 0x88, 0x40, 0x02, + 0x48, 0x40, 0x02, 0x48, 0x40, 0x02, 0x48, 0x20, 0x02, 0x88, 0x7C, 0x02, 0xC8, 0x43, 0x02, 0x10, 0x40, 0x02, 0x10, 0x20, 0x01, + 0x60, 0x10, 0x01, 0x80, 0x8F, // 64 + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x80, 0x07, 0x00, 0x70, 0x04, 0x00, 0x08, 0x04, 0x00, 0x70, 0x04, 0x00, + 0x80, 0x07, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x60, // 65 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, + 0x08, 0x41, 0x00, 0x90, 0x22, 0x00, 0x60, 0x1C, // 66 + 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, + 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x10, 0x20, 0x00, 0x20, 0x10, // 67 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, + 0x08, 0x40, 0x00, 0x10, 0x20, 0x00, 0x20, 0x10, 0x00, 0xC0, 0x0F, // 68 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, + 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x40, // 69 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, + 0x08, 0x02, 0x00, 0x08, // 70 + 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x42, 0x00, + 0x08, 0x42, 0x00, 0x10, 0x22, 0x00, 0x20, 0x12, 0x00, 0x00, 0x0E, // 71 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xF8, 0x7F, // 72 + 0x00, 0x00, 0x00, 0xF8, 0x7F, // 73 + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, 0x3F, // 74 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x80, 0x03, 0x00, 0x40, 0x04, 0x00, + 0x20, 0x18, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, // 75 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, // 76 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x30, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x7F, // 77 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x10, 0x00, 0x00, 0x60, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x20, 0x00, 0xF8, 0x7F, // 78 + 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, + 0x08, 0x40, 0x00, 0x10, 0x20, 0x00, 0x20, 0x10, 0x00, 0xC0, 0x0F, // 79 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, + 0x08, 0x02, 0x00, 0x10, 0x01, 0x00, 0xE0, // 80 + 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x50, 0x00, + 0x08, 0x50, 0x00, 0x10, 0x20, 0x00, 0x20, 0x70, 0x00, 0xC0, 0x4F, // 81 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x0E, 0x00, + 0x08, 0x1A, 0x00, 0x10, 0x21, 0x00, 0xE0, 0x40, // 82 + 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x90, 0x20, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x42, 0x00, + 0x08, 0x42, 0x00, 0x10, 0x22, 0x00, 0x20, 0x1C, // 83 + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, // 84 + 0x00, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0xF8, 0x1F, // 85 + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x07, 0x00, 0xE0, 0x00, 0x00, 0x18, // 86 + 0x18, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x80, 0x03, 0x00, 0x70, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x70, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1E, 0x00, 0xE0, 0x01, 0x00, + 0x18, // 87 + 0x00, 0x40, 0x00, 0x08, 0x20, 0x00, 0x10, 0x18, 0x00, 0x60, 0x04, 0x00, 0x80, 0x02, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, + 0x60, 0x0C, 0x00, 0x10, 0x10, 0x00, 0x08, 0x20, 0x00, 0x00, 0x40, // 88 + 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x7E, 0x00, 0x80, 0x01, 0x00, 0x40, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x08, // 89 + 0x00, 0x40, 0x00, 0x08, 0x60, 0x00, 0x08, 0x58, 0x00, 0x08, 0x44, 0x00, 0x08, 0x43, 0x00, 0x88, 0x40, 0x00, 0x68, 0x40, 0x00, + 0x18, 0x40, 0x00, 0x08, 0x40, // 90 + 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x03, 0x08, 0x00, 0x02, 0x08, 0x00, 0x02, // 91 + 0x18, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x60, // 92 + 0x08, 0x00, 0x02, 0x08, 0x00, 0x02, 0xF8, 0xFF, 0x03, // 93 + 0x00, 0x01, 0x00, 0xC0, 0x00, 0x00, 0x30, 0x00, 0x00, 0x08, 0x00, 0x00, 0x30, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x01, // 94 + 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, // 95 + 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x10, // 96 + 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x80, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x42, 0x00, 0x40, 0x22, 0x00, + 0x80, 0x7F, // 97 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, + 0x00, 0x1F, // 98 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, // 99 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, + 0xF8, 0x7F, // 100 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x24, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x80, 0x24, 0x00, + 0x00, 0x17, // 101 + 0x40, 0x00, 0x00, 0xF0, 0x7F, 0x00, 0x48, 0x00, 0x00, 0x48, // 102 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x01, 0x80, 0x20, 0x02, 0x40, 0x40, 0x02, 0x40, 0x40, 0x02, 0x40, 0x40, 0x02, 0x80, 0x20, 0x01, + 0xC0, 0xFF, // 103 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x7F, // 104 + 0x00, 0x00, 0x00, 0xC8, 0x7F, // 105 + 0x00, 0x00, 0x02, 0xC8, 0xFF, 0x01, // 106 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00, 0x00, 0x19, 0x00, 0x80, 0x20, 0x00, + 0x40, 0x40, // 107 + 0x00, 0x00, 0x00, 0xF8, 0x7F, // 108 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x7F, 0x00, + 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x7F, // 109 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, 0x7F, // 110 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, + 0x00, 0x1F, // 111 + 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x03, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, + 0x00, 0x1F, // 112 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, + 0xC0, 0xFF, 0x03, // 113 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, // 114 + 0x00, 0x00, 0x00, 0x80, 0x23, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x80, 0x38, // 115 + 0x40, 0x00, 0x00, 0xF0, 0x7F, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, // 116 + 0x00, 0x00, 0x00, 0xC0, 0x3F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, 0xC0, 0x7F, // 117 + 0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x03, 0x00, 0xC0, // 118 + 0xC0, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1F, 0x00, 0xC0, // 119 + 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1B, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, // 120 + 0xC0, 0x01, 0x00, 0x00, 0x06, 0x02, 0x00, 0x38, 0x02, 0x00, 0xC0, 0x01, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0xC0, // 121 + 0x40, 0x40, 0x00, 0x40, 0x60, 0x00, 0x40, 0x58, 0x00, 0x40, 0x44, 0x00, 0x40, 0x43, 0x00, 0xC0, 0x40, 0x00, 0x40, 0x40, // 122 + 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0xF0, 0xFB, 0x01, 0x08, 0x00, 0x02, 0x08, 0x00, 0x02, // 123 + 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x03, // 124 + 0x08, 0x00, 0x02, 0x08, 0x00, 0x02, 0xF0, 0xFB, 0x01, 0x00, 0x04, 0x00, 0x00, 0x04, // 125 + 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, + 0x00, 0x01, // 126 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x7F, 0x00, 0x20, 0x40, 0x00, 0x20, 0x40, 0x00, 0x20, 0x40, 0x00, 0x20, 0x40, 0x00, + 0x20, 0x40, 0x00, 0x20, 0x40, 0x00, 0xE0, 0x7F, // 127 + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x02, 0x00, 0x08, 0x01, 0x00, + 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x3E, // 1026 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x09, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, // 1027 + 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, // 8218 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x40, 0x00, 0x00, 0x50, 0x00, 0x00, 0x48, 0x00, 0x00, 0x40, // 1107 + 0x00, 0xC0, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x01, // 8222 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, // 8230 + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xF8, 0xFF, 0x03, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x40, // 8224 + 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0xF8, 0xFF, 0x03, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, + 0x40, 0x40, // 8225 + 0x00, 0x05, 0x00, 0xC0, 0x1F, 0x00, 0x20, 0x25, 0x00, 0x10, 0x45, 0x00, 0x08, 0x45, 0x00, 0x08, 0x45, 0x00, 0x08, 0x45, 0x00, + 0x10, 0x20, // 8364 + 0xF0, 0x00, 0x00, 0x08, 0x01, 0x00, 0x08, 0x01, 0x00, 0x08, 0x71, 0x00, 0xF0, 0x0C, 0x00, 0x00, 0x03, 0x00, 0xE0, 0x3C, 0x00, + 0x18, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x42, 0x00, + 0x00, 0x42, 0x00, 0x00, 0x42, 0x00, 0x00, 0x3C, // 8240 + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, 0x3F, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, + 0x00, 0x41, 0x00, 0x00, 0x3E, // 1033 + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1B, 0x00, 0x80, 0x20, // 8249 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, + 0xF8, 0x7F, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, + 0x00, 0x3E, // 1034 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x82, 0x02, 0x00, 0x61, 0x04, 0x00, 0x10, 0x08, 0x00, + 0x08, 0x30, 0x00, 0x08, 0x40, // 1036 + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x02, 0x00, 0x08, 0x01, 0x00, + 0x08, 0x01, 0x00, 0x08, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x7E, // 1035 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, 0x7F, // 1039 + 0x10, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x90, 0x00, 0x00, 0x50, 0x00, 0x00, 0x50, 0x00, 0x00, 0x40, 0x00, 0x02, 0x80, 0xFF, + 0x03, // 1106 + 0x00, 0x00, 0x00, 0x38, // 8216 + 0x00, 0x00, 0x00, 0x38, // 8217 + 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, // 8220 + 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, // 8221 + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x80, 0x07, 0x00, 0x80, 0x07, 0x00, 0x00, 0x03, // 8226 + 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x04, // 8211 + 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x04, 0x00, 0x00, 0x04, // 8212 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x7F, 0x00, 0x20, 0x40, 0x00, 0x20, 0x40, 0x00, 0x20, 0x40, 0x00, 0x20, 0x40, 0x00, + 0x20, 0x40, 0x00, 0x20, 0x40, 0x00, 0xE0, 0x7F, // 65533 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x18, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x01, 0x00, 0xE0, 0x00, 0x00, 0x18, 0x00, 0x00, + 0xF8, 0x01, // 8482 + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xC0, 0x3F, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, + 0xC0, 0x7F, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x64, 0x00, 0x00, + 0x38, // 1113 + 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x04, // 8250 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0xC0, 0x7F, 0x00, + 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x38, // 1114 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x04, 0x00, 0x10, 0x04, 0x00, 0x08, 0x1B, 0x00, 0xC0, 0x20, 0x00, 0x40, + 0x40, // 1116 + 0x10, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x90, 0x00, 0x00, 0x50, 0x00, 0x00, 0x50, 0x00, 0x00, 0x40, 0x00, 0x00, 0x80, + 0x7F, // 1115 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x40, 0x00, 0xC0, + 0x7F, // 1119 + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, 0x40, 0x00, 0x81, 0x41, 0x00, 0x02, 0x66, 0x00, 0x02, 0x18, 0x00, 0x02, 0x06, 0x00, + 0x81, 0x01, 0x00, 0x60, 0x00, 0x00, 0x18, // 1038 + 0xC0, 0x01, 0x00, 0x08, 0x06, 0x02, 0x10, 0x38, 0x02, 0x10, 0xC0, 0x01, 0x10, 0x38, 0x00, 0x08, 0x07, 0x00, 0xC0, // 1118 + 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, + 0x3F, // 1032 + 0x00, 0x00, 0x00, 0x40, 0x0B, 0x00, 0x80, 0x04, 0x00, 0x40, 0x08, 0x00, 0x40, 0x08, 0x00, 0x80, 0x04, 0x00, 0x40, 0x0B, // 164 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x0F, // 1168 + 0x00, 0x00, 0x00, 0xF8, 0xF1, 0x03, // 166 + 0x00, 0x86, 0x00, 0x70, 0x09, 0x01, 0xC8, 0x10, 0x02, 0x88, 0x10, 0x02, 0x08, 0x21, 0x02, 0x08, 0x61, 0x02, 0x30, 0xD2, 0x01, + 0x00, 0x0C, // 167 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x41, 0x00, 0x0A, 0x41, 0x00, 0x08, 0x41, 0x00, 0x0A, 0x41, 0x00, 0x08, 0x41, 0x00, + 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x40, // 1025 + 0xC0, 0x0F, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0xC8, 0x47, 0x00, 0x28, 0x48, 0x00, 0x28, 0x48, 0x00, 0x28, 0x48, 0x00, + 0x28, 0x48, 0x00, 0x48, 0x44, 0x00, 0x10, 0x20, 0x00, 0x20, 0x10, 0x00, 0xC0, 0x0F, // 169 + 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x20, 0x11, 0x00, 0x10, 0x21, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, + 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x10, 0x20, 0x00, 0x20, 0x10, // 1028 + 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1B, 0x00, 0x80, 0x20, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1B, 0x00, 0x80, 0x20, // 171 + 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x80, 0x0F, // 172 + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, // 173 + 0xC0, 0x0F, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0xE8, 0x4F, 0x00, 0x28, 0x41, 0x00, 0x28, 0x41, 0x00, 0x28, 0x43, 0x00, + 0x28, 0x45, 0x00, 0xC8, 0x48, 0x00, 0x10, 0x20, 0x00, 0x20, 0x10, 0x00, 0xC0, 0x0F, // 174 + 0x02, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x02, // 1031 + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x48, 0x00, 0x00, 0x48, 0x00, 0x00, 0x30, // 176 + 0x00, 0x00, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0xE0, 0x4F, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, + 0x00, 0x41, // 177 + 0x00, 0x00, 0x00, 0xF8, 0x7F, // 1030 + 0x00, 0x00, 0x00, 0xC8, 0x7F, // 1110 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x78, // 1169 + 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x03, 0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x20, 0x00, + 0xC0, 0x7F, // 181 + 0xF0, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xF8, 0x01, 0x00, 0xF8, 0x01, 0x00, 0xF8, 0xFF, 0x03, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0xF8, 0xFF, 0x03, 0x08, // 182 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // 183 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x24, 0x00, 0x50, 0x44, 0x00, 0x40, 0x44, 0x00, 0x50, 0x44, 0x00, 0x80, 0x24, 0x00, + 0x00, 0x17, // 1105 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x20, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x10, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x80, 0x27, 0x00, 0x40, 0x28, 0x00, 0x40, 0x28, 0x00, 0x40, 0x28, 0x00, + 0x40, 0x28, 0x00, 0x80, 0x27, // 8470 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x24, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x80, 0x20, 0x00, 0x00, + 0x11, // 1108 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x04, 0x00, 0x80, 0x20, 0x00, 0x00, 0x1B, 0x00, + 0x00, 0x04, // 187 + 0x00, 0x00, 0x02, 0xC8, 0xFF, 0x01, // 1112 + 0x00, 0x00, 0x00, 0x60, 0x10, 0x00, 0x90, 0x20, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x42, 0x00, + 0x08, 0x42, 0x00, 0x10, 0x22, 0x00, 0x20, 0x1C, // 1029 + 0x00, 0x00, 0x00, 0x80, 0x23, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x80, + 0x38, // 1109 + 0x10, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x10, // 1111 + 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x1C, 0x00, 0x80, 0x07, 0x00, 0x70, 0x04, 0x00, 0x08, 0x04, 0x00, 0x70, 0x04, 0x00, + 0x80, 0x07, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x60, // 1040 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, + 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x00, 0x3E, // 1041 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, + 0x08, 0x41, 0x00, 0x90, 0x22, 0x00, 0x60, 0x1C, // 1042 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, // 1043 + 0x00, 0xC0, 0x03, 0x00, 0x60, 0x00, 0x00, 0x5C, 0x00, 0xF8, 0x43, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, + 0x08, 0x40, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0xC0, 0x03, // 1044 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, + 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x08, 0x40, // 1045 + 0x08, 0x30, 0x00, 0x10, 0x08, 0x00, 0x60, 0x04, 0x00, 0x80, 0x02, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xF8, 0x7F, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x60, 0x04, 0x00, 0x10, 0x08, 0x00, 0x08, 0x30, 0x00, 0x08, + 0x40, // 1046 + 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, 0x88, 0x42, 0x00, + 0x70, 0x42, 0x00, 0x00, 0x3C, // 1047 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x30, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x00, + 0x80, 0x00, 0x00, 0x40, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x7F, // 1048 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x30, 0x00, 0x00, 0x08, 0x00, 0x01, 0x04, 0x00, 0x02, 0x02, 0x00, 0x02, 0x01, 0x00, + 0x82, 0x00, 0x00, 0x41, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x7F, // 1049 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, 0x60, 0x04, 0x00, 0x10, 0x08, 0x00, + 0x08, 0x30, 0x00, 0x08, 0x40, // 1050 + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, 0x3F, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0xF8, 0x7F, // 1051 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x30, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x1C, 0x00, 0x00, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF8, 0x7F, // 1052 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0xF8, 0x7F, // 1053 + 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, + 0x08, 0x40, 0x00, 0x10, 0x20, 0x00, 0x20, 0x10, 0x00, 0xC0, 0x0F, // 1054 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0xF8, 0x7F, // 1055 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, + 0x08, 0x02, 0x00, 0x10, 0x01, 0x00, 0xE0, // 1056 + 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, + 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x10, 0x20, 0x00, 0x20, 0x10, // 1057 + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x08, // 1058 + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, 0x40, 0x00, 0x80, 0x41, 0x00, 0x00, 0x66, 0x00, 0x00, 0x18, 0x00, 0x00, 0x06, 0x00, + 0x80, 0x01, 0x00, 0x60, 0x00, 0x00, 0x18, // 1059 + 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x40, 0x08, 0x00, 0x20, 0x10, 0x00, 0x20, 0x10, 0x00, 0xF8, 0x7F, 0x00, 0x20, 0x10, 0x00, + 0x20, 0x10, 0x00, 0x40, 0x08, 0x00, 0x80, 0x07, // 1060 + 0x00, 0x40, 0x00, 0x08, 0x20, 0x00, 0x10, 0x18, 0x00, 0x60, 0x04, 0x00, 0x80, 0x02, 0x00, 0x00, 0x01, 0x00, 0x80, 0x02, 0x00, + 0x60, 0x0C, 0x00, 0x10, 0x10, 0x00, 0x08, 0x20, 0x00, 0x00, 0x40, // 1061 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0xC0, 0x03, // 1062 + 0x00, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x02, 0x00, 0xF8, 0x7F, // 1063 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, 0x7F, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, 0x7F, // 1064 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, 0x7F, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0xC0, 0x03, // 1065 + 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, + 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x3E, // 1066 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, + 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x7F, // 1067 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, + 0x00, 0x41, 0x00, 0x00, 0x41, 0x00, 0x00, 0x3E, // 1068 + 0x00, 0x00, 0x00, 0x20, 0x10, 0x00, 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x41, 0x00, 0x08, 0x41, 0x00, + 0x08, 0x41, 0x00, 0x10, 0x21, 0x00, 0x20, 0x11, 0x00, 0xC0, 0x0F, // 1069 + 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0x00, 0x02, 0x00, 0xC0, 0x0F, 0x00, 0x20, 0x10, 0x00, + 0x10, 0x20, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x08, 0x40, 0x00, 0x10, 0x20, 0x00, 0x20, 0x10, 0x00, + 0xC0, 0x0F, // 1070 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x40, 0x00, 0x10, 0x21, 0x00, 0x08, 0x1A, 0x00, 0x08, 0x0E, 0x00, 0x08, 0x02, 0x00, + 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0x08, 0x02, 0x00, 0xF8, 0x7F, // 1071 + 0x00, 0x00, 0x00, 0x00, 0x39, 0x00, 0x80, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x42, 0x00, 0x40, 0x22, 0x00, + 0x80, 0x7F, // 1072 + 0x00, 0x00, 0x00, 0xE0, 0x1F, 0x00, 0x90, 0x20, 0x00, 0x48, 0x40, 0x00, 0x48, 0x40, 0x00, 0x48, 0x40, 0x00, 0x88, 0x20, 0x00, + 0x08, 0x1F, // 1073 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, + 0x80, 0x3B, // 1074 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, // 1075 + 0x00, 0xC0, 0x01, 0x00, 0x70, 0x00, 0xC0, 0x4F, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0xC0, 0x7F, 0x00, + 0x00, 0xC0, 0x01, // 1076 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x24, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x80, 0x24, 0x00, + 0x00, 0x17, // 1077 + 0xC0, 0x20, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, + 0x00, 0x1B, 0x00, 0xC0, 0x20, 0x00, 0x40, 0x40, // 1078 + 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x80, 0x3B, // 1079 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x02, 0x00, 0x80, 0x01, 0x00, 0xC0, + 0x7F, // 1080 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x08, 0x30, 0x00, 0x10, 0x0C, 0x00, 0x10, 0x02, 0x00, 0x90, 0x01, 0x00, 0xC8, + 0x7F, // 1081 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1B, 0x00, 0xC0, 0x20, 0x00, 0x40, + 0x40, // 1082 + 0x00, 0x40, 0x00, 0xC0, 0x3F, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, + 0x7F, // 1083 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x06, 0x00, 0x00, 0x18, 0x00, 0x00, 0x60, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x06, 0x00, 0xC0, 0x01, 0x00, 0xC0, 0x7F, // 1084 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0xC0, + 0x7F, // 1085 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, + 0x00, 0x1F, // 1086 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, + 0x7F, // 1087 + 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x03, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, + 0x00, 0x1F, // 1088 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, + 0x20, // 1089 + 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, // 1090 + 0xC0, 0x01, 0x00, 0x00, 0x06, 0x02, 0x00, 0x38, 0x02, 0x00, 0xC0, 0x01, 0x00, 0x38, 0x00, 0x00, 0x07, 0x00, 0xC0, // 1091 + 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, 0xF8, 0xFF, 0x03, + 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, 0x00, 0x1F, // 1092 + 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1B, 0x00, 0x80, 0x20, 0x00, 0x40, + 0x40, // 1093 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, + 0xC0, 0x7F, 0x00, 0x00, 0xC0, 0x03, // 1094 + 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0x04, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0xC0, + 0x7F, // 1095 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xC0, 0x7F, // 1096 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x40, 0x00, + 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0xC0, 0x03, // 1097 + 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, + 0x00, 0x44, 0x00, 0x00, 0x38, // 1098 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, + 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x7F, // 1099 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, 0x00, 0x44, 0x00, + 0x00, 0x38, // 1100 + 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x80, 0x20, 0x00, 0x40, 0x44, 0x00, 0x40, 0x44, 0x00, 0x80, 0x24, 0x00, 0x00, + 0x1F, // 1101 + 0x00, 0x00, 0x00, 0xC0, 0x7F, 0x00, 0x00, 0x04, 0x00, 0x00, 0x04, 0x00, 0x00, 0x1F, 0x00, 0x80, 0x20, 0x00, 0x40, 0x40, 0x00, + 0x40, 0x40, 0x00, 0x40, 0x40, 0x00, 0x80, 0x20, 0x00, 0x00, 0x1F, // 1102 + 0x00, 0x00, 0x00, 0x80, 0x63, 0x00, 0x40, 0x14, 0x00, 0x40, 0x0C, 0x00, 0x40, 0x04, 0x00, 0x40, 0x04, 0x00, 0x40, 0x04, 0x00, + 0xC0, 0x7F, // 1103 +}; + +const uint8_t ArialMT_Plain_24_UA[] PROGMEM = { + 0x18, // Width: 24 + 0x1C, // Height: 28 + 0x20, // First Char: 32 + 0xE0, // Numbers of Chars: 224 + // Jump Table: + 0xFF, 0xFF, 0x00, 0x07, // 32= :65535 + 0x00, 0x00, 0x13, 0x08, // 33=!:0 + 0x00, 0x13, 0x1A, 0x09, // 34=":19 + 0x00, 0x2D, 0x33, 0x0D, // 35=#:45 + 0x00, 0x60, 0x2F, 0x0D, // 36=$:96 + 0x00, 0x8F, 0x4F, 0x15, // 37=%:143 + 0x00, 0xDE, 0x3B, 0x10, // 38=&:222 + 0x01, 0x19, 0x0A, 0x05, // 39=':281 + 0x01, 0x23, 0x1C, 0x08, // 40=(:291 + 0x01, 0x3F, 0x1B, 0x08, // 41=):319 + 0x01, 0x5A, 0x22, 0x09, // 42=*:346 + 0x01, 0x7C, 0x33, 0x0E, // 43=+:380 + 0x01, 0xAF, 0x10, 0x07, // 44=,:431 + 0x01, 0xBF, 0x1B, 0x08, // 45=-:447 + 0x01, 0xDA, 0x0F, 0x07, // 46=.:474 + 0x01, 0xE9, 0x1A, 0x07, // 47=/:489 + 0x02, 0x03, 0x2F, 0x0D, // 48=0:515 + 0x02, 0x32, 0x23, 0x0D, // 49=1:562 + 0x02, 0x55, 0x2F, 0x0D, // 50=2:597 + 0x02, 0x84, 0x2F, 0x0D, // 51=3:644 + 0x02, 0xB3, 0x2F, 0x0D, // 52=4:691 + 0x02, 0xE2, 0x2F, 0x0D, // 53=5:738 + 0x03, 0x11, 0x2F, 0x0D, // 54=6:785 + 0x03, 0x40, 0x2E, 0x0D, // 55=7:832 + 0x03, 0x6E, 0x2F, 0x0D, // 56=8:878 + 0x03, 0x9D, 0x2F, 0x0D, // 57=9:925 + 0x03, 0xCC, 0x0F, 0x07, // 58=::972 + 0x03, 0xDB, 0x10, 0x07, // 59=;:987 + 0x03, 0xEB, 0x2F, 0x0E, // 60=<:1003 + 0x04, 0x1A, 0x2F, 0x0E, // 61==:1050 + 0x04, 0x49, 0x2E, 0x0E, // 62=>:1097 + 0x04, 0x77, 0x2E, 0x0D, // 63=?:1143 + 0x04, 0xA5, 0x5C, 0x18, // 64=@:1189 + 0x05, 0x01, 0x3B, 0x0F, // 65=A:1281 + 0x05, 0x3C, 0x3B, 0x10, // 66=B:1340 + 0x05, 0x77, 0x3F, 0x11, // 67=C:1399 + 0x05, 0xB6, 0x3F, 0x11, // 68=D:1462 + 0x05, 0xF5, 0x3B, 0x10, // 69=E:1525 + 0x06, 0x30, 0x36, 0x0F, // 70=F:1584 + 0x06, 0x66, 0x43, 0x13, // 71=G:1638 + 0x06, 0xA9, 0x3B, 0x11, // 72=H:1705 + 0x06, 0xE4, 0x0F, 0x06, // 73=I:1764 + 0x06, 0xF3, 0x27, 0x0C, // 74=J:1779 + 0x07, 0x1A, 0x3F, 0x10, // 75=K:1818 + 0x07, 0x59, 0x2F, 0x0D, // 76=L:1881 + 0x07, 0x88, 0x43, 0x13, // 77=M:1928 + 0x07, 0xCB, 0x3B, 0x11, // 78=N:1995 + 0x08, 0x06, 0x47, 0x13, // 79=O:2054 + 0x08, 0x4D, 0x3A, 0x10, // 80=P:2125 + 0x08, 0x87, 0x48, 0x13, // 81=Q:2183 + 0x08, 0xCF, 0x3F, 0x11, // 82=R:2255 + 0x09, 0x0E, 0x3B, 0x10, // 83=S:2318 + 0x09, 0x49, 0x36, 0x0E, // 84=T:2377 + 0x09, 0x7F, 0x3B, 0x11, // 85=U:2431 + 0x09, 0xBA, 0x39, 0x0F, // 86=V:2490 + 0x09, 0xF3, 0x5A, 0x17, // 87=W:2547 + 0x0A, 0x4D, 0x3B, 0x0F, // 88=X:2637 + 0x0A, 0x88, 0x3D, 0x10, // 89=Y:2696 + 0x0A, 0xC5, 0x37, 0x0F, // 90=Z:2757 + 0x0A, 0xFC, 0x14, 0x07, // 91=[:2812 + 0x0B, 0x10, 0x1B, 0x07, // 92=\:2832 + 0x0B, 0x2B, 0x18, 0x07, // 93=]:2859 + 0x0B, 0x43, 0x2A, 0x0C, // 94=^:2883 + 0x0B, 0x6D, 0x34, 0x0D, // 95=_:2925 + 0x0B, 0xA1, 0x12, 0x08, // 96=`:2977 + 0x0B, 0xB3, 0x2F, 0x0D, // 97=a:2995 + 0x0B, 0xE2, 0x33, 0x0E, // 98=b:3042 + 0x0C, 0x15, 0x2B, 0x0C, // 99=c:3093 + 0x0C, 0x40, 0x2F, 0x0E, // 100=d:3136 + 0x0C, 0x6F, 0x2F, 0x0D, // 101=e:3183 + 0x0C, 0x9E, 0x1A, 0x07, // 102=f:3230 + 0x0C, 0xB8, 0x30, 0x0E, // 103=g:3256 + 0x0C, 0xE8, 0x2F, 0x0E, // 104=h:3304 + 0x0D, 0x17, 0x0F, 0x05, // 105=i:3351 + 0x0D, 0x26, 0x10, 0x06, // 106=j:3366 + 0x0D, 0x36, 0x2F, 0x0C, // 107=k:3382 + 0x0D, 0x65, 0x0F, 0x06, // 108=l:3429 + 0x0D, 0x74, 0x47, 0x14, // 109=m:3444 + 0x0D, 0xBB, 0x2F, 0x0E, // 110=n:3515 + 0x0D, 0xEA, 0x2F, 0x0D, // 111=o:3562 + 0x0E, 0x19, 0x33, 0x0E, // 112=p:3609 + 0x0E, 0x4C, 0x30, 0x0E, // 113=q:3660 + 0x0E, 0x7C, 0x1E, 0x08, // 114=r:3708 + 0x0E, 0x9A, 0x2B, 0x0C, // 115=s:3738 + 0x0E, 0xC5, 0x1B, 0x07, // 116=t:3781 + 0x0E, 0xE0, 0x2F, 0x0E, // 117=u:3808 + 0x0F, 0x0F, 0x2A, 0x0B, // 118=v:3855 + 0x0F, 0x39, 0x42, 0x11, // 119=w:3897 + 0x0F, 0x7B, 0x2B, 0x0B, // 120=x:3963 + 0x0F, 0xA6, 0x2A, 0x0C, // 121=y:4006 + 0x0F, 0xD0, 0x2B, 0x0C, // 122=z:4048 + 0x0F, 0xFB, 0x1C, 0x08, // 123={:4091 + 0x10, 0x17, 0x10, 0x06, // 124=|:4119 + 0x10, 0x27, 0x1B, 0x08, // 125=}:4135 + 0x10, 0x42, 0x33, 0x0E, // 126=~:4162 + 0xFF, 0xFF, 0x00, 0x12, // 127:65535 + 0x10, 0x75, 0x4F, 0x15, // 1026=� �..:4213 + 0x10, 0xC4, 0x32, 0x0D, // 1027=� �.:4292 + 0x10, 0xF6, 0x0C, 0x05, // 8218=��.�.:4342 + 0x11, 0x02, 0x22, 0x09, // 1107=�.�..:4354 + 0x11, 0x24, 0x1C, 0x08, // 8222=��.�.:4388 + 0x11, 0x40, 0x4B, 0x18, // 8230=��.�.:4416 + 0x11, 0x8B, 0x32, 0x0D, // 8224=��.� :4491 + 0x11, 0xBD, 0x33, 0x0D, // 8225=��.�.:4541 + 0x11, 0xF0, 0x2F, 0x0D, // 8364=��..�.:4592 + 0x12, 0x1F, 0x63, 0x1A, // 8240=��.��:4639 + 0x12, 0x82, 0x5F, 0x19, // 1033=� �.�:4738 + 0x12, 0xE1, 0x17, 0x08, // 8249=��.�..:4833 + 0x12, 0xF8, 0x5B, 0x18, // 1034=� �.:4856 + 0x13, 0x53, 0x37, 0x0E, // 1036=� �.:4947 + 0x13, 0x8A, 0x4F, 0x16, // 1035=� �..:5002 + 0x13, 0xD9, 0x3B, 0x11, // 1039=� �.:5081 + 0x14, 0x14, 0x30, 0x0E, // 1106=�.�..:5140 + 0x14, 0x44, 0x0A, 0x05, // 8216=��.Ч.:5188 + 0x14, 0x4E, 0x0A, 0x05, // 8217=��.�..:5198 + 0x14, 0x58, 0x1A, 0x08, // 8220=��.�.:5208 + 0x14, 0x72, 0x1A, 0x08, // 8221=��.�.:5234 + 0x14, 0x8C, 0x1B, 0x08, // 8226=��.�.:5260 + 0x14, 0xA7, 0x33, 0x0D, // 8211=��.�..:5287 + 0x14, 0xDA, 0x5F, 0x18, // 8212=��.�..:5338 + 0xFF, 0xFF, 0x00, 0x12, // 65533=��.�.:65535 + 0x15, 0x39, 0x5B, 0x18, // 8482=��..�.:5433 + 0x15, 0x94, 0x53, 0x16, // 1113=�.�..:5524 + 0x15, 0xE7, 0x1B, 0x08, // 8250=��.�.:5607 + 0x16, 0x02, 0x4B, 0x14, // 1114=�.�.:5634 + 0x16, 0x4D, 0x2B, 0x0B, // 1116=�.�.:5709 + 0x16, 0x78, 0x2F, 0x0E, // 1115=�.�.�:5752 + 0x16, 0xA7, 0x2F, 0x0D, // 1119=�.�.:5799 + 0xFF, 0xFF, 0x00, 0x07, // 160=�.� :65535 + 0x16, 0xD6, 0x36, 0x0F, // 1038=� �.:5846 + 0x17, 0x0C, 0x2A, 0x0C, // 1118=�.�.:5900 + 0x17, 0x36, 0x27, 0x0C, // 1032=� �..:5942 + 0x17, 0x5D, 0x33, 0x0D, // 164=�.�.:5981 + 0x17, 0x90, 0x2A, 0x0C, // 1168=�.�.:6032 + 0x17, 0xBA, 0x10, 0x06, // 166=�.�.:6074 + 0x17, 0xCA, 0x2F, 0x0D, // 167=�.�.:6090 + 0x17, 0xF9, 0x3B, 0x10, // 1025=� �.:6137 + 0x18, 0x34, 0x47, 0x12, // 169=�.��:6196 + 0x18, 0x7B, 0x3F, 0x11, // 1028=� �..:6267 + 0x18, 0xBA, 0x27, 0x0D, // 171=�.�.:6330 + 0x18, 0xE1, 0x2F, 0x0E, // 172=�.�.:6369 + 0x19, 0x10, 0x1B, 0x08, // 173=�.�:6416 + 0x19, 0x2B, 0x47, 0x12, // 174=�.�.:6443 + 0x19, 0x72, 0x15, 0x06, // 1031=� �..:6514 + 0x19, 0x87, 0x1E, 0x0A, // 176=�.��:6535 + 0x19, 0xA5, 0x33, 0x0D, // 177=�.�.:6565 + 0x19, 0xD8, 0x0F, 0x06, // 1030=� �. :6616 + 0x19, 0xE7, 0x0F, 0x05, // 1110=�.�..:6631 + 0x19, 0xF6, 0x22, 0x0A, // 1169=�.�.:6646 + 0x1A, 0x18, 0x2F, 0x0E, // 181=�.�.:6680 + 0x1A, 0x47, 0x32, 0x0D, // 182=�.�.:6727 + 0x1A, 0x79, 0x13, 0x08, // 183=�.��:6777 + 0x1A, 0x8C, 0x2F, 0x0D, // 1105=�.�.:6796 + 0x1A, 0xBB, 0x63, 0x1A, // 8470=��..�..:6843 + 0x1B, 0x1E, 0x2B, 0x0C, // 1108=�.�..:6942 + 0x1B, 0x49, 0x2F, 0x0D, // 187=�.�.:6985 + 0x1B, 0x78, 0x10, 0x06, // 1112=�.Ч.:7032 + 0x1B, 0x88, 0x3B, 0x10, // 1029=� �..:7048 + 0x1B, 0xC3, 0x2B, 0x0C, // 1109=�.�..:7107 + 0x1B, 0xEE, 0x16, 0x06, // 1111=�.�..:7150 + 0x1C, 0x04, 0x3B, 0x0F, // 1040=� �.:7172 + 0x1C, 0x3F, 0x3B, 0x10, // 1041=� �.:7231 + 0x1C, 0x7A, 0x3B, 0x10, // 1042=� �..:7290 + 0x1C, 0xB5, 0x32, 0x0D, // 1043=� �..:7349 + 0x1C, 0xE7, 0x40, 0x10, // 1044=� �..:7399 + 0x1D, 0x27, 0x3B, 0x10, // 1045=� �..:7463 + 0x1D, 0x62, 0x57, 0x16, // 1046=� �..:7522 + 0x1D, 0xB9, 0x37, 0x0F, // 1047=� �..:7609 + 0x1D, 0xF0, 0x3B, 0x11, // 1048=� Ч.:7664 + 0x1E, 0x2B, 0x3B, 0x11, // 1049=� �..:7723 + 0x1E, 0x66, 0x37, 0x0E, // 1050=� �.:7782 + 0x1E, 0x9D, 0x37, 0x10, // 1051=� �.�:7837 + 0x1E, 0xD4, 0x43, 0x13, // 1052=� �.:7892 + 0x1F, 0x17, 0x3B, 0x11, // 1053=� �.:7959 + 0x1F, 0x52, 0x47, 0x13, // 1054=� �.:8018 + 0x1F, 0x99, 0x3B, 0x11, // 1055=� �.:8089 + 0x1F, 0xD4, 0x3A, 0x10, // 1056=� � :8148 + 0x20, 0x0E, 0x3F, 0x11, // 1057=� �.:8206 + 0x20, 0x4D, 0x36, 0x0E, // 1058=� �.:8269 + 0x20, 0x83, 0x36, 0x0F, // 1059=� �.:8323 + 0x20, 0xB9, 0x43, 0x12, // 1060=� �.:8377 + 0x20, 0xFC, 0x3B, 0x0F, // 1061=� �.:8444 + 0x21, 0x37, 0x44, 0x12, // 1062=� �.:8503 + 0x21, 0x7B, 0x37, 0x10, // 1063=� �.:8571 + 0x21, 0xB2, 0x53, 0x16, // 1064=� �.:8626 + 0x22, 0x05, 0x5C, 0x17, // 1065=� ��:8709 + 0x22, 0x61, 0x47, 0x13, // 1066=� �.:8801 + 0x22, 0xA8, 0x4B, 0x15, // 1067=� �.:8872 + 0x22, 0xF3, 0x3B, 0x10, // 1068=� �.:8947 + 0x23, 0x2E, 0x3F, 0x11, // 1069=� �:9006 + 0x23, 0x6D, 0x5B, 0x18, // 1070=� �.:9069 + 0x23, 0xC8, 0x3B, 0x11, // 1071=� �.:9160 + 0x24, 0x03, 0x2F, 0x0D, // 1072=� ��:9219 + 0x24, 0x32, 0x33, 0x0E, // 1073=� �.:9266 + 0x24, 0x65, 0x2F, 0x0D, // 1074=� �.:9317 + 0x24, 0x94, 0x22, 0x09, // 1075=� �.:9364 + 0x24, 0xB6, 0x34, 0x0E, // 1076=� �.:9398 + 0x24, 0xEA, 0x2F, 0x0D, // 1077=� �.:9450 + 0x25, 0x19, 0x3B, 0x10, // 1078=� �.:9497 + 0x25, 0x54, 0x27, 0x0B, // 1079=� ��:9556 + 0x25, 0x7B, 0x2F, 0x0D, // 1080=� �.:9595 + 0x25, 0xAA, 0x2F, 0x0D, // 1081=� �..:9642 + 0x25, 0xD9, 0x2B, 0x0B, // 1082=� �.:9689 + 0x26, 0x04, 0x2F, 0x0E, // 1083=� �.:9732 + 0x26, 0x33, 0x3B, 0x11, // 1084=� �:9779 + 0x26, 0x6E, 0x2F, 0x0D, // 1085=� �.:9838 + 0x26, 0x9D, 0x2F, 0x0D, // 1086=� �.:9885 + 0x26, 0xCC, 0x2F, 0x0D, // 1087=� �.:9932 + 0x26, 0xFB, 0x33, 0x0E, // 1088=�.�.:9979 + 0x27, 0x2E, 0x2B, 0x0C, // 1089=�.�.:10030 + 0x27, 0x59, 0x26, 0x0B, // 1090=�.�..:10073 + 0x27, 0x7F, 0x2A, 0x0C, // 1091=�.�.:10111 + 0x27, 0xA9, 0x4B, 0x14, // 1092=�.�..:10153 + 0x27, 0xF4, 0x2B, 0x0B, // 1093=�.�..:10228 + 0x28, 0x1F, 0x34, 0x0E, // 1094=�.�. :10271 + 0x28, 0x53, 0x2B, 0x0D, // 1095=�.�..:10323 + 0x28, 0x7E, 0x47, 0x13, // 1096=�.�..:10366 + 0x28, 0xC5, 0x4C, 0x14, // 1097=�.�.�:10437 + 0x29, 0x11, 0x37, 0x0F, // 1098=�.�.:10513 + 0x29, 0x48, 0x3B, 0x11, // 1099=�.�..:10568 + 0x29, 0x83, 0x2F, 0x0D, // 1100=�.�.:10627 + 0x29, 0xB2, 0x2B, 0x0C, // 1101=�.�.:10674 + 0x29, 0xDD, 0x43, 0x12, // 1102=�.�.:10717 + 0x2A, 0x20, 0x2B, 0x0D, // 1103=�.�.:10784 + // Font Data: + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xCF, 0x00, 0x80, 0xFF, 0xCF, // 33 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x1F, 0x00, 0x00, 0x80, 0x1F, // 34 + 0x00, 0x30, 0x0C, 0x00, 0x00, 0x30, 0xCC, 0x00, 0x00, 0x30, 0xFE, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0xFE, 0x0F, 0x00, 0x80, + 0x3F, 0x0C, 0x00, 0x80, 0x31, 0xCC, 0x00, 0x00, 0x30, 0xFE, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0xFE, 0x0D, 0x00, 0x80, 0x3F, + 0x0C, 0x00, 0x80, 0x31, 0x0C, 0x00, 0x00, 0x30, 0x0C, // 35 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x18, 0x00, 0x00, 0x3F, 0x78, 0x00, 0x00, 0x63, 0x70, 0x00, 0x80, 0x61, 0xE0, 0x00, 0x80, + 0xC1, 0xC0, 0x00, 0xC0, 0xFF, 0xFF, 0x03, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0x81, 0xC1, 0x00, 0x00, 0x83, 0x61, 0x00, 0x00, 0x07, + 0x7F, 0x00, 0x00, 0x04, 0x1E, // 36 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, + 0x80, 0x80, 0x00, 0x80, 0xC1, 0xE0, 0x00, 0x00, 0x7F, 0x78, 0x00, 0x00, 0x3E, 0x3E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0xC0, + 0x03, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x3C, 0x3E, 0x00, 0x00, 0x0F, 0x7F, 0x00, 0x80, 0x83, 0xC1, 0x00, 0x80, 0x80, 0x80, + 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3E, // 37 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x8E, 0x73, 0x00, 0x00, 0xDF, 0xE1, 0x00, 0x80, + 0xF3, 0xC0, 0x00, 0x80, 0xE1, 0xC0, 0x00, 0x80, 0xE1, 0xC1, 0x00, 0x80, 0xB3, 0xE3, 0x00, 0x00, 0x3F, 0x6E, 0x00, 0x00, 0x0E, + 0x7C, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0xE2, 0x00, 0x00, 0x00, 0x40, // 38 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x80, 0x1F, // 39 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x3F, 0x00, 0x00, 0xF8, 0xFF, 0x01, 0x00, 0x3E, 0xC0, 0x07, 0x00, 0x07, 0x00, 0x0E, 0x80, + 0x01, 0x00, 0x18, 0x80, 0x00, 0x00, 0x10, // 40 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x10, 0x80, 0x01, 0x00, 0x18, 0x00, 0x07, 0x00, 0x0E, 0x00, 0x3E, 0xC0, 0x07, 0x00, + 0xF8, 0xFF, 0x01, 0x00, 0xC0, 0x3F, // 41 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x80, + 0x0F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, 0x02, // 42 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0xFC, 0x3F, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, // 43 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0xC0, 0x07, // 44 + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, // 45 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, // 46 + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x80, + 0x0F, 0x00, 0x00, 0x80, 0x01, // 47 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x07, 0x70, 0x00, 0x80, 0x03, 0xE0, 0x00, 0x80, + 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x03, 0xE0, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0xFE, + 0x3F, 0x00, 0x00, 0xF8, 0x0F, // 48 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 49 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xC0, 0x00, 0x00, 0x0F, 0xE0, 0x00, 0x00, 0x03, 0xF0, 0x00, 0x80, 0x01, 0xD8, 0x00, 0x80, + 0x01, 0xCC, 0x00, 0x80, 0x01, 0xC6, 0x00, 0x80, 0x01, 0xC3, 0x00, 0x80, 0x81, 0xC1, 0x00, 0x00, 0xC3, 0xC0, 0x00, 0x00, 0x7F, + 0xC0, 0x00, 0x00, 0x3C, 0xC0, // 50 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x18, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x03, 0x70, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, + 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x00, 0xE3, 0xC0, 0x00, 0x00, 0xBF, 0x61, 0x00, 0x00, 0x1E, + 0x3F, 0x00, 0x00, 0x00, 0x1E, // 51 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0xF0, 0x0C, 0x00, 0x00, + 0x38, 0x0C, 0x00, 0x00, 0x1E, 0x0C, 0x00, 0x00, 0x07, 0x0C, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, + 0x0C, 0x00, 0x00, 0x00, 0x0C, // 52 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x18, 0x00, 0x00, 0xFE, 0x38, 0x00, 0x80, 0x7F, 0x60, 0x00, 0x80, 0x21, 0xC0, 0x00, 0x80, + 0x31, 0xC0, 0x00, 0x80, 0x31, 0xC0, 0x00, 0x80, 0x31, 0xC0, 0x00, 0x80, 0x31, 0xC0, 0x00, 0x80, 0x61, 0x70, 0x00, 0x80, 0xC1, + 0x3F, 0x00, 0x00, 0x80, 0x0F, // 53 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x8F, 0x71, 0x00, 0x00, 0xC3, 0xE0, 0x00, 0x80, + 0x61, 0xC0, 0x00, 0x80, 0x61, 0xC0, 0x00, 0x80, 0x61, 0xC0, 0x00, 0x80, 0x61, 0xC0, 0x00, 0x80, 0xC3, 0x60, 0x00, 0x00, 0xC7, + 0x3F, 0x00, 0x00, 0x06, 0x1F, // 54 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x80, + 0x01, 0xFE, 0x00, 0x80, 0xC1, 0x0F, 0x00, 0x80, 0xE1, 0x01, 0x00, 0x80, 0x39, 0x00, 0x00, 0x80, 0x0D, 0x00, 0x00, 0x80, 0x07, + 0x00, 0x00, 0x80, 0x01, // 55 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x1E, 0x7F, 0x00, 0x00, 0xBF, 0x61, 0x00, 0x80, 0xE3, 0xC0, 0x00, 0x80, + 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xE3, 0xC0, 0x00, 0x00, 0xBF, 0x61, 0x00, 0x00, 0x1E, + 0x7F, 0x00, 0x00, 0x00, 0x1E, // 56 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x30, 0x00, 0x00, 0xFE, 0x71, 0x00, 0x00, 0x87, 0xE1, 0x00, 0x80, 0x01, 0xC3, 0x00, 0x80, + 0x01, 0xC3, 0x00, 0x80, 0x01, 0xC3, 0x00, 0x80, 0x01, 0xC3, 0x00, 0x80, 0x81, 0x61, 0x00, 0x00, 0xC7, 0x78, 0x00, 0x00, 0xFE, + 0x3F, 0x00, 0x00, 0xF8, 0x07, // 57 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, // 58 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC0, 0x0C, 0x00, 0x18, 0xC0, 0x07, // 59 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, + 0x60, 0x03, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, 0x18, + 0x0C, 0x00, 0x00, 0x0C, 0x18, // 60 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, + 0x30, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x30, + 0x06, 0x00, 0x00, 0x30, 0x06, // 61 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x18, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, 0x18, 0x0C, 0x00, 0x00, 0x10, 0x04, 0x00, 0x00, + 0x30, 0x06, 0x00, 0x00, 0x30, 0x06, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xC0, + 0x01, 0x00, 0x00, 0x80, // 62 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, + 0x01, 0xCE, 0x00, 0x80, 0x01, 0xCF, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x00, 0xE3, 0x00, 0x00, 0x00, 0x7F, + 0x00, 0x00, 0x00, 0x1C, // 63 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0xE0, 0xFF, 0x00, 0x00, 0x78, 0xC0, 0x03, 0x00, 0x1C, 0x00, 0x07, 0x00, + 0x0E, 0x1F, 0x06, 0x00, 0xC7, 0x7F, 0x0E, 0x00, 0xE3, 0x60, 0x0C, 0x00, 0x33, 0xC0, 0x0C, 0x80, 0x39, 0xC0, 0x18, 0x80, 0x19, + 0xC0, 0x18, 0x80, 0x19, 0x60, 0x18, 0x80, 0x19, 0x30, 0x18, 0x80, 0x31, 0x78, 0x18, 0x80, 0xE1, 0xFF, 0x18, 0x80, 0xFB, 0xC7, + 0x18, 0x00, 0x3B, 0xC0, 0x18, 0x00, 0x07, 0x60, 0x0C, 0x00, 0x0E, 0x70, 0x0C, 0x00, 0x1C, 0x3C, 0x06, 0x00, 0xF8, 0x1F, 0x06, + 0x00, 0xE0, 0x07, 0x03, 0x00, 0x00, 0x00, 0x01, // 64 + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, + 0x3E, 0x06, 0x00, 0x80, 0x0F, 0x06, 0x00, 0x80, 0x01, 0x06, 0x00, 0x80, 0x0F, 0x06, 0x00, 0x00, 0x3E, 0x06, 0x00, 0x00, 0xF8, + 0x07, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xC0, // 65 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, + 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, + 0xC0, 0x00, 0x00, 0xE3, 0xC1, 0x00, 0x00, 0xFF, 0x61, 0x00, 0x00, 0x1E, 0x7F, 0x00, 0x00, 0x00, 0x1E, // 66 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, + 0x03, 0x60, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, + 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x0E, 0x3C, 0x00, 0x00, 0x08, + 0x0C, // 67 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, + 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, + 0xC0, 0x00, 0x80, 0x03, 0x60, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x0E, 0x38, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xF0, + 0x07, // 68 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, + 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, + 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0x01, 0xC0, // 69 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, + 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, + 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0x01, // 70 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, + 0x03, 0x60, 0x00, 0x80, 0x03, 0x60, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x81, + 0xC1, 0x00, 0x80, 0x81, 0xC1, 0x00, 0x80, 0x83, 0xC1, 0x00, 0x00, 0x83, 0x61, 0x00, 0x00, 0x87, 0x61, 0x00, 0x00, 0x8E, 0x3F, + 0x00, 0x00, 0x88, 0x3F, // 71 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 72 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 73 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x3F, // 74 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, + 0xC0, 0x01, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x9C, 0x07, 0x00, 0x00, 0x0E, + 0x1E, 0x00, 0x00, 0x07, 0x3C, 0x00, 0x80, 0x03, 0x78, 0x00, 0x80, 0x01, 0xE0, 0x00, 0x80, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0x80, // 75 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xC0, // 76 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, + 0x3F, 0x00, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x80, 0xFF, 0xFF, + 0x00, 0x80, 0xFF, 0xFF, // 77 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x70, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 78 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, + 0x03, 0x60, 0x00, 0x80, 0x03, 0xE0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, + 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x03, 0xE0, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x1E, 0x3C, + 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xF0, 0x07, // 79 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, + 0x81, 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, 0x81, + 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x3C, // 80 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x07, 0x30, 0x00, 0x00, + 0x03, 0x60, 0x00, 0x80, 0x03, 0x60, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, + 0xD8, 0x00, 0x80, 0x01, 0xD8, 0x00, 0x80, 0x03, 0xF0, 0x00, 0x00, 0x03, 0x70, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x1E, 0xFC, + 0x00, 0x00, 0xFC, 0xDF, 0x01, 0x00, 0xF0, 0x87, 0x01, // 81 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, + 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x01, 0x00, 0x80, 0xC1, 0x03, 0x00, 0x80, 0xC1, + 0x0F, 0x00, 0x80, 0xC1, 0x1E, 0x00, 0x80, 0x63, 0x7C, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x00, 0x3E, 0xC0, 0x00, 0x00, 0x00, + 0x80, // 82 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x3C, 0x00, 0x00, 0x7F, 0x70, 0x00, 0x00, 0x63, 0x60, 0x00, 0x80, + 0xE1, 0xE0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, + 0xC1, 0x00, 0x80, 0x83, 0xE1, 0x00, 0x00, 0x87, 0x63, 0x00, 0x00, 0x0E, 0x3F, 0x00, 0x00, 0x0C, 0x1E, // 83 + 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, // 84 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x0F, 0x00, 0x80, 0xFF, 0x3F, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x70, 0x00, 0x80, 0xFF, 0x3F, 0x00, 0x80, 0xFF, 0x0F, // 85 + 0x80, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, + 0x00, 0x3F, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0xE0, + 0x07, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x80, // 86 + 0x80, 0x01, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0xFE, 0x03, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x80, 0x0F, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x80, 0x3F, + 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0xFE, 0x03, 0x00, + 0x80, 0x1F, 0x00, 0x00, 0x80, 0x01, // 87 + 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x80, 0x07, 0x78, 0x00, 0x00, 0x0F, 0x1E, 0x00, 0x00, + 0x3C, 0x0F, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x1E, 0x0F, 0x00, 0x00, 0x0F, + 0x1C, 0x00, 0x80, 0x07, 0x78, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x80, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x80, // 88 + 0x80, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, + 0x78, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, // 89 + 0x00, 0x00, 0xC0, 0x00, 0x80, 0x01, 0xE0, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x80, 0x01, 0xDC, 0x00, 0x80, 0x01, 0xCE, 0x00, 0x80, + 0x01, 0xC7, 0x00, 0x80, 0x81, 0xC3, 0x00, 0x80, 0xE1, 0xC0, 0x00, 0x80, 0x71, 0xC0, 0x00, 0x80, 0x39, 0xC0, 0x00, 0x80, 0x1D, + 0xC0, 0x00, 0x80, 0x07, 0xC0, 0x00, 0x80, 0x03, 0xC0, 0x00, 0x80, 0x01, 0xC0, // 90 + 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x1F, 0x80, 0xFF, 0xFF, 0x1F, 0x80, 0x01, 0x00, 0x18, 0x80, 0x01, 0x00, 0x18, // 91 + 0x80, 0x01, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, + 0x00, 0xF8, 0x00, 0x00, 0x00, 0xC0, // 92 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x18, 0x80, 0x01, 0x00, 0x18, 0x80, 0xFF, 0xFF, 0x1F, 0x80, + 0xFF, 0xFF, 0x1F, // 93 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x80, + 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, + 0x80, // 94 + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, + 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, + 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, // 95 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x02, // 96 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x38, 0x00, 0x00, 0x70, 0x7C, 0x00, 0x00, 0x30, 0xE6, 0x00, 0x00, 0x18, 0xC6, 0x00, 0x00, + 0x18, 0xC6, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x18, 0x63, 0x00, 0x00, 0x38, 0x63, 0x00, 0x00, 0xF0, 0x7F, 0x00, 0x00, 0xE0, + 0xFF, 0x00, 0x00, 0x00, 0x80, // 97 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, + 0x30, 0x60, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x70, + 0x70, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x80, 0x0F, // 98 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x60, + 0x30, // 99 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x70, 0x30, 0x00, 0x80, 0xFF, + 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 100 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x73, 0x00, 0x00, 0x38, 0xE3, 0x00, 0x00, + 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x38, 0xE3, 0x00, 0x00, 0x70, 0x63, 0x00, 0x00, 0xE0, + 0x33, 0x00, 0x00, 0xC0, 0x13, // 101 + 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x19, 0x00, 0x00, 0x80, + 0x19, 0x00, 0x00, 0x80, 0x19, // 102 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0F, 0x06, 0x00, 0xE0, 0x3F, 0x0E, 0x00, 0x70, 0x70, 0x1C, 0x00, 0x38, 0xE0, 0x18, 0x00, + 0x18, 0xC0, 0x18, 0x00, 0x18, 0xC0, 0x18, 0x00, 0x18, 0xC0, 0x18, 0x00, 0x30, 0x60, 0x1C, 0x00, 0x60, 0x30, 0x0E, 0x00, 0xF8, + 0xFF, 0x07, 0x00, 0xF8, 0xFF, 0x03, // 103 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF0, + 0xFF, 0x00, 0x00, 0xE0, 0xFF, // 104 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF9, 0xFF, 0x00, 0x80, 0xF9, 0xFF, // 105 + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x80, 0xF9, 0xFF, 0x1F, 0x80, 0xF9, 0xFF, 0x0F, // 106 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0xC0, 0x07, 0x00, 0x00, 0x60, 0x1E, 0x00, 0x00, 0x30, 0x38, 0x00, 0x00, 0x18, 0xF0, 0x00, 0x00, 0x08, + 0xC0, 0x00, 0x00, 0x00, 0x80, // 107 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 108 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0xE0, + 0xFF, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x38, 0x00, + 0x00, 0x00, 0xF0, 0xFF, 0x00, 0x00, 0xE0, 0xFF, // 109 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF0, + 0xFF, 0x00, 0x00, 0xE0, 0xFF, // 110 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0xE0, + 0x3F, 0x00, 0x00, 0xC0, 0x1F, // 111 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x1F, 0x00, 0xF8, 0xFF, 0x1F, 0x00, 0x60, 0x30, 0x00, 0x00, + 0x30, 0x60, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x70, + 0x70, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0xC0, 0x0F, // 112 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x30, 0x60, 0x00, 0x00, 0x60, 0x30, 0x00, 0x00, 0xF8, + 0xFF, 0x1F, 0x00, 0xF8, 0xFF, 0x1F, // 113 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, // 114 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x30, 0x00, 0x00, 0xF0, 0x71, 0x00, 0x00, 0xB8, 0xE3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, + 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC7, 0x00, 0x00, 0x18, 0xC7, 0x00, 0x00, 0x38, 0xE6, 0x00, 0x00, 0x70, 0x7E, 0x00, 0x00, 0x60, + 0x3C, // 115 + 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, // 116 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x3F, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 117 + 0x00, 0x18, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, + 0x00, 0xE0, 0x00, 0x00, 0x00, 0x7C, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, + 0x18, // 118 + 0x00, 0x38, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, + 0x00, 0x7E, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x80, + 0x0F, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0xF8, 0x01, + 0x00, 0x00, 0x38, // 119 + 0x00, 0x08, 0x80, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x78, 0xF0, 0x00, 0x00, 0xE0, 0x38, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0xE0, 0x38, 0x00, 0x00, 0x70, 0xF0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x08, + 0x80, // 120 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x18, 0x00, 0xC0, 0x07, 0x18, 0x00, 0x00, 0x3E, 0x1C, 0x00, + 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, + 0x18, // 121 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x18, 0xF0, 0x00, 0x00, 0x18, 0xF8, 0x00, 0x00, 0x18, 0xDC, 0x00, 0x00, + 0x18, 0xCF, 0x00, 0x00, 0x98, 0xC3, 0x00, 0x00, 0xD8, 0xC1, 0x00, 0x00, 0xF8, 0xC0, 0x00, 0x00, 0x78, 0xC0, 0x00, 0x00, 0x18, + 0xC0, // 122 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0xFF, 0xF9, 0x0F, 0x80, 0xFF, 0xF0, 0x1F, 0x80, + 0x01, 0x00, 0x18, 0x80, 0x01, 0x00, 0x18, // 123 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x3F, 0x80, 0xFF, 0xFF, 0x3F, // 124 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x18, 0x80, 0x01, 0x00, 0x18, 0x80, 0xFF, 0xF0, 0x1F, 0x00, 0xFF, 0xFD, 0x0F, 0x00, + 0x00, 0x0F, 0x00, 0x00, 0x00, 0x06, // 125 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x80, 0x01, // 126 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, + 0x00, 0x00, 0x80, 0x61, 0x00, 0x00, 0x80, 0x61, 0x60, 0x00, 0x80, 0x61, 0xC0, 0x00, 0x80, 0x61, 0xC0, 0x00, 0x00, 0x60, 0xC0, + 0x00, 0x00, 0xE0, 0xE0, 0x00, 0x00, 0xC0, 0x71, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x1F, // 1026 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0xA0, 0x01, 0x00, 0x00, 0xB8, 0x01, 0x00, 0x00, 0x98, 0x01, 0x00, 0x00, 0x88, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, // 1027 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0xC0, 0x07, // 8218 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x80, + 0x1B, 0x00, 0x00, 0x80, 0x19, 0x00, 0x00, 0x80, 0x18, 0x00, 0x00, 0x00, 0x18, // 1107 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0x00, 0x00, 0xC0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xC0, 0x0C, 0x00, 0x00, 0xC0, 0x07, // 8222 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, // 8230 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, + 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, // 8224 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x80, 0xFF, 0xFF, 0x0F, 0x80, 0xFF, 0xFF, 0x0F, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, + 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, // 8225 + 0x00, 0x30, 0x03, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0xFE, 0x1F, 0x00, 0x00, 0x36, 0x3B, 0x00, 0x00, 0x33, 0x73, 0x00, 0x00, + 0x33, 0x63, 0x00, 0x80, 0x31, 0xC3, 0x00, 0x80, 0x31, 0xC3, 0x00, 0x80, 0x31, 0xC3, 0x00, 0x80, 0x31, 0xC3, 0x00, 0x80, 0x31, + 0xC0, 0x00, 0x00, 0x03, 0x60, // 8364 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, + 0xC1, 0xE0, 0x00, 0x00, 0x7F, 0xF8, 0x00, 0x00, 0x3E, 0x3E, 0x00, 0x00, 0xC0, 0x07, 0x00, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x3E, + 0x3E, 0x00, 0x80, 0x0F, 0x7F, 0x00, 0x80, 0x81, 0xC1, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x00, 0x7F, + 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x80, 0xC1, 0x00, + 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x3E, // 8240 + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x3F, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, + 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, + 0x00, 0x80, 0x61, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x1E, // 1033 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0xE0, 0x3D, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, + 0x10, 0x40, // 8249 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, + 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x80, 0x61, 0x00, + 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x1E, // 1034 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x20, 0x60, 0x03, 0x00, 0x38, 0x78, 0x07, 0x00, 0x18, 0x1E, 0x0E, 0x00, 0x08, 0x07, + 0x38, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0x80, // 1036 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, + 0x00, 0x00, 0x80, 0x61, 0x00, 0x00, 0x80, 0x61, 0x00, 0x00, 0x80, 0x61, 0x00, 0x00, 0x80, 0x61, 0x00, 0x00, 0x00, 0x60, 0x00, + 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0xFF, 0x00, 0x00, 0x00, 0xFF, // 1035 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1039 + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x18, 0x00, 0x18, 0x00, 0x18, 0x00, 0x38, 0x00, 0x18, 0x00, 0xF0, + 0xFF, 0x1F, 0x00, 0xE0, 0xFF, 0x0F, // 1106 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x80, 0x19, // 8216 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x19, 0x00, 0x00, 0x80, 0x0F, // 8217 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0x80, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1F, 0x00, 0x00, 0x80, 0x19, // 8220 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x19, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, + 0x19, 0x00, 0x00, 0x80, 0x0F, // 8221 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x03, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, + 0xE0, 0x07, 0x00, 0x00, 0xC0, 0x03, // 8226 + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, // 8211 + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, + 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, // 8212 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00, 0x80, 0xFF, 0x01, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00, 0x80, 0xFF, 0x01, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00, 0x1E, 0x00, + 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, + 0x80, 0xFF, 0x01, 0x00, 0x80, 0xFF, 0x01, // 8482 + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, + 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, + 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, + 0x3C, // 1113 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0xE0, 0x3D, 0x00, 0x00, + 0x80, 0x0F, 0x00, 0x00, 0x00, 0x02, // 8250 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, + 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x3C, // 1114 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x02, 0x02, 0x00, 0x80, + 0x03, 0x07, 0x00, 0x80, 0xC1, 0x0D, 0x00, 0x80, 0xF0, 0x38, 0x00, 0x00, 0x18, 0x70, 0x00, 0x00, 0x18, 0xE0, 0x00, 0x00, 0x00, + 0x80, // 1116 + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, + 0x33, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x1B, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF0, + 0xFF, 0x00, 0x00, 0xE0, 0xFF, // 1115 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 1119 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x1E, 0xC0, 0x00, 0x18, 0x78, 0xC0, 0x00, 0x30, + 0xE0, 0xC1, 0x00, 0x20, 0x80, 0x77, 0x00, 0x20, 0x00, 0x3E, 0x00, 0x20, 0x80, 0x07, 0x00, 0x30, 0xE0, 0x01, 0x00, 0x18, 0x78, + 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x80, 0x01, // 1038 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x18, 0x80, 0xC1, 0x07, 0x18, 0x00, 0x03, 0x3E, 0x1C, 0x00, + 0x02, 0xF8, 0x0F, 0x00, 0x02, 0xF0, 0x03, 0x00, 0x02, 0x7F, 0x00, 0x00, 0xE3, 0x0F, 0x00, 0x80, 0xF9, 0x00, 0x00, 0x00, + 0x18, // 1118 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x3F, // 1032 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x00, 0x00, 0xDC, 0x3B, 0x00, 0x00, 0xF8, 0x1F, 0x00, 0x00, 0x30, 0x0C, 0x00, 0x00, + 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x30, 0x0C, 0x00, 0x00, 0xF8, + 0x1F, 0x00, 0x00, 0xDC, 0x3B, 0x00, 0x00, 0x08, 0x10, // 164 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xFC, 0x01, 0x00, 0x00, 0xFC, + 0x01, // 1168 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xE1, 0x3F, 0x80, 0xFF, 0xE1, 0x3F, // 166 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0xCE, 0x07, 0x03, 0x00, 0x7F, 0x0C, 0x0F, 0x80, 0x33, 0x1C, 0x0C, 0x80, + 0x71, 0x18, 0x18, 0x80, 0x61, 0x30, 0x18, 0x80, 0xC1, 0x70, 0x18, 0x80, 0xC3, 0xE1, 0x1C, 0x00, 0x87, 0xD3, 0x0F, 0x00, 0x06, + 0x9F, 0x07, 0x00, 0x00, 0x0E, // 167 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0xB0, + 0xC1, 0xC0, 0x00, 0xB0, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0xB0, 0xC1, 0xC0, 0x00, 0xB0, 0xC1, + 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0x01, 0xC0, // 1025 + 0x00, 0xE0, 0x03, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0xE7, 0x71, 0x00, 0x00, + 0xFB, 0x67, 0x00, 0x80, 0x19, 0xC6, 0x00, 0x80, 0x0D, 0xCC, 0x00, 0x80, 0x0D, 0xCC, 0x00, 0x80, 0x0D, 0xCC, 0x00, 0x80, 0x0D, + 0xCC, 0x00, 0x80, 0x1D, 0xCE, 0x00, 0x00, 0x1B, 0x66, 0x00, 0x00, 0x17, 0x72, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x1C, 0x1C, + 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xE0, 0x03, // 169 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xCE, 0x3C, 0x00, 0x00, 0xC7, 0x70, 0x00, 0x00, + 0xC3, 0x60, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0x01, + 0xC0, 0x00, 0x80, 0x03, 0xE0, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x0F, 0x78, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x08, + 0x08, // 1028 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0xE0, 0x3D, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, + 0x10, 0x42, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0xE0, 0x3D, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x10, 0x40, // 171 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0xF0, + 0x07, 0x00, 0x00, 0xF0, 0x07, // 172 + 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, // 173 + 0x00, 0xE0, 0x03, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, + 0xFB, 0x6F, 0x00, 0x80, 0xF9, 0xCF, 0x00, 0x80, 0x99, 0xC1, 0x00, 0x80, 0x99, 0xC1, 0x00, 0x80, 0x99, 0xC3, 0x00, 0x80, 0xF9, + 0xC7, 0x00, 0x80, 0xF1, 0xCC, 0x00, 0x00, 0x03, 0x68, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x1C, 0x1C, + 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xE0, 0x03, // 174 + 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x30, // 1031 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80, + 0x20, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x0E, // 176 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, + 0x80, 0xC1, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, + 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, // 177 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1030 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF9, 0xFF, 0x00, 0x80, 0xF9, 0xFF, // 1110 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x80, 0x1F, // 1169 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x1F, 0x00, 0xF8, 0xFF, 0x1F, 0x00, 0x00, 0x60, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 181 + 0x00, 0x3C, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00, 0x80, 0xFF, 0x01, 0x00, 0x80, + 0xFF, 0xFF, 0x1F, 0x80, 0xFF, 0xFF, 0x1F, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x1F, 0x80, 0xFF, + 0xFF, 0x1F, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, // 182 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, // 183 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x73, 0x00, 0x00, 0x3B, 0xE3, 0x00, 0x00, + 0x1B, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x3B, 0xE3, 0x00, 0x00, 0x73, 0x63, 0x00, 0x00, 0xE0, + 0x33, 0x00, 0x00, 0xC0, 0x13, // 1105 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x00, + 0x1C, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, + 0x0E, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x78, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x63, 0x00, 0x00, 0xF0, 0x67, 0x00, 0x00, 0x38, 0x6E, 0x00, 0x00, 0x18, 0x6C, 0x00, + 0x00, 0x18, 0x6C, 0x00, 0x00, 0x38, 0x6E, 0x00, 0x00, 0xF0, 0x67, 0x00, 0x00, 0xE0, 0x63, // 8470 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0x70, 0x73, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, + 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x38, 0x60, 0x00, 0x00, 0x70, 0x78, 0x00, 0x00, 0x60, + 0x18, // 1108 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, + 0xE0, 0x3D, 0x00, 0x00, 0x80, 0x0F, 0x00, 0x00, 0x10, 0x42, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0xE0, 0x3D, 0x00, 0x00, 0x80, + 0x0F, 0x00, 0x00, 0x00, 0x02, // 187 + 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x80, 0xF9, 0xFF, 0x1F, 0x80, 0xF9, 0xFF, 0x0F, // 1112 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x1C, 0x3C, 0x00, 0x00, 0x7F, 0x70, 0x00, 0x00, 0x63, 0x60, 0x00, 0x80, + 0xE1, 0xE0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, + 0xC1, 0x00, 0x80, 0x83, 0xE1, 0x00, 0x00, 0x87, 0x63, 0x00, 0x00, 0x0E, 0x3F, 0x00, 0x00, 0x0C, 0x1E, // 1029 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x30, 0x00, 0x00, 0xF0, 0x71, 0x00, 0x00, 0xB8, 0xE3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, + 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC7, 0x00, 0x00, 0x18, 0xC7, 0x00, 0x00, 0x38, 0xE6, 0x00, 0x00, 0x70, 0x7E, 0x00, 0x00, 0x60, + 0x3C, // 1109 + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, // 1111 + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, + 0x3E, 0x06, 0x00, 0x80, 0x0F, 0x06, 0x00, 0x80, 0x01, 0x06, 0x00, 0x80, 0x0F, 0x06, 0x00, 0x00, 0x3E, 0x06, 0x00, 0x00, 0xF8, + 0x07, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0xC0, // 1040 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, + 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, + 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0x81, 0x61, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x1E, // 1041 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, + 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, + 0xC0, 0x00, 0x00, 0xE3, 0xC1, 0x00, 0x00, 0xFF, 0x61, 0x00, 0x00, 0x1E, 0x7F, 0x00, 0x00, 0x00, 0x1E, // 1042 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, // 1043 + 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0xDF, 0x00, 0x80, 0xFF, 0xC7, 0x00, 0x80, + 0x7F, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, + 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0xC0, + 0x0F, // 1044 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, + 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, + 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0x01, 0xC0, // 1045 + 0x80, 0x01, 0x80, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x00, 0x07, 0x3C, 0x00, 0x00, 0x1E, 0x0E, 0x00, 0x00, + 0x38, 0x07, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0xFF, + 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xE0, 0x03, + 0x00, 0x00, 0x38, 0x07, 0x00, 0x00, 0x1E, 0x0E, 0x00, 0x00, 0x07, 0x3C, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x80, 0x01, 0xC0, 0x00, + 0x80, 0x01, 0x80, // 1046 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x08, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x07, 0x78, 0x00, 0x80, 0x03, 0x60, 0x00, 0x80, + 0x01, 0xE0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x00, 0xE3, + 0xE1, 0x00, 0x00, 0xBF, 0x73, 0x00, 0x00, 0x1C, 0x3F, 0x00, 0x00, 0x00, 0x1E, // 1047 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x38, + 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1048 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x70, 0x00, 0x18, + 0x00, 0x3C, 0x00, 0x30, 0x00, 0x0E, 0x00, 0x20, 0x80, 0x07, 0x00, 0x20, 0xC0, 0x01, 0x00, 0x20, 0xF0, 0x00, 0x00, 0x30, 0x38, + 0x00, 0x00, 0x18, 0x1E, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1049 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x01, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x78, 0x07, 0x00, 0x00, 0x1E, 0x0E, 0x00, 0x00, 0x07, + 0x38, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0x80, // 1050 + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x80, 0xFF, 0x7F, 0x00, 0x80, 0xFF, 0x3F, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1051 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, + 0x3F, 0x00, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x3F, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x80, 0xFF, 0xFF, + 0x00, 0x80, 0xFF, 0xFF, // 1052 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1053 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, + 0x03, 0x60, 0x00, 0x80, 0x03, 0xE0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, + 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x03, 0xE0, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x1E, 0x3C, + 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xF0, 0x07, // 1054 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1055 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, + 0x81, 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x80, 0x81, + 0x01, 0x00, 0x80, 0x81, 0x01, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x3C, // 1056 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, + 0x03, 0x60, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, + 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x0E, 0x3C, 0x00, 0x00, 0x08, + 0x0C, // 1057 + 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, + 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, // 1058 + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x1E, 0xC0, 0x00, 0x00, 0x78, 0xC0, 0x00, 0x00, + 0xE0, 0xC1, 0x00, 0x00, 0x80, 0x77, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x78, + 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x80, 0x01, // 1059 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x03, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0x0C, 0x18, 0x00, 0x00, + 0x0E, 0x38, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x06, 0x30, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x06, + 0x30, 0x00, 0x00, 0x06, 0x30, 0x00, 0x00, 0x0E, 0x38, 0x00, 0x00, 0x0C, 0x18, 0x00, 0x00, 0x1C, 0x1C, 0x00, 0x00, 0xF8, 0x0F, + 0x00, 0x00, 0xE0, 0x03, // 1060 + 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x80, 0x07, 0x78, 0x00, 0x00, 0x0F, 0x1E, 0x00, 0x00, + 0x3C, 0x0F, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x1E, 0x0F, 0x00, 0x00, 0x0F, + 0x1C, 0x00, 0x80, 0x07, 0x78, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x80, 0x00, 0xC0, 0x00, 0x00, 0x00, 0x80, // 1061 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, + 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, + 0x1F, 0x00, 0x00, 0xC0, 0x1F, // 1062 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x80, 0xFF, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x80, + 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1063 + 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0xFF, + 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, + 0xFF, // 1064 + 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0xFF, + 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, + 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xC0, 0x1F, // 1065 + 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x80, + 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, + 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x80, 0x61, + 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x1E, // 1066 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, + 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, + 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x80, 0x61, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1067 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, + 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0xC0, + 0xC0, 0x00, 0x00, 0xC0, 0xC0, 0x00, 0x00, 0x80, 0x61, 0x00, 0x00, 0x80, 0x7F, 0x00, 0x00, 0x00, 0x1E, // 1068 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x0F, 0x78, 0x00, 0x00, 0x03, 0x60, 0x00, 0x80, + 0x03, 0xE0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, 0xC0, 0x00, 0x80, 0xC1, + 0xC0, 0x00, 0x00, 0xC3, 0x60, 0x00, 0x00, 0xC7, 0x70, 0x00, 0x00, 0xCE, 0x38, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xF0, + 0x07, // 1069 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0xF0, 0x07, 0x00, 0x00, 0xFC, 0x1F, 0x00, 0x00, 0x1E, 0x3C, 0x00, 0x00, 0x07, + 0x70, 0x00, 0x00, 0x03, 0x60, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, + 0x00, 0x80, 0x01, 0xC0, 0x00, 0x80, 0x01, 0xC0, 0x00, 0x00, 0x03, 0x60, 0x00, 0x00, 0x07, 0x70, 0x00, 0x00, 0x1E, 0x3C, 0x00, + 0x00, 0xFC, 0x1F, 0x00, 0x00, 0xF0, 0x07, // 1070 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x3E, 0xC0, 0x00, 0x00, 0x7F, 0xF0, 0x00, 0x80, 0x63, 0x7C, 0x00, 0x80, + 0xC1, 0x1E, 0x00, 0x80, 0xC1, 0x0F, 0x00, 0x80, 0xC1, 0x03, 0x00, 0x80, 0xC1, 0x01, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, + 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xC1, 0x00, 0x00, 0x80, 0xFF, 0xFF, 0x00, 0x80, 0xFF, 0xFF, // 1071 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x38, 0x00, 0x00, 0x70, 0x7C, 0x00, 0x00, 0x30, 0xE6, 0x00, 0x00, 0x18, 0xC6, 0x00, 0x00, + 0x18, 0xC6, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x18, 0x63, 0x00, 0x00, 0x38, 0x63, 0x00, 0x00, 0xF0, 0x7F, 0x00, 0x00, 0xE0, + 0xFF, 0x00, 0x00, 0x00, 0x80, // 1072 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xFE, 0x3F, 0x00, 0x00, 0x73, 0x70, 0x00, 0x00, 0x31, 0xE0, 0x00, 0x80, + 0x19, 0xC0, 0x00, 0x80, 0x19, 0xC0, 0x00, 0x80, 0x19, 0xC0, 0x00, 0x80, 0x19, 0xC0, 0x00, 0x80, 0x39, 0xE0, 0x00, 0x80, 0x71, + 0x70, 0x00, 0x80, 0xE1, 0x3F, 0x00, 0x80, 0x80, 0x0F, // 1073 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, + 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0xF0, 0xE7, 0x00, 0x00, 0xF0, + 0x7E, 0x00, 0x00, 0x00, 0x3C, // 1074 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, // 1075 + 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xFC, 0x00, 0x00, 0xF8, 0xDF, 0x00, 0x00, 0xF8, 0xC3, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0xC0, 0x0F, // 1076 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x73, 0x00, 0x00, 0x38, 0xE3, 0x00, 0x00, + 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x38, 0xE3, 0x00, 0x00, 0x70, 0x63, 0x00, 0x00, 0xE0, + 0x33, 0x00, 0x00, 0xC0, 0x13, // 1077 + 0x00, 0x18, 0xE0, 0x00, 0x00, 0x18, 0x70, 0x00, 0x00, 0xF8, 0x38, 0x00, 0x00, 0xE0, 0x0D, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0xE0, + 0x0D, 0x00, 0x00, 0xF8, 0x38, 0x00, 0x00, 0x18, 0x70, 0x00, 0x00, 0x18, 0xE0, 0x00, 0x00, 0x00, 0x80, // 1078 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x30, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, + 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x38, 0xE7, 0x00, 0x00, 0xF0, 0x7F, 0x00, 0x00, 0xE0, 0x3C, // 1079 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, + 0x00, 0x3C, 0x00, 0x00, 0x00, 0x0F, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 1080 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x80, 0x01, 0xF0, 0x00, 0x00, + 0x03, 0x3C, 0x00, 0x00, 0x02, 0x0F, 0x00, 0x00, 0x82, 0x07, 0x00, 0x00, 0xE2, 0x01, 0x00, 0x00, 0x7B, 0x00, 0x00, 0x80, 0xF9, + 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 1081 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x00, 0xC0, 0x0D, 0x00, 0x00, 0xF0, 0x38, 0x00, 0x00, 0x18, 0x70, 0x00, 0x00, 0x18, 0xE0, 0x00, 0x00, 0x00, + 0x80, // 1082 + 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 1083 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, + 0xF0, 0x03, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x80, + 0x1F, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 1084 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 1085 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0xE0, + 0x3F, 0x00, 0x00, 0xC0, 0x1F, // 1086 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, + 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 1087 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x1F, 0x00, 0xF8, 0xFF, 0x1F, 0x00, 0x60, 0x30, 0x00, 0x00, + 0x30, 0x60, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x70, + 0x70, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0xC0, 0x0F, // 1088 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x60, + 0x30, // 1089 + 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, + 0xF8, 0xFF, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, // 1090 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x18, 0x00, 0xC0, 0x07, 0x18, 0x00, 0x00, 0x3E, 0x1C, 0x00, + 0x00, 0xF8, 0x0F, 0x00, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x7F, 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, + 0x18, // 1091 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, + 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x70, 0x60, 0x00, 0x80, 0xFF, 0xFF, 0x1F, 0x80, 0xFF, + 0xFF, 0x1F, 0x00, 0x70, 0x60, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xE0, + 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0xC0, 0x1F, // 1092 + 0x00, 0x08, 0x80, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x78, 0xF0, 0x00, 0x00, 0xE0, 0x38, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, + 0x00, 0x07, 0x00, 0x00, 0x80, 0x1F, 0x00, 0x00, 0xE0, 0x38, 0x00, 0x00, 0x70, 0xF0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x08, + 0x80, // 1093 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x1F, 0x00, 0x00, 0xC0, 0x1F, // 1094 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x01, 0x00, 0x00, 0xF8, 0x07, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, + 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, + 0xFF, // 1095 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 1096 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, + 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, + 0xFF, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0x00, 0x00, 0x00, 0xC0, + 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x1F, 0x00, 0x00, 0xC0, 0x1F, // 1097 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, + 0xF8, 0xFF, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, + 0xC3, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, 0x7E, 0x00, 0x00, 0x00, 0x3C, // 1098 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, + 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, // 1099 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, + 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x00, 0xE7, 0x00, 0x00, 0x00, + 0x7E, 0x00, 0x00, 0x00, 0x3C, // 1100 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x18, 0x00, 0x00, 0x70, 0x78, 0x00, 0x00, 0x38, 0x60, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, + 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x18, 0xC3, 0x00, 0x00, 0x70, 0x73, 0x00, 0x00, 0xE0, 0x7F, 0x00, 0x00, 0xC0, + 0x1F, // 1101 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, + 0x00, 0x03, 0x00, 0x00, 0xC0, 0x1F, 0x00, 0x00, 0xE0, 0x3F, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x18, + 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x18, 0xC0, 0x00, 0x00, 0x38, 0xE0, 0x00, 0x00, 0x70, 0x70, 0x00, 0x00, 0xE0, 0x3F, + 0x00, 0x00, 0xC0, 0x1F, // 1102 + 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xC1, 0x00, 0x00, 0xF0, 0xE3, 0x00, 0x00, 0x38, 0x7B, 0x00, 0x00, 0x18, 0x1A, 0x00, 0x00, + 0x18, 0x0E, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0x18, 0x06, 0x00, 0x00, 0xF8, 0xFF, 0x00, 0x00, 0xF8, + 0xFF, // 1103 }; \ No newline at end of file diff --git a/src/graphics/fonts/OLEDDisplayFontsUA.h b/src/graphics/fonts/OLEDDisplayFontsUA.h index 3bd9bb4ca..dc313aed2 100644 --- a/src/graphics/fonts/OLEDDisplayFontsUA.h +++ b/src/graphics/fonts/OLEDDisplayFontsUA.h @@ -8,4 +8,6 @@ #endif extern const uint8_t ArialMT_Plain_10_UA[] PROGMEM; +extern const uint8_t ArialMT_Plain_16_UA[] PROGMEM; +extern const uint8_t ArialMT_Plain_24_UA[] PROGMEM; #endif \ No newline at end of file diff --git a/src/input/cardKbI2cImpl.cpp b/src/input/cardKbI2cImpl.cpp index b940f5448..eb9b07d6e 100644 --- a/src/input/cardKbI2cImpl.cpp +++ b/src/input/cardKbI2cImpl.cpp @@ -49,10 +49,11 @@ void CardKbI2cImpl::init() kb_model = 0x00; } } - LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x", kb_info.type, kb_model, cardkb_found.address); if (cardkb_found.address == 0x00) { disable(); return; + } else { + LOG_DEBUG("Keyboard Type: 0x%02x Model: 0x%02x Address: 0x%02x", kb_info.type, kb_model, cardkb_found.address); } } #else diff --git a/src/main.cpp b/src/main.cpp index df18dae98..53a662272 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,3 @@ -#include "../userPrefs.h" #include "configuration.h" #if !MESHTASTIC_EXCLUDE_GPS #include "GPS.h" @@ -83,7 +82,7 @@ NRF52Bluetooth *nrf52Bluetooth = nullptr; #include "STM32WLE5JCInterface.h" #endif -#if !HAS_RADIO && defined(ARCH_PORTDUINO) +#if defined(ARCH_PORTDUINO) #include "platform/portduino/SimRadio.h" #endif @@ -150,10 +149,6 @@ ScanI2C::DeviceAddress accelerometer_found = ScanI2C::ADDRESS_NONE; // The I2C address of the RGB LED (if found) ScanI2C::FoundDevice rgb_found = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, ScanI2C::ADDRESS_NONE); -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) -ATECCX08A atecc; -#endif - #ifdef T_WATCH_S3 Adafruit_DRV2605 drv; #endif @@ -572,49 +567,37 @@ void setup() LOG_DEBUG("acc_info = %i", acc_info.type); #endif -#define STRING(S) #S - -#define SCANNER_TO_SENSORS_MAP(SCANNER_T, PB_T) \ - { \ - auto found = i2cScanner->find(SCANNER_T); \ - if (found.type != ScanI2C::DeviceType::NONE) { \ - nodeTelemetrySensorsMap[PB_T].first = found.address.address; \ - nodeTelemetrySensorsMap[PB_T].second = i2cScanner->fetchI2CBus(found.address); \ - LOG_DEBUG("found i2c sensor %s", STRING(PB_T)); \ - } \ - } - - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_3XX, meshtastic_TelemetrySensorType_BMP3XX) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::BMP_085, meshtastic_TelemetrySensorType_BMP085) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::LPS22HB, meshtastic_TelemetrySensorType_LPS22) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC6310, meshtastic_TelemetrySensorType_QMC6310) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::TSL2591, meshtastic_TelemetrySensorType_TSL25911FN) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::OPT3001, meshtastic_TelemetrySensorType_OPT3001) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MLX90632, meshtastic_TelemetrySensorType_MLX90632) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102) - SCANNER_TO_SENSORS_MAP(ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS) + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BME_680, meshtastic_TelemetrySensorType_BME680); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BME_280, meshtastic_TelemetrySensorType_BME280); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_280, meshtastic_TelemetrySensorType_BMP280); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_3XX, meshtastic_TelemetrySensorType_BMP3XX); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::BMP_085, meshtastic_TelemetrySensorType_BMP085); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA260, meshtastic_TelemetrySensorType_INA260); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA219, meshtastic_TelemetrySensorType_INA219); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::INA3221, meshtastic_TelemetrySensorType_INA3221); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX17048, meshtastic_TelemetrySensorType_MAX17048); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MCP9808, meshtastic_TelemetrySensorType_MCP9808); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHT31, meshtastic_TelemetrySensorType_SHT31); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHTC3, meshtastic_TelemetrySensorType_SHTC3); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::LPS22HB, meshtastic_TelemetrySensorType_LPS22); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC6310, meshtastic_TelemetrySensorType_QMC6310); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMI8658, meshtastic_TelemetrySensorType_QMI8658); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::QMC5883L, meshtastic_TelemetrySensorType_QMC5883L); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::HMC5883L, meshtastic_TelemetrySensorType_QMC5883L); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::PMSA0031, meshtastic_TelemetrySensorType_PMSA003I); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::RCWL9620, meshtastic_TelemetrySensorType_RCWL9620); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::VEML7700, meshtastic_TelemetrySensorType_VEML7700); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::TSL2591, meshtastic_TelemetrySensorType_TSL25911FN); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::OPT3001, meshtastic_TelemetrySensorType_OPT3001); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90632, meshtastic_TelemetrySensorType_MLX90632); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MLX90614, meshtastic_TelemetrySensorType_MLX90614); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::SHT4X, meshtastic_TelemetrySensorType_SHT4X); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::AHT10, meshtastic_TelemetrySensorType_AHT10); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::DFROBOT_LARK, meshtastic_TelemetrySensorType_DFROBOT_LARK); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::ICM20948, meshtastic_TelemetrySensorType_ICM20948); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::MAX30102, meshtastic_TelemetrySensorType_MAX30102); + scannerToSensorsMap(i2cScanner, ScanI2C::DeviceType::CGRADSENS, meshtastic_TelemetrySensorType_RADSENS); i2cScanner.reset(); #endif @@ -875,6 +858,51 @@ void setup() LOG_INFO("SX1280 init success"); } } + } else if (settingsMap[use_lr1110]) { + if (!rIf) { + LOG_DEBUG("Activate lr1110 radio on SPI port %s", settingsStrings[spidev].c_str()); + LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); + rIf = new LR1110Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], + settingsMap[busy]); + if (!rIf->init()) { + LOG_WARN("No LR1110 radio"); + delete rIf; + rIf = NULL; + exit(EXIT_FAILURE); + } else { + LOG_INFO("LR1110 init success"); + } + } + } else if (settingsMap[use_lr1120]) { + if (!rIf) { + LOG_DEBUG("Activate lr1120 radio on SPI port %s", settingsStrings[spidev].c_str()); + LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); + rIf = new LR1120Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], + settingsMap[busy]); + if (!rIf->init()) { + LOG_WARN("No LR1120 radio"); + delete rIf; + rIf = NULL; + exit(EXIT_FAILURE); + } else { + LOG_INFO("LR1120 init success"); + } + } + } else if (settingsMap[use_lr1121]) { + if (!rIf) { + LOG_DEBUG("Activate lr1121 radio on SPI port %s", settingsStrings[spidev].c_str()); + LockingArduinoHal *RadioLibHAL = new LockingArduinoHal(SPI, spiSettings); + rIf = new LR1121Interface((LockingArduinoHal *)RadioLibHAL, settingsMap[cs], settingsMap[irq], settingsMap[reset], + settingsMap[busy]); + if (!rIf->init()) { + LOG_WARN("No LR1121 radio"); + delete rIf; + rIf = NULL; + exit(EXIT_FAILURE); + } else { + LOG_INFO("LR1121 init success"); + } + } } else if (settingsMap[use_sx1268]) { if (!rIf) { LOG_DEBUG("Activate sx1268 radio on SPI port %s", settingsStrings[spidev].c_str()); @@ -913,7 +941,7 @@ void setup() } #endif -#if !HAS_RADIO && defined(ARCH_PORTDUINO) +#if defined(ARCH_PORTDUINO) if (!rIf) { rIf = new SimRadio; if (!rIf->init()) { @@ -1192,6 +1220,19 @@ extern meshtastic_DeviceMetadata getDeviceMetadata() #endif return deviceMetadata; } + +#if !MESHTASTIC_EXCLUDE_I2C +void scannerToSensorsMap(const std::unique_ptr &i2cScanner, ScanI2C::DeviceType deviceType, + meshtastic_TelemetrySensorType sensorType) +{ + auto found = i2cScanner->find(deviceType); + if (found.type != ScanI2C::DeviceType::NONE) { + nodeTelemetrySensorsMap[sensorType].first = found.address.address; + nodeTelemetrySensorsMap[sensorType].second = i2cScanner->fetchI2CBus(found.address); + } +} +#endif + #ifndef PIO_UNIT_TESTING void loop() { @@ -1222,4 +1263,4 @@ void loop() mainDelay.delay(delayMsec); } } -#endif \ No newline at end of file +#endif diff --git a/src/main.h b/src/main.h index 5722f7cf0..b3f58ae4b 100644 --- a/src/main.h +++ b/src/main.h @@ -10,9 +10,6 @@ #include "mesh/generated/meshtastic/telemetry.pb.h" #include #include -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) -#include -#endif #if defined(ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32S2) #include "nimble/NimbleBluetooth.h" extern NimbleBluetooth *nimbleBluetooth; @@ -21,6 +18,9 @@ extern NimbleBluetooth *nimbleBluetooth; #include "NRF52Bluetooth.h" extern NRF52Bluetooth *nrf52Bluetooth; #endif +#if !MESHTASTIC_EXCLUDE_I2C +#include "detect/ScanI2CTwoWire.h" +#endif #if ARCH_PORTDUINO extern HardwareSPI *DisplaySPI; @@ -39,10 +39,6 @@ extern bool pmu_found; extern bool isCharging; extern bool isUSBPowered; -#if !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) -extern ATECCX08A atecc; -#endif - #ifdef T_WATCH_S3 #include extern Adafruit_DRV2605 drv; @@ -84,6 +80,10 @@ extern bool pauseBluetoothLogging; void nrf52Setup(), esp32Setup(), nrf52Loop(), esp32Loop(), rp2040Setup(), clearBonds(), enterDfuMode(); meshtastic_DeviceMetadata getDeviceMetadata(); +#if !MESHTASTIC_EXCLUDE_I2C +void scannerToSensorsMap(const std::unique_ptr &i2cScanner, ScanI2C::DeviceType deviceType, + meshtastic_TelemetrySensorType sensorType); +#endif // We default to 4MHz SPI, SPI mode 0 extern SPISettings spiSettings; \ No newline at end of file diff --git a/src/mesh/Channels.cpp b/src/mesh/Channels.cpp index a516268eb..4bdd9e674 100644 --- a/src/mesh/Channels.cpp +++ b/src/mesh/Channels.cpp @@ -1,5 +1,5 @@ #include "Channels.h" -#include "../userPrefs.h" + #include "CryptoEngine.h" #include "Default.h" #include "DisplayFormatters.h" @@ -178,12 +178,11 @@ CryptoKey Channels::getKey(ChannelIndex chIndex) { meshtastic_Channel &ch = getByIndex(chIndex); const meshtastic_ChannelSettings &channelSettings = ch.settings; - assert(ch.has_settings); CryptoKey k; memset(k.bytes, 0, sizeof(k.bytes)); // In case the user provided a short key, we want to pad the rest with zeros - if (ch.role == meshtastic_Channel_Role_DISABLED) { + if (!ch.has_settings || ch.role == meshtastic_Channel_Role_DISABLED) { k.length = -1; // invalid } else { memcpy(k.bytes, channelSettings.psk.bytes, channelSettings.psk.size); diff --git a/src/mesh/Default.cpp b/src/mesh/Default.cpp index ba1dafe70..1bd0340f8 100644 --- a/src/mesh/Default.cpp +++ b/src/mesh/Default.cpp @@ -1,5 +1,5 @@ #include "Default.h" -#include "../userPrefs.h" + #include "meshUtils.h" uint32_t Default::getConfiguredOrDefaultMs(uint32_t configuredInterval, uint32_t defaultInterval) diff --git a/src/mesh/FloodingRouter.cpp b/src/mesh/FloodingRouter.cpp index 81ea72381..e29c596df 100644 --- a/src/mesh/FloodingRouter.cpp +++ b/src/mesh/FloodingRouter.cpp @@ -1,5 +1,5 @@ #include "FloodingRouter.h" -#include "../userPrefs.h" + #include "configuration.h" #include "mesh-pb-constants.h" @@ -36,7 +36,8 @@ bool FloodingRouter::shouldFilterReceived(const meshtastic_MeshPacket *p) if (isRepeated) { LOG_DEBUG("Repeated reliable tx"); if (!perhapsRebroadcast(p) && isToUs(p) && p->want_ack) { - sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, p->channel, 0); + // FIXME - channel index should be used, but the packet is still encrypted here + sendAckNak(meshtastic_Routing_Error_NONE, getFrom(p), p->id, 0, 0); } } diff --git a/src/mesh/MeshService.cpp b/src/mesh/MeshService.cpp index 0100aebe3..82b294852 100644 --- a/src/mesh/MeshService.cpp +++ b/src/mesh/MeshService.cpp @@ -166,27 +166,10 @@ NodeNum MeshService::getNodenumFromRequestId(uint32_t request_id) */ void MeshService::handleToRadio(meshtastic_MeshPacket &p) { -#if defined(ARCH_PORTDUINO) && !HAS_RADIO - // Simulates device received a packet via the LoRa chip - if (p.decoded.portnum == meshtastic_PortNum_SIMULATOR_APP) { - // Simulator packet (=Compressed packet) is encapsulated in a MeshPacket, so need to unwrap first - meshtastic_Compressed scratch; - meshtastic_Compressed *decoded = NULL; - if (p.which_payload_variant == meshtastic_MeshPacket_decoded_tag) { - memset(&scratch, 0, sizeof(scratch)); - p.decoded.payload.size = - pb_decode_from_bytes(p.decoded.payload.bytes, p.decoded.payload.size, &meshtastic_Compressed_msg, &scratch); - if (p.decoded.payload.size) { - decoded = &scratch; - // Extract the original payload and replace - memcpy(&p.decoded.payload, &decoded->data, sizeof(decoded->data)); - // Switch the port from PortNum_SIMULATOR_APP back to the original PortNum - p.decoded.portnum = decoded->portnum; - } else - LOG_ERROR("Error decoding proto for simulator message!"); - } - // Let SimRadio receive as if it did via its LoRa chip - SimRadio::instance->startReceive(&p); +#if defined(ARCH_PORTDUINO) + if (SimRadio::instance && p.decoded.portnum == meshtastic_PortNum_SIMULATOR_APP) { + // Simulates device received a packet via the LoRa chip + SimRadio::instance->unpackAndReceive(p); return; } #endif @@ -271,7 +254,7 @@ bool MeshService::trySendPosition(NodeNum dest, bool wantReplies) assert(node); - if (hasValidPosition(node)) { + if (nodeDB->hasValidPosition(node)) { #if HAS_GPS && !MESHTASTIC_EXCLUDE_GPS if (positionModule) { LOG_INFO("Send position ping to 0x%x, wantReplies=%d, channel=%d", dest, wantReplies, node->channel); diff --git a/src/mesh/MeshService.h b/src/mesh/MeshService.h index 52ba60663..51767e521 100644 --- a/src/mesh/MeshService.h +++ b/src/mesh/MeshService.h @@ -10,7 +10,7 @@ #include "MeshTypes.h" #include "Observer.h" #include "PointerQueue.h" -#if defined(ARCH_PORTDUINO) && !HAS_RADIO +#if defined(ARCH_PORTDUINO) #include "../platform/portduino/SimRadio.h" #endif #if !MESHTASTIC_EXCLUDE_STOREFORWARD diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 07d0d1766..d64f97730 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -1,4 +1,3 @@ -#include "../userPrefs.h" #include "configuration.h" #if !MESHTASTIC_EXCLUDE_GPS #include "GPS.h" @@ -468,7 +467,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false) #endif #if defined(USERPREFS_CONFIG_GPS_MODE) config.position.gps_mode = USERPREFS_CONFIG_GPS_MODE; -#elif !HAS_GPS || defined(T_DECK) || defined(TLORA_T3S3_EPAPER) +#elif !HAS_GPS || GPS_DEFAULT_NOT_PRESENT config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_NOT_PRESENT; #elif !defined(GPS_RX_PIN) if (config.position.rx_gpio == 0) @@ -545,7 +544,7 @@ void NodeDB::initConfigIntervals() config.display.screen_on_secs = default_screen_on_secs; -#if defined(T_WATCH_S3) || defined(T_DECK) || defined(RAK14014) || defined(SENSECAP_INDICATOR) +#if defined(T_WATCH_S3) || defined(T_DECK) || defined(RAK14014) config.power.is_power_saving = true; config.display.screen_on_secs = 30; config.power.wait_bluetooth_secs = 30; @@ -1246,7 +1245,6 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde return false; } - LOG_DEBUG("old user %s/%s, channel=%d", info->user.long_name, info->user.short_name, info->channel); #if !(MESHTASTIC_EXCLUDE_PKI) if (p.public_key.size > 0) { printBytes("Incoming Pubkey: ", p.public_key.bytes, 32); @@ -1270,7 +1268,8 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde } if (nodeId != getNodeNum()) info->channel = channelIndex; // Set channel we need to use to reach this node (but don't set our own channel) - LOG_DEBUG("Update changed=%d user %s/%s, channel=%d", changed, info->user.long_name, info->user.short_name, info->channel); + LOG_DEBUG("Update changed=%d user %s/%s, id=0x%08x, channel=%d", changed, info->user.long_name, info->user.short_name, nodeId, + info->channel); info->has_user = true; if (changed) { @@ -1278,10 +1277,14 @@ bool NodeDB::updateUser(uint32_t nodeId, meshtastic_User &p, uint8_t channelInde powerFSM.trigger(EVENT_NODEDB_UPDATED); notifyObservers(true); // Force an update whether or not our node counts have changed - // We just changed something about the user, store our DB - Throttle::execute( - &lastNodeDbSave, ONE_MINUTE_MS, []() { nodeDB->saveToDisk(SEGMENT_DEVICESTATE); }, - []() { LOG_DEBUG("Defer NodeDB saveToDisk for now"); }); // since we saved less than a minute ago + // We just changed something about a User, + // store our DB unless we just did so less than a minute ago + if (!Throttle::isWithinTimespanMs(lastNodeDbSave, ONE_MINUTE_MS)) { + saveToDisk(SEGMENT_DEVICESTATE); + lastNodeDbSave = millis(); + } else { + LOG_DEBUG("Defer NodeDB saveToDisk for now"); + } } return changed; @@ -1348,7 +1351,7 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n) if (!lite) { if (isFull()) { - LOG_INFO("Node database full with %i nodes and %i bytes free. Erasing oldest entry", numMeshNodes, + LOG_INFO("Node database full with %i nodes and %u bytes free. Erasing oldest entry", numMeshNodes, memGet.getFreeHeap()); // look for oldest node and erase it uint32_t oldest = UINT32_MAX; @@ -1372,11 +1375,14 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n) if (oldestBoringIndex != -1) { oldestIndex = oldestBoringIndex; } - // Shove the remaining nodes down the chain - for (int i = oldestIndex; i < numMeshNodes - 1; i++) { - meshNodes->at(i) = meshNodes->at(i + 1); + + if (oldestIndex != -1) { + // Shove the remaining nodes down the chain + for (int i = oldestIndex; i < numMeshNodes - 1; i++) { + meshNodes->at(i) = meshNodes->at(i + 1); + } + (numMeshNodes)--; } - (numMeshNodes)--; } // add the node at the end lite = &meshNodes->at((numMeshNodes)++); @@ -1384,12 +1390,19 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n) // everything is missing except the nodenum memset(lite, 0, sizeof(*lite)); lite->num = n; - LOG_INFO("Adding node to database with %i nodes and %i bytes free!", numMeshNodes, memGet.getFreeHeap()); + LOG_INFO("Adding node to database with %i nodes and %u bytes free!", numMeshNodes, memGet.getFreeHeap()); } return lite; } +/// Sometimes we will have Position objects that only have a time, so check for +/// valid lat/lon +bool NodeDB::hasValidPosition(const meshtastic_NodeInfoLite *n) +{ + return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0); +} + /// Record an error that should be reported via analytics void recordCriticalError(meshtastic_CriticalErrorCode code, uint32_t address, const char *filename) { diff --git a/src/mesh/NodeDB.h b/src/mesh/NodeDB.h index 2f9980f14..7e51a1240 100644 --- a/src/mesh/NodeDB.h +++ b/src/mesh/NodeDB.h @@ -165,6 +165,8 @@ class NodeDB localPosition = position; } + bool hasValidPosition(const meshtastic_NodeInfoLite *n); + private: uint32_t lastNodeDbSave = 0; // when we last saved our db to flash /// Find a node in our DB, create an empty NodeInfoLite if missing @@ -217,13 +219,6 @@ extern NodeDB *nodeDB; prefs.is_power_saving = True */ -/// Sometimes we will have Position objects that only have a time, so check for -/// valid lat/lon -static inline bool hasValidPosition(const meshtastic_NodeInfoLite *n) -{ - return n->has_position && (n->position.latitude_i != 0 || n->position.longitude_i != 0); -} - /** The current change # for radio settings. Starts at 0 on boot and any time the radio settings * might have changed is incremented. Allows others to detect they might now be on a new channel. */ diff --git a/src/mesh/PhoneAPI.cpp b/src/mesh/PhoneAPI.cpp index 20421e73e..f49718c5e 100644 --- a/src/mesh/PhoneAPI.cpp +++ b/src/mesh/PhoneAPI.cpp @@ -613,13 +613,14 @@ bool PhoneAPI::handleToRadioPacket(meshtastic_MeshPacket &p) { printPacket("PACKET FROM PHONE", &p); -// For use with the simulator, we should not ignore duplicate packets -#if !(defined(ARCH_PORTDUINO) && !HAS_RADIO) - if (p.id > 0 && wasSeenRecently(p.id)) { - LOG_DEBUG("Ignore packet from phone, already seen recently"); - return false; - } +#if defined(ARCH_PORTDUINO) + // For use with the simulator, we should not ignore duplicate packets from the phone + if (SimRadio::instance == nullptr) #endif + if (p.id > 0 && wasSeenRecently(p.id)) { + LOG_DEBUG("Ignore packet from phone, already seen recently"); + return false; + } if (p.decoded.portnum == meshtastic_PortNum_TRACEROUTE_APP && lastPortNumToRadio[p.decoded.portnum] && Throttle::isWithinTimespanMs(lastPortNumToRadio[p.decoded.portnum], THIRTY_SECONDS_MS)) { @@ -656,4 +657,4 @@ int PhoneAPI::onNotify(uint32_t newValue) } return timeout ? -1 : 0; // If we timed out, MeshService should stop iterating through observers as we just removed one -} +} \ No newline at end of file diff --git a/src/mesh/RadioInterface.cpp b/src/mesh/RadioInterface.cpp index 53b66ff0a..5161ac41f 100644 --- a/src/mesh/RadioInterface.cpp +++ b/src/mesh/RadioInterface.cpp @@ -284,8 +284,8 @@ uint32_t RadioInterface::getTxDelayMsecWeighted(float snr) void printPacket(const char *prefix, const meshtastic_MeshPacket *p) { #ifdef DEBUG_PORT - std::string out = DEBUG_PORT.mt_sprintf("%s (id=0x%08x fr=0x%02x to=0x%02x, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id, - p->from & 0xff, p->to & 0xff, p->want_ack, p->hop_limit, p->channel); + std::string out = DEBUG_PORT.mt_sprintf("%s (id=0x%08x fr=0x%08x to=0x%08x, WantAck=%d, HopLim=%d Ch=0x%x", prefix, p->id, + p->from, p->to, p->want_ack, p->hop_limit, p->channel); if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { auto &s = p->decoded; @@ -622,4 +622,4 @@ size_t RadioInterface::beginSending(meshtastic_MeshPacket *p) sendingPacket = p; return p->encrypted.size + sizeof(PacketHeader); -} +} \ No newline at end of file diff --git a/src/mesh/Router.cpp b/src/mesh/Router.cpp index 7b792db30..e714ef215 100644 --- a/src/mesh/Router.cpp +++ b/src/mesh/Router.cpp @@ -6,6 +6,7 @@ #include "NodeDB.h" #include "RTC.h" #include "configuration.h" +#include "detect/LoRaRadioType.h" #include "main.h" #include "mesh-pb-constants.h" #include "meshUtils.h" @@ -20,7 +21,6 @@ #if ENABLE_JSON_LOGGING || ARCH_PORTDUINO #include "serialization/MeshPacketSerializer.h" #endif -#include "../userPrefs.h" #define MAX_RX_FROMRADIO \ 4 // max number of packets destined to our queue, we dispatch packets quickly so it doesn't need to be big @@ -271,6 +271,7 @@ ErrorCode Router::send(meshtastic_MeshPacket *p) auto encodeResult = perhapsEncode(p); if (encodeResult != meshtastic_Routing_Error_NONE) { packetPool.release(p_decoded); + p->channel = 0; // Reset the channel to 0, so we don't use the failing hash again abortSendAndNak(encodeResult, p); return encodeResult; // FIXME - this isn't a valid ErrorCode } @@ -492,6 +493,8 @@ meshtastic_Routing_Error perhapsEncode(meshtastic_MeshPacket *p) // is not in the local nodedb // First, only PKC encrypt packets we are originating if (isFromUs(p) && + // Don't use PKC with simulator + radioType != SIM_RADIO && // Don't use PKC with Ham mode !owner.is_licensed && // Don't use PKC if it's not explicitly requested and a non-primary channel is requested diff --git a/src/mesh/aes-ccm.cpp b/src/mesh/aes-ccm.cpp index b9af14fdb..8bc2989bf 100644 --- a/src/mesh/aes-ccm.cpp +++ b/src/mesh/aes-ccm.cpp @@ -10,7 +10,7 @@ #include "aes-ccm.h" #if !MESHTASTIC_EXCLUDE_PKI -static inline void WPA_PUT_BE16(uint8_t *a, uint16_t val) +static void WPA_PUT_BE16(uint8_t *a, uint16_t val) { a[0] = val >> 8; a[1] = val & 0xff; diff --git a/src/mesh/api/ServerAPI.h b/src/mesh/api/ServerAPI.h index 5b84fddd7..fe6a733a7 100644 --- a/src/mesh/api/ServerAPI.h +++ b/src/mesh/api/ServerAPI.h @@ -2,6 +2,8 @@ #include "StreamAPI.h" +#define SERVER_API_DEFAULT_PORT 4403 + /** * Provides both debug printing and, if the client starts sending protobufs to us, switches to send/receive protobufs * (and starts dropping debug printing - FIXME, eventually those prints should be encapsulated in protobufs). diff --git a/src/mesh/api/WiFiServerAPI.h b/src/mesh/api/WiFiServerAPI.h index 7a3d2967f..6e60bb678 100644 --- a/src/mesh/api/WiFiServerAPI.h +++ b/src/mesh/api/WiFiServerAPI.h @@ -22,5 +22,5 @@ class WiFiServerPort : public APIServerPort explicit WiFiServerPort(int port); }; -void initApiServer(int port = 4403); +void initApiServer(int port = SERVER_API_DEFAULT_PORT); void deInitApiServer(); \ No newline at end of file diff --git a/src/mesh/api/ethServerAPI.h b/src/mesh/api/ethServerAPI.h index 6f214c75a..9d25a2fc1 100644 --- a/src/mesh/api/ethServerAPI.h +++ b/src/mesh/api/ethServerAPI.h @@ -22,4 +22,4 @@ class ethServerPort : public APIServerPort explicit ethServerPort(int port); }; -void initApiServer(int port = 4403); +void initApiServer(int port = SERVER_API_DEFAULT_PORT); diff --git a/src/mesh/generated/meshtastic/mesh.pb.h b/src/mesh/generated/meshtastic/mesh.pb.h index 3e195e7f5..da439c375 100644 --- a/src/mesh/generated/meshtastic/mesh.pb.h +++ b/src/mesh/generated/meshtastic/mesh.pb.h @@ -215,6 +215,11 @@ typedef enum _meshtastic_HardwareModel { /* WisMesh Tap RAK-4631 w/ TFT in injection modled case */ meshtastic_HardwareModel_WISMESH_TAP = 84, + /* Similar to PORTDUINO but used by Routastic devices, this is not any + particular device and does not run Meshtastic's code but supports + the same frame format. + Runs on linux, see https://github.com/Jorropo/routastic */ + meshtastic_HardwareModel_ROUTASTIC = 85, /* ------------------------------------------------------------------------------------------------------------------------------------------ Reserved ID For developing private Ports. These will show up in live traffic sparsely, so we can use a high number. Keep it within 8 bits. ------------------------------------------------------------------------------------------------------------------------------------------ */ @@ -229,7 +234,7 @@ typedef enum _meshtastic_Constants { /* From mesh.options note: this payload length is ONLY the bytes that are sent inside of the Data protobuf (excluding protobuf overhead). The 16 byte header is outside of this envelope */ - meshtastic_Constants_DATA_PAYLOAD_LEN = 237 + meshtastic_Constants_DATA_PAYLOAD_LEN = 233 } meshtastic_Constants; /* Error codes for critical errors @@ -603,7 +608,7 @@ typedef struct _meshtastic_Routing { }; } meshtastic_Routing; -typedef PB_BYTES_ARRAY_T(237) meshtastic_Data_payload_t; +typedef PB_BYTES_ARRAY_T(233) meshtastic_Data_payload_t; /* (Formerly called SubPacket) The payload portion fo a packet, this is the actual bytes that are sent inside a radio packet (because from/to are broken out by the comms library) */ @@ -882,7 +887,7 @@ typedef struct _meshtastic_FileInfo { uint32_t size_bytes; } meshtastic_FileInfo; -typedef PB_BYTES_ARRAY_T(237) meshtastic_Compressed_data_t; +typedef PB_BYTES_ARRAY_T(233) meshtastic_Compressed_data_t; /* Compressed message payload */ typedef struct _meshtastic_Compressed { /* PortNum to determine the how to handle the compressed payload. */ @@ -1730,14 +1735,14 @@ extern const pb_msgdesc_t meshtastic_ChunkedPayloadResponse_msg; #define MESHTASTIC_MESHTASTIC_MESH_PB_H_MAX_SIZE meshtastic_FromRadio_size #define meshtastic_ChunkedPayload_size 245 #define meshtastic_ClientNotification_size 415 -#define meshtastic_Compressed_size 243 -#define meshtastic_Data_size 273 +#define meshtastic_Compressed_size 239 +#define meshtastic_Data_size 269 #define meshtastic_DeviceMetadata_size 54 #define meshtastic_FileInfo_size 236 #define meshtastic_FromRadio_size 510 #define meshtastic_Heartbeat_size 0 #define meshtastic_LogRecord_size 426 -#define meshtastic_MeshPacket_size 375 +#define meshtastic_MeshPacket_size 371 #define meshtastic_MqttClientProxyMessage_size 501 #define meshtastic_MyNodeInfo_size 77 #define meshtastic_NeighborInfo_size 258 diff --git a/src/mesh/generated/meshtastic/storeforward.pb.h b/src/mesh/generated/meshtastic/storeforward.pb.h index 71f2fcad5..44ffd098c 100644 --- a/src/mesh/generated/meshtastic/storeforward.pb.h +++ b/src/mesh/generated/meshtastic/storeforward.pb.h @@ -91,7 +91,7 @@ typedef struct _meshtastic_StoreAndForward_Heartbeat { uint32_t secondary; } meshtastic_StoreAndForward_Heartbeat; -typedef PB_BYTES_ARRAY_T(237) meshtastic_StoreAndForward_text_t; +typedef PB_BYTES_ARRAY_T(233) meshtastic_StoreAndForward_text_t; /* TODO: REPLACE */ typedef struct _meshtastic_StoreAndForward { /* TODO: REPLACE */ @@ -211,7 +211,7 @@ extern const pb_msgdesc_t meshtastic_StoreAndForward_Heartbeat_msg; #define meshtastic_StoreAndForward_Heartbeat_size 12 #define meshtastic_StoreAndForward_History_size 18 #define meshtastic_StoreAndForward_Statistics_size 50 -#define meshtastic_StoreAndForward_size 242 +#define meshtastic_StoreAndForward_size 238 #ifdef __cplusplus } /* extern "C" */ diff --git a/src/mesh/raspihttp/PiWebServer.cpp b/src/mesh/raspihttp/PiWebServer.cpp index f9ba9c235..846d70723 100644 --- a/src/mesh/raspihttp/PiWebServer.cpp +++ b/src/mesh/raspihttp/PiWebServer.cpp @@ -232,9 +232,9 @@ int handleAPIv1ToRadio(const struct _u_request *req, struct _u_response *res, vo ulfius_add_header_to_response(res, "X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/protobufs/master/meshtastic/mesh.proto"); - if (req->http_verb == "OPTIONS") { + if (strcmp(req->http_verb, "OPTIONS") == 0) { ulfius_set_response_properties(res, U_OPT_STATUS, 204); - return U_CALLBACK_CONTINUE; + return U_CALLBACK_COMPLETE; } byte buffer[MAX_TO_FROM_RADIO_SIZE]; @@ -269,6 +269,11 @@ int handleAPIv1FromRadio(const struct _u_request *req, struct _u_response *res, ulfius_add_header_to_response(res, "X-Protobuf-Schema", "https://raw.githubusercontent.com/meshtastic/protobufs/master/meshtastic/mesh.proto"); + if (strcmp(req->http_verb, "OPTIONS") == 0) { + ulfius_set_response_properties(res, U_OPT_STATUS, 204); + return U_CALLBACK_COMPLETE; + } + uint8_t txBuf[MAX_STREAM_BUF_SIZE]; uint32_t len = 1; @@ -493,7 +498,9 @@ PiWebServerThread::PiWebServerThread() // Maximum body size sent by the client is 1 Kb instanceWeb.max_post_body_size = 1024; ulfius_add_endpoint_by_val(&instanceWeb, "GET", PREFIX, "/api/v1/fromradio/*", 1, &handleAPIv1FromRadio, NULL); + ulfius_add_endpoint_by_val(&instanceWeb, "OPTIONS", PREFIX, "/api/v1/fromradio/*", 1, &handleAPIv1FromRadio, NULL); ulfius_add_endpoint_by_val(&instanceWeb, "PUT", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, configWeb.rootPath); + ulfius_add_endpoint_by_val(&instanceWeb, "OPTIONS", PREFIX, "/api/v1/toradio/*", 1, &handleAPIv1ToRadio, NULL); // Add callback function to all endpoints for the Web Server ulfius_add_endpoint_by_val(&instanceWeb, "GET", NULL, "/*", 2, &callback_static_file, &configWeb); diff --git a/src/mesh/wifi/WiFiAPClient.cpp b/src/mesh/wifi/WiFiAPClient.cpp index 779576d64..f9e5d1cc9 100644 --- a/src/mesh/wifi/WiFiAPClient.cpp +++ b/src/mesh/wifi/WiFiAPClient.cpp @@ -62,21 +62,17 @@ static void onNetworkConnected() LOG_INFO("Start WiFi network services"); // start mdns - if ( -#ifdef ARCH_RP2040 - !moduleConfig.mqtt.enabled && // MDNS is not supported when MQTT is enabled on ARCH_RP2040 -#endif - !MDNS.begin("Meshtastic")) { + if (!MDNS.begin("Meshtastic")) { LOG_ERROR("Error setting up MDNS responder!"); } else { LOG_INFO("mDNS Host: Meshtastic.local"); + MDNS.addService("meshtastic", "tcp", SERVER_API_DEFAULT_PORT); #ifdef ARCH_ESP32 MDNS.addService("http", "tcp", 80); MDNS.addService("https", "tcp", 443); + // ESP32 prints obtained IP address in WiFiEvent #elif defined(ARCH_RP2040) - // ARCH_RP2040 does not support HTTPS, create a "meshtastic" service - MDNS.addService("meshtastic", "tcp", 4403); - // ESP32 handles this in WiFiEvent + // ARCH_RP2040 does not support HTTPS LOG_INFO("Obtained IP address: %s", WiFi.localIP().toString().c_str()); #endif } diff --git a/src/modules/AdminModule.cpp b/src/modules/AdminModule.cpp index c81b6ede4..2d33b723d 100644 --- a/src/modules/AdminModule.cpp +++ b/src/modules/AdminModule.cpp @@ -18,7 +18,7 @@ #ifdef ARCH_PORTDUINO #include "unistd.h" #endif -#include "../userPrefs.h" + #include "Default.h" #include "TypeConversions.h" @@ -1123,4 +1123,4 @@ void disableBluetooth() nrf52Bluetooth->shutdown(); #endif #endif -} +} \ No newline at end of file diff --git a/src/modules/ExternalNotificationModule.cpp b/src/modules/ExternalNotificationModule.cpp index 3ec6ff690..bbb3f90e0 100644 --- a/src/modules/ExternalNotificationModule.cpp +++ b/src/modules/ExternalNotificationModule.cpp @@ -124,7 +124,8 @@ int32_t ExternalNotificationModule::runOnce() if (externalTurnedOn[2] + (moduleConfig.external_notification.output_ms ? moduleConfig.external_notification.output_ms : EXT_NOTIFICATION_MODULE_OUTPUT_MS) < millis()) { - LOG_DEBUG("EXTERNAL 2 %d compared to %d", externalTurnedOn[2]+moduleConfig.external_notification.output_ms, millis()); + LOG_DEBUG("EXTERNAL 2 %d compared to %d", externalTurnedOn[2] + moduleConfig.external_notification.output_ms, + millis()); setExternalState(2, !getExternal(2)); } #if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE) diff --git a/src/modules/PositionModule.cpp b/src/modules/PositionModule.cpp index d977cfdec..6285d7aa5 100644 --- a/src/modules/PositionModule.cpp +++ b/src/modules/PositionModule.cpp @@ -389,7 +389,7 @@ int32_t PositionModule::runOnce() } if (lastGpsSend == 0 || msSinceLastSend >= intervalMs) { - if (hasValidPosition(node)) { + if (nodeDB->hasValidPosition(node)) { lastGpsSend = now; lastGpsLatitude = node->position.latitude_i; @@ -403,7 +403,7 @@ int32_t PositionModule::runOnce() } else if (config.position.position_broadcast_smart_enabled) { const meshtastic_NodeInfoLite *node2 = service->refreshLocalMeshNode(); // should guarantee there is now a position - if (hasValidPosition(node2)) { + if (nodeDB->hasValidPosition(node2)) { // The minimum time (in seconds) that would pass before we are able to send a new position packet. auto smartPosition = getDistanceTraveledSinceLastSend(node->position); @@ -464,7 +464,7 @@ void PositionModule::handleNewPosition() meshtastic_NodeInfoLite *node = nodeDB->getMeshNode(nodeDB->getNodeNum()); const meshtastic_NodeInfoLite *node2 = service->refreshLocalMeshNode(); // should guarantee there is now a position // We limit our GPS broadcasts to a max rate - if (hasValidPosition(node2)) { + if (nodeDB->hasValidPosition(node2)) { auto smartPosition = getDistanceTraveledSinceLastSend(node->position); uint32_t msSinceLastSend = millis() - lastGpsSend; if (smartPosition.hasTraveledOverThreshold && @@ -483,4 +483,4 @@ void PositionModule::handleNewPosition() } } -#endif +#endif \ No newline at end of file diff --git a/src/modules/SerialModule.cpp b/src/modules/SerialModule.cpp index 531be274e..bf53b1748 100644 --- a/src/modules/SerialModule.cpp +++ b/src/modules/SerialModule.cpp @@ -205,7 +205,7 @@ int32_t SerialModule::runOnce() uint32_t readIndex = 0; const meshtastic_NodeInfoLite *tempNodeInfo = nodeDB->readNextMeshNode(readIndex); while (tempNodeInfo != NULL) { - if (tempNodeInfo->has_user && hasValidPosition(tempNodeInfo)) { + if (tempNodeInfo->has_user && nodeDB->hasValidPosition(tempNodeInfo)) { printWPL(outbuf, sizeof(outbuf), tempNodeInfo->position, tempNodeInfo->user.long_name, true); serialPrint->printf("%s", outbuf); } @@ -474,7 +474,7 @@ void SerialModule::processWXSerial() if (windDirPos != NULL) { // Extract data after "=" for WindDir strcpy(windDir, windDirPos + 15); // Add 15 to skip "WindDir = " - double radians = toRadians(strtof(windDir, nullptr)); + double radians = GeoCoord::toRadians(strtof(windDir, nullptr)); dir_sum_sin += sin(radians); dir_sum_cos += cos(radians); dirCount++; @@ -541,7 +541,7 @@ void SerialModule::processWXSerial() double avgCos = dir_sum_cos / dirCount; double avgRadians = atan2(avgSin, avgCos); - float dirAvg = toDegrees(avgRadians); + float dirAvg = GeoCoord::toDegrees(avgRadians); if (dirAvg < 0) { dirAvg += 360.0; diff --git a/src/modules/Telemetry/DeviceTelemetry.cpp b/src/modules/Telemetry/DeviceTelemetry.cpp index 4989b88e2..192754e09 100644 --- a/src/modules/Telemetry/DeviceTelemetry.cpp +++ b/src/modules/Telemetry/DeviceTelemetry.cpp @@ -130,6 +130,14 @@ meshtastic_Telemetry DeviceTelemetryModule::getLocalStatsTelemetry() telemetry.variant.local_stats.num_packets_rx_bad = RadioLibInterface::instance->rxBad; telemetry.variant.local_stats.num_tx_relay = RadioLibInterface::instance->txRelay; } +#ifdef ARCH_PORTDUINO + if (SimRadio::instance) { + telemetry.variant.local_stats.num_packets_tx = SimRadio::instance->txGood; + telemetry.variant.local_stats.num_packets_rx = SimRadio::instance->rxGood + SimRadio::instance->rxBad; + telemetry.variant.local_stats.num_packets_rx_bad = SimRadio::instance->rxBad; + telemetry.variant.local_stats.num_tx_relay = SimRadio::instance->txRelay; + } +#endif if (router) { telemetry.variant.local_stats.num_rx_dupe = router->rxDupe; telemetry.variant.local_stats.num_tx_relay_canceled = router->txRelayCanceled; diff --git a/src/modules/WaypointModule.cpp b/src/modules/WaypointModule.cpp index 48e0c4242..b8b738309 100644 --- a/src/modules/WaypointModule.cpp +++ b/src/modules/WaypointModule.cpp @@ -126,7 +126,7 @@ void WaypointModule::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, } // If our node has a position: - if (ourNode && (hasValidPosition(ourNode) || screen->hasHeading())) { + if (ourNode && (nodeDB->hasValidPosition(ourNode) || screen->hasHeading())) { const meshtastic_PositionLite &op = ourNode->position; float myHeading; if (screen->hasHeading()) diff --git a/src/mqtt/MQTT.cpp b/src/mqtt/MQTT.cpp index 3d5948976..967db04d6 100644 --- a/src/mqtt/MQTT.cpp +++ b/src/mqtt/MQTT.cpp @@ -167,17 +167,26 @@ void MQTT::onReceive(char *topic, byte *payload, size_t length) if (isFromUs(p)) { LOG_INFO("Ignore downlink message we originally sent"); packetPool.release(p); + free(e.channel_id); + free(e.gateway_id); + free(e.packet); return; } if (p->which_payload_variant == meshtastic_MeshPacket_decoded_tag) { if (moduleConfig.mqtt.encryption_enabled) { LOG_INFO("Ignore decoded message on MQTT, encryption is enabled"); packetPool.release(p); + free(e.channel_id); + free(e.gateway_id); + free(e.packet); return; } if (p->decoded.portnum == meshtastic_PortNum_ADMIN_APP) { LOG_INFO("Ignore decoded admin packet"); packetPool.release(p); + free(e.channel_id); + free(e.gateway_id); + free(e.packet); return; } p->channel = ch.index; @@ -336,7 +345,7 @@ void MQTT::reconnect() mqttPassword = moduleConfig.mqtt.password; } #if HAS_WIFI && !defined(ARCH_PORTDUINO) -#if !defined(CONFIG_IDF_TARGET_ESP32C6) && !defined(RPI_PICO) +#if !defined(CONFIG_IDF_TARGET_ESP32C6) if (moduleConfig.mqtt.tls_enabled) { // change default for encrypted to 8883 try { @@ -771,4 +780,4 @@ bool MQTT::isPrivateIpAddress(const char address[]) int octet2Num = atoi(octet2); return octet2Num >= 16 && octet2Num <= 31; -} \ No newline at end of file +} diff --git a/src/mqtt/MQTT.h b/src/mqtt/MQTT.h index fcefb94a2..7e0378238 100644 --- a/src/mqtt/MQTT.h +++ b/src/mqtt/MQTT.h @@ -35,7 +35,7 @@ class MQTT : private concurrency::OSThread #if HAS_WIFI WiFiClient mqttClient; #if !defined(ARCH_PORTDUINO) -#if defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR < 3 +#if (defined(ESP_ARDUINO_VERSION_MAJOR) && ESP_ARDUINO_VERSION_MAJOR < 3) || defined(RPI_PICO) WiFiClientSecure wifiSecureClient; #endif #endif @@ -130,4 +130,4 @@ class MQTT : private concurrency::OSThread void mqttInit(); -extern MQTT *mqtt; \ No newline at end of file +extern MQTT *mqtt; diff --git a/src/platform/portduino/PortduinoGlue.cpp b/src/platform/portduino/PortduinoGlue.cpp index 686564cc1..b6a017d9f 100644 --- a/src/platform/portduino/PortduinoGlue.cpp +++ b/src/platform/portduino/PortduinoGlue.cpp @@ -5,21 +5,27 @@ #include "sleep.h" #include "target_specific.h" +#include "PortduinoGlue.h" +#include "api/ServerAPI.h" +#include "linux/gpio/LinuxGPIOPin.h" +#include "meshUtils.h" +#include "yaml-cpp/yaml.h" #include #include - -#include "PortduinoGlue.h" -#include "linux/gpio/LinuxGPIOPin.h" -#include "yaml-cpp/yaml.h" +#include +#include #include +#include #include #include +#include #include std::map settingsMap; std::map settingsStrings; std::ofstream traceFile; char *configPath = nullptr; +char *optionMac = nullptr; // FIXME - move setBluetoothEnable into a HALPlatform class void setBluetoothEnable(bool enable) @@ -34,7 +40,7 @@ void cpuDeepSleep(uint32_t msecs) void updateBatteryLevel(uint8_t level) NOT_IMPLEMENTED("updateBatteryLevel"); -int TCPPort = 4403; +int TCPPort = SERVER_API_DEFAULT_PORT; static error_t parse_opt(int key, char *arg, struct argp_state *state) { @@ -48,6 +54,10 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) case 'c': configPath = arg; break; + case 'h': + optionMac = arg; + break; + case ARGP_KEY_ARG: return 0; default: @@ -60,6 +70,7 @@ void portduinoCustomInit() { static struct argp_option options[] = {{"port", 'p', "PORT", 0, "The TCP port to use."}, {"config", 'c', "CONFIG_PATH", 0, "Full path of the .yaml config file to use."}, + {"hwid", 'h', "HWID", 0, "The mac address to assign to this virtual machine"}, {0}}; static void *childArguments; static char doc[] = "Meshtastic native build."; @@ -69,6 +80,51 @@ void portduinoCustomInit() portduinoAddArguments(child, childArguments); } +void getMacAddr(uint8_t *dmac) +{ + // We should store this value, and short-circuit all this if it's already been set. + if (optionMac != nullptr && strlen(optionMac) > 0) { + if (strlen(optionMac) >= 12) { + MAC_from_string(optionMac, dmac); + std::cout << optionMac << std::endl; + } else { + uint32_t hwId = sscanf(optionMac, "%u", &hwId); + dmac[0] = 0x80; + dmac[1] = 0; + dmac[2] = hwId >> 24; + dmac[3] = hwId >> 16; + dmac[4] = hwId >> 8; + dmac[5] = hwId & 0xff; + } + } else if (settingsStrings[mac_address].length() > 11) { + MAC_from_string(settingsStrings[mac_address], dmac); + std::cout << settingsStrings[mac_address] << std::endl; + exit; + } else { + + struct hci_dev_info di; + di.dev_id = 0; + bdaddr_t bdaddr; + char addr[18]; + int btsock; + btsock = socket(AF_BLUETOOTH, SOCK_RAW, 1); + if (btsock < 0) { // If anything fails, just return with the default value + return; + } + + if (ioctl(btsock, HCIGETDEVINFO, (void *)&di)) { + return; + } + + dmac[0] = di.bdaddr.b[5]; + dmac[1] = di.bdaddr.b[4]; + dmac[2] = di.bdaddr.b[3]; + dmac[3] = di.bdaddr.b[2]; + dmac[4] = di.bdaddr.b[1]; + dmac[5] = di.bdaddr.b[0]; + } +} + /** apps run under portduino can optionally define a portduinoSetup() to * use portduino specific init code (such as gpioBind) to setup portduino on their host machine, * before running 'arduino' code. @@ -113,10 +169,20 @@ void portduinoSetup() std::cout << "Unable to use " << configPath << " as config file" << std::endl; exit(EXIT_FAILURE); } - } else if (access("config.yaml", R_OK) == 0 && loadConfig("config.yaml")) { - std::cout << "Using local config.yaml as config file" << std::endl; - } else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0 && loadConfig("/etc/meshtasticd/config.yaml")) { - std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl; + } else if (access("config.yaml", R_OK) == 0) { + if (loadConfig("config.yaml")) { + std::cout << "Using local config.yaml as config file" << std::endl; + } else { + std::cout << "Unable to use local config.yaml as config file" << std::endl; + exit(EXIT_FAILURE); + } + } else if (access("/etc/meshtasticd/config.yaml", R_OK) == 0) { + if (loadConfig("/etc/meshtasticd/config.yaml")) { + std::cout << "Using /etc/meshtasticd/config.yaml as config file" << std::endl; + } else { + std::cout << "Unable to use /etc/meshtasticd/config.yaml as config file" << std::endl; + exit(EXIT_FAILURE); + } } else { std::cout << "No 'config.yaml' found, running simulated." << std::endl; settingsMap[maxnodes] = 200; // Default to 200 nodes @@ -137,6 +203,14 @@ void portduinoSetup() } } + uint8_t dmac[6]; + getMacAddr(dmac); + if (dmac[0] == 0 && dmac[1] == 0 && dmac[2] == 0 && dmac[3] == 0 && dmac[4] == 0 && dmac[5] == 0) { + std::cout << "*** Blank MAC Address not allowed!" << std::endl; + std::cout << "Please set a MAC Address in config.yaml using either MACAddress or MACAddressSource." << std::endl; + exit(EXIT_FAILURE); + } + printBytes("MAC Address: ", dmac, 6); // Rather important to set this, if not running simulated. randomSeed(time(NULL)); @@ -272,6 +346,9 @@ bool loadConfig(const char *configPath) settingsMap[use_sx1262] = false; settingsMap[use_rf95] = false; settingsMap[use_sx1280] = false; + settingsMap[use_lr1110] = false; + settingsMap[use_lr1120] = false; + settingsMap[use_lr1121] = false; settingsMap[use_sx1268] = false; if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1262") { @@ -280,6 +357,12 @@ bool loadConfig(const char *configPath) settingsMap[use_rf95] = true; } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1280") { settingsMap[use_sx1280] = true; + } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "lr1110") { + settingsMap[use_lr1110] = true; + } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "lr1120") { + settingsMap[use_lr1120] = true; + } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "lr1121") { + settingsMap[use_lr1121] = true; } else if (yamlConfig["Lora"]["Module"] && yamlConfig["Lora"]["Module"].as("") == "sx1268") { settingsMap[use_sx1268] = true; } @@ -404,8 +487,23 @@ bool loadConfig(const char *configPath) settingsMap[maxnodes] = (yamlConfig["General"]["MaxNodes"]).as(200); settingsMap[maxtophone] = (yamlConfig["General"]["MaxMessageQueue"]).as(100); settingsStrings[config_directory] = (yamlConfig["General"]["ConfigDirectory"]).as(""); - } + if ((yamlConfig["General"]["MACAddress"]).as("") != "" && + (yamlConfig["General"]["MACAddressSource"]).as("") != "") { + std::cout << "Cannot set both MACAddress and MACAddressSource!" << std::endl; + exit(EXIT_FAILURE); + } + settingsStrings[mac_address] = (yamlConfig["General"]["MACAddress"]).as(""); + if ((yamlConfig["General"]["MACAddressSource"]).as("") != "") { + std::ifstream infile("/sys/class/net/" + (yamlConfig["General"]["MACAddressSource"]).as("") + + "/address"); + std::getline(infile, settingsStrings[mac_address]); + } + // https://stackoverflow.com/a/20326454 + settingsStrings[mac_address].erase( + std::remove(settingsStrings[mac_address].begin(), settingsStrings[mac_address].end(), ':'), + settingsStrings[mac_address].end()); + } } catch (YAML::Exception &e) { std::cout << "*** Exception " << e.what() << std::endl; return false; @@ -417,4 +515,20 @@ bool loadConfig(const char *configPath) static bool ends_with(std::string_view str, std::string_view suffix) { return str.size() >= suffix.size() && str.compare(str.size() - suffix.size(), suffix.size(), suffix) == 0; +} + +bool MAC_from_string(std::string mac_str, uint8_t *dmac) +{ + mac_str.erase(std::remove(mac_str.begin(), mac_str.end(), ':'), mac_str.end()); + if (mac_str.length() == 12) { + dmac[0] = std::stoi(settingsStrings[mac_address].substr(0, 2), nullptr, 16); + dmac[1] = std::stoi(settingsStrings[mac_address].substr(2, 2), nullptr, 16); + dmac[2] = std::stoi(settingsStrings[mac_address].substr(4, 2), nullptr, 16); + dmac[3] = std::stoi(settingsStrings[mac_address].substr(6, 2), nullptr, 16); + dmac[4] = std::stoi(settingsStrings[mac_address].substr(8, 2), nullptr, 16); + dmac[5] = std::stoi(settingsStrings[mac_address].substr(10, 2), nullptr, 16); + return true; + } else { + return false; + } } \ No newline at end of file diff --git a/src/platform/portduino/PortduinoGlue.h b/src/platform/portduino/PortduinoGlue.h index 95d82c1a2..01541eeed 100644 --- a/src/platform/portduino/PortduinoGlue.h +++ b/src/platform/portduino/PortduinoGlue.h @@ -16,6 +16,9 @@ enum configNames { ch341Quirk, use_rf95, use_sx1280, + use_lr1110, + use_lr1120, + use_lr1121, use_sx1268, user, gpiochip, @@ -56,7 +59,8 @@ enum configNames { maxtophone, maxnodes, ascii_logs, - config_directory + config_directory, + mac_address }; enum { no_screen, x11, st7789, st7735, st7735s, st7796, ili9341, ili9342, ili9488, hx8357d }; enum { no_touchscreen, xpt2046, stmpe610, gt911, ft5x06 }; @@ -67,4 +71,6 @@ extern std::map settingsStrings; extern std::ofstream traceFile; int initGPIOPin(int pinNum, std::string gpioChipname); bool loadConfig(const char *configPath); -static bool ends_with(std::string_view str, std::string_view suffix); \ No newline at end of file +static bool ends_with(std::string_view str, std::string_view suffix); +void getMacAddr(uint8_t *dmac); +bool MAC_from_string(std::string mac_str, uint8_t *dmac); \ No newline at end of file diff --git a/src/platform/portduino/SimRadio.cpp b/src/platform/portduino/SimRadio.cpp index 0a77b6088..7e63b995e 100644 --- a/src/platform/portduino/SimRadio.cpp +++ b/src/platform/portduino/SimRadio.cpp @@ -73,6 +73,10 @@ void SimRadio::handleTransmitInterrupt() // ignore the transmit interrupt if (sendingPacket) completeSending(); + + isReceiving = true; + if (receivingPacket) // This happens when we don't consider something a collision if we weren't sending long enough + handleReceiveInterrupt(); } void SimRadio::completeSending() @@ -84,6 +88,8 @@ void SimRadio::completeSending() if (p) { txGood++; + if (!isFromUs(p)) + txRelay++; printPacket("Completed sending", p); // We are done sending that packet, release it @@ -113,12 +119,12 @@ bool SimRadio::canSendImmediately() bool SimRadio::isActivelyReceiving() { - return false; // TODO check how this should be simulated + return receivingPacket != nullptr; } bool SimRadio::isChannelActive() { - return false; // TODO ask simulator + return receivingPacket != nullptr; } /** Attempt to cancel a previously sent packet. Returns true if a packet was found we could cancel */ @@ -142,10 +148,16 @@ void SimRadio::onNotify(uint32_t notification) startTransmitTimer(); break; case ISR_RX: + handleReceiveInterrupt(); // LOG_DEBUG("rx complete - starting timer"); startTransmitTimer(); break; case TRANSMIT_DELAY_COMPLETED: + if (receivingPacket) { // This happens when we had a timer pending and we started receiving + handleReceiveInterrupt(); + startTransmitTimer(); + break; + } LOG_DEBUG("delay done"); // If we are not currently in receive mode, then restart the random delay (this can happen if the main thread @@ -183,6 +195,7 @@ void SimRadio::onNotify(uint32_t notification) void SimRadio::startSend(meshtastic_MeshPacket *txp) { printPacket("Start low level send", txp); + isReceiving = false; size_t numbytes = beginSending(txp); meshtastic_MeshPacket *p = packetPool.allocCopy(*txp); perhapsDecode(p); @@ -201,15 +214,64 @@ void SimRadio::startSend(meshtastic_MeshPacket *txp) service->sendQueueStatusToPhone(router->getQueueStatus(), 0, p->id); service->sendToPhone(p); // Sending back to simulator + service->loop(); // Process the send immediately +} + +// Simulates device received a packet via the LoRa chip +void SimRadio::unpackAndReceive(meshtastic_MeshPacket &p) +{ + // Simulator packet (=Compressed packet) is encapsulated in a MeshPacket, so need to unwrap first + meshtastic_Compressed scratch; + meshtastic_Compressed *decoded = NULL; + if (p.which_payload_variant == meshtastic_MeshPacket_decoded_tag) { + memset(&scratch, 0, sizeof(scratch)); + p.decoded.payload.size = + pb_decode_from_bytes(p.decoded.payload.bytes, p.decoded.payload.size, &meshtastic_Compressed_msg, &scratch); + if (p.decoded.payload.size) { + decoded = &scratch; + // Extract the original payload and replace + memcpy(&p.decoded.payload, &decoded->data, sizeof(decoded->data)); + // Switch the port from PortNum_SIMULATOR_APP back to the original PortNum + p.decoded.portnum = decoded->portnum; + } else + LOG_ERROR("Error decoding proto for simulator message!"); + } + // Let SimRadio receive as if it did via its LoRa chip + startReceive(&p); } void SimRadio::startReceive(meshtastic_MeshPacket *p) { +#ifdef USERPREFS_SIMRADIO_EMULATE_COLLISIONS + if (isActivelyReceiving()) { + LOG_WARN("Collision detected, dropping current and previous packet!"); + rxBad++; + airTime->logAirtime(RX_ALL_LOG, getPacketTime(receivingPacket)); + packetPool.release(receivingPacket); + receivingPacket = nullptr; + return; + } else if (sendingPacket) { + uint32_t airtimeLeft = tillRun(millis()); + if (airtimeLeft <= 0) { + LOG_WARN("Transmitting packet was already done"); + handleTransmitInterrupt(); // Finish sending first + } else if ((interval - airtimeLeft) > preambleTimeMsec) { + // Only if transmitting for longer than preamble there is a collision + // (channel should actually be detected as active otherwise) + LOG_WARN("Collision detected during transmission!"); + return; + } + } isReceiving = true; - size_t length = getPacketLength(p); - uint32_t xmitMsec = getPacketTime(length); - delay(xmitMsec); // Model the time it is busy receiving - handleReceiveInterrupt(p); + receivingPacket = packetPool.allocCopy(*p); + uint32_t airtimeMsec = getPacketTime(p); + notifyLater(airtimeMsec, ISR_RX, false); // Model the time it is busy receiving +#else + isReceiving = true; + receivingPacket = packetPool.allocCopy(*p); + handleReceiveInterrupt(); // Simulate receiving the packet immediately + startTransmitTimer(); +#endif } meshtastic_QueueStatus SimRadio::getQueueStatus() @@ -223,28 +285,27 @@ meshtastic_QueueStatus SimRadio::getQueueStatus() return qs; } -void SimRadio::handleReceiveInterrupt(meshtastic_MeshPacket *p) +void SimRadio::handleReceiveInterrupt() { - LOG_DEBUG("HANDLE RECEIVE INTERRUPT"); - uint32_t xmitMsec; + if (receivingPacket == nullptr) { + return; + } if (!isReceiving) { LOG_DEBUG("*** WAS_ASSERT *** handleReceiveInterrupt called when not in receive mode"); return; } - isReceiving = false; + LOG_DEBUG("HANDLE RECEIVE INTERRUPT"); + rxGood++; - // read the number of actually received bytes - size_t length = getPacketLength(p); - xmitMsec = getPacketTime(length); - // LOG_DEBUG("Payload size %d vs length (includes header) %d", p->decoded.payload.size, length); - - meshtastic_MeshPacket *mp = packetPool.allocCopy(*p); // keep a copy in packetPool + meshtastic_MeshPacket *mp = packetPool.allocCopy(*receivingPacket); // keep a copy in packetPool + packetPool.release(receivingPacket); // release the original + receivingPacket = nullptr; printPacket("Lora RX", mp); - airTime->logAirtime(RX_LOG, xmitMsec); + airTime->logAirtime(RX_LOG, getPacketTime(mp)); deliverToReceiver(mp); } @@ -265,4 +326,4 @@ int16_t SimRadio::readData(uint8_t *data, size_t len) } return state; -} +} \ No newline at end of file diff --git a/src/platform/portduino/SimRadio.h b/src/platform/portduino/SimRadio.h index 1edb4963b..c082444e5 100644 --- a/src/platform/portduino/SimRadio.h +++ b/src/platform/portduino/SimRadio.h @@ -11,11 +11,6 @@ class SimRadio : public RadioInterface, protected concurrency::NotifiedWorkerThr { enum PendingISR { ISR_NONE = 0, ISR_RX, ISR_TX, TRANSMIT_DELAY_COMPLETED }; - /** - * Debugging counts - */ - uint32_t rxBad = 0, rxGood = 0, txGood = 0; - MeshPacketQueue txQueue = MeshPacketQueue(MAX_TX_QUEUE); public: @@ -47,9 +42,17 @@ class SimRadio : public RadioInterface, protected concurrency::NotifiedWorkerThr meshtastic_QueueStatus getQueueStatus() override; + // Convert Compressed_msg to normal msg and receive it + void unpackAndReceive(meshtastic_MeshPacket &p); + + /** + * Debugging counts + */ + uint32_t rxBad = 0, rxGood = 0, txGood = 0, txRelay = 0; + protected: /// are _trying_ to receive a packet currently (note - we might just be waiting for one) - bool isReceiving = false; + bool isReceiving = true; private: void setTransmitDelay(); @@ -61,7 +64,7 @@ class SimRadio : public RadioInterface, protected concurrency::NotifiedWorkerThr void startTransmitTimerSNR(float snr); void handleTransmitInterrupt(); - void handleReceiveInterrupt(meshtastic_MeshPacket *p); + void handleReceiveInterrupt(); void onNotify(uint32_t notification); @@ -73,6 +76,8 @@ class SimRadio : public RadioInterface, protected concurrency::NotifiedWorkerThr int16_t readData(uint8_t *str, size_t len); + meshtastic_MeshPacket *receivingPacket = nullptr; // The packet we are currently receiving + protected: /** Could we send right now (i.e. either not actively receiving or transmitting)? */ virtual bool canSendImmediately(); diff --git a/src/platform/portduino/architecture.h b/src/platform/portduino/architecture.h index 321949226..3dde87199 100644 --- a/src/platform/portduino/architecture.h +++ b/src/platform/portduino/architecture.h @@ -11,6 +11,9 @@ #ifndef HAS_WIFI #define HAS_WIFI 1 #endif +#ifndef HAS_RADIO +#define HAS_RADIO 1 +#endif #ifndef HAS_RTC #define HAS_RTC 1 #endif diff --git a/src/sleep.cpp b/src/sleep.cpp index 05597cdfa..69eb0349a 100644 --- a/src/sleep.cpp +++ b/src/sleep.cpp @@ -336,6 +336,12 @@ esp_sleep_wakeup_cause_t doLightSleep(uint64_t sleepMsec) // FIXME, use a more r { // LOG_DEBUG("Enter light sleep"); + // LORA_DIO1 is an extended IO pin. Setting it as a wake-up pin will cause problems, such as the indicator device not entering + // LightSleep. +#if defined(SENSECAP_INDICATOR) + return ESP_SLEEP_WAKEUP_TIMER; +#endif + waitEnterSleep(false); uint64_t sleepUsec = sleepMsec * 1000LL; diff --git a/userPrefs.h b/userPrefs.h deleted file mode 100644 index 00f04149a..000000000 --- a/userPrefs.h +++ /dev/null @@ -1,107 +0,0 @@ -#ifndef _USERPREFS_ -#define _USERPREFS_ - -// Slipstream values: - -#define USERPREFS_TZ_STRING "tzplaceholder " - -// Uncomment and modify to set device defaults - -// #define USERPREFS_EVENT_MODE 1 - -// #define USERPREFS_CONFIG_LORA_REGION meshtastic_Config_LoRaConfig_RegionCode_US -// #define USERPREFS_LORACONFIG_MODEM_PRESET meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST -// #define USERPREFS_LORACONFIG_CHANNEL_NUM 31 -// #define USERPREFS_CONFIG_LORA_IGNORE_MQTT true - -// #define USERPREFS_CONFIG_GPS_MODE meshtastic_Config_PositionConfig_GpsMode_ENABLED - -// #define USERPREFS_CHANNELS_TO_WRITE 3 -/* -#define USERPREFS_CHANNEL_0_PSK \ - { \ - 0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36, 0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, \ - 0xbf, 0x74, 0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa1 \ - } -*/ -// #define USERPREFS_CHANNEL_0_NAME "DEFCONnect" -// #define USERPREFS_CHANNEL_0_PRECISION 14 -// #define USERPREFS_CHANNEL_0_UPLINK_ENABLED true -// #define USERPREFS_CHANNEL_0_DOWNLINK_ENABLED true -/* -#define USERPREFS_CHANNEL_1_PSK \ - { \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \ - } -*/ -// #define USERPREFS_CHANNEL_1_NAME "REPLACEME" -// #define USERPREFS_CHANNEL_1_PRECISION 14 -// #define USERPREFS_CHANNEL_1_UPLINK_ENABLED true -// #define USERPREFS_CHANNEL_1_DOWNLINK_ENABLED true -/* -#define USERPREFS_CHANNEL_2_PSK \ - { \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 \ - } -*/ -// #define USERPREFS_CHANNEL_2_NAME "REPLACEME" -// #define USERPREFS_CHANNEL_2_PRECISION 14 -// #define USERPREFS_CHANNEL_2_UPLINK_ENABLED true -// #define USERPREFS_CHANNEL_2_DOWNLINK_ENABLED true - -// #define USERPREFS_CONFIG_OWNER_LONG_NAME "My Long Name" -// #define USERPREFS_CONFIG_OWNER_SHORT_NAME "MLN" - -// #define USERPREFS_SPLASH_TITLE "DEFCONtastic" -// #define icon_width 34 -// #define icon_height 29 -// #define USERPREFS_HAS_SPLASH -/* -static unsigned char icon_bits[] = { - 0x00, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0xF8, 0x7F, 0x00, 0x00, 0x00, 0xFC, 0xFF, 0x00, 0x00, 0x00, - 0x9E, 0xE7, 0x00, 0x00, 0x00, 0x0E, 0xC7, 0x01, 0x00, 0x1C, 0x0F, 0xC7, 0x01, 0x00, 0x1C, 0xDF, 0xE7, 0x63, 0x00, 0x1C, 0xFF, - 0xBF, 0xE1, 0x00, 0x3C, 0xF3, 0xBF, 0xE3, 0x00, 0x7F, 0xF7, 0xBF, 0xF1, 0x00, 0xFF, 0xF7, 0xBF, 0xF9, 0x03, 0xFF, 0xE7, 0x9F, - 0xFF, 0x03, 0xC0, 0xCF, 0xEF, 0xDF, 0x03, 0x00, 0xDF, 0xE3, 0x8F, 0x00, 0x00, 0x7C, 0xFB, 0x03, 0x00, 0x00, 0xF8, 0xFF, 0x00, - 0x00, 0x00, 0xE0, 0x0F, 0x00, 0x00, 0x00, 0xC0, 0x0F, 0x00, 0x00, 0x00, 0x78, 0x3F, 0x00, 0x00, 0x00, 0xFC, 0xFC, 0x00, 0x00, - 0x98, 0x3F, 0xF0, 0x23, 0x00, 0xFC, 0x0F, 0xE0, 0x7F, 0x00, 0xFC, 0x03, 0x80, 0xFF, 0x01, 0xFC, 0x00, 0x00, 0x3E, 0x00, 0x70, - 0x00, 0x00, 0x1C, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00, 0x70, 0x00, 0x00, 0x1C, 0x00}; -*/ - -/* - * PKI Admin keys. - * If a Admin key is set with '{};' - * then it will be ignored, a PKI key must have a size of 32 byte. - */ -/* -#define USERPREFS_USE_ADMIN_KEY_0 \ - { \ - 0xcd, 0xc0, 0xb4, 0x3c, 0x53, 0x24, 0xdf, 0x13, 0xca, 0x5a, 0xa6, 0x0c, 0x0d, 0xec, 0x85, 0x5a, 0x4c, 0xf6, 0x1a, 0x96, \ - 0x04, 0x1a, 0x3e, 0xfc, 0xbb, 0x8e, 0x33, 0x71, 0xe5, 0xfc, 0xff, 0x3c \ - }; -*/ -// #define USERPREFS_USE_ADMIN_KEY_1 {}; -// #define USERPREFS_USE_ADMIN_KEY_2 {}; - -/* - * USERPREF_FIXED_GPS_LAT and USERPREF_FIXED_GPS_LON must be set, USERPREF_FIXED_GPS_ALT is optional - * - * Fixed GPS is Eiffel Tower, Paris, France - */ -// #define USERPREFS_FIXED_GPS -// #define USERPREFS_FIXED_GPS_LAT 48.85873920 -// #define USERPREFS_FIXED_GPS_LON 2.294508368 -// #define USERPREFS_FIXED_GPS_ALT 0 - -/* - * Set Fixed Bluetooth paring code - */ -// #define USERPREFS_FIXED_BLUETOOTH 121212 - -/* - * Will overwrite BUTTON_PIN if set - */ -// #define USERPREFS_BUTTON_PIN 36 - -#endif \ No newline at end of file diff --git a/userPrefs.json b/userPrefs.json deleted file mode 100644 index bc62602be..000000000 --- a/userPrefs.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "USERPREFS_CHANNEL_0_NAME": "\"DEFCONnect\"", - "USERPREFS_CHANNEL_0_PRECISION": "14", - "USERPREFS_CHANNEL_0_PSK": "{ 0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36, 0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74, 0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa1 }", - "USERPREFS_CONFIG_LORA_IGNORE_MQTT": "true", - "USERPREFS_CONFIG_LORA_REGION": "meshtastic_Config_LoRaConfig_RegionCode_US", - "USERPREFS_CONFIG_OWNER_LONG_NAME": "\"My Long Name\"", - "USERPREFS_CONFIG_OWNER_SHORT_NAME": "\"MLN\"", - "USERPREFS_EVENT_MODE": "1", - "USERPREFS_HAS_SPLASH": "", - "USERPREFS_LORACONFIG_CHANNEL_NUM": "31", - "USERPREFS_LORACONFIG_MODEM_PRESET": "meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST", - "USERPREFS_SPLASH_TITLE": "\"DEFCONtastic\"", - "USERPREFS_TZ_STRING": "\"tzplaceholder \"", - "USERPREFS_USE_ADMIN_KEY": "1" -} diff --git a/userPrefs.jsonc b/userPrefs.jsonc new file mode 100644 index 000000000..055f59273 --- /dev/null +++ b/userPrefs.jsonc @@ -0,0 +1,37 @@ +{ + // "USERPREFS_BUTTON_PIN": "36", + // "USERPREFS_CHANNELS_TO_WRITE": "3", + // "USERPREFS_CHANNEL_0_DOWNLINK_ENABLED": "true", + // "USERPREFS_CHANNEL_0_NAME": "DEFCONnect", + // "USERPREFS_CHANNEL_0_PRECISION": "14", + // "USERPREFS_CHANNEL_0_PSK": "{ 0x38, 0x4b, 0xbc, 0xc0, 0x1d, 0xc0, 0x22, 0xd1, 0x81, 0xbf, 0x36, 0xb8, 0x61, 0x21, 0xe1, 0xfb, 0x96, 0xb7, 0x2e, 0x55, 0xbf, 0x74, 0x22, 0x7e, 0x9d, 0x6a, 0xfb, 0x48, 0xd6, 0x4c, 0xb1, 0xa1 }", + // "USERPREFS_CHANNEL_0_UPLINK_ENABLED": "true", + // "USERPREFS_CHANNEL_1_DOWNLINK_ENABLED": "true", + // "USERPREFS_CHANNEL_1_NAME": "REPLACEME", + // "USERPREFS_CHANNEL_1_PRECISION": "14", + // "USERPREFS_CHANNEL_1_PSK": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }", + // "USERPREFS_CHANNEL_1_UPLINK_ENABLED": "true", + // "USERPREFS_CHANNEL_2_DOWNLINK_ENABLED": "true", + // "USERPREFS_CHANNEL_2_NAME": "REPLACEME", + // "USERPREFS_CHANNEL_2_PRECISION": "14", + // "USERPREFS_CHANNEL_2_PSK": "{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }", + // "USERPREFS_CHANNEL_2_UPLINK_ENABLED": "true", + // "USERPREFS_CONFIG_GPS_MODE": "meshtastic_Config_PositionConfig_GpsMode_ENABLED", + // "USERPREFS_CONFIG_LORA_IGNORE_MQTT": "true", + // "USERPREFS_CONFIG_LORA_REGION": "meshtastic_Config_LoRaConfig_RegionCode_US", + // "USERPREFS_CONFIG_OWNER_LONG_NAME": "My Long Name", + // "USERPREFS_CONFIG_OWNER_SHORT_NAME": "MLN", + // "USERPREFS_EVENT_MODE": "1", + // "USERPREFS_FIXED_BLUETOOTH": "121212", + // "USERPREFS_FIXED_GPS": "", + // "USERPREFS_FIXED_GPS_ALT": "0", + // "USERPREFS_FIXED_GPS_LAT": "48.85873920", + // "USERPREFS_FIXED_GPS_LON": "2.294508368", + // "USERPREFS_LORACONFIG_CHANNEL_NUM": "31", + // "USERPREFS_LORACONFIG_MODEM_PRESET": "meshtastic_Config_LoRaConfig_ModemPreset_SHORT_FAST", + // "USERPREFS_SPLASH_TITLE": "DEFCONtastic", + "USERPREFS_TZ_STRING": "tzplaceholder " + // "USERPREFS_USE_ADMIN_KEY_0": "{ 0xcd, 0xc0, 0xb4, 0x3c, 0x53, 0x24, 0xdf, 0x13, 0xca, 0x5a, 0xa6, 0x0c, 0x0d, 0xec, 0x85, 0x5a, 0x4c, 0xf6, 0x1a, 0x96, 0x04, 0x1a, 0x3e, 0xfc, 0xbb, 0x8e, 0x33, 0x71, 0xe5, 0xfc, 0xff, 0x3c }", + // "USERPREFS_USE_ADMIN_KEY_1": "{}", + // "USERPREFS_USE_ADMIN_KEY_2": "{}" +} \ No newline at end of file diff --git a/variants/diy/platformio.ini b/variants/diy/platformio.ini index 83e2175c8..b60d46996 100644 --- a/variants/diy/platformio.ini +++ b/variants/diy/platformio.ini @@ -2,7 +2,6 @@ [env:meshtastic-diy-v1] extends = esp32_base board = esp32doit-devkit-v1 -board_level = extra board_check = true build_flags = ${esp32_base.build_flags} @@ -62,7 +61,6 @@ debug_tool = jlink [env:nrf52_promicro_diy_tcxo] extends = nrf52840_base board = promicro-nrf52840 -board_level = extra build_flags = ${nrf52840_base.build_flags} -I variants/diy/nrf52_promicro_diy_tcxo -D NRF52_PROMICRO_DIY @@ -158,4 +156,4 @@ build_src_filter = ${esp32_base.build_src_filter} lib_deps = ${esp32_base.lib_deps} lovyan03/LovyanGFX@^1.1.16 earlephilhower/ESP8266Audio@^1.9.7 - earlephilhower/ESP8266SAM@^1.0.1 + earlephilhower/ESP8266SAM@^1.0.1 \ No newline at end of file diff --git a/variants/heltec_capsule_sensor_v3/platformio.ini b/variants/heltec_capsule_sensor_v3/platformio.ini index f1aef925d..b5ffb65c2 100644 --- a/variants/heltec_capsule_sensor_v3/platformio.ini +++ b/variants/heltec_capsule_sensor_v3/platformio.ini @@ -7,5 +7,4 @@ build_flags = ${esp32s3_base.build_flags} -I variants/heltec_capsule_sensor_v3 -D HELTEC_CAPSULE_SENSOR_V3 -D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. - ;-D DEBUG_DISABLED ; uncomment this line to disable DEBUG output - + ;-D DEBUG_DISABLED ; uncomment this line to disable DEBUG output \ No newline at end of file diff --git a/variants/heltec_wireless_paper_v1/platformio.ini b/variants/heltec_wireless_paper_v1/platformio.ini index 999f1586a..c94bcacca 100644 --- a/variants/heltec_wireless_paper_v1/platformio.ini +++ b/variants/heltec_wireless_paper_v1/platformio.ini @@ -1,5 +1,6 @@ [env:heltec-wireless-paper-v1_0] extends = esp32s3_base +board_level = extra board = heltec_wifi_lora_32_V3 build_flags = ${esp32s3_base.build_flags} diff --git a/variants/heltec_wireless_tracker_V1_0/platformio.ini b/variants/heltec_wireless_tracker_V1_0/platformio.ini index 303e27dbf..0e48c72f2 100644 --- a/variants/heltec_wireless_tracker_V1_0/platformio.ini +++ b/variants/heltec_wireless_tracker_V1_0/platformio.ini @@ -1,14 +1,13 @@ [env:heltec-wireless-tracker-V1-0] extends = esp32s3_base +board_level = extra board = heltec_wireless_tracker upload_protocol = esptool - build_flags = ${esp32s3_base.build_flags} -I variants/heltec_wireless_tracker_V1_0 -D HELTEC_TRACKER_V1_0 -D GPS_POWER_TOGGLE ; comment this line to disable triple press function on the user button to turn off gps entirely. ;-D DEBUG_DISABLED ; uncomment this line to disable DEBUG output - lib_deps = ${esp32s3_base.lib_deps} lovyan03/LovyanGFX@^1.1.8 \ No newline at end of file diff --git a/variants/seeed-sensecap-indicator/variant.h b/variants/seeed-sensecap-indicator/variant.h index 55895f353..6028a3ffa 100644 --- a/variants/seeed-sensecap-indicator/variant.h +++ b/variants/seeed-sensecap-indicator/variant.h @@ -40,6 +40,7 @@ // // Buzzer // #define PIN_BUZZER 19 +#define GPS_DEFAULT_NOT_PRESENT 1 #define GPS_RX_PIN 20 #define GPS_TX_PIN 19 #define HAS_GPS 1 diff --git a/variants/seeed_xiao_s3/variant.h b/variants/seeed_xiao_s3/variant.h index ab886d354..8f9282a7a 100644 --- a/variants/seeed_xiao_s3/variant.h +++ b/variants/seeed_xiao_s3/variant.h @@ -41,7 +41,7 @@ L76K GPS Module Information : https://www.seeedstudio.com/L76K-GNSS-Module-for-S L76K Expansion Board can not directly used, L76K Reset Pin needs to override or physically remove it, otherwise it will conflict with the SPI pins */ -// #define GPS_L76K +#define GPS_L76K #ifdef GPS_L76K #define GPS_RX_PIN 44 #define GPS_TX_PIN 43 @@ -80,5 +80,7 @@ L76K GPS Module Information : https://www.seeedstudio.com/L76K-GNSS-Module-for-S // DIO2 controlls an antenna switch and the TCXO voltage is controlled by DIO3 #define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_RXEN 38 +#define SX126X_TXEN RADIOLIB_NC #define SX126X_DIO3_TCXO_VOLTAGE 1.8 -#endif \ No newline at end of file +#endif diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h index 6d398391e..91c12ab3d 100644 --- a/variants/t-deck/variant.h +++ b/variants/t-deck/variant.h @@ -29,7 +29,7 @@ #define BUTTON_PIN 0 // #define BUTTON_NEED_PULLUP - +#define GPS_DEFAULT_NOT_PRESENT 1 #define GPS_RX_PIN 44 #define GPS_TX_PIN 43 diff --git a/variants/tlora_t3s3_epaper/variant.h b/variants/tlora_t3s3_epaper/variant.h index 461ce0c31..732869b20 100644 --- a/variants/tlora_t3s3_epaper/variant.h +++ b/variants/tlora_t3s3_epaper/variant.h @@ -19,6 +19,7 @@ #define I2C_SCL SCL // external qwiic connector +#define GPS_DEFAULT_NOT_PRESENT 1 #define GPS_RX_PIN 44 #define GPS_TX_PIN 43 diff --git a/variants/tlora_v2_1_16/variant.h b/variants/tlora_v2_1_16/variant.h index 8bb5ce3b1..48c069ab7 100644 --- a/variants/tlora_v2_1_16/variant.h +++ b/variants/tlora_v2_1_16/variant.h @@ -8,10 +8,7 @@ #define I2C_SDA 21 // I2C pins for this board #define I2C_SCL 22 -#define LED_PIN 25 // If defined we will blink this LED -#define BUTTON_PIN 12 // If defined, this will be used for user button presses, - -#define BUTTON_NEED_PULLUP +#define LED_PIN 25 // If defined we will blink this LED #define USE_RF95 #define LORA_DIO0 26 // a No connect on the SX1262 module diff --git a/version.properties b/version.properties index bed14bad5..addcab501 100644 --- a/version.properties +++ b/version.properties @@ -1,4 +1,4 @@ [VERSION] major = 2 minor = 5 -build = 14 +build = 17