Merge branch 'master' into nomad-gemini

This commit is contained in:
Thomas Göttgens
2025-05-24 22:08:42 +02:00
committed by GitHub
358 changed files with 9701 additions and 1765 deletions
+8 -1
View File
@@ -43,6 +43,13 @@ runs:
id: base
uses: ./.github/actions/setup-base
- name: Get web ui version
if: inputs.include-web-ui == 'true'
id: webver
shell: bash
run: |
echo "ver=$(cat bin/web.version)" >> $GITHUB_OUTPUT
- name: Pull web ui
if: inputs.include-web-ui == 'true'
uses: dsaltares/fetch-gh-release-asset@master
@@ -51,7 +58,7 @@ runs:
file: build.tar
target: build.tar
token: ${{ inputs.github_token }}
version: tags/v2.5.3
version: tags/v${{ steps.webver.outputs.ver }}
- name: Unpack web ui
if: inputs.include-web-ui == 'true'
-29
View File
@@ -1,29 +0,0 @@
#trunk-ignore-all(yamllint/quoted-strings): required by dependabot syntax check
version: 2
updates:
- package-ecosystem: docker
directory: /.devcontainer
schedule:
interval: daily
time: "05:00"
timezone: US/Pacific
- package-ecosystem: docker
directory: /
schedule:
interval: daily
time: "05:00"
timezone: US/Pacific
- package-ecosystem: gitsubmodule
directory: /
schedule:
interval: daily
time: "05:00"
timezone: US/Pacific
ignore:
- dependency-name: protobufs
- package-ecosystem: github-actions
directory: /.github/workflows
schedule:
interval: daily
time: "05:00"
timezone: US/Pacific
+7
View File
@@ -26,6 +26,11 @@ on:
required: false
type: boolean
default: false
pio_env:
description: PlatformIO environment to build
required: false
type: string
default: native
outputs:
digest:
description: Digest of built image
@@ -90,3 +95,5 @@ jobs:
push: ${{ inputs.push }}
tags: ${{ steps.meta.outputs.tags }} # Tag is only meant to be consumed by the "manifest" job
platforms: ${{ inputs.platform }}
build-args: |
PIO_ENV=${{ inputs.pio_env }}
+82 -22
View File
@@ -5,14 +5,20 @@ concurrency:
on:
# # Triggers the workflow on push but only for the master branch
push:
branches: [master, develop]
branches:
- master
- develop
- event/*
paths-ignore:
- "**.md"
- version.properties
# Note: This is different from "pull_request". Need to specify ref when doing checkouts.
pull_request_target:
branches: [master, develop]
branches:
- master
- develop
- event/*
paths-ignore:
- "**.md"
#- "**.yml"
@@ -32,12 +38,12 @@ jobs:
name: Checkout base
- id: jsonStep
run: |
if [[ "${{ github.head_ref }}" == "" ]]; then
if [[ "$GITHUB_HEAD_REF" == "" ]]; then
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}})
else
TARGETS=$(./bin/generate_ci_matrix.py ${{matrix.arch}} quick)
fi
echo "Name: ${{ github.ref_name }} Base: ${{ github.base_ref }} } Ref: ${{ github.ref }} Targets: $TARGETS"
echo "Name: $GITHUB_REF_NAME Base: $GITHUB_BASE_REF Ref: $GITHUB_REF Targets: $TARGETS"
echo "${{matrix.arch}}=$(jq -cn --argjson environments "$TARGETS" '{board: $environments}')" >> $GITHUB_OUTPUT
outputs:
esp32: ${{ steps.jsonStep.outputs.esp32 }}
@@ -143,9 +149,10 @@ jobs:
secrets: inherit
test-native:
if: ${{ !contains(github.ref_name, 'event/') }}
uses: ./.github/workflows/test_native.yml
docker-debian-amd64:
docker-deb-amd64:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
@@ -153,7 +160,16 @@ jobs:
runs-on: ubuntu-24.04
push: false
docker-alpine-amd64:
docker-deb-amd64-tft:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
platform: linux/amd64
runs-on: ubuntu-24.04
push: false
pio_env: native-tft
docker-alp-amd64:
uses: ./.github/workflows/docker_build.yml
with:
distro: alpine
@@ -161,7 +177,16 @@ jobs:
runs-on: ubuntu-24.04
push: false
docker-debian-arm64:
docker-alp-amd64-tft:
uses: ./.github/workflows/docker_build.yml
with:
distro: alpine
platform: linux/amd64
runs-on: ubuntu-24.04
push: false
pio_env: native-tft
docker-deb-arm64:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
@@ -169,7 +194,7 @@ jobs:
runs-on: ubuntu-24.04-arm
push: false
docker-debian-armv7:
docker-deb-armv7:
uses: ./.github/workflows/docker_build.yml
with:
distro: debian
@@ -177,17 +202,6 @@ jobs:
runs-on: ubuntu-24.04-arm
push: false
after-checks:
runs-on: ubuntu-latest
if: ${{ github.event_name != 'workflow_dispatch' }}
needs: [check]
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
gather-artifacts:
permissions:
contents: write
@@ -332,7 +346,7 @@ jobs:
merge-multiple: true
path: ./output/pio-deps-native-tft
- name: Zip linux sources
- name: Zip Linux sources
working-directory: output
run: |
zip -j -9 -r ./meshtasticd-${{ steps.version.outputs.deb }}-src.zip ./debian-src
@@ -342,7 +356,9 @@ jobs:
- name: Display structure of downloaded files
run: ls -lR
- name: Add linux sources to release
- name: Add Linux sources to GtiHub Release
# Only run when targeting master branch with workflow_dispatch
if: ${{ github.ref_name == 'master' }}
run: |
gh release upload v${{ steps.version.outputs.long }} ./output/meshtasticd-${{ steps.version.outputs.deb }}-src.zip
gh release upload v${{ steps.version.outputs.long }} ./output/platformio-deps-native-tft-${{ steps.version.outputs.long }}.zip
@@ -400,9 +416,53 @@ jobs:
- name: Display structure of downloaded files
run: ls -lR
- name: Add bins and debug elfs to release
- name: Add bins and debug elfs to GitHub Release
# Only run when targeting master branch with workflow_dispatch
if: ${{ github.ref_name == 'master' }}
run: |
gh release upload v${{ steps.version.outputs.long }} ./firmware-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
gh release upload v${{ steps.version.outputs.long }} ./debug-elfs-${{matrix.arch}}-${{ steps.version.outputs.long }}.zip
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
publish-firmware:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'workflow_dispatch' }}
needs: [release-firmware]
env:
targets: esp32,esp32s3,esp32c3,esp32c6,nrf52840,rp2040,stm32
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: 3.x
- name: Get release version string
run: echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
id: version
- uses: actions/download-artifact@v4
with:
pattern: firmware-{${{ env.targets }}}-${{ steps.version.outputs.long }}
merge-multiple: true
path: ./publish
- name: Publish firmware to meshtastic.github.io
uses: peaceiris/actions-gh-pages@v4
env:
# On event/* branches, use the event name as the destination prefix
DEST_PREFIX: ${{ contains(github.ref_name, 'event/') && format('{0}/', github.ref_name) || '' }}
with:
deploy_key: ${{ secrets.DIST_PAGES_DEPLOY_KEY }}
external_repository: meshtastic/meshtastic.github.io
publish_branch: master
publish_dir: ./publish
destination_dir: ${{ env.DEST_PREFIX }}firmware-${{ steps.version.outputs.long }}
keep_files: true
user_name: github-actions[bot]
user_email: github-actions[bot]@users.noreply.github.com
commit_message: ${{ steps.version.outputs.long }}
enable_jekyll: true
+31 -16
View File
@@ -46,11 +46,14 @@ jobs:
# Create a PR to bump version when a release is Published
bump-version:
if: ${{ github.event.release.published }}
if: github.event.action == 'published'
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: write
defaults:
run:
shell: bash
steps:
- name: Checkout
uses: actions/checkout@v4
@@ -60,32 +63,44 @@ jobs:
with:
python-version: 3.x
- name: Get release version string
run: |
echo "long=$(./bin/buildinfo.py long)" >> $GITHUB_OUTPUT
echo "deb=$(./bin/buildinfo.py deb)" >> $GITHUB_OUTPUT
id: version
env:
BUILD_LOCATION: local
- name: Bump version.properties
run: >-
bin/bump_version.py
run: |
# Bump version.properties
chmod +x ./bin/bump_version.py
./bin/bump_version.py
- name: Get new release version string
run: |
echo "short=$(./bin/buildinfo.py short)" >> $GITHUB_OUTPUT
id: new_version
- name: Ensure debian deps are installed
shell: bash
run: |
sudo apt-get update -y --fix-missing
sudo apt-get install -y devscripts
- name: Update debian changelog
run: >-
debian/ci_changelog.sh
run: |
# Update debian changelog
chmod +x ./debian/ci_changelog.sh
./debian/ci_changelog.sh
- name: Create version.properties pull request
- name: Bump org.meshtastic.meshtasticd.metainfo.xml
run: |
# Bump org.meshtastic.meshtasticd.metainfo.xml
pip install -r bin/bump_metainfo/requirements.txt -q
chmod +x ./bin/bump_metainfo/bump_metainfo.py
./bin/bump_metainfo/bump_metainfo.py --file bin/org.meshtastic.meshtasticd.metainfo.xml "${{ steps.new_version.outputs.short }}"
env:
PIP_DISABLE_PIP_VERSION_CHECK: 1
- name: Create Bumps pull request
uses: peter-evans/create-pull-request@v7
with:
title: Bump version.properties
base: ${{ github.event.repository.default_branch }}
title: Bump release version
commit-message: automated bumps
add-paths: |
version.properties
debian/changelog
bin/org.meshtastic.meshtasticd.metainfo.xml
+1 -1
View File
@@ -13,7 +13,7 @@ permissions:
jobs:
semgrep-full:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
container:
image: semgrep/semgrep
+1 -1
View File
@@ -6,7 +6,7 @@ permissions: read-all
jobs:
semgrep-diff:
runs-on: ubuntu-22.04
runs-on: ubuntu-24.04
container:
image: semgrep/semgrep
+1 -1
View File
@@ -143,7 +143,7 @@ jobs:
merge-multiple: true
- name: Test Report
uses: dorny/test-reporter@v2.0.0
uses: dorny/test-reporter@v2.1.0
with:
name: PlatformIO Tests
path: testreport.xml
+5 -2
View File
@@ -5,7 +5,10 @@ on:
- cron: 0 0 * * * # Run every day at midnight
workflow_dispatch: {}
permissions: read-all
permissions:
contents: read
actions: read
checks: write
jobs:
native-tests:
@@ -44,7 +47,7 @@ jobs:
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
node-version: 22
- name: Setup pnpm
uses: pnpm/action-setup@v4
+1
View File
@@ -0,0 +1 @@
renovate.json
+10 -11
View File
@@ -1,34 +1,33 @@
version: 0.1
cli:
version: 1.22.11
version: 1.22.15
plugins:
sources:
- id: trunk
ref: v1.6.7
ref: v1.6.8
uri: https://github.com/trunk-io/plugins
lint:
enabled:
- renovate@40.0.6
- prettier@3.5.3
- trufflehog@3.88.20
- yamllint@1.37.0
- trufflehog@3.88.29
- yamllint@1.37.1
- bandit@1.8.3
- checkov@3.2.394
- terrascan@1.19.9
- trivy@0.61.0
- trivy@0.62.1
- taplo@0.9.3
- ruff@0.11.2
- ruff@0.11.9
- isort@6.0.1
- markdownlint@0.44.0
- oxipng@9.1.4
- oxipng@9.1.5
- svgo@3.3.2
- actionlint@1.7.7
- flake8@7.1.2
- flake8@7.2.0
- hadolint@2.12.1-beta
- shfmt@3.6.0
- shellcheck@0.10.0
- black@25.1.0
- git-diff-check
- gitleaks@8.24.2
- gitleaks@8.26.0
- clang-format@16.0.3
ignore:
- linters: [ALL]
+27 -9
View File
@@ -1,20 +1,20 @@
# trunk-ignore-all(terrascan/AC_DOCKER_0002): Known terrascan issue
# trunk-ignore-all(trivy/DS002): We must run as root for this container
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
# trunk-ignore-all(hadolint/DL3008): Do not pin apt package versions
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
FROM python:3.13-bookworm AS builder
ARG PIO_ENV=native
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
# Install Dependencies
ENV PIP_ROOT_USER_ACTION=ignore
RUN apt-get update && apt-get install --no-install-recommends -y \
wget g++ zip git ca-certificates \
curl wget g++ zip git ca-certificates pkg-config \
libgpiod-dev libyaml-cpp-dev libbluetooth-dev libi2c-dev libuv1-dev \
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev pkg-config \
libusb-1.0-0-dev libulfius-dev liborcania-dev libssl-dev \
libx11-dev libinput-dev libxkbcommon-x11-dev \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& pip install --no-cache-dir -U platformio \
&& mkdir /tmp/firmware
@@ -24,13 +24,26 @@ WORKDIR /tmp/firmware
COPY . /tmp/firmware
# Build
RUN bash ./bin/build-native.sh && \
RUN bash ./bin/build-native.sh "$PIO_ENV" && \
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
# Fetch web assets
RUN curl -L "https://github.com/meshtastic/web/releases/download/v$(cat /tmp/firmware/bin/web.version)/build.tar" -o /tmp/web.tar \
&& mkdir -p /tmp/web \
&& tar -xf /tmp/web.tar -C /tmp/web/ \
&& gzip -dr /tmp/web \
&& rm /tmp/web.tar
##### PRODUCTION BUILD #############
FROM debian:bookworm-slim
LABEL org.opencontainers.image.title="Meshtastic" \
org.opencontainers.image.description="Debian Meshtastic daemon and web interface" \
org.opencontainers.image.url="https://meshtastic.org" \
org.opencontainers.image.documentation="https://meshtastic.org/docs/" \
org.opencontainers.image.authors="Meshtastic" \
org.opencontainers.image.licenses="GPL-3.0-or-later" \
org.opencontainers.image.source="https://github.com/meshtastic/firmware/"
ENV DEBIAN_FRONTEND=noninteractive
ENV TZ=Etc/UTC
@@ -38,14 +51,17 @@ ENV TZ=Etc/UTC
USER root
RUN apt-get update && apt-get --no-install-recommends -y install \
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev liborcania2.3 libulfius2.7 libssl3 \
libc-bin libc6 libgpiod2 libyaml-cpp0.7 libi2c0 libuv1 libusb-1.0-0-dev \
liborcania2.3 libulfius2.7 libssl3 \
libx11-6 libinput10 libxkbcommon-x11-0 \
&& apt-get clean && rm -rf /var/lib/apt/lists/* \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d \
&& mkdir -p /etc/meshtasticd/ssl
# Fetch compiled binary from the builder
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/
COPY --from=builder /tmp/web /usr/share/meshtasticd/
# Copy config templates
COPY ./bin/config.d /etc/meshtasticd/available.d
@@ -54,7 +70,9 @@ VOLUME /var/lib/meshtasticd
# Expose Meshtastic TCP API port from the host
EXPOSE 4403
# Expose Meshtastic Web UI port from the host
EXPOSE 9443
CMD [ "sh", "-cx", "meshtasticd -d /var/lib/meshtasticd" ]
CMD [ "sh", "-cx", "meshtasticd --fsdir=/var/lib/meshtasticd" ]
HEALTHCHECK NONE
HEALTHCHECK NONE
+2 -2
View File
@@ -4,8 +4,8 @@
| Firmware Version | Supported |
| ---------------- | ------------------ |
| 2.5.x | :white_check_mark: |
| <= 2.4.x | :x: |
| 2.6.x | :white_check_mark: |
| <= 2.5.x | :x: |
## Reporting a Vulnerability
+18 -5
View File
@@ -1,15 +1,16 @@
# trunk-ignore-all(trivy/DS002): We must run as root for this container
# trunk-ignore-all(checkov/CKV_DOCKER_8): We must run as root for this container
# trunk-ignore-all(hadolint/DL3002): We must run as root for this container
# trunk-ignore-all(hadolint/DL3018): Do not pin apk package versions
# trunk-ignore-all(hadolint/DL3013): Do not pin pip package versions
FROM python:3.13-alpine3.21 AS builder
ARG PIO_ENV=native
ENV PIP_ROOT_USER_ACTION=ignore
RUN apk --no-cache add \
bash g++ libstdc++-dev linux-headers zip git ca-certificates libgpiod-dev yaml-cpp-dev bluez-dev \
libusb-dev i2c-tools-dev libuv-dev openssl-dev pkgconf argp-standalone \
libx11-dev libinput-dev libxkbcommon-dev \
&& rm -rf /var/cache/apk/* \
&& pip install --no-cache-dir -U platformio \
&& mkdir /tmp/firmware
@@ -21,23 +22,35 @@ COPY . /tmp/firmware
# Add `argp` for musl
ENV PLATFORMIO_BUILD_FLAGS="-Os -ffunction-sections -fdata-sections -Wl,--gc-sections -largp"
RUN bash ./bin/build-native.sh && \
RUN bash ./bin/build-native.sh "$PIO_ENV" && \
cp "/tmp/firmware/release/meshtasticd_linux_$(uname -m)" "/tmp/firmware/release/meshtasticd"
# ##### PRODUCTION BUILD #############
FROM alpine:3.21
LABEL org.opencontainers.image.title="Meshtastic" \
org.opencontainers.image.description="Alpine Meshtastic daemon" \
org.opencontainers.image.url="https://meshtastic.org" \
org.opencontainers.image.documentation="https://meshtastic.org/docs/" \
org.opencontainers.image.authors="Meshtastic" \
org.opencontainers.image.licenses="GPL-3.0-or-later" \
org.opencontainers.image.source="https://github.com/meshtastic/firmware/"
# nosemgrep: dockerfile.security.last-user-is-root.last-user-is-root
USER root
RUN apk --no-cache add \
libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \
shadow libstdc++ libgpiod yaml-cpp libusb i2c-tools libuv \
libx11 libinput libxkbcommon \
&& rm -rf /var/cache/apk/* \
&& mkdir -p /var/lib/meshtasticd \
&& mkdir -p /etc/meshtasticd/config.d \
&& mkdir -p /etc/meshtasticd/ssl
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/sbin/
# Fetch compiled binary from the builder
COPY --from=builder /tmp/firmware/release/meshtasticd /usr/bin/
# Copy config templates
COPY ./bin/config.d /etc/meshtasticd/available.d
WORKDIR /var/lib/meshtasticd
VOLUME /var/lib/meshtasticd
+12 -3
View File
@@ -2,7 +2,9 @@
[esp32_base]
extends = arduino_base
custom_esp32_kind = esp32
platform = platformio/espressif32@6.10.0
platform =
# renovate: datasource=custom.pio depName=platformio/espressif32 packageName=platformio/platform/espressif32
platformio/espressif32@6.10.0
build_src_filter =
${arduino_base.build_src_filter} -<platform/nrf52/> -<platform/stm32wl> -<platform/rp2xx0> -<mesh/eth/> -<mesh/raspihttp>
@@ -44,13 +46,20 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
https://github.com/meshtastic/esp32_https_server/archive/23665b3adc080a311dcbb586ed5941b5f94d6ea2.zip
# renovate: datasource=git-refs depName=meshtastic-esp32_https_server packageName=https://github.com/meshtastic/esp32_https_server gitBranch=master
https://github.com/meshtastic/esp32_https_server/archive/896f1771ceb5979987a0b41028bf1b4e7aad419b.zip
# renovate: datasource=custom.pio depName=NimBLE-Arduino packageName=h2zero/library/NimBLE-Arduino
h2zero/NimBLE-Arduino@^1.4.3
# renovate: datasource=git-refs depName=libpax packageName=https://github.com/dbinfrago/libpax gitBranch=master
https://github.com/dbinfrago/libpax/archive/3cdc0371c375676a97967547f4065607d4c53fd1.zip
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
lewisxhe/XPowersLib@^0.2.7
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
rweather/Crypto@^0.4.0
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
lib_ignore =
segger_rtt
+8 -2
View File
@@ -1,6 +1,8 @@
[esp32c6_base]
extends = esp32_base
platform = https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip
platform =
# Do not renovate until we have switched to pioarduino tagged builds
https://github.com/Jason2866/platform-espressif32/archive/22faa566df8c789000f8136cd8d0aca49617af55.zip
build_flags =
${arduino_base.build_flags}
-Wall
@@ -23,10 +25,14 @@ lib_deps =
${arduino_base.lib_deps}
${networking_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
# renovate: datasource=custom.pio depName=XPowersLib packageName=lewisxhe/library/XPowersLib
lewisxhe/XPowersLib@^0.2.7
# renovate: datasource=git-refs depName=meshtastic-ESP32_Codec2 packageName=https://github.com/meshtastic/ESP32_Codec2 gitBranch=master
https://github.com/meshtastic/ESP32_Codec2/archive/633326c78ac251c059ab3a8c430fcdf25b41672f.zip
rweather/Crypto@^0.4.0
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
build_src_filter =
${esp32_base.build_src_filter} -<mesh/http>
+1 -1
View File
@@ -16,4 +16,4 @@ build_flags =
lib_ignore =
${esp32_base.lib_ignore}
NimBLE-Arduino
libpax
libpax
-1
View File
@@ -3,4 +3,3 @@ extends = esp32_base
custom_esp32_kind = esp32s3
monitor_speed = 115200
+8 -3
View File
@@ -1,10 +1,14 @@
[nrf52_base]
; Instead of the standard nordicnrf52 platform, we use our fork which has our added variant files
platform = platformio/nordicnrf52@^10.8.0
platform =
# renovate: datasource=custom.pio depName=platformio/nordicnrf52 packageName=platformio/platform/nordicnrf52
platformio/nordicnrf52@^10.8.0
extends = arduino_base
platform_packages =
; our custom Git version until they merge our PR
# TODO renovate
platformio/framework-arduinoadafruitnrf52 @ https://github.com/meshtastic/Adafruit_nRF52_Arduino#e13f5820002a4fb2a5e6754b42ace185277e5adf
; Don't renovate toolchain-gccarmnoneeabi
platformio/toolchain-gccarmnoneeabi@~1.90301.0
build_type = debug
@@ -24,8 +28,9 @@ build_src_filter =
lib_deps=
${arduino_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto@^0.4.0
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
lib_ignore =
BluetoothOTA
lvgl
lvgl
+3 -1
View File
@@ -6,7 +6,9 @@ build_flags = ${nrf52_base.build_flags}
lib_deps =
${nrf52_base.lib_deps}
${environmental_base.lib_deps}
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/e31a8825ea3300b163a0a3c1ddd5de34e10e1371.zip
${environmental_extra.lib_deps}
# renovate: datasource=git-refs depName=Kongduino-Adafruit_nRFCrypto packageName=https://github.com/Kongduino/Adafruit_nRFCrypto gitBranch=master
https://github.com/Kongduino/Adafruit_nRFCrypto/archive/5f838d2709461a2c981f642917aa50254a25c14c.zip
; Common NRF52 debugging settings follow. See the Meshtastic developer docs for how to connect SWD debugging probes to your board.
+12 -6
View File
@@ -1,6 +1,8 @@
; The Portduino based 'native' environment. Currently supported on Linux targets with real LoRa hardware (or simulated).
[portduino_base]
platform = https://github.com/meshtastic/platform-native/archive/c5bd469ab9b5a6966321e09557b27d906961da63.zip
platform =
# renovate: datasource=git-refs depName=platform-native packageName=https://github.com/meshtastic/platform-native gitBranch=develop
https://github.com/meshtastic/platform-native/archive/622341c6de8a239704318b10c3dbb00c21a3eab3.zip
framework = arduino
build_src_filter =
@@ -15,18 +17,19 @@ build_src_filter =
+<mesh/raspihttp/>
-<mesh/eth/>
-<modules/esp32>
-<modules/Telemetry/EnvironmentTelemetry.cpp>
-<modules/Telemetry/AirQualityTelemetry.cpp>
-<modules/Telemetry/Sensor>
+<../variants/portduino>
lib_deps =
${env.lib_deps}
${networking_base.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto@^0.4.0
${environmental_base.lib_deps}
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
# renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX
lovyan03/LovyanGFX@^1.2.0
https://github.com/pine64/libch341-spi-userspace/archive/a9b17e3452f7fb747000d9b4ad4409155b39f6ef.zip
# renovate: datasource=git-refs depName=libch341-spi-userspace packageName=https://github.com/pine64/libch341-spi-userspace gitBranch=main
https://github.com/pine64/libch341-spi-userspace/archive/af9bc27c9c30fa90772279925b7c5913dff789b4.zip
build_flags =
${arduino_base.build_flags}
@@ -42,4 +45,7 @@ build_flags =
-lyaml-cpp
-li2c
-luv
-std=gnu17
-std=c++17
lib_ignore = Adafruit NeoPixel
+10 -3
View File
@@ -1,8 +1,13 @@
; Common settings for rp2040 Processor based targets
[rp2040_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
platform =
# TODO renovate
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
; For arduino-pico >= 4.4.3
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
platform_packages =
# TODO renovate
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@@ -23,5 +28,7 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
+11 -4
View File
@@ -1,8 +1,13 @@
; Common settings for rp2040 Processor based targets
; Common settings for rp2350 Processor based targets
[rp2350_base]
platform = https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5 ; For arduino-pico >= 4.4.3
platform =
# TODO renovate
https://github.com/maxgerhardt/platform-raspberrypi#76ecf3c7e9dd4503af0331154c4ca1cddc4b03e5
; For arduino-pico >= 4.4.3
extends = arduino_base
platform_packages = framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
platform_packages =
# TODO renovate
framework-arduinopico@https://github.com/earlephilhower/arduino-pico#4.4.3
board_build.core = earlephilhower
board_build.filesystem_size = 0.5m
@@ -20,5 +25,7 @@ lib_ignore =
lib_deps =
${arduino_base.lib_deps}
${environmental_base.lib_deps}
${environmental_extra.lib_deps}
${radiolib_base.lib_deps}
rweather/Crypto
# renovate: datasource=custom.pio depName=rweather/Crypto packageName=rweather/library/Crypto
rweather/Crypto@0.4.0
+7 -2
View File
@@ -1,7 +1,11 @@
[stm32_base]
extends = arduino_base
platform = ststm32
platform_packages = platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
platform =
# renovate: datasource=custom.pio depName=platformio/ststm32 packageName=platformio/platform/ststm32
platformio/ststm32@19.1.0
platform_packages =
# TODO renovate
platformio/framework-arduinoststm32@https://github.com/stm32duino/Arduino_Core_STM32/archive/2.10.1.zip
extra_scripts =
${env.extra_scripts}
post:extra_scripts/extra_stm32.py
@@ -35,6 +39,7 @@ debug_tool = stlink
lib_deps =
${env.lib_deps}
${radiolib_base.lib_deps}
# renovate: datasource=git-refs depName=caveman99-stm32-Crypto packageName=https://github.com/caveman99/Crypto gitBranch=main
https://github.com/caveman99/Crypto/archive/eae9c768054118a9399690f8af202853d1ae8516.zip
lib_ignore =
+4
View File
@@ -0,0 +1,4 @@
# Set spidev ownership to 'spi' group.
SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660"
# Allow access to USB CH341 devices
SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666"
+4 -3
View File
@@ -15,6 +15,7 @@ platformioFailed() {
VERSION=$(bin/buildinfo.py long)
SHORT_VERSION=$(bin/buildinfo.py short)
PIO_ENV=${1:-native}
OUTDIR=release/
@@ -24,7 +25,7 @@ mkdir -p $OUTDIR/
rm -r $OUTDIR/* || true
# Important to pull latest version of libs into all device flavors, otherwise some devices might be stale
pio pkg update --environment native || platformioFailed
pio run --environment native || platformioFailed
cp .pio/build/native/program "$OUTDIR/meshtasticd_linux_$(uname -m)"
pio pkg update --environment "$PIO_ENV" || platformioFailed
pio run --environment "$PIO_ENV" || platformioFailed
cp ".pio/build/$PIO_ENV/program" "$OUTDIR/meshtasticd_linux_$(uname -m)"
cp bin/native-install.* $OUTDIR
+72
View File
@@ -0,0 +1,72 @@
#!/usr/bin/env python3
import argparse
import xml.etree.ElementTree as ET
from defusedxml.ElementTree import parse
from datetime import datetime, timezone
# Indent by 2 spaces to align with xml formatting.
def indent(elem, level=0):
i = "\n" + level * " "
if len(elem):
if not elem.text or not elem.text.strip():
elem.text = i + " "
for child in elem:
indent(child, level + 1)
if not child.tail or not child.tail.strip():
child.tail = i
if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i
def main():
parser = argparse.ArgumentParser(
description="Prepend new release entry to metainfo.xml file.")
parser.add_argument("--file", help="Path to the metainfo.xml file",
default="org.meshtastic.meshtasticd.metainfo.xml")
parser.add_argument("version", help="Version string (e.g. 2.6.4)")
parser.add_argument("--date", help="Release date (YYYY-MM-DD), defaults to today",
default=datetime.now(timezone.utc).date().isoformat())
args = parser.parse_args()
tree = parse(args.file)
root = tree.getroot()
releases = root.find('releases')
if releases is None:
raise RuntimeError("<releases> element not found in XML.")
existing_versions = {
release.get('version'): release
for release in releases.findall('release')
}
existing_release = existing_versions.get(args.version)
if existing_release is not None:
if not existing_release.get('date'):
print(f"Version {args.version} found without date. Adding date...")
existing_release.set('date', args.date)
else:
print(
f"Version {args.version} is already present with date, skipping insertion.")
else:
new_release = ET.Element('release', {
'version': args.version,
'date': args.date
})
url = ET.SubElement(new_release, 'url', {'type': 'details'})
url.text = f"https://github.com/meshtastic/firmware/releases?q=tag%3Av{args.version}"
releases.insert(0, new_release)
indent(releases, level=1)
releases.tail = "\n"
print(f"Inserted new release: {args.version}")
tree.write(args.file, encoding='UTF-8', xml_declaration=True)
if __name__ == "__main__":
main()
+1
View File
@@ -0,0 +1 @@
defusedxml==0.7.1
+10 -2
View File
@@ -188,14 +188,22 @@ Logging:
# AsciiLogs: true # default if not specified is !isatty() on stdout
Webserver:
# Port: 443 # Port for Webserver & Webservices
# Port: 9443 # Port for Webserver & Webservices
# RootPath: /usr/share/meshtasticd/web # Root Dir of WebServer
# SSLKey: /etc/meshtasticd/ssl/private_key.pem # Path to SSL Key, generated if not present
# SSLCert: /etc/meshtasticd/ssl/certificate.pem # Path to SSL Certificate, generated if not present
HostMetrics:
# ReportInterval: 30 # Interval in minutes between HostMetrics report packets, or 0 for disabled
# Channel: 0 # channel to send Host Metrics over. Defaults to the primary channel.
# UserStringCommand: cat /sys/firmware/devicetree/base/serial-number # Command to execute, to send the results as the userString
General:
MaxNodes: 200
MaxMessageQueue: 100
ConfigDirectory: /etc/meshtasticd/config.d/
AvailableDirectory: /etc/meshtasticd/available.d/
# MACAddress: AA:BB:CC:DD:EE:FF
# MACAddressSource: eth0
# MACAddressSource: eth0
+3 -1
View File
@@ -1,3 +1,5 @@
# MeshAdv-Pi E22-900M30S
# https://github.com/chrismyers2000/MeshAdv-Pi-Hat
Lora:
Module: sx1262
CS: 21
@@ -9,4 +11,4 @@ Lora:
DIO3_TCXO_VOLTAGE: true
# Only for E22-900M33S:
# Limit the output power to 8 dBm
# SX126X_MAX_POWER: 8
# SX126X_MAX_POWER: 8
@@ -0,0 +1,11 @@
# MeshAdv Mini E22-900M22S
# https://github.com/chrismyers2000/MeshAdv-Mini
Lora:
Module: sx1262 # Ebyte E22-900M22S
CS: 8
IRQ: 16
Busy: 20
Reset: 24
TXen: 13
DIO2_AS_RF_SWITCH: true
DIO3_TCXO_VOLTAGE: true
+11
View File
@@ -0,0 +1,11 @@
Lora:
Module: lr1121
CS: 0
IRQ: 6
Reset: 2
Busy: 4
spidev: ch341
DIO3_TCXO_VOLTAGE: 1.8
# USB_Serialnum: 12345678
USB_PID: 0x5512
USB_VID: 0x1A86
+2 -2
View File
@@ -17,8 +17,8 @@ SET "LOGCOUNTER=0"
SET "S3=s3 v3 t-deck wireless-paper wireless-tracker station-g2 unphone"
SET "C3=esp32c3"
@REM FIXME: Determine flash size from PlatformIO variant, this is unmaintainable.
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core t-watch-s3 tracksenger"
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite"
SET "BIGDB_8MB=picomputer-s3 unphone seeed-sensecap-indicator crowpanel-esp32s3 heltec_capsule_sensor_v3 heltec-v3 heltec-vision-master-e213 heltec-vision-master-e290 heltec-vision-master-t190 heltec-wireless-paper heltec-wireless-tracker heltec-wsl-v3 icarus seeed-xiao-s3 tbeam-s3-core tracksenger"
SET "BIGDB_16MB=t-deck mesh-tab t-energy-s3 dreamcatcher ESP32-S3-Pico m5stack-cores3 station-g2 t-eth-elite t-watch-s3"
GOTO getopts
:help
+14 -4
View File
@@ -22,7 +22,6 @@ BIGDB_8MB=(
"icarus"
"seeed-xiao-s3"
"tbeam-s3-core"
"t-watch-s3"
"tracksenger"
)
BIGDB_16MB=(
@@ -34,6 +33,7 @@ BIGDB_16MB=(
"m5stack-cores3"
"station-g2"
"t-eth-elite"
"t-watch-s3"
)
S3_VARIANTS=(
"s3"
@@ -43,6 +43,16 @@ S3_VARIANTS=(
"wireless-tracker"
"station-g2"
"unphone"
"t-eth-elite"
"mesh-tab"
"dreamcatcher"
"ESP32-S3-Pico"
"seeed-sensecap-indicator"
"heltec_capsule_sensor_v3"
"vision-master"
"icarus"
"tracksenger"
"elecrow-adv"
)
# Determine the correct esptool command to use
@@ -138,7 +148,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
# littlefs* offset for BigDB 8mb and OTA OFFSET.
for variant in "${BIGDB_8MB[@]}"; do
if [ -n "${FILENAME##*"$variant"*}" ]; then
if [ -z "${FILENAME##*"$variant"*}" ]; then
OFFSET=0x670000
OTA_OFFSET=0x340000
fi
@@ -146,7 +156,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
# littlefs* offset for BigDB 16mb and OTA OFFSET.
for variant in "${BIGDB_16MB[@]}"; do
if [ -n "${FILENAME##*"$variant"*}" ]; then
if [ -z "${FILENAME##*"$variant"*}" ]; then
OFFSET=0xc90000
OTA_OFFSET=0x650000
fi
@@ -155,7 +165,7 @@ if [ -f "${FILENAME}" ] && [ -n "${FILENAME##*"update"*}" ]; then
# Account for S3 board's different OTA partition
# FIXME: Use PlatformIO info to determine MCU type, this is unmaintainable
for variant in "${S3_VARIANTS[@]}"; do
if [ -n "${FILENAME##*"$variant"*}" ]; then
if [ -z "${FILENAME##*"$variant"*}" ]; then
MCU="esp32s3"
fi
done
+4 -3
View File
@@ -5,10 +5,11 @@ StartLimitInterval=200
StartLimitBurst=5
[Service]
User=root
Group=root
AmbientCapabilities=CAP_NET_BIND_SERVICE
User=meshtasticd
Group=meshtasticd
Type=simple
ExecStart=/usr/sbin/meshtasticd
ExecStart=/usr/bin/meshtasticd
Restart=always
RestartSec=3
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
cp "release/meshtasticd_linux_$(uname -m)" /usr/sbin/meshtasticd
cp "release/meshtasticd_linux_$(uname -m)" /usr/bin/meshtasticd
mkdir -p /etc/meshtasticd
if [[ -f "/etc/meshtasticd/config.yaml" ]]; then
cp bin/config-dist.yaml /etc/meshtasticd/config-upgrade.yaml
+8
View File
@@ -0,0 +1,8 @@
[Desktop Entry]
Name=Meshtastic
Comment=Meshtastic App
Exec=meshtasticd
Icon=org.meshtastic.meshtasticd
Terminal=true
Type=Application
Categories=Network;Chat;HamRadio;
+109
View File
@@ -0,0 +1,109 @@
<?xml version='1.0' encoding='UTF-8'?>
<component type="desktop-application">
<id>org.meshtastic.meshtasticd</id>
<name>Meshtastic</name>
<summary>Decentralized mesh communication</summary>
<metadata_license>CC-BY-4.0</metadata_license>
<project_license>GPL-3.0-or-later</project_license>
<developer id="org.meshtastic">
<name>Meshtastic</name>
</developer>
<description>
<p>
Meshtastic is an open source project for creating off-grid, affordable, and resilient communication with LoRa mesh networks.
</p>
</description>
<launchable type="desktop-id">org.meshtastic.meshtasticd.desktop</launchable>
<categories>
<category>Network</category>
<category>Chat</category>
<category>HamRadio</category>
</categories>
<keywords>
<keyword>mesh</keyword>
<keyword>LoRa</keyword>
</keywords>
<recommends>
<control>keyboard</control>
<control>pointing</control>
<control>touch</control>
</recommends>
<requires>
<display_length compare="ge">360</display_length>
</requires>
<branding>
<color type="primary" scheme_preference="light">#97be89</color>
<color type="primary" scheme_preference="dark">#206538</color>
</branding>
<content_rating type="oars-1.1">
<content_attribute id="social-chat">intense</content_attribute>
<content_attribute id="social-location">intense</content_attribute>
</content_rating>
<url type="bugtracker">https://github.com/meshtastic/firmware/issues</url>
<url type="homepage">https://meshtastic.org/</url>
<url type="donation">https://opencollective.com/meshtastic</url>
<url type="faq">https://meshtastic.org/docs/software/linux/usage/</url>
<url type="vcs-browser">https://github.com/meshtastic/firmware/</url>
<screenshots>
<screenshot type="default">
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_home_dashboard_dark.webp</image>
<caption>Home Dashboard</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_initial_boot.webp</image>
<caption>Setup</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_node_list_dark.webp</image>
<caption>Nodes List</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_chat_list_dark.webp</image>
<caption>Chats List</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_chat_message_dark.webp</image>
<caption>Messages</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_map_dark.webp</image>
<caption>Map</caption>
</screenshot>
<screenshot>
<image>https://meshtastic.org/img/software/meshtastic-ui/mui_settings_dark.webp</image>
<caption>Settings</caption>
</screenshot>
</screenshots>
<releases>
<release version="2.6.9" date="2025-05-15">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.9</url>
</release>
<release version="2.6.8" date="2025-05-05">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.8</url>
</release>
<release version="2.6.7" date="2025-04-28">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.7</url>
</release>
<release version="2.6.6" date="2025-04-15">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.6</url>
</release>
<release version="2.6.5" date="2025-03-30">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.5</url>
</release>
<release version="2.6.4" date="2025-03-28">
<url type="details">https://github.com/meshtastic/firmware/releases?q=tag%3Av2.6.4</url>
</release>
</releases>
</component>
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="512" height="512" viewBox="0 0 512 512" xml:space="preserve">
<desc>Created with Fabric.js 4.6.0</desc>
<defs>
</defs>
<g transform="matrix(1 0 0 1 256 256)" id="xYQ9Gk9Jwpgj_HMOXB3F_" >
<path style="stroke: rgb(213,130,139); stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: miter; stroke-miterlimit: 4; fill: rgb(103,234,148); fill-rule: nonzero; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-256, -256)" d="M 0 0 L 512 0 L 512 512 L 0 512 z" stroke-linecap="round" />
</g>
<g transform="matrix(1.79 0 0 1.79 313.74 258.36)" id="1xBsk2n9FZp60Rz1O-ceJ" >
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-250.97, -362.41)" d="M 250.908 330.267 L 193.126 415.005 L 180.938 406.694 L 244.802 313.037 C 246.174 311.024 248.453 309.819 250.889 309.816 C 253.326 309.814 255.606 311.015 256.982 313.026 L 320.994 406.536 L 308.821 414.869 L 250.908 330.267 Z" stroke-linecap="round" />
</g>
<g transform="matrix(1.81 0 0 1.81 145 256.15)" id="KxN7E9YpbyPgz0S4z4Cl6" >
<path style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-dashoffset: 0; stroke-linejoin: round; stroke-miterlimit: 2; fill: rgb(44,45,60); fill-rule: evenodd; opacity: 1;" vector-effect="non-scaling-stroke" transform=" translate(-115.14, -528.06)" d="M 87.642 581.398 L 154.757 482.977 L 142.638 474.713 L 75.523 573.134 L 87.642 581.398 Z" stroke-linecap="round" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

+4
View File
@@ -2,6 +2,10 @@ function meshtastic_version {
meshtastic_version=$(python3 bin/buildinfo.py short)
echo -n "$meshtastic_version"
}
function web_version {
web_version=$(cat bin/web.version)
echo -n "$web_version"
}
function git_commits_num {
total_commits=$(git rev-list --all --count)
echo -n "$total_commits"
+1
View File
@@ -0,0 +1 @@
2.5.3
+43
View File
@@ -0,0 +1,43 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_opi",
"partitions": "default_16MB.csv"
},
"core": "esp32",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DARDUINO_USB_CDC_ON_BOOT=0",
"-DARDUINO_USB_MODE=1",
"-DARDUINO_RUNNING_CORE=1",
"-DARDUINO_EVENT_RUNNING_CORE=0"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [["0x303A", "0x1001"]],
"mcu": "esp32s3",
"variant": "ESP32-S3-WROOM-1-N16R8"
},
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"default_tool": "esp-builtin",
"onboard_tools": ["esp-builtin"],
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino", "espidf"],
"name": "ESP32-S3-WROOM-1-N16R8 (16 MB Flash, 8 MB PSRAM)",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 524288,
"maximum_size": 16777216,
"require_upload_port": true,
"speed": 921600
},
"monitor": {
"speed": 115200
},
"url": "https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdf",
"vendor": "Espressif"
}
+53
View File
@@ -0,0 +1,53 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x4405"],
["0x239A", "0x0029"],
["0x239A", "0x002A"]
],
"usb_product": "HT-n5262",
"mcu": "nrf52840",
"variant": "heltec_mesh_pocket",
"variants_dir": "variants",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"onboard_tools": ["jlink"],
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Heltec nrf (Adafruit BSP)",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://heltec.org/project/meshpocket/",
"vendor": "Heltec"
}
+3 -1
View File
@@ -2,7 +2,8 @@
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_8MB.csv"
"partitions": "default_8MB.csv",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
@@ -15,6 +16,7 @@
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"psram_type": "opi",
"hwids": [
["0x303A", "0x1001"],
["0x303A", "0x0002"]
+3 -1
View File
@@ -2,7 +2,8 @@
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_8MB.csv"
"partitions": "default_8MB.csv",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
@@ -15,6 +16,7 @@
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"psram_type": "opi",
"hwids": [
["0x303A", "0x1001"],
["0x303A", "0x0002"]
+3 -1
View File
@@ -2,7 +2,8 @@
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_8MB.csv"
"partitions": "default_8MB.csv",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
@@ -15,6 +16,7 @@
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"psram_type": "opi",
"hwids": [
["0x303A", "0x1001"],
["0x303A", "0x0002"]
+1
View File
@@ -18,6 +18,7 @@
"f_boot": "120000000L",
"boot": "qio",
"flash_mode": "qio",
"psram_type": "opi",
"hwids": [["0x1A86", "0x7523"]],
"mcu": "esp32s3",
"variant": "esp32s3"
+1
View File
@@ -15,6 +15,7 @@
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"psram_type": "opi",
"hwids": [["0x2886", "0x0059"]],
"mcu": "esp32s3",
"variant": "seeed-xiao-s3"
+54
View File
@@ -0,0 +1,54 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v7.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_MDBT50Q_RX -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [["0x2886", "0x0059"]],
"usb_product": "XIAO-BOOT",
"mcu": "nrf52840",
"variant": "seeed_solar_node",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "7.3.0",
"sd_fwid": "0x0123"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "seeed_solar_node",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": [
"jlink",
"nrfjprog",
"nrfutil",
"stlink",
"cmsis-dap",
"blackmagic"
],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://www.seeedstudio.com/Seeed-XIAO-BLE-Sense-nRF52840-p-5253.html",
"vendor": "Seeed Studio"
}
+4 -3
View File
@@ -16,6 +16,7 @@
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"psram_type": "opi",
"hwids": [
["0x303A", "0x1001"],
["0x303A", "0x0002"]
@@ -23,16 +24,16 @@
"mcu": "esp32s3",
"variant": "t-watch-s3"
},
"connectivity": ["wifi", "bluetooth"],
"connectivity": ["wifi", "bluetooth", "lora"],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": ["arduino"],
"name": "LilyGo T-Watch 2020 V3",
"upload": {
"flash_size": "8MB",
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 8388608,
"maximum_size": 16777216,
"require_upload_port": true,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
+9 -2
View File
@@ -1,9 +1,16 @@
meshtasticd (2.5.22.0) UNRELEASED; urgency=medium
meshtasticd (2.6.9.0) UNRELEASED; urgency=medium
[ Austin Lane ]
* Initial packaging
* GitHub Actions Automatic version bump
* GitHub Actions Automatic version bump
* GitHub Actions Automatic version bump
* GitHub Actions Automatic version bump
-- Austin Lane <github-actions[bot]@users.noreply.github.com> Wed, 05 Feb 2025 01:10:33 +0000
[ ]
* GitHub Actions Automatic version bump
[ ]
* GitHub Actions Automatic version bump
-- <github-actions[bot]@users.noreply.github.com> Thu, 15 May 2025 11:13:30 +0000
+5 -4
View File
@@ -5,13 +5,14 @@ export PLATFORMIO_PACKAGES_DIR=pio/packages
export PLATFORMIO_CORE_DIR=pio/core
# Download libraries to `pio`
platformio pkg install -e native
platformio pkg install -e native -t platformio/tool-scons@4.40502.0
platformio pkg install -e native-tft
platformio pkg install -e native-tft -t platformio/tool-scons@4.40502.0
# Compress `pio` directory to prevent dh_clean from sanitizing it
tar -cf pio.tar pio/
rm -rf pio
# Download the latest meshtastic/web release build.tar to `web.tar`
curl -L https://github.com/meshtastic/web/releases/latest/download/build.tar -o web.tar
# Download the meshtastic/web release build.tar to `web.tar`
web_ver=$(cat bin/web.version)
curl -L "https://github.com/meshtastic/web/releases/download/v$web_ver/build.tar" -o web.tar
package=$(dpkg-parsechangelog --show-field Source)
+8 -3
View File
@@ -21,14 +21,19 @@ Build-Depends: debhelper-compat (= 13),
openssl,
libssl-dev,
libulfius-dev,
liborcania-dev
liborcania-dev,
libx11-dev,
libinput-dev,
libxkbcommon-x11-dev
Standards-Version: 4.6.2
Homepage: https://github.com/meshtastic/firmware
Rules-Requires-Root: no
Package: meshtasticd
Architecture: any
Depends: ${misc:Depends}, ${shlibs:Depends}
Depends: adduser,
${misc:Depends},
${shlibs:Depends}
Description: Meshtastic daemon for communicating with Meshtastic devices
Meshtastic is an off-grid text communication platform that uses inexpensive
LoRa radios.
LoRa radios.
+2 -1
View File
@@ -1,5 +1,6 @@
var/lib/meshtasticd
etc/meshtasticd
etc/meshtasticd/config.d
etc/meshtasticd/available.d
usr/share/meshtasticd/web
etc/meshtasticd/ssl
etc/meshtasticd/ssl
+5 -5
View File
@@ -1,8 +1,8 @@
.pio/build/native/meshtasticd usr/sbin
.pio/build/native-tft/meshtasticd usr/bin
bin/config.yaml etc/meshtasticd
bin/config.d/* etc/meshtasticd/available.d
bin/config.yaml etc/meshtasticd
bin/config.d/* etc/meshtasticd/available.d
bin/meshtasticd.service lib/systemd/system
bin/meshtasticd.service lib/systemd/system
web/* usr/share/meshtasticd/web
web/* usr/share/meshtasticd/web
Vendored Executable
+79
View File
@@ -0,0 +1,79 @@
#!/bin/sh
# postinst script for meshtasticd
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postinst> `configure' <most-recently-configured-version>
# * <old-postinst> `abort-upgrade' <new version>
# * <conflictor's-postinst> `abort-remove' `in-favour' <package>
# <new-version>
# * <postinst> `abort-remove'
# * <deconfigured's-postinst> `abort-deconfigure' `in-favour'
# <failed-install-package> <version> `removing'
# <conflicting-package> <version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
configure|reconfigure)
# create spi group (for udev rules)
# this group already exists on Raspberry Pi OS
getent group spi >/dev/null 2>/dev/null || addgroup --system spi
# create a meshtasticd group and user
getent passwd meshtasticd >/dev/null 2>/dev/null || adduser --system --home /var/lib/meshtasticd --no-create-home meshtasticd
getent group meshtasticd >/dev/null 2>/dev/null || addgroup --system meshtasticd
adduser meshtasticd meshtasticd >/dev/null 2>/dev/null
adduser meshtasticd spi >/dev/null 2>/dev/null
# add meshtasticd user to appropriate groups (if they exist)
getent group gpio >/dev/null 2>/dev/null && adduser meshtasticd gpio >/dev/null 2>/dev/null
getent group plugdev >/dev/null 2>/dev/null && adduser meshtasticd plugdev >/dev/null 2>/dev/null
getent group dialout >/dev/null 2>/dev/null && adduser meshtasticd dialout >/dev/null 2>/dev/null
getent group i2c >/dev/null 2>/dev/null && adduser meshtasticd i2c >/dev/null 2>/dev/null
getent group video >/dev/null 2>/dev/null && adduser meshtasticd video >/dev/null 2>/dev/null
getent group audio >/dev/null 2>/dev/null && adduser meshtasticd audio >/dev/null 2>/dev/null
getent group input >/dev/null 2>/dev/null && adduser meshtasticd input >/dev/null 2>/dev/null
# migrate /root/.portduino to /var/lib/meshtasticd/.portduino
# should only run once, upon upgrade from < 2.6.9
if [ -n "$2" ] && dpkg --compare-versions "$2" lt 2.6.9; then
if [ -d /root/.portduino ] && [ ! -e /var/lib/meshtasticd/.portduino ]; then
cp -r /root/.portduino /var/lib/meshtasticd/.portduino
echo "Migrated meshtasticd VFS from /root/.portduino to /var/lib/meshtasticd/.portduino"
echo "meshtasticd now runs as the 'meshtasticd' user, not 'root'."
echo "See https://github.com/meshtastic/firmware/pull/6718 for details"
fi
fi
if [ -d /var/lib/meshtasticd ]; then
chown -R meshtasticd:meshtasticd /var/lib/meshtasticd
fi
if [ -d /etc/meshtasticd ]; then
chown -R meshtasticd:meshtasticd /etc/meshtasticd
fi
if [ -d /usr/share/meshtasticd ]; then
chown -R meshtasticd:meshtasticd /usr/share/meshtasticd
fi
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0
Vendored Executable
+41
View File
@@ -0,0 +1,41 @@
#!/bin/sh
# postrm script for meshtasticd
#
# see: dh_installdeb(1)
set -e
# summary of how this script can be called:
# * <postrm> `remove'
# * <postrm> `purge'
# * <old-postrm> `upgrade' <new-version>
# * <new-postrm> `failed-upgrade' <old-version>
# * <new-postrm> `abort-install'
# * <new-postrm> `abort-install' <old-version>
# * <new-postrm> `abort-upgrade' <old-version>
# * <disappearer's-postrm> `disappear' <overwriter>
# <overwriter-version>
# for details, see http://www.debian.org/doc/debian-policy/ or
# the debian-policy package
case "$1" in
purge|remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear)
# Only remove /var/lib/meshtasticd on purge
if [ "${1}" = "purge" ] ; then
rm -rf /var/lib/meshtasticd
fi
;;
*)
echo "postrm called with unknown argument \`$1'" >&2
exit 1
;;
esac
# dh_installdeb will replace this with shell code automatically
# generated by other debhelper scripts.
#DEBHELPER#
exit 0
+4
View File
@@ -0,0 +1,4 @@
# Set spidev ownership to 'spi' group.
SUBSYSTEM=="spidev", KERNEL=="spidev*", GROUP="spi", MODE="0660"
# Allow access to USB CH341 devices
SUBSYSTEM=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="5512", MODE="0666"
+2 -2
View File
@@ -26,7 +26,7 @@ override_dh_auto_build:
mkdir -p web && tar -xf web.tar -C web
gunzip web/ -r
# Build with platformio
$(PIO_ENV) platformio run -e native
$(PIO_ENV) platformio run -e native-tft
# Move the binary and default config to the correct name
mv .pio/build/native/program .pio/build/native/meshtasticd
mv .pio/build/native-tft/program .pio/build/native-tft/meshtasticd
cp bin/config-dist.yaml bin/config.yaml
+69 -7
View File
@@ -10,6 +10,8 @@
# - https://docs.pagure.org/rpkg-util/v3/index.html
# - https://docs.fedoraproject.org/en-US/packaging-guidelines/Versioning/
%global meshtasticd_user meshtasticd
Name: meshtasticd
# Version Ex: 2.5.19
Version: {{{ meshtastic_version }}}
@@ -21,7 +23,7 @@ Summary: Meshtastic daemon for communicating with Meshtastic devices
License: GPL-3.0
URL: https://github.com/meshtastic/firmware
Source0: {{{ git_dir_pack }}}
Source1: https://github.com/meshtastic/web/releases/latest/download/build.tar
Source1: https://github.com/meshtastic/web/releases/download/v{{{ web_version }}}/build.tar
BuildRequires: systemd-rpm-macros
BuildRequires: python3-devel
@@ -42,6 +44,12 @@ BuildRequires: pkgconfig(openssl)
BuildRequires: pkgconfig(liborcania)
BuildRequires: pkgconfig(libyder)
BuildRequires: pkgconfig(libulfius)
# TFT components:
BuildRequires: pkgconfig(x11)
BuildRequires: pkgconfig(libinput)
BuildRequires: pkgconfig(xkbcommon-x11)
Requires: systemd-udev
%description
Meshtastic daemon for controlling Meshtastic devices. Meshtastic is an off-grid
@@ -55,19 +63,29 @@ tar -xf %{SOURCE1} -C web
gzip -dr web
%build
# Use the “native” environment from platformio to build a Linux binary
platformio run -e native
# Use the “native-tft” environment from platformio to build a Linux binary
platformio run -e native-tft
%install
mkdir -p %{buildroot}%{_sbindir}
install -m 0755 .pio/build/native/program %{buildroot}%{_sbindir}/meshtasticd
# Install meshtasticd binary
mkdir -p %{buildroot}%{_bindir}
install -m 0755 .pio/build/native-tft/program %{buildroot}%{_bindir}/meshtasticd
# Install portduino VFS dir
install -p -d -m 0770 %{buildroot}%{_localstatedir}/lib/meshtasticd
# Install udev rules
mkdir -p %{buildroot}%{_udevrulesdir}
install -m 0644 bin/99-meshtasticd-udev.rules %{buildroot}%{_udevrulesdir}/99-meshtasticd-udev.rules
# Install config dirs
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd
install -m 0644 bin/config-dist.yaml %{buildroot}%{_sysconfdir}/meshtasticd/config.yaml
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/config.d
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/available.d
cp -r bin/config.d/* %{buildroot}%{_sysconfdir}/meshtasticd/available.d
# Install systemd service
install -D -m 0644 bin/meshtasticd.service %{buildroot}%{_unitdir}/meshtasticd.service
# Install the web files under /usr/share/meshtasticd/web
@@ -76,10 +94,54 @@ cp -r web/* %{buildroot}%{_datadir}/meshtasticd/web
# Install default SSL storage directory (for web)
mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl
%pre
# create spi group (for udev rules)
getent group spi > /dev/null || groupadd -r spi
# create a meshtasticd group and user
getent group %{meshtasticd_user} > /dev/null || groupadd -r %{meshtasticd_user}
getent passwd %{meshtasticd_user} > /dev/null || \
useradd -r -d %{_localstatedir}/lib/meshtasticd -g %{meshtasticd_user} -G spi \
-s /sbin/nologin -c "Meshtastic Daemon" %{meshtasticd_user}
# add meshtasticd user to appropriate groups (if they exist)
getent group gpio > /dev/null && usermod -a -G gpio %{meshtasticd_user} > /dev/null
getent group plugdev > /dev/null && usermod -a -G plugdev %{meshtasticd_user} > /dev/null
getent group dialout > /dev/null && usermod -a -G dialout %{meshtasticd_user} > /dev/null
getent group i2c > /dev/null && usermod -a -G i2c %{meshtasticd_user} > /dev/null
getent group video > /dev/null && usermod -a -G video %{meshtasticd_user} > /dev/null
getent group audio > /dev/null && usermod -a -G audio %{meshtasticd_user} > /dev/null
getent group input > /dev/null && usermod -a -G input %{meshtasticd_user} > /dev/null
exit 0
%triggerin -- meshtasticd < 2.6.9
# migrate .portduino (if it exists and hasn’t already been copied)
if [ -d /root/.portduino ] && [ ! -e /var/lib/meshtasticd/.portduino ]; then
mkdir -p /var/lib/meshtasticd
cp -r /root/.portduino /var/lib/meshtasticd/.portduino
chown -R %{meshtasticd_user}:%{meshtasticd_user} \
%{_localstatedir}/lib/meshtasticd || :
# Fix SELinux labels if present (no-op on non-SELinux systems)
restorecon -R /var/lib/meshtasticd/.portduino 2>/dev/null || :
echo "Migrated meshtasticd VFS from /root/.portduino to /var/lib/meshtasticd/.portduino"
echo "meshtasticd now runs as the 'meshtasticd' user, not 'root'."
echo "See https://github.com/meshtastic/firmware/pull/6718 for details"
fi
%post
%systemd_post meshtasticd.service
%preun
%systemd_preun meshtasticd.service
%postun
%systemd_postun_with_restart meshtasticd.service
%files
%defattr(-,%{meshtasticd_user},%{meshtasticd_user})
%license LICENSE
%doc README.md
%{_sbindir}/meshtasticd
%{_bindir}/meshtasticd
%dir %{_localstatedir}/lib/meshtasticd
%{_udevrulesdir}/99-meshtasticd-udev.rules
%dir %{_sysconfdir}/meshtasticd
%dir %{_sysconfdir}/meshtasticd/config.d
%dir %{_sysconfdir}/meshtasticd/available.d
@@ -92,4 +154,4 @@ mkdir -p %{buildroot}%{_sysconfdir}/meshtasticd/ssl
%dir %{_sysconfdir}/meshtasticd/ssl
%changelog
%autochangelog
%autochangelog
+74 -23
View File
@@ -51,18 +51,26 @@ build_flags = -Wno-missing-field-initializers
-DMESHTASTIC_EXCLUDE_REMOTEHARDWARE=1
-DMESHTASTIC_EXCLUDE_HEALTH_TELEMETRY=1
-DMESHTASTIC_EXCLUDE_POWERSTRESS=1 ; exclude power stress test module from main firmware
-DMESHTASTIC_EXCLUDE_GENERIC_THREAD_MODULE=1
#-DBUILD_EPOCH=$UNIX_TIME
#-D OLED_PL=1
monitor_speed = 115200
monitor_filters = direct
lib_deps =
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/e16cee124fe26490cb14880c679321ad8ac89c95.zip
# renovate: datasource=git-refs depName=meshtastic-esp8266-oled-ssd1306 packageName=https://github.com/meshtastic/esp8266-oled-ssd1306 gitBranch=master
https://github.com/meshtastic/esp8266-oled-ssd1306/archive/0119501e9983bd894830b02f545c377ee08d66fe.zip
# renovate: datasource=custom.pio depName=OneButton packageName=mathertel/library/OneButton
mathertel/OneButton@2.6.1
# renovate: datasource=git-refs depName=meshtastic-arduino-fsm packageName=https://github.com/meshtastic/arduino-fsm gitBranch=master
https://github.com/meshtastic/arduino-fsm/archive/7db3702bf0cfe97b783d6c72595e3f38e0b19159.zip
# renovate: datasource=git-refs depName=meshtastic-TinyGPSPlus packageName=https://github.com/meshtastic/TinyGPSPlus gitBranch=master
https://github.com/meshtastic/TinyGPSPlus/archive/71a82db35f3b973440044c476d4bcdc673b104f4.zip
# renovate: datasource=git-refs depName=meshtastic-ArduinoThread packageName=https://github.com/meshtastic/ArduinoThread gitBranch=master
https://github.com/meshtastic/ArduinoThread/archive/7c3ee9e1951551b949763b1f5280f8db1fa4068d.zip
# renovate: datasource=custom.pio depName=Nanopb packageName=nanopb/library/Nanopb
nanopb/Nanopb@0.4.91
# renovate: datasource=custom.pio depName=ErriezCRC32 packageName=erriez/library/ErriezCRC32
erriez/ErriezCRC32@1.0.1
; Used for the code analysis in PIO Home / Inspect
@@ -78,6 +86,7 @@ check_flags =
framework = arduino
lib_deps =
${env.lib_deps}
# renovate: datasource=custom.pio depName=NonBlockingRTTTL packageName=end2endzone/library/NonBlockingRTTTL
end2endzone/NonBlockingRTTTL@1.3.0
build_flags = ${env.build_flags} -Os
build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/niche/>
@@ -85,57 +94,99 @@ build_src_filter = ${env.build_src_filter} -<platform/portduino/> -<graphics/nic
; Common libs for communicating over TCP/IP networks such as MQTT
[networking_base]
lib_deps =
knolleary/PubSubClient@2.8
arduino-libraries/NTPClient@3.1.0
# renovate: datasource=custom.pio depName=TBPubSubClient packageName=thingsboard/library/TBPubSubClient
thingsboard/TBPubSubClient@2.12.1
# renovate: datasource=custom.pio depName=NTPClient packageName=arduino-libraries/library/NTPClient
arduino-libraries/NTPClient@3.2.1
# renovate: datasource=custom.pio depName=Syslog packageName=arcao/library/Syslog
arcao/Syslog@2.0.0
[radiolib_base]
lib_deps =
# renovate: datasource=custom.pio depName=RadioLib packageName=jgromes/library/RadioLib
jgromes/RadioLib@7.1.2
[device-ui_base]
lib_deps =
https://github.com/meshtastic/device-ui/archive/99171e87a70452395b56cce713a951c1c2964370.zip
# renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master
https://github.com/meshtastic/device-ui/archive/0e9bb792bb4b015b487397427781eda2767c87e6.zip
; Common libs for environmental measurements in telemetry module
; (not included in native / portduino)
[environmental_base]
lib_deps =
adafruit/Adafruit BusIO@1.17.0
# renovate: datasource=custom.pio depName=Adafruit BusIO packageName=adafruit/library/Adafruit BusIO
adafruit/Adafruit BusIO@1.17.1
# renovate: datasource=custom.pio depName=Adafruit Unified Sensor packageName=adafruit/library/Adafruit Unified Sensor
adafruit/Adafruit Unified Sensor@1.1.15
# renovate: datasource=custom.pio depName=Adafruit BMP280 packageName=adafruit/library/Adafruit BMP280 Library
adafruit/Adafruit BMP280 Library@2.6.8
# renovate: datasource=custom.pio depName=Adafruit BMP085 packageName=adafruit/library/Adafruit BMP085 Library
adafruit/Adafruit BMP085 Library@1.2.4
adafruit/Adafruit BME280 Library@2.2.4
adafruit/Adafruit BMP3XX Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit BME280 packageName=adafruit/library/Adafruit BME280 Library
adafruit/Adafruit BME280 Library@2.3.0
# renovate: datasource=custom.pio depName=Adafruit DPS310 packageName=adafruit/library/Adafruit DPS310
adafruit/Adafruit DPS310@1.1.5
# renovate: datasource=custom.pio depName=Adafruit MCP9808 packageName=adafruit/library/Adafruit MCP9808 Library
adafruit/Adafruit MCP9808 Library@2.0.2
# renovate: datasource=custom.pio depName=Adafruit INA260 packageName=adafruit/library/Adafruit INA260 Library
adafruit/Adafruit INA260 Library@1.5.2
# renovate: datasource=custom.pio depName=Adafruit INA219 packageName=adafruit/library/Adafruit INA219
adafruit/Adafruit INA219@1.2.3
adafruit/Adafruit MAX1704X@1.0.3
adafruit/Adafruit SHTC3 Library@1.0.1
adafruit/Adafruit LPS2X@2.0.6
adafruit/Adafruit SHT31 Library@2.2.2
adafruit/Adafruit PM25 AQI Sensor@1.2.0
# renovate: datasource=custom.pio depName=Adafruit PM25 AQI Sensor packageName=adafruit/library/Adafruit PM25 AQI Sensor
adafruit/Adafruit PM25 AQI Sensor@2.0.0
# renovate: datasource=custom.pio depName=Adafruit MPU6050 packageName=adafruit/library/Adafruit MPU6050
adafruit/Adafruit MPU6050@2.2.6
# renovate: datasource=custom.pio depName=Adafruit LIS3DH packageName=adafruit/library/Adafruit LIS3DH
adafruit/Adafruit LIS3DH@1.3.0
# renovate: datasource=custom.pio depName=Adafruit AHTX0 packageName=adafruit/library/Adafruit AHTX0
adafruit/Adafruit AHTX0@2.0.5
# renovate: datasource=custom.pio depName=Adafruit LSM6DS packageName=adafruit/library/Adafruit LSM6DS
adafruit/Adafruit LSM6DS@4.7.4
adafruit/Adafruit VEML7700 Library@2.1.6
adafruit/Adafruit SHT4x Library@1.0.5
# renovate: datasource=custom.pio depName=Adafruit TSL2591 packageName=adafruit/library/Adafruit TSL2591 Library
adafruit/Adafruit TSL2591 Library@1.4.5
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.0
ClosedCube OPT3001@1.1.2
# renovate: datasource=custom.pio depName=EmotiBit MLX90632 packageName=emotibit/library/EmotiBit MLX90632
emotibit/EmotiBit MLX90632@1.0.8
# renovate: datasource=custom.pio depName=Adafruit MLX90614 packageName=adafruit/library/Adafruit MLX90614 Library
adafruit/Adafruit MLX90614 Library@2.1.5
https://github.com/boschsensortec/Bosch-BSEC2-Library/archive/v1.7.2502.zip
boschsensortec/BME68x Sensor Library@1.1.40407
# renovate: datasource=github-tags depName=INA3221 packageName=KodinLanewave/INA3221
https://github.com/KodinLanewave/INA3221/archive/1.0.1.zip
# renovate: datasource=custom.pio depName=QMC5883L Compass packageName=mprograms/library/QMC5883LCompass
mprograms/QMC5883LCompass@1.2.3
# renovate: datasource=custom.pio depName=DFRobot_RTU packageName=dfrobot/library/DFRobot_RTU
dfrobot/DFRobot_RTU@1.0.3
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
# renovate: datasource=git-refs depName=DFRobot_RainfallSensor packageName=https://github.com/DFRobot/DFRobot_RainfallSensor gitBranch=master
https://github.com/DFRobot/DFRobot_RainfallSensor/archive/38fea5e02b40a5430be6dab39a99a6f6347d667e.zip
# renovate: datasource=custom.pio depName=INA226 packageName=robtillaart/library/INA226
robtillaart/INA226@0.6.4
; Health Sensor Libraries
# renovate: datasource=custom.pio depName=SparkFun MAX3010x packageName=sparkfun/library/SparkFun MAX3010x Pulse and Proximity Sensor Library
sparkfun/SparkFun MAX3010x Pulse and Proximity Sensor Library@1.1.2
# renovate: datasource=custom.pio depName=SparkFun 9DoF IMU Breakout ICM 20948 packageName=sparkfun/library/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
sparkfun/SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library@1.3.2
; (not included in native / portduino)
[environmental_extra]
lib_deps =
# renovate: datasource=custom.pio depName=Adafruit BMP3XX packageName=adafruit/library/Adafruit BMP3XX Library
adafruit/Adafruit BMP3XX Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit MAX1704X packageName=adafruit/library/Adafruit MAX1704X
adafruit/Adafruit MAX1704X@1.0.3
# renovate: datasource=custom.pio depName=Adafruit SHTC3 packageName=adafruit/library/Adafruit SHTC3 Library
adafruit/Adafruit SHTC3 Library@1.0.1
# renovate: datasource=custom.pio depName=Adafruit LPS2X packageName=adafruit/library/Adafruit LPS2X
adafruit/Adafruit LPS2X@2.0.6
# renovate: datasource=custom.pio depName=Adafruit SHT31 packageName=adafruit/library/Adafruit SHT31 Library
adafruit/Adafruit SHT31 Library@2.2.2
# renovate: datasource=custom.pio depName=Adafruit VEML7700 packageName=adafruit/library/Adafruit VEML7700 Library
adafruit/Adafruit VEML7700 Library@2.1.6
# renovate: datasource=custom.pio depName=Adafruit SHT4x packageName=adafruit/library/Adafruit SHT4x Library
adafruit/Adafruit SHT4x Library@1.0.5
# renovate: datasource=custom.pio depName=SparkFun Qwiic Scale NAU7802 packageName=sparkfun/library/SparkFun Qwiic Scale NAU7802 Arduino Library
sparkfun/SparkFun Qwiic Scale NAU7802 Arduino Library@1.0.6
# renovate: datasource=custom.pio depName=ClosedCube OPT3001 packageName=closedcube/library/ClosedCube OPT3001
ClosedCube OPT3001@1.1.2
# renovate: datasource=custom.pio depName=Bosch BSEC2 packageName=boschsensortec/library/bsec2
boschsensortec/bsec2@1.10.2610
# renovate: datasource=custom.pio depName=Bosch BME68x packageName=boschsensortec/library/BME68x Sensor Library
boschsensortec/BME68x Sensor Library@1.3.40408
# renovate: datasource=git-refs depName=meshtastic-DFRobot_LarkWeatherStation packageName=https://github.com/meshtastic/DFRobot_LarkWeatherStation gitBranch=master
https://github.com/meshtastic/DFRobot_LarkWeatherStation/archive/4de3a9cadef0f6a5220a8a906cf9775b02b0040d.zip
+99
View File
@@ -0,0 +1,99 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
":dependencyDashboard",
":semanticCommitTypeAll(chore)",
":ignoreModulesAndTests",
"group:recommended",
"replacements:all",
"workarounds:all"
],
"forkProcessing": "enabled",
"ignoreDeps": [
"protobufs"
],
"git-submodules": {
"enabled": true
},
"pip_requirements": {
"managerFilePatterns": [
"/bin/bump_metainfo/requirements.txt/"
]
},
"commitMessageTopic": "{{depName}}",
"labels": [
"dependencies"
],
"customDatasources": {
"pio": {
"description": "PlatformIO Registry",
"defaultRegistryUrlTemplate": "https://api.registry.platformio.org/v3/packages/{{packageName}}",
"format": "json",
"transformTemplates": [
"{\"releases\": [$map($.versions, function($v) { { \"version\": $v.name, \"releaseTimestamp\": $v.released_at } })], \"homepage\": $encodeUrl($join([\"https://registry.platformio.org/\",$.type,\"/\",$.owner.username,\"/\",$.name])) }"
]
}
},
"customManagers": [
{
"customType": "regex",
"description": "Match meshtastic/web version",
"managerFilePatterns": [
"/bin/web.version/"
],
"matchStrings": [
"(?<currentValue>.+)$"
],
"datasourceTemplate": "github-releases",
"depNameTemplate": "meshtastic/web",
"versioningTemplate": "semver-coerced"
},
{
"customType": "regex",
"description": "Match normal PIO dependencies",
"managerFilePatterns": [
"/.*\\.ini$/"
],
"matchStrings": [
"# renovate: datasource=(?<datasource>.*?)(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\s+?.+?@(?<currentValue>.+?)\\s"
],
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}"
},
{
"customType": "regex",
"description": "Match PIO zipped dependencies with github tag ref",
"managerFilePatterns": [
"/.*\\.ini$/"
],
"matchStrings": [
"# renovate: datasource=github-tags(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\s+?https://.+?archive/(?<currentValue>.+?).zip\\s"
],
"datasourceTemplate": "github-tags",
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}semver-coerced{{/if}}"
},
{
"customType": "regex",
"description": "Match PIO zipped dependencies with git commit ref",
"managerFilePatterns": [
"/.*\\.ini$/"
],
"matchStrings": [
"# renovate: datasource=git-refs(?: depName=(?<depName>.+?))? packageName=(?<packageName>.+?)(?: versioning=(?<versioning>[a-z-]+?))?\\sgitBranch=(?<gitBranch>.+?)\\s+?https://.+?archive/(?<currentDigest>.+?).zip\\s"
],
"datasourceTemplate": "git-refs",
"currentValueTemplate": "{{{gitBranch}}}",
"versioningTemplate": "{{#if versioning}}{{{versioning}}}{{else}}git{{/if}}"
}
],
"packageRules": [
{
"matchDepNames": [
"meshtastic/device-ui"
],
"reviewers": [
"mverch67"
],
"changelogUrl": "https://github.com/meshtastic/device-ui/compare/{{currentDigest}}...{{newDigest}}"
}
]
}
+34 -9
View File
@@ -6,6 +6,11 @@
NCP5623 rgb;
#endif
#ifdef HAS_LP5562
#include <graphics/NomadStarLED.h>
LP5562 rgbw;
#endif
#ifdef HAS_NEOPIXEL
#include <graphics/NeoPixel.h>
Adafruit_NeoPixel pixels(NEOPIXEL_COUNT, NEOPIXEL_DATA, NEOPIXEL_TYPE);
@@ -26,7 +31,7 @@ class AmbientLightingThread : public concurrency::OSThread
notifyDeepSleepObserver.observe(&notifyDeepSleep); // Let us know when shutdown() is issued.
// Enables Ambient Lighting by default if conditions are meet.
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
#ifdef HAS_RGB_LED
#ifdef ENABLE_AMBIENTLIGHTING
moduleConfig.ambient_lighting.led_state = true;
#endif
@@ -39,7 +44,7 @@ class AmbientLightingThread : public concurrency::OSThread
// moduleConfig.ambient_lighting.green = (myNodeInfo.my_node_num & 0x00FF00) >> 8;
// moduleConfig.ambient_lighting.blue = myNodeInfo.my_node_num & 0x0000FF;
#ifdef HAS_NCP5623
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
_type = type;
if (_type == ScanI2C::DeviceType::NONE) {
LOG_DEBUG("AmbientLighting Disable due to no RGB leds found on I2C bus");
@@ -47,17 +52,21 @@ class AmbientLightingThread : public concurrency::OSThread
return;
}
#endif
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
#ifdef HAS_RGB_LED
if (!moduleConfig.ambient_lighting.led_state) {
LOG_DEBUG("AmbientLighting Disable due to moduleConfig.ambient_lighting.led_state OFF");
disable();
return;
}
LOG_DEBUG("AmbientLighting init");
#ifdef HAS_NCP5623
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
if (_type == ScanI2C::NCP5623) {
rgb.begin();
#endif
#ifdef HAS_LP5562
} else if (_type == ScanI2C::LP5562) {
rgbw.begin();
#endif
#ifdef RGBLED_RED
pinMode(RGBLED_RED, OUTPUT);
pinMode(RGBLED_GREEN, OUTPUT);
@@ -70,7 +79,7 @@ class AmbientLightingThread : public concurrency::OSThread
#endif
setLighting();
#endif
#ifdef HAS_NCP5623
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
}
#endif
}
@@ -78,13 +87,13 @@ class AmbientLightingThread : public concurrency::OSThread
protected:
int32_t runOnce() override
{
#if defined(HAS_NCP5623) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
#ifdef HAS_NCP5623
if (_type == ScanI2C::NCP5623 && moduleConfig.ambient_lighting.led_state) {
#ifdef HAS_RGB_LED
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
if ((_type == ScanI2C::NCP5623 || _type == ScanI2C::LP5562) && moduleConfig.ambient_lighting.led_state) {
#endif
setLighting();
return 30000; // 30 seconds to reset from any animations that may have been running from Ext. Notification
#ifdef HAS_NCP5623
#if defined(HAS_NCP5623) || defined(HAS_LP5562)
}
#endif
#endif
@@ -108,6 +117,14 @@ class AmbientLightingThread : public concurrency::OSThread
rgb.setBlue(0);
LOG_INFO("OFF: NCP5623 Ambient lighting");
#endif
#ifdef HAS_LP5562
rgbw.setCurrent(0);
rgbw.setRed(0);
rgbw.setGreen(0);
rgbw.setBlue(0);
rgbw.setWhite(0);
LOG_INFO("OFF: LP5562 Ambient lighting");
#endif
#ifdef HAS_NEOPIXEL
pixels.clear();
pixels.show();
@@ -141,6 +158,14 @@ class AmbientLightingThread : public concurrency::OSThread
LOG_DEBUG("Init NCP5623 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef HAS_LP5562
rgbw.setCurrent(moduleConfig.ambient_lighting.current);
rgbw.setRed(moduleConfig.ambient_lighting.red);
rgbw.setGreen(moduleConfig.ambient_lighting.green);
rgbw.setBlue(moduleConfig.ambient_lighting.blue);
LOG_DEBUG("Init LP5562 Ambient light w/ current=%d, red=%d, green=%d, blue=%d", moduleConfig.ambient_lighting.current,
moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green, moduleConfig.ambient_lighting.blue);
#endif
#ifdef HAS_NEOPIXEL
pixels.fill(pixels.Color(moduleConfig.ambient_lighting.red, moduleConfig.ambient_lighting.green,
moduleConfig.ambient_lighting.blue),
+90 -77
View File
@@ -116,46 +116,55 @@ ButtonThread::ButtonThread() : OSThread("Button")
#endif
}
void ButtonThread::switchPage()
{
#ifdef BUTTON_PIN
#if !defined(USERPREFS_BUTTON_PIN)
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
moduleConfig.canned_message.inputbroker_pin_press) ||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS);
}
#endif
#if defined(USERPREFS_BUTTON_PIN)
if (((config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN) !=
moduleConfig.canned_message.inputbroker_pin_press) ||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS);
}
#endif
#endif
#if defined(ARCH_PORTDUINO)
if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) &&
(settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) ||
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS);
}
#endif
}
void ButtonThread::sendAdHocPosition()
{
service->refreshLocalMeshNode();
auto sentPosition = service->trySendPosition(NODENUM_BROADCAST, true);
if (screen) {
if (sentPosition)
screen->print("Sent ad-hoc position\n");
else
screen->print("Sent ad-hoc nodeinfo\n");
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
}
}
int32_t ButtonThread::runOnce()
{
// If the button is pressed we suppress CPU sleep until release
canSleep = true; // Assume we should not keep the board awake
#if defined(BUTTON_PIN) || defined(USERPREFS_BUTTON_PIN)
// #if defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M2)
// buzzer_updata();
// if (buttonPressed) {
// buttonPressed = false; // 清除标志
// LOG_INFO("PIN_BUTTON2 pressed!"); // 串口打印信息
// // off_currentTime = millis();
// while (digitalRead(PIN_BUTTON2) == HIGH) {
// if (cont < 40) {
// // unsigned long currentTime = millis(); // 获取当前时间
// // if (currentTime - off_currentTime >= 1000) {
// cont++;
// // off_currentTime = currentTime;
// // }
// delay(100);
// } else {
// currentState = OFF;
// isBuzzing = false;
// cont = 0;
// BEEP_STATE = false;
// analogWrite(M2_buzzer, 0);
// pinMode(M2_buzzer, INPUT);
// screen->setOn(false);
// cont = 0;
// LOG_INFO("GGGGGGGGGGGGGGGGGGGGGGGGG");
// pinMode(1, OUTPUT);
// digitalWrite(1, LOW);
// pinMode(6, OUTPUT);
// digitalWrite(6, LOW);
// }
// }
// }
// #endif
userButton.tick();
canSleep &= userButton.isIdle();
#elif defined(ARCH_PORTDUINO)
@@ -180,32 +189,27 @@ int32_t ButtonThread::runOnce()
// If a nag notification is running, stop it and prevent other actions
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
externalNotificationModule->stopNow();
return 50;
}
#ifdef BUTTON_PIN
#if !defined(USERPREFS_BUTTON_PIN)
if (((config.device.button_gpio ? config.device.button_gpio : BUTTON_PIN) !=
#endif
#if defined(USERPREFS_BUTTON_PIN)
if (((config.device.button_gpio ? config.device.button_gpio : USERPREFS_BUTTON_PIN) !=
#endif
moduleConfig.canned_message.inputbroker_pin_press) ||
!(moduleConfig.canned_message.updown1_enabled || moduleConfig.canned_message.rotary1_enabled) ||
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS);
}
#endif
#if defined(ARCH_PORTDUINO)
if ((settingsMap.count(user) != 0 && settingsMap[user] != RADIOLIB_NC) &&
(settingsMap[user] != moduleConfig.canned_message.inputbroker_pin_press) ||
!moduleConfig.canned_message.enabled) {
powerFSM.trigger(EVENT_PRESS);
break;
}
#ifdef ELECROW_ThinkNode_M1
sendAdHocPosition();
break;
#endif
switchPage();
break;
}
case BUTTON_EVENT_PRESSED_SCREEN: {
LOG_BUTTON("AltPress!");
#ifdef ELECROW_ThinkNode_M1
// If a nag notification is running, stop it and prevent other actions
if (moduleConfig.external_notification.enabled && (externalNotificationModule->nagCycleCutoff != UINT32_MAX)) {
externalNotificationModule->stopNow();
break;
}
switchPage();
break;
#endif
// turn screen on or off
screen_flag = !screen_flag;
if (screen)
@@ -215,22 +219,18 @@ int32_t ButtonThread::runOnce()
case BUTTON_EVENT_DOUBLE_PRESSED: {
LOG_BUTTON("Double press!");
service->refreshLocalMeshNode();
auto sentPosition = service->trySendPosition(NODENUM_BROADCAST, true);
if (screen) {
if (sentPosition)
screen->print("Sent ad-hoc position\n");
else
screen->print("Sent ad-hoc nodeinfo\n");
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
}
#ifdef ELECROW_ThinkNode_M1
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
break;
#endif
sendAdHocPosition();
break;
}
case BUTTON_EVENT_MULTI_PRESSED: {
LOG_BUTTON("Mulitipress! %hux", multipressClickCount);
switch (multipressClickCount) {
#if HAS_GPS
#if HAS_GPS && !defined(ELECROW_ThinkNode_M1)
// 3 clicks: toggle GPS
case 3:
if (!config.device.disable_triple_click && (gps != nullptr)) {
@@ -239,23 +239,23 @@ int32_t ButtonThread::runOnce()
screen->forceDisplay(true); // Force a new UI frame, then force an EInk update
}
break;
#elif defined(ELECROW_ThinkNode_M2)
#elif defined(ELECROW_ThinkNode_M1) || defined(ELECROW_ThinkNode_M2)
case 3:
LOG_INFO("3 clicks: toggle buzzer");
buzzer_flag = !buzzer_flag;
if (buzzer_flag) {
playBeep();
}
if (!buzzer_flag)
noTone(PIN_BUZZER);
break;
#endif
#if defined(USE_EINK) && defined(PIN_EINK_EN) // i.e. T-Echo
#if defined(USE_EINK) && defined(PIN_EINK_EN) && !defined(ELECROW_ThinkNode_M1) // i.e. T-Echo
// 4 clicks: toggle backlight
case 4:
digitalWrite(PIN_EINK_EN, digitalRead(PIN_EINK_EN) == LOW);
break;
#endif
#if defined(RAK_4631)
#if !MESHTASTIC_EXCLUDE_SCREEN && HAS_SCREEN
// 5 clicks: start accelerometer/magenetometer calibration for 30 seconds
case 5:
if (accelerometerThread) {
@@ -300,14 +300,23 @@ int32_t ButtonThread::runOnce()
#ifdef BUTTON_PIN_TOUCH
case BUTTON_EVENT_TOUCH_LONG_PRESSED: {
LOG_BUTTON("Touch press!");
if (screen) {
// Wake if asleep
if (powerFSM.getState() == &stateDARK)
powerFSM.trigger(EVENT_PRESS);
// Ignore if: no screen
if (!screen)
break;
// Update display (legacy behaviour)
screen->forceDisplay();
}
#ifdef TTGO_T_ECHO
// Ignore if: TX in progress
// Uncommon T-Echo hardware bug, LoRa TX triggers touch button
if (!RadioLibInterface::instance || RadioLibInterface::instance->isSending())
break;
#endif
// Wake if asleep
if (powerFSM.getState() == &stateDARK)
powerFSM.trigger(EVENT_PRESS);
// Update display (legacy behaviour)
screen->forceDisplay();
break;
}
#endif // BUTTON_PIN_TOUCH
@@ -349,8 +358,12 @@ void ButtonThread::attachButtonInterrupts()
#endif
#ifdef BUTTON_PIN_ALT
#ifdef ELECROW_ThinkNode_M2
wakeOnIrq(BUTTON_PIN_ALT, RISING);
#else
wakeOnIrq(BUTTON_PIN_ALT, FALLING);
#endif
#endif
#ifdef BUTTON_PIN_TOUCH
wakeOnIrq(BUTTON_PIN_TOUCH, FALLING);
+7 -6
View File
@@ -37,6 +37,9 @@ class ButtonThread : public concurrency::OSThread
void attachButtonInterrupts();
void detachButtonInterrupts();
void storeClickCount();
bool isBuzzing() { return buzzer_flag; }
void setScreenFlag(bool flag) { screen_flag = flag; }
bool getScreenFlag() { return screen_flag; }
// Disconnect and reconnect interrupts for light sleep
#ifdef ARCH_ESP32
@@ -72,14 +75,12 @@ class ButtonThread : public concurrency::OSThread
static void wakeOnIrq(int irq, int mode);
static void sendAdHocPosition();
static void switchPage();
// IRQ callbacks
static void userButtonPressed() { btnEvent = BUTTON_EVENT_PRESSED; }
static void userButtonPressedScreen()
{
if (millis() > c_holdOffTime) {
btnEvent = BUTTON_EVENT_PRESSED_SCREEN;
}
}
static void userButtonPressedScreen() { btnEvent = BUTTON_EVENT_PRESSED_SCREEN; }
static void userButtonDoublePressed() { btnEvent = BUTTON_EVENT_DOUBLE_PRESSED; }
static void userButtonMultiPressed(void *callerThread); // Retrieve click count from non-static Onebutton while still valid
static void userButtonPressedLongStart();
-3
View File
@@ -27,9 +27,6 @@ const char *DisplayFormatters::getModemPresetDisplayName(meshtastic_Config_LoRaC
case meshtastic_Config_LoRaConfig_ModemPreset_LONG_MODERATE:
return useShortName ? "LongM" : "LongMod";
break;
case meshtastic_Config_LoRaConfig_ModemPreset_VERY_LONG_SLOW:
return useShortName ? "VeryL" : "VLongSlow";
break;
default:
return useShortName ? "Custom" : "Invalid";
break;
+5 -4
View File
@@ -12,13 +12,14 @@
#include "SPILock.h"
#include "configuration.h"
#ifdef HAS_SDCARD
// Software SPI is used by MUI so disable SD card here until it's also implemented
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
#include <SD.h>
#include <SPI.h>
#ifdef SDCARD_USE_SPI1
SPIClass SPI1(HSPI);
#define SDHandler SPI1
SPIClass SPI_HSPI(HSPI);
#define SDHandler SPI_HSPI
#else
#define SDHandler SPI
#endif
@@ -306,7 +307,7 @@ void fsInit()
*/
void setupSDCard()
{
#ifdef HAS_SDCARD
#if defined(HAS_SDCARD) && !defined(SDCARD_USE_SOFT_SPI)
concurrency::LockGuard g(spiLock);
SDHandler.begin(SPI_SCK, SPI_MISO, SPI_MOSI);
if (!SD.begin(SDCARD_CS, SDHandler, SD_SPI_FREQUENCY)) {
+52 -30
View File
@@ -76,23 +76,47 @@ static const uint8_t ext_chrg_detect_value = EXT_CHRG_DETECT_VALUE;
#endif
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if __has_include(<Adafruit_INA219.h>)
INA219Sensor ina219Sensor;
INA226Sensor ina226Sensor;
INA260Sensor ina260Sensor;
INA3221Sensor ina3221Sensor;
#else
NullSensor ina219Sensor;
#endif
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if __has_include(<INA226.h>)
INA226Sensor ina226Sensor;
#else
NullSensor ina226Sensor;
#endif
#if __has_include(<Adafruit_INA260.h>)
INA260Sensor ina260Sensor;
#else
NullSensor ina260Sensor;
#endif
#if __has_include(<INA3221.h>)
INA3221Sensor ina3221Sensor;
#else
NullSensor ina3221Sensor;
#endif
#endif
#if !MESHTASTIC_EXCLUDE_I2C && !defined(ARCH_STM32WL)
#include "modules/Telemetry/Sensor/MAX17048Sensor.h"
#include <utility>
extern std::pair<uint8_t, TwoWire *> nodeTelemetrySensorsMap[_meshtastic_TelemetrySensorType_MAX + 1];
#if HAS_TELEMETRY && (!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR || !MESHTASTIC_EXCLUDE_POWER_TELEMETRY)
#if __has_include(<Adafruit_MAX1704X.h>)
MAX17048Sensor max17048Sensor;
#else
NullSensor max17048Sensor;
#endif
#endif
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT && !defined(ARCH_PORTDUINO)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && HAS_RAKPROT
RAK9154Sensor rak9154Sensor;
#endif
@@ -203,7 +227,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
*/
virtual int getBatteryPercent() override
{
#if defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU)
#if defined(HAS_RAKPROT) && !defined(HAS_PMU)
if (hasRAK()) {
return rak9154Sensor.getBusBatteryPercent();
}
@@ -248,15 +272,13 @@ class AnalogBatteryLevel : public HasBatteryLevel
virtual uint16_t getBattVoltage() override
{
#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && !defined(HAS_PMU) && \
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if HAS_TELEMETRY && defined(HAS_RAKPROT) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasRAK()) {
return getRAKVoltage();
}
#endif
#if HAS_TELEMETRY && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && \
!MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
#if HAS_TELEMETRY && !defined(ARCH_STM32WL) && !defined(HAS_PMU) && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR
if (hasINA()) {
return getINAVoltage();
}
@@ -380,6 +402,20 @@ class AnalogBatteryLevel : public HasBatteryLevel
// if we have a integrated device with a battery, we can assume that the battery is always connected
#ifdef BATTERY_IMMUTABLE
virtual bool isBatteryConnect() override { return true; }
#elif defined(ADC_V)
virtual bool isBatteryConnect() override
{
int lastReading = digitalRead(ADC_V);
// 判断值是否变化
for (int i = 2; i < 500; i++) {
int reading = digitalRead(ADC_V);
if (reading != lastReading) {
return false; // 有变化,USB供电, 没接电池
}
}
return true;
}
#else
virtual bool isBatteryConnect() override { return getBatteryPercent() != -1; }
#endif
@@ -412,8 +448,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
/// we can't be smart enough to say 'full'?
virtual bool isCharging() override
{
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(ARCH_PORTDUINO) && \
!defined(HAS_PMU)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && defined(HAS_RAKPROT) && !defined(HAS_PMU)
if (hasRAK()) {
return (rak9154Sensor.isCharging()) ? OptTrue : OptFalse;
}
@@ -421,7 +456,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
#ifdef EXT_CHRG_DETECT
return digitalRead(EXT_CHRG_DETECT) == ext_chrg_detect_value;
#else
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL) && \
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL) && \
!defined(DISABLE_INA_CHARGING_DETECTION)
if (hasINA()) {
// get current flow from INA sensor - negative value means power flowing into the battery
@@ -436,6 +471,8 @@ class AnalogBatteryLevel : public HasBatteryLevel
return isBatteryConnect() && isVbusIn();
#endif
#endif
// by default, we check the battery voltage only
return isVbusIn();
}
private:
@@ -466,7 +503,7 @@ class AnalogBatteryLevel : public HasBatteryLevel
}
#endif
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_PORTDUINO) && !defined(ARCH_STM32WL)
#if HAS_TELEMETRY && !MESHTASTIC_EXCLUDE_ENVIRONMENTAL_SENSOR && !defined(ARCH_STM32WL)
uint16_t getINAVoltage()
{
if (nodeTelemetrySensorsMap[meshtastic_TelemetrySensorType_INA219].first == config.power.device_battery_ina_address) {
@@ -533,9 +570,6 @@ Power::Power() : OSThread("Power")
{
statusHandler = {};
low_voltage_counter = 0;
#if defined(ELECROW_ThinkNode_M1) || defined(POWER_CFG)
low_voltage_counter_led3 = 0;
#endif
#ifdef DEBUG_HEAP
lastheap = memGet.getFreeHeap();
#endif
@@ -716,9 +750,6 @@ void Power::readPowerStatus()
const PowerStatus powerStatus2 = PowerStatus(hasBattery, usbPowered, isChargingNow, batteryVoltageMv, batteryChargePercent);
LOG_DEBUG("Battery: usbPower=%d, isCharging=%d, batMv=%d, batPct=%d", powerStatus2.getHasUSB(), powerStatus2.getIsCharging(),
powerStatus2.getBatteryVoltageMv(), powerStatus2.getBatteryChargePercent());
#if defined(ELECROW_ThinkNode_M1) || defined(POWER_CFG)
power_num = powerStatus2.getBatteryVoltageMv();
#endif
newStatus.notifyObservers(&powerStatus2);
#ifdef DEBUG_HEAP
if (lastheap != memGet.getFreeHeap()) {
@@ -766,9 +797,6 @@ void Power::readPowerStatus()
if (batteryLevel && powerStatus2.getHasBattery() && !powerStatus2.getHasUSB()) {
if (batteryLevel->getBattVoltage() < OCV[NUM_OCV_POINTS - 1]) {
low_voltage_counter++;
#if defined(ELECROW_ThinkNode_M1)
low_voltage_counter_led3 = low_voltage_counter;
#endif
LOG_DEBUG("Low voltage counter: %d/10", low_voltage_counter);
if (low_voltage_counter > 10) {
#ifdef ARCH_NRF52
@@ -781,13 +809,7 @@ void Power::readPowerStatus()
}
} else {
low_voltage_counter = 0;
#if defined(ELECROW_ThinkNode_M1)
low_voltage_counter_led3 = low_voltage_counter;
#endif
}
#ifdef POWER_CFG
low_voltage_counter_led3 = low_voltage_counter;
#endif
}
}
+11 -6
View File
@@ -19,7 +19,7 @@
#include "sleep.h"
#include "target_specific.h"
#if HAS_WIFI && !defined(ARCH_PORTDUINO)
#if HAS_WIFI && !defined(ARCH_PORTDUINO) || defined(MESHTASTIC_EXCLUDE_WIFI)
#include "mesh/wifi/WiFiAPClient.h"
#endif
@@ -269,9 +269,6 @@ Fsm powerFSM(&stateBOOT);
void PowerFSM_setup()
{
bool isRouter = (config.device.role == meshtastic_Config_DeviceConfig_Role_ROUTER ? 1 : 0);
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
bool hasPower = isPowered();
LOG_INFO("PowerFSM init, USB power=%d", hasPower ? 1 : 0);
@@ -383,6 +380,12 @@ void PowerFSM_setup()
// See: https://github.com/meshtastic/firmware/issues/1071
// 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 HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI)
bool isTrackerOrSensor = config.device.role == meshtastic_Config_DeviceConfig_Role_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_TAK_TRACKER ||
config.device.role == meshtastic_Config_DeviceConfig_Role_SENSOR;
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,
@@ -400,7 +403,9 @@ void PowerFSM_setup()
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs),
NULL, "Screen-on timeout");
}
#else
#endif // HAS_WIFI || !defined(MESHTASTIC_EXCLUDE_WIFI)
#else // (not) ARCH_ESP32
// If not ESP32, light-sleep not used. Check periodically if config has drifted out of stateDark
powerFSM.add_timed_transition(&stateDARK, &stateDARK,
Default::getConfiguredOrDefaultMs(config.display.screen_on_secs, default_screen_on_secs), NULL,
@@ -409,4 +414,4 @@ void PowerFSM_setup()
powerFSM.run_machine(); // run one iteration of the state machine, so we run our on enter tasks for the initial DARK state
}
#endif
#endif
+7
View File
@@ -152,6 +152,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#define MLX90614_ADDR_DEF 0x5A
#define CGRADSENS_ADDR 0x66
#define LTR390UV_ADDR 0x53
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34 // same adress as TCA8418
// -----------------------------------------------------------------------------
// ACCELEROMETER
@@ -170,6 +171,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
// LED
// -----------------------------------------------------------------------------
#define NCP5623_ADDR 0x38
#define LP5562_ADDR 0x30
// -----------------------------------------------------------------------------
// Security
@@ -295,6 +297,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#error HW_VENDOR must be defined
#endif
// Support multiple RGB LED configuration
#if defined(HAS_NCP5623) || defined(HAS_LP5562) || defined(RGBLED_RED) || defined(HAS_NEOPIXEL) || defined(UNPHONE)
#define HAS_RGB_LED
#endif
// -----------------------------------------------------------------------------
// Global switches to turn off features for a minimized build
// -----------------------------------------------------------------------------
+8 -2
View File
@@ -31,8 +31,8 @@ ScanI2C::FoundDevice ScanI2C::firstRTC() const
ScanI2C::FoundDevice ScanI2C::firstKeyboard() const
{
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB};
return firstOfOrNONE(5, types);
ScanI2C::DeviceType types[] = {CARDKB, TDECKKB, BBQ10KB, RAK14004, MPR121KB, TCA8418KB};
return firstOfOrNONE(6, types);
}
ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
@@ -41,6 +41,12 @@ ScanI2C::FoundDevice ScanI2C::firstAccelerometer() const
return firstOfOrNONE(8, types);
}
ScanI2C::FoundDevice ScanI2C::firstRGBLED() const
{
ScanI2C::DeviceType types[] = {NCP5623, LP5562};
return firstOfOrNONE(2, types);
}
ScanI2C::FoundDevice ScanI2C::find(ScanI2C::DeviceType) const
{
return DEVICE_NONE;
+5 -1
View File
@@ -18,7 +18,7 @@ class ScanI2C
TDECKKB,
BBQ10KB,
RAK14004,
PMU_AXP192_AXP2101,
PMU_AXP192_AXP2101, // has the same adress as the TCA8418KB
BME_680,
BME_280,
BMP_280,
@@ -49,6 +49,7 @@ class ScanI2C
VEML7700,
RCWL9620,
NCP5623,
LP5562,
TSL2591,
OPT3001,
MLX90632,
@@ -69,6 +70,7 @@ class ScanI2C
DFROBOT_RAIN,
DPS310,
LTR390UV,
TCA8418KB,
} DeviceType;
// typedef uint8_t DeviceAddress;
@@ -121,6 +123,8 @@ class ScanI2C
FoundDevice firstAccelerometer() const;
FoundDevice firstRGBLED() const;
virtual FoundDevice find(DeviceType) const;
virtual bool exists(DeviceType) const;
+13 -7
View File
@@ -10,11 +10,6 @@
#include "meshUtils.h" // vformat
#endif
// AXP192 and AXP2101 have the same device address, we just need to identify it in Power.cpp
#ifndef XPOWERS_AXP192_AXP2101_ADDRESS
#define XPOWERS_AXP192_AXP2101_ADDRESS 0x34
#endif
bool in_array(uint8_t *array, int size, uint8_t lookfor)
{
int i;
@@ -218,9 +213,20 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize)
#ifdef HAS_NCP5623
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", (uint8_t)addr.address)
#ifdef HAS_LP5562
SCAN_SIMPLE_CASE(LP5562_ADDR, LP5562, "LP5562", (uint8_t)addr.address);
#endif
case XPOWERS_AXP192_AXP2101_ADDRESS:
// Do we have the axp2101/192 or the TCA8418
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0x90), 1);
if (registerValue == 0x0) {
logFoundDevice("TCA8418", (uint8_t)addr.address);
type = TCA8418KB;
} else {
logFoundDevice("AXP192/AXP2101", (uint8_t)addr.address);
type = PMU_AXP192_AXP2101;
}
break;
case BME_ADDR:
case BME_ADDR_ALTERNATE:
registerValue = getRegisterValue(ScanI2CTwoWire::RegisterLocation(addr, 0xD0), 1); // GET_ID
+64 -10
View File
@@ -12,6 +12,7 @@
#include "RTC.h"
#include "Throttle.h"
#include "buzz.h"
#include "concurrency/Periodic.h"
#include "meshUtils.h"
#include "main.h" // pmu_found
@@ -89,6 +90,45 @@ static const char *getGPSPowerStateString(GPSPowerState state)
}
}
#ifdef PIN_GPS_SWITCH
// If we have a hardware switch, define a periodic watcher outside of the GPS runOnce thread, since this can be sleeping
// idefinitely
int lastState = LOW;
bool firstrun = true;
static int32_t gpsSwitch()
{
if (gps) {
int currentState = digitalRead(PIN_GPS_SWITCH);
// if the switch is set to zero, disable the GPS Thread
if (firstrun)
if (currentState == LOW)
lastState = HIGH;
if (currentState != lastState) {
if (currentState == LOW) {
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_DISABLED;
if (!firstrun)
playGPSDisableBeep();
gps->disable();
} else {
config.position.gps_mode = meshtastic_Config_PositionConfig_GpsMode_ENABLED;
if (!firstrun)
playGPSEnableBeep();
gps->enable();
}
lastState = currentState;
}
firstrun = false;
}
return 1000;
}
static concurrency::Periodic *gpsPeriodic;
#endif
static void UBXChecksum(uint8_t *message, size_t length)
{
uint8_t CK_A = 0, CK_B = 0;
@@ -530,6 +570,19 @@ bool GPS::setup()
// Switch to Fitness Mode, for running and walking purpose with low speed (<5 m/s)
_serial_gps->write("$PMTK886,1*29\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_MTK_PA1010D) {
// PA1010D is used in the Pimoroni GPS board.
// Enable all constellations.
_serial_gps->write("$PMTK353,1,1,1,1,1*2A\r\n");
// Above command will reset the GPS and takes longer before it will accept new commands
delay(1000);
// Only ask for RMC and GGA (GNRMC and GNGGA)
_serial_gps->write("$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n");
delay(250);
// Enable SBAS / WAAS
_serial_gps->write("$PMTK301,2*2E\r\n");
delay(250);
} else if (gnssModel == GNSS_MODEL_MTK_PA1616S) {
// PA1616S is used in some GPS breakout boards from Adafruit
// PA1616S does not have GLONASS capability. PA1616D does, but is not implemented here.
@@ -770,13 +823,6 @@ void GPS::setPowerState(GPSPowerState newState, uint32_t sleepTime)
powerState = newState;
LOG_INFO("GPS power state move from %s to %s", getGPSPowerStateString(oldState), getGPSPowerStateString(newState));
#ifdef HELTEC_MESH_NODE_T114
if ((oldState == GPS_OFF || oldState == GPS_HARDSLEEP) && (newState != GPS_OFF && newState != GPS_HARDSLEEP)) {
_serial_gps->begin(serialSpeeds[speedSelect]);
} else if ((newState == GPS_OFF || newState == GPS_HARDSLEEP) && (oldState != GPS_OFF && oldState != GPS_HARDSLEEP)) {
_serial_gps->end();
}
#endif
switch (newState) {
case GPS_ACTIVE:
case GPS_IDLE:
@@ -1204,9 +1250,11 @@ GnssModel_t GPS::probe(int serialSpeed)
// Close all NMEA sentences, valid for MTK3333 and MTK3339 platforms
_serial_gps->write("$PMTK514,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*2E\r\n");
delay(20);
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B},
{"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S},
{"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B}};
std::vector<ChipInfo> mtk = {{"L76B", "Quectel-L76B", GNSS_MODEL_MTK_L76B}, {"PA1010D", "1010D", GNSS_MODEL_MTK_PA1010D},
{"PA1616S", "1616S", GNSS_MODEL_MTK_PA1616S}, {"LS20031", "MC-1513", GNSS_MODEL_MTK_L76B},
{"L96", "Quectel-L96", GNSS_MODEL_MTK_L76B}, {"L80-R", "_3337_", GNSS_MODEL_MTK_L76B},
{"L80", "_3339_", GNSS_MODEL_MTK_L76B}};
PROBE_FAMILY("MTK Family", "$PMTK605*31", mtk, 500);
uint8_t cfg_rate[] = {0xB5, 0x62, 0x06, 0x08, 0x00, 0x00, 0x00, 0x00};
@@ -1389,6 +1437,12 @@ GPS *GPS::createGps()
pinMode(PIN_GPS_PPS, INPUT);
#endif
#ifdef PIN_GPS_SWITCH
// toggle GPS via external GPIO switch
pinMode(PIN_GPS_SWITCH, INPUT);
gpsPeriodic = new concurrency::Periodic("GPSSwitch", gpsSwitch);
#endif
// Currently disabled per issue #525 (TinyGPS++ crash bug)
// when fixed upstream, can be un-disabled to enable 3D FixType and PDOP
#ifndef TINYGPS_OPTION_NO_CUSTOM_FIELDS
+1
View File
@@ -27,6 +27,7 @@ typedef enum {
GNSS_MODEL_UC6580,
GNSS_MODEL_UNKNOWN,
GNSS_MODEL_MTK_L76B,
GNSS_MODEL_MTK_PA1010D,
GNSS_MODEL_MTK_PA1616S,
GNSS_MODEL_AG3335,
GNSS_MODEL_AG3352,
+3 -3
View File
@@ -224,7 +224,7 @@ static const uint8_t _message_GSA[] = {
0x00, // Rate for DDC
0x00, // Rate for UART1
0x00, // Rate for UART2
0x00, // Rate for USB usefull for native linux
0x00, // Rate for USB useful for native linux
0x00, // Rate for SPI
0x00 // Reserved
};
@@ -258,7 +258,7 @@ static const uint8_t _message_RMC[] = {
0x00, // Rate for DDC
0x01, // Rate for UART1
0x00, // Rate for UART2
0x01, // Rate for USB usefull for native linux
0x01, // Rate for USB useful for native linux
0x00, // Rate for SPI
0x00 // Reserved
};
@@ -269,7 +269,7 @@ static const uint8_t _message_GGA[] = {
0x00, // Rate for DDC
0x01, // Rate for UART1
0x00, // Rate for UART2
0x01, // Rate for USB, usefull for native linux
0x01, // Rate for USB, useful for native linux
0x00, // Rate for SPI
0x00 // Reserved
};
+18 -3
View File
@@ -129,9 +129,10 @@ bool EInkDisplay::connect()
// backlight power, HIGH is backlight on, LOW is off
pinMode(PIN_EINK_EN, OUTPUT);
#ifdef ELECROW_ThinkNode_M1
digitalWrite(PIN_EINK_EN, LOW);
#else
// ThinkNode M1 has a hardware dimmable backlight. Start enabled
digitalWrite(PIN_EINK_EN, HIGH);
#else
digitalWrite(PIN_EINK_EN, LOW);
#endif
#endif
@@ -180,7 +181,6 @@ bool EInkDisplay::connect()
// Start HSPI
hspi = new SPIClass(HSPI);
hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); // SCLK, MISO, MOSI, SS
// VExt already enabled in setup()
// RTC GPIO hold disabled in setup()
@@ -217,6 +217,21 @@ bool EInkDisplay::connect()
adafruitDisplay->setRotation(1);
adafruitDisplay->setPartialWindow(0, 0, EINK_WIDTH, EINK_HEIGHT);
}
#elif defined(HELTEC_MESH_POCKET)
{
spi1 = &SPI1;
spi1->begin();
// VExt already enabled in setup()
// RTC GPIO hold disabled in setup()
// Create GxEPD2 objects
auto lowLevel = new EINK_DISPLAY_MODEL(PIN_EINK_CS, PIN_EINK_DC, PIN_EINK_RES, PIN_EINK_BUSY, *spi1);
adafruitDisplay = new GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT>(*lowLevel);
// Init GxEPD2
adafruitDisplay->init();
adafruitDisplay->setRotation(3);
}
#endif
return true;
+4
View File
@@ -73,6 +73,10 @@ class EInkDisplay : public OLEDDisplay
SPIClass *hspi = NULL;
#endif
#if defined(HELTEC_MESH_POCKET)
SPIClass *spi1 = NULL;
#endif
private:
// FIXME quick hack to limit drawing to a very slow rate
uint32_t lastDrawMsec = 0;
+5
View File
@@ -0,0 +1,5 @@
#ifdef HAS_LP5562
#include <LP5562.h>
extern LP5562 rgbw;
#endif
+21 -10
View File
@@ -30,6 +30,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#if !MESHTASTIC_EXCLUDE_GPS
#include "GPS.h"
#endif
#include "ButtonThread.h"
#include "MeshService.h"
#include "NodeDB.h"
#include "error.h"
@@ -1103,7 +1104,7 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const NodeStat
char usersString[20];
snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal());
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x, y + 3, 8, 8, imgUser);
#else
@@ -1544,7 +1545,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O
dispdev = new SSD1306Wire(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || \
defined(RAK14014) || defined(HX8357_CS)
defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS)
dispdev = new TFTDisplay(address.address, -1, -1, geometry,
(address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE);
#elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY)
@@ -1606,10 +1607,14 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
if (on != screenOn) {
if (on) {
LOG_INFO("Turn on screen");
buttonThread->setScreenFlag(true);
powerMon->setState(meshtastic_PowerMon_State_Screen_On);
#ifdef T_WATCH_S3
PMU->enablePowerOutput(XPOWERS_ALDO2);
#endif
#ifdef HELTEC_TRACKER_V1_X
uint8_t tft_vext_enabled = digitalRead(VEXT_ENABLE);
#endif
#if !ARCH_PORTDUINO
dispdev->displayOn();
#endif
@@ -1620,6 +1625,12 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
#endif
dispdev->displayOn();
#ifdef HELTEC_TRACKER_V1_X
// If the TFT VEXT power is not enabled, initialize the UI.
if (!tft_vext_enabled) {
ui->init();
}
#endif
#ifdef USE_ST7789
pinMode(VTFT_CTRL, OUTPUT);
digitalWrite(VTFT_CTRL, LOW);
@@ -1641,6 +1652,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver)
setScreensaverFrames(einkScreensaver);
#endif
LOG_INFO("Turn off screen");
buttonThread->setScreenFlag(false);
#ifdef ELECROW_ThinkNode_M1
if (digitalRead(PIN_EINK_EN) == HIGH) {
digitalWrite(PIN_EINK_EN, LOW);
@@ -1748,7 +1760,7 @@ void Screen::setup()
// flip it. If you have a headache now, you're welcome.
if (!config.display.flip_screen) {
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || \
defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS)
defined(ST7789_CS) || defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS)
static_cast<TFTDisplay *>(dispdev)->flipScreenVertically();
#elif defined(USE_ST7789)
static_cast<ST7789Spi *>(dispdev)->flipScreenVertically();
@@ -1793,7 +1805,9 @@ void Screen::setup()
powerStatusObserver.observe(&powerStatus->onNewStatus);
gpsStatusObserver.observe(&gpsStatus->onNewStatus);
nodeStatusObserver.observe(&nodeStatus->onNewStatus);
#if !MESHTASTIC_EXCLUDE_ADMIN
adminMessageObserver.observe(adminModule);
#endif
if (textMessageModule)
textMessageObserver.observe(textMessageModule);
if (inputBroker)
@@ -2487,7 +2501,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
if (!Throttle::isWithinTimespanMs(storeForwardModule->lastHeartbeat,
(storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgQuestionL1);
@@ -2499,7 +2513,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
#endif
} else {
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8,
imgSFL1);
@@ -2514,7 +2528,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16
} else {
// TODO: Raspberry Pi supports more than just the one screen size
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8,
imgInfoL1);
@@ -2835,9 +2849,6 @@ int Screen::handleInputEvent(const InputEvent *event)
int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
{
// Note: only selected admin messages notify this observer
// If you wish to handle a new type of message, you should modify AdminModule.cpp first
switch (arg->which_payload_variant) {
// Node removed manually (i.e. via app)
case meshtastic_AdminMessage_remove_by_nodenum_tag:
@@ -2854,4 +2865,4 @@ int Screen::handleAdminMessage(const meshtastic_AdminMessage *arg)
} // namespace graphics
#else
graphics::Screen::Screen(ScanI2C::DeviceAddress, meshtastic_Config_DisplayConfig_OledType, OLEDDISPLAY_GEOMETRY) {}
#endif // HAS_SCREEN
#endif // HAS_SCREEN
+1 -1
View File
@@ -65,7 +65,7 @@
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS)) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS)) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
// The screen is bigger so use bigger fonts
#define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19
+318 -12
View File
@@ -120,6 +120,303 @@ static void rak14014_tpIntHandle(void)
_rak14014_touch_int = true;
}
#elif defined(ST72xx_DE)
#include <LovyanGFX.hpp>
#include <TCA9534.h>
#include <lgfx/v1/platforms/esp32s3/Bus_RGB.hpp>
#include <lgfx/v1/platforms/esp32s3/Panel_RGB.hpp>
TCA9534 ioex;
class LGFX : public lgfx::LGFX_Device
{
lgfx::Bus_RGB _bus_instance;
lgfx::Panel_RGB _panel_instance;
lgfx::Touch_GT911 _touch_instance;
public:
const uint16_t screenWidth = TFT_WIDTH;
const uint16_t screenHeight = TFT_HEIGHT;
bool init_impl(bool use_reset, bool use_clear) override
{
ioex.attach(Wire);
ioex.setDeviceAddress(0x18);
ioex.config(1, TCA9534::Config::OUT);
ioex.config(2, TCA9534::Config::OUT);
ioex.config(3, TCA9534::Config::OUT);
ioex.config(4, TCA9534::Config::OUT);
ioex.output(1, TCA9534::Level::H);
ioex.output(3, TCA9534::Level::L);
ioex.output(4, TCA9534::Level::H);
pinMode(1, OUTPUT);
digitalWrite(1, LOW);
ioex.output(2, TCA9534::Level::L);
delay(20);
ioex.output(2, TCA9534::Level::H);
delay(100);
pinMode(1, INPUT);
return LGFX_Device::init_impl(use_reset, use_clear);
}
LGFX(void)
{
{
auto cfg = _panel_instance.config();
cfg.memory_width = screenWidth;
cfg.memory_height = screenHeight;
cfg.panel_width = screenWidth;
cfg.panel_height = screenHeight;
cfg.offset_x = 0;
cfg.offset_y = 0;
cfg.offset_rotation = 0;
_panel_instance.config(cfg);
}
{
auto cfg = _panel_instance.config_detail();
cfg.use_psram = 0;
_panel_instance.config_detail(cfg);
}
{
auto cfg = _bus_instance.config();
cfg.panel = &_panel_instance;
cfg.pin_d0 = ST72xx_B0; // B0
cfg.pin_d1 = ST72xx_B1; // B1
cfg.pin_d2 = ST72xx_B2; // B2
cfg.pin_d3 = ST72xx_B3; // B3
cfg.pin_d4 = ST72xx_B4; // B4
cfg.pin_d5 = ST72xx_G0; // G0
cfg.pin_d6 = ST72xx_G1; // G1
cfg.pin_d7 = ST72xx_G2; // G2
cfg.pin_d8 = ST72xx_G3; // G3
cfg.pin_d9 = ST72xx_G4; // G4
cfg.pin_d10 = ST72xx_G5; // G5
cfg.pin_d11 = ST72xx_R0; // R0
cfg.pin_d12 = ST72xx_R1; // R1
cfg.pin_d13 = ST72xx_R2; // R2
cfg.pin_d14 = ST72xx_R3; // R3
cfg.pin_d15 = ST72xx_R4; // R4
cfg.pin_henable = ST72xx_DE;
cfg.pin_vsync = ST72xx_VSYNC;
cfg.pin_hsync = ST72xx_HSYNC;
cfg.pin_pclk = ST72xx_PCLK;
cfg.freq_write = 13000000;
#ifdef ST7265_HSYNC_POLARITY
cfg.hsync_polarity = ST7265_HSYNC_POLARITY;
cfg.hsync_front_porch = ST7265_HSYNC_FRONT_PORCH; // 8;
cfg.hsync_pulse_width = ST7265_HSYNC_PULSE_WIDTH; // 4;
cfg.hsync_back_porch = ST7265_HSYNC_BACK_PORCH; // 8;
cfg.vsync_polarity = ST7265_VSYNC_POLARITY; // 0;
cfg.vsync_front_porch = ST7265_VSYNC_FRONT_PORCH; // 8;
cfg.vsync_pulse_width = ST7265_VSYNC_PULSE_WIDTH; // 4;
cfg.vsync_back_porch = ST7265_VSYNC_BACK_PORCH; // 8;
cfg.pclk_idle_high = 1;
cfg.pclk_active_neg = ST7265_PCLK_ACTIVE_NEG; // 0;
// cfg.pclk_idle_high = 0;
// cfg.de_idle_high = 1;
#endif
#ifdef ST7262_HSYNC_POLARITY
cfg.hsync_polarity = ST7262_HSYNC_POLARITY;
cfg.hsync_front_porch = ST7262_HSYNC_FRONT_PORCH; // 8;
cfg.hsync_pulse_width = ST7262_HSYNC_PULSE_WIDTH; // 4;
cfg.hsync_back_porch = ST7262_HSYNC_BACK_PORCH; // 8;
cfg.vsync_polarity = ST7262_VSYNC_POLARITY; // 0;
cfg.vsync_front_porch = ST7262_VSYNC_FRONT_PORCH; // 8;
cfg.vsync_pulse_width = ST7262_VSYNC_PULSE_WIDTH; // 4;
cfg.vsync_back_porch = ST7262_VSYNC_BACK_PORCH; // 8;
cfg.pclk_idle_high = 1;
cfg.pclk_active_neg = ST7262_PCLK_ACTIVE_NEG; // 0;
// cfg.pclk_idle_high = 0;
// cfg.de_idle_high = 1;
#endif
#ifdef SC7277_HSYNC_POLARITY
cfg.hsync_polarity = SC7277_HSYNC_POLARITY;
cfg.hsync_front_porch = SC7277_HSYNC_FRONT_PORCH; // 8;
cfg.hsync_pulse_width = SC7277_HSYNC_PULSE_WIDTH; // 4;
cfg.hsync_back_porch = SC7277_HSYNC_BACK_PORCH; // 8;
cfg.vsync_polarity = SC7277_VSYNC_POLARITY; // 0;
cfg.vsync_front_porch = SC7277_VSYNC_FRONT_PORCH; // 8;
cfg.vsync_pulse_width = SC7277_VSYNC_PULSE_WIDTH; // 4;
cfg.vsync_back_porch = SC7277_VSYNC_BACK_PORCH; // 8;
cfg.pclk_idle_high = 1;
cfg.pclk_active_neg = SC7277_PCLK_ACTIVE_NEG; // 0;
// cfg.pclk_idle_high = 0;
// cfg.de_idle_high = 1;
#endif
_bus_instance.config(cfg);
}
_panel_instance.setBus(&_bus_instance);
{
auto cfg = _touch_instance.config();
cfg.x_min = 0;
cfg.x_max = TFT_WIDTH;
cfg.y_min = 0;
cfg.y_max = TFT_HEIGHT;
cfg.pin_int = -1;
cfg.pin_rst = -1;
cfg.bus_shared = true;
cfg.offset_rotation = 0;
cfg.i2c_port = 0;
cfg.i2c_addr = 0x5D;
cfg.pin_sda = I2C_SDA;
cfg.pin_scl = I2C_SCL;
cfg.freq = 400000;
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance);
}
setPanel(&_panel_instance);
}
};
static LGFX *tft = nullptr;
#elif defined(ILI9488_CS)
#include <LovyanGFX.hpp> // Graphics and font library for ILI9488 driver chip
class LGFX : public lgfx::LGFX_Device
{
lgfx::Panel_ILI9488 _panel_instance;
lgfx::Bus_SPI _bus_instance;
lgfx::Light_PWM _light_instance;
lgfx::Touch_GT911 _touch_instance;
public:
LGFX(void)
{
{
auto cfg = _bus_instance.config();
// configure SPI
cfg.spi_host = ILI9488_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST
cfg.spi_mode = 0;
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
// 80MHz by an integer)
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
cfg.spi_3wire = false; // Set to true if reception is done on the MOSI pin
cfg.use_lock = true; // Set to true to use transaction locking
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
// SPI_DMA_CH_AUTO=auto setting)
cfg.pin_sclk = ILI9488_SCK; // Set SPI SCLK pin number
cfg.pin_mosi = ILI9488_SDA; // Set SPI MOSI pin number
cfg.pin_miso = ILI9488_MISO; // Set SPI MISO pin number (-1 = disable)
cfg.pin_dc = ILI9488_RS; // Set SPI DC pin number (-1 = disable)
_bus_instance.config(cfg); // applies the set value to the bus.
_panel_instance.setBus(&_bus_instance); // set the bus on the panel.
}
{ // Set the display panel control.
auto cfg = _panel_instance.config(); // Gets a structure for display panel settings.
cfg.pin_cs = ILI9488_CS; // Pin number where CS is connected (-1 = disable)
cfg.pin_rst = -1; // Pin number where RST is connected (-1 = disable)
cfg.pin_busy = -1; // Pin number where BUSY is connected (-1 = disable)
// The following setting values ​​are general initial values ​​for each panel, so please comment out any
// unknown items and try them.
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
#ifdef TFT_DUMMY_READ_PIXELS
cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout
#else
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
#endif
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit =
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
// Set the following only when the display is shifted with a driver with a variable number of pixels, such as the
// ST7735 or ILI9163.
// cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
// cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
_panel_instance.config(cfg);
}
#ifdef ILI9488_BL
// Set the backlight control
{
auto cfg = _light_instance.config(); // Gets a structure for backlight settings.
cfg.pin_bl = ILI9488_BL; // Pin number to which the backlight is connected
cfg.invert = false; // true to invert the brightness of the backlight
// cfg.freq = 44100; // PWM frequency of backlight
// cfg.pwm_channel = 1; // PWM channel number to use
_light_instance.config(cfg);
_panel_instance.setLight(&_light_instance); // Set the backlight on the panel.
}
#endif
#if HAS_TOUCHSCREEN
// Configure settings for touch screen control.
{
auto cfg = _touch_instance.config();
cfg.pin_cs = -1;
cfg.x_min = 0;
cfg.x_max = TFT_HEIGHT - 1;
cfg.y_min = 0;
cfg.y_max = TFT_WIDTH - 1;
cfg.pin_int = SCREEN_TOUCH_INT;
#ifdef SCREEN_TOUCH_RST
cfg.pin_rst = SCREEN_TOUCH_RST;
#endif
cfg.bus_shared = true;
cfg.offset_rotation = TFT_OFFSET_ROTATION;
// cfg.freq = 2500000;
// I2C
cfg.i2c_port = TOUCH_I2C_PORT;
cfg.i2c_addr = TOUCH_SLAVE_ADDRESS;
#ifdef SCREEN_TOUCH_USE_I2C1
cfg.pin_sda = I2C_SDA1;
cfg.pin_scl = I2C_SCL1;
#else
cfg.pin_sda = I2C_SDA;
cfg.pin_scl = I2C_SCL;
#endif
// cfg.freq = 400000;
_touch_instance.config(cfg);
_panel_instance.setTouch(&_touch_instance);
}
#endif
setPanel(&_panel_instance);
}
};
static LGFX *tft = nullptr;
#elif defined(ST7789_CS)
#include <LovyanGFX.hpp> // Graphics and font library for ST7735 driver chip
@@ -129,7 +426,7 @@ class LGFX : public lgfx::LGFX_Device
lgfx::Bus_SPI _bus_instance;
lgfx::Light_PWM _light_instance;
#if HAS_TOUCHSCREEN
#ifdef T_WATCH_S3
#if defined(T_WATCH_S3) || defined(ELECROW)
lgfx::Touch_FT5x06 _touch_instance;
#else
lgfx::Touch_GT911 _touch_instance;
@@ -171,16 +468,22 @@ class LGFX : public lgfx::LGFX_Device
// The following setting values ​​are general initial values ​​for each panel, so please comment out any
// unknown items and try them.
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC
cfg.panel_width = TFT_WIDTH; // actual displayable width
cfg.panel_height = TFT_HEIGHT; // actual displayable height
cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction
cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction
cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is mirrored)
#ifdef TFT_DUMMY_READ_PIXELS
cfg.dummy_read_pixel = TFT_DUMMY_READ_PIXELS; // Number of bits for dummy read before pixel readout
#else
cfg.dummy_read_pixel = 9; // Number of bits for dummy read before pixel readout
#endif
cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read
cfg.readable = true; // Set to true if data can be read
cfg.invert = true; // Set to true if the light/darkness of the panel is reversed
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit =
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
@@ -217,6 +520,9 @@ class LGFX : public lgfx::LGFX_Device
cfg.y_min = 0;
cfg.y_max = TFT_WIDTH - 1;
cfg.pin_int = SCREEN_TOUCH_INT;
#ifdef SCREEN_TOUCH_RST
cfg.pin_rst = SCREEN_TOUCH_RST;
#endif
cfg.bus_shared = true;
cfg.offset_rotation = TFT_OFFSET_ROTATION;
// cfg.freq = 2500000;
@@ -640,7 +946,7 @@ static LGFX *tft = nullptr;
#endif
#if defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \
defined(RAK14014) || defined(HX8357_CS) || (ARCH_PORTDUINO && HAS_SCREEN != 0)
defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST72xx_DE) || (ARCH_PORTDUINO && HAS_SCREEN != 0)
#include "SPILock.h"
#include "TFTDisplay.h"
#include <SPI.h>
+1 -1
View File
@@ -21,7 +21,7 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03
#endif
#if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || ARCH_PORTDUINO) && \
defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || ARCH_PORTDUINO) && \
!defined(DISPLAY_FORCE_SMALL_FONTS)
const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff};
const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f};
@@ -1 +0,0 @@
#include "./DEPG0154BNS800.h"
@@ -1,34 +0,0 @@
/*
E-Ink display driver
- DEPG0154BNS800
- Manufacturer: DKE
- Size: 1.54 inch
- Resolution: 152px x 152px
- Flex connector marking: FPC7525
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./SSD16XX.h"
namespace NicheGraphics::Drivers
{
class DEPG0154BNS800 : public SSD16XX
{
// Display properties
private:
static constexpr uint32_t width = 152;
static constexpr uint32_t height = 152;
static constexpr UpdateTypes supported = (UpdateTypes)(FULL);
public:
DEPG0154BNS800() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte
};
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
@@ -0,0 +1,132 @@
#include "./DEPG0213BNS800.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
using namespace NicheGraphics::Drivers;
// Describes the operation performed when a "fast refresh" is performed
// Source: Modified from GxEPD2 (GxEPD2_213_BN)
static const uint8_t LUT_FAST[] = {
// 1 2 3
0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B2B (Existing black pixels)
0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // B2W (New white pixels)
0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // W2B (New black pixels)
0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // W2W (Existing white pixels)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // VCOM
0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // 1. Any pixels changing W2B or B2W. Two medium taps.
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 2. All pixels. One short tap.
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 3. Cooldown
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, //
};
// How strongly the pixels are pulled and pushed
void DEPG0213BNS800::configVoltages()
{
switch (updateType) {
case FAST:
// Reference: display datasheet, GxEPD1
sendCommand(0x03); // Gate voltage
sendData(0x17); // VGH: 20V
// Reference: display datasheet, GxEPD1
sendCommand(0x04); // Source voltage
sendData(0x41); // VSH1: 15V
sendData(0x00); // VSH2: NA
sendData(0x32); // VSL: -15V
// GxEPD1 sets this at -1.2V, but that seems to be drive the pixels very hard
sendCommand(0x2C); // VCOM voltage
sendData(0x08); // VCOM: -0.2V
break;
case FULL:
default:
// From OTP memory
break;
}
}
// Load settings about how the pixels are moved from old state to new state during a refresh
// - manually specified,
// - or with stored values from displays OTP memory
void DEPG0213BNS800::configWaveform()
{
switch (updateType) {
case FAST:
sendCommand(0x3C); // Border waveform:
sendData(0x80); // VSS
sendCommand(0x32); // Write LUT register from MCU:
sendData(LUT_FAST, sizeof(LUT_FAST)); // (describes operation for a FAST refresh)
break;
case FULL:
default:
// From OTP memory
break;
}
}
// Describes the sequence of events performed by the displays controller IC during a refresh
// Includes "power up", "load settings from memory", "update the pixels", etc
void DEPG0213BNS800::configUpdateSequence()
{
switch (updateType) {
case FAST:
sendCommand(0x22); // Set "update sequence"
sendData(0xCF); // Differential, use manually loaded waveform
break;
case FULL:
default:
sendCommand(0x22); // Set "update sequence"
sendData(0xF7); // Non-differential, load waveform from OTP
break;
}
}
// Once the refresh operation has been started,
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
// Only used when refresh is "async"
void DEPG0213BNS800::detachFromUpdate()
{
switch (updateType) {
case FAST:
return beginPolling(50, 500); // At least 500ms, then poll every 50ms
case FULL:
default:
return beginPolling(100, 3500); // At least 3500ms, then poll every 100ms
}
}
// For this display, we do not need to re-write the new image.
// We're overriding SSD16XX::finalizeUpdate to make this small optimization.
// The display does also work just fine with the generic SSD16XX method, though.
void DEPG0213BNS800::finalizeUpdate()
{
// Put a copy of the image into the "old memory".
// Used with differential refreshes (e.g. FAST update), to determine which px need to move, and which can remain in place
// We need to keep the "old memory" up to date, because don't know whether next refresh will be FULL or FAST etc.
if (updateType != FULL) {
// writeNewImage(); // Not required for this display
writeOldImage();
sendCommand(0x7F); // Terminate image write without update
wait();
}
// Enter deep-sleep to save a few µA
// Waking from this requires that display's reset pin is broken out
if (pin_rst != 0xFF)
deepSleep();
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
@@ -0,0 +1,44 @@
/*
E-Ink display driver
- DEPG0213BNS800
- Manufacturer: DKE
- Size: 2.13 inch
- Resolution: 122px x 250px
- Flex connector marking: FPC-7528B
Note: this is from an older generation of DKE panels, which still used Solomon Systech controller ICs.
DKE's website suggests that the latest DEPG0213BN displays may use Fitipower controllers instead.
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./SSD16XX.h"
namespace NicheGraphics::Drivers
{
class DEPG0213BNS800 : public SSD16XX
{
// Display properties
private:
static constexpr uint32_t width = 122;
static constexpr uint32_t height = 250;
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
public:
DEPG0213BNS800() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte
protected:
void configVoltages() override;
void configWaveform() override;
void configUpdateSequence() override;
void detachFromUpdate() override;
void finalizeUpdate() override; // Only overriden for a slight optimization
};
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
@@ -116,5 +116,10 @@ void DEPG0290BNS800::finalizeUpdate()
sendCommand(0x7F); // Terminate image write without update
wait();
}
// Enter deep-sleep to save a few µA
// Waking from this requires that display's reset pin is broken out
if (pin_rst != 0xFF)
deepSleep();
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
@@ -0,0 +1,68 @@
#include "./LCMEN2R13ECC1.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
using namespace NicheGraphics::Drivers;
// Map the display controller IC's output to the connected panel
void LCMEN2R13ECC1::configScanning()
{
// "Driver output control"
sendCommand(0x01);
sendData(0xF9);
sendData(0x00);
sendData(0x00);
// To-do: delete this method?
// Values set here might be redundant: F9, 00, 00 seems to be default
}
// Specify which information is used to control the sequence of voltages applied to move the pixels
// - For this display, configUpdateSequence() specifies that a suitable LUT will be loaded from
// the controller IC's OTP memory, when the update procedure begins.
void LCMEN2R13ECC1::configWaveform()
{
switch (updateType) {
case FAST:
sendCommand(0x3C); // Border waveform:
sendData(0x85);
break;
case FULL:
default:
// From OTP memory
break;
}
}
void LCMEN2R13ECC1::configUpdateSequence()
{
switch (updateType) {
case FAST:
sendCommand(0x22); // Set "update sequence"
sendData(0xFF); // Will load LUT from OTP memory, Display mode 2 "differential refresh"
break;
case FULL:
default:
sendCommand(0x22); // Set "update sequence"
sendData(0xF7); // Will load LUT from OTP memory
break;
}
}
// Once the refresh operation has been started,
// begin periodically polling the display to check for completion, using the normal Meshtastic threading code
// Only used when refresh is "async"
void LCMEN2R13ECC1::detachFromUpdate()
{
switch (updateType) {
case FAST:
return beginPolling(50, 800); // At least 500ms for fast refresh
case FULL:
default:
return beginPolling(100, 2500); // At least 2 seconds for full refresh
}
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
@@ -0,0 +1,41 @@
/*
E-Ink display driver
- SSD1680
- Manufacturer: WISEVAST
- Size: 2.13 inch
- Resolution: 122px x 255px
- Flex connector marking: Soldering connector, no connector is needed
*/
#pragma once
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "configuration.h"
#include "./SSD16XX.h"
namespace NicheGraphics::Drivers
{
class LCMEN2R13ECC1 : public SSD16XX
{
// Display properties
private:
static constexpr uint32_t width = 122;
static constexpr uint32_t height = 250;
static constexpr UpdateTypes supported = (UpdateTypes)(FULL | FAST);
public:
LCMEN2R13ECC1() : SSD16XX(width, height, supported, 1) {} // Note: left edge of this display is offset by 1 byte
protected:
virtual void configScanning() override;
virtual void configWaveform() override;
virtual void configUpdateSequence() override;
void detachFromUpdate() override;
};
} // namespace NicheGraphics::Drivers
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
@@ -1,9 +1,11 @@
#include "./LCMEN2R13EFC1.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./LCMEN2R13EFC1.h"
#include <assert.h>
#include "SPILock.h"
using namespace NicheGraphics::Drivers;
// Look up table: fast refresh, common electrode
@@ -42,11 +44,10 @@ static const uint8_t LUT_FAST_BW[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
};
// Look up table: fash refresh, pixels which change from white to black
// Look up table: fast refresh, pixels which change from white to black
static const uint8_t LUT_FAST_WB[] = {
0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, //
0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, //
0x01, 0x46, 0x43, 0x02, 0x01, 0x01, 0x01, //
0x01, 0x46, 0x42, 0x01, 0x01, 0x01, 0x01, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
@@ -55,7 +56,7 @@ static const uint8_t LUT_FAST_WB[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //
};
// Look up table: fash refresh, pixels which remain black
// Look up table: fast refresh, pixels which remain black
static const uint8_t LUT_FAST_BB[] = {
0x01, 0x06, 0x03, 0x42, 0x41, 0x01, 0x01, //
0x01, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01, //
@@ -151,6 +152,9 @@ void LCMEN213EFC1::reset()
void LCMEN213EFC1::sendCommand(const uint8_t command)
{
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, LOW); // DC pin low indicates command
digitalWrite(pin_cs, LOW);
@@ -158,6 +162,8 @@ void LCMEN213EFC1::sendCommand(const uint8_t command)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void LCMEN213EFC1::sendData(uint8_t data)
@@ -167,6 +173,9 @@ void LCMEN213EFC1::sendData(uint8_t data)
void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
{
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
digitalWrite(pin_cs, LOW);
@@ -184,6 +193,8 @@ void LCMEN213EFC1::sendData(const uint8_t *data, uint32_t size)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void LCMEN213EFC1::configFull()
+27 -1
View File
@@ -1,6 +1,9 @@
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "./SSD16XX.h"
#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS
#include "SPILock.h"
using namespace NicheGraphics::Drivers;
SSD16XX::SSD16XX(uint16_t width, uint16_t height, UpdateTypes supported, uint8_t bufferOffsetX)
@@ -82,6 +85,9 @@ void SSD16XX::sendCommand(const uint8_t command)
if (failed)
return;
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, LOW); // DC pin low indicates command
digitalWrite(pin_cs, LOW);
@@ -89,6 +95,8 @@ void SSD16XX::sendCommand(const uint8_t command)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void SSD16XX::sendData(uint8_t data)
@@ -103,6 +111,9 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
if (failed)
return;
// Take firmware's SPI lock
spiLock->lock();
spi->beginTransaction(spiSettings);
digitalWrite(pin_dc, HIGH); // DC pin HIGH indicates data, instead of command
digitalWrite(pin_cs, LOW);
@@ -119,6 +130,8 @@ void SSD16XX::sendData(const uint8_t *data, uint32_t size)
digitalWrite(pin_cs, HIGH);
digitalWrite(pin_dc, HIGH);
spi->endTransaction();
spiLock->unlock();
}
void SSD16XX::configFullscreen()
@@ -242,5 +255,18 @@ void SSD16XX::finalizeUpdate()
sendCommand(0x7F); // Terminate image write without update
wait();
}
// Enter deep-sleep to save a few µA
// Waking from this requires that display's reset pin is broken out
if (pin_rst != 0xFF)
deepSleep();
}
// Enter a lower-power state
// May only save a few µA..
void SSD16XX::deepSleep()
{
sendCommand(0x10); // Enter deep sleep
sendData(0x01); // Mode 1: preserve image RAM
}
#endif // MESHTASTIC_INCLUDE_NICHE_GRAPHICS
@@ -44,6 +44,7 @@ class SSD16XX : public EInk
virtual void detachFromUpdate();
virtual bool isUpdateDone() override;
virtual void finalizeUpdate() override;
virtual void deepSleep();
protected:
uint8_t bufferOffsetX = 0; // In bytes. Panel x=0 does not always align with controller x=0. Quirky internal wiring?
+37 -3
View File
@@ -13,6 +13,7 @@ Avoid bloating everyone's protobuf code for our one-off UI implementations
#include "configuration.h"
#include "SPILock.h"
#include "SafeFile.h"
namespace NicheGraphics
@@ -46,6 +47,9 @@ template <typename T> class FlashData
public:
static bool load(T *data, const char *label)
{
// Take firmware's SPI lock
concurrency::LockGuard guard(spiLock);
// Set false if we run into issues
bool okay = true;
@@ -103,14 +107,18 @@ template <typename T> class FlashData
return okay;
}
// Save module's custom data (settings?) to flash. Does use protobufs
// Save module's custom data (settings?) to flash. Doesn't use protobufs
// Takes the firmware's SPI lock, in case the files are stored on SD card
// Need to lock and unlock around specific FS methods, as the SafeFile class takes the lock for itself internally.
static void save(T *data, const char *label)
{
// Get a filename based on the label
std::string filename = getFilename(label);
#ifdef FSCom
spiLock->lock();
FSCom.mkdir("/NicheGraphics");
spiLock->unlock();
auto f = SafeFile(filename.c_str(), true); // "true": full atomic. Write new data to temp file, then rename.
@@ -119,10 +127,10 @@ template <typename T> class FlashData
// Calculate a hash of the data
uint32_t hash = getHash(data);
spiLock->lock();
f.write((uint8_t *)data, sizeof(T)); // Write the actual data
f.write((uint8_t *)&hash, sizeof(hash)); // Append the hash
// f.flush();
spiLock->unlock();
bool writeSucceeded = f.close();
@@ -135,6 +143,32 @@ template <typename T> class FlashData
}
};
// Erase contents of the NicheGraphics data directory
inline void clearFlashData()
{
// Take firmware's SPI lock, in case the files are stored on SD card
concurrency::LockGuard guard(spiLock);
#ifdef FSCom
File dir = FSCom.open("/NicheGraphics"); // Open the directory
File file = dir.openNextFile(); // Attempt to open the first file in the directory
// While the directory still contains files
while (file) {
std::string path = "/NicheGraphics/";
path += file.name();
LOG_DEBUG("Erasing %s", path.c_str());
file.close();
FSCom.remove(path.c_str());
file = dir.openNextFile();
}
#else
LOG_ERROR("ERROR: Filesystem not implemented\n");
#endif
}
} // namespace NicheGraphics
#endif
+193 -124
View File
@@ -1,129 +1,198 @@
#pragma once
const uint8_t FreeSans6pt7bBitmaps[] PROGMEM = {
0xAA, 0xA8, 0xC0, 0xF6, 0xA0, 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, 0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00,
0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, 0x70, 0x91, 0x23, 0x86, 0x12, 0xA2, 0x4E, 0xF4, 0xE0,
0x5A, 0xAA, 0x94, 0x89, 0x12, 0x49, 0x29, 0x00, 0x27, 0x50, 0x21, 0x3E, 0x42, 0x00, 0xE0, 0xC0, 0x80, 0x24, 0xA4, 0xA4, 0x80,
0x74, 0xE3, 0x18, 0xC6, 0x33, 0x70, 0x27, 0x92, 0x49, 0x20, 0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, 0x79, 0x30, 0x43, 0x18,
0x10, 0x71, 0x78, 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, 0x7D, 0x04, 0x1E, 0x44, 0x10, 0x51, 0x78, 0x74, 0x61, 0xE8, 0xC6,
0x31, 0x70, 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, 0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, 0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53,
0x78, 0x82, 0x87, 0x01, 0xF1, 0x83, 0x04, 0xF8, 0x3E, 0x07, 0x06, 0x36, 0x40, 0x74, 0x42, 0x11, 0x10, 0x80, 0x20, 0x0F, 0x86,
0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42,
0x42, 0xC3, 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, 0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, 0xF9, 0x0A, 0x1C,
0x18, 0x30, 0x61, 0xC2, 0xF8, 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, 0x1E, 0x61,
0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, 0xFF, 0x80, 0x08, 0x42, 0x10, 0x87,
0x29, 0x70, 0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, 0xC3, 0xC3, 0xC3, 0xA5, 0xA5,
0xA5, 0x99, 0x99, 0x99, 0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6,
0x1E, 0x00, 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, 0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1F, 0x00, 0x00,
0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, 0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04,
0x08, 0x10, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, 0xC2, 0x42, 0x42, 0x64, 0x24, 0x24, 0x38, 0x18, 0x18, 0xC4, 0x28,
0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, 0x42, 0x66, 0x24, 0x18, 0x18, 0x18, 0x24, 0x46, 0x42, 0xC3,
0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, 0xEA, 0xAA, 0xAB, 0x92, 0x24,
0x89, 0x20, 0xE9, 0x24, 0x92, 0x49, 0x70, 0x46, 0xA9, 0x10, 0xFE, 0x40, 0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, 0x84, 0x3D, 0x18,
0xC6, 0x31, 0xF0, 0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, 0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, 0x39, 0x38, 0x7F, 0x81, 0x13,
0x80, 0x6B, 0xA4, 0x92, 0x40, 0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, 0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, 0xBF, 0x80,
0x45, 0x55, 0x57, 0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, 0xFF, 0x80, 0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, 0xF4, 0x63, 0x18,
0xC6, 0x20, 0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, 0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, 0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04,
0xF2, 0x49, 0x20, 0x79, 0x24, 0x1C, 0x0B, 0x27, 0x80, 0x5D, 0x24, 0x93, 0x8C, 0x63, 0x18, 0xCF, 0xA0, 0x85, 0x24, 0x92, 0x30,
0xC3, 0x00, 0x89, 0x2C, 0x96, 0x4A, 0xA5, 0x61, 0x30, 0x98, 0x49, 0x23, 0x08, 0x31, 0x2C, 0x80, 0x89, 0x24, 0x94, 0x50, 0xC2,
0x08, 0x21, 0x00, 0x78, 0x44, 0x46, 0x23, 0xE0, 0x6A, 0xAA, 0xA9, 0xFF, 0xE0, 0x95, 0x55, 0x56, 0x66, 0x60};
/* ' ' 0x20 */
/* '!' 0x21 */ 0xFE, 0x80,
/* '"' 0x22 */ 0xB6, 0x80,
/* '#' 0x23 */ 0x24, 0x49, 0xF9, 0x42, 0x9F, 0x92, 0x28,
/* '$' 0x24 */ 0x23, 0xAB, 0x5A, 0x38, 0xB5, 0xAB, 0x88,
/* '%' 0x25 */ 0x71, 0x22, 0x88, 0xA2, 0x30, 0x74, 0x02, 0x60, 0xA4, 0x49, 0x11, 0x80,
/* '&' 0x26 */ 0x31, 0x24, 0x8C, 0x72, 0x58, 0xA3, 0x74,
/* ''' 0x27 */ 0xE0,
/* '(' 0x28 */ 0x5A, 0xAA, 0x94,
/* ')' 0x29 */ 0x89, 0x12, 0x49, 0x49, 0x00,
/* '*' 0x2A */ 0x5E, 0x80,
/* '+' 0x2B */ 0x21, 0x3E, 0x42, 0x00,
/* ',' 0x2C */ 0xE0,
/* '-' 0x2D */ 0xE0,
/* '.' 0x2E */ 0x80,
/* '/' 0x2F */ 0x25, 0x24, 0xA4, 0x80,
/* '0' 0x30 */ 0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70,
/* '1' 0x31 */ 0x5D, 0x55, 0x40,
/* '2' 0x32 */ 0x74, 0x42, 0x11, 0x11, 0x10, 0xF8,
/* '3' 0x33 */ 0x74, 0x42, 0x13, 0x04, 0x31, 0x70,
/* '4' 0x34 */ 0x11, 0x8C, 0xA9, 0x4B, 0xE2, 0x10,
/* '5' 0x35 */ 0x7D, 0x04, 0x1E, 0x4C, 0x10, 0x63, 0x78,
/* '6' 0x36 */ 0x72, 0x61, 0xE8, 0xC6, 0x39, 0x70,
/* '7' 0x37 */ 0xF8, 0x44, 0x22, 0x11, 0x08, 0x40,
/* '8' 0x38 */ 0x7A, 0x18, 0x61, 0x7A, 0x18, 0x61, 0x78,
/* '9' 0x39 */ 0x7B, 0x28, 0x61, 0xCD, 0xD0, 0x62, 0x70,
/* ':' 0x3A */ 0x82,
/* ';' 0x3B */ 0x87,
/* '<' 0x3C */ 0x3E, 0x30, 0x60, 0x80,
/* '=' 0x3D */ 0xF8, 0x3E,
/* '>' 0x3E */ 0xE0, 0xC6, 0xC8, 0x00,
/* '?' 0x3F */ 0x74, 0x42, 0x11, 0x10, 0x80, 0x20,
/* '@' 0x40 */ 0x0F, 0x06, 0x19, 0x3B, 0xC4, 0x99, 0x13, 0x22, 0x64, 0x96, 0x6E, 0x40, 0x04, 0x00, 0x7C, 0x00,
/* 'A' 0x41 */ 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3,
/* 'B' 0x42 */ 0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xF8,
/* 'C' 0x43 */ 0x3E, 0x41, 0x80, 0x80, 0x80, 0x80, 0x81, 0x43, 0x3E,
/* 'D' 0x44 */ 0xF9, 0x0A, 0x0C, 0x18, 0x30, 0x60, 0xC2, 0xF8,
/* 'E' 0x45 */ 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0xFC,
/* 'F' 0x46 */ 0xFC, 0x21, 0x0F, 0xC2, 0x10, 0x80,
/* 'G' 0x47 */ 0x3E, 0x41, 0x80, 0x80, 0x87, 0x81, 0xC1, 0x43, 0x3D,
/* 'H' 0x48 */ 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82,
/* 'I' 0x49 */ 0xFF, 0x80,
/* 'J' 0x4A */ 0x08, 0x42, 0x10, 0x86, 0x31, 0x70,
/* 'K' 0x4B */ 0x86, 0x29, 0x28, 0xD2, 0x48, 0xA1, 0x84,
/* 'L' 0x4C */ 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8,
/* 'M' 0x4D */ 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99,
/* 'N' 0x4E */ 0xC3, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86,
/* 'O' 0x4F */ 0x3E, 0x31, 0xB0, 0x70, 0x18, 0x0C, 0x07, 0x06, 0xC6, 0x3E, 0x00,
/* 'P' 0x50 */ 0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80,
/* 'Q' 0x51 */ 0x3E, 0x31, 0xB0, 0x70, 0x18, 0x0C, 0x07, 0x06, 0xC6, 0x3F, 0x00, 0x40,
/* 'R' 0x52 */ 0xF9, 0x0A, 0x14, 0x2F, 0x90, 0xA1, 0x42, 0x86,
/* 'S' 0x53 */ 0x7A, 0x18, 0x30, 0x78, 0x38, 0x71, 0x78,
/* 'T' 0x54 */ 0xFC, 0x41, 0x04, 0x10, 0x41, 0x04, 0x10,
/* 'U' 0x55 */ 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE3, 0x7C,
/* 'V' 0x56 */ 0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18,
/* 'W' 0x57 */ 0x84, 0x38, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0xD2, 0x8C, 0x61, 0x8C, 0x31, 0x80,
/* 'X' 0x58 */ 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84,
/* 'Y' 0x59 */ 0x82, 0x89, 0x11, 0x43, 0x82, 0x04, 0x08, 0x10,
/* 'Z' 0x5A */ 0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE,
/* '[' 0x5B */ 0xEA, 0xAA, 0xAB,
/* '\' 0x5C */ 0x92, 0x24, 0x91, 0x20,
/* ']' 0x5D */ 0xD5, 0x55, 0x57,
/* '^' 0x5E */ 0x46, 0xA9, 0x10,
/* '_' 0x5F */ 0xFE,
/* '`' 0x60 */ 0x80,
/* 'a' 0x61 */ 0x79, 0x08, 0x11, 0xEC, 0x51, 0x9D, 0x80,
/* 'b' 0x62 */ 0x84, 0x3D, 0xB8, 0xC6, 0x3B, 0xF0,
/* 'c' 0x63 */ 0x7B, 0x18, 0x20, 0x83, 0x17, 0x80,
/* 'd' 0x64 */ 0x04, 0x17, 0xF3, 0x86, 0x18, 0x73, 0x74,
/* 'e' 0x65 */ 0x7B, 0x38, 0x7F, 0x83, 0x17, 0x80,
/* 'f' 0x66 */ 0x6B, 0xA4, 0x92, 0x40,
/* 'g' 0x67 */ 0x77, 0x38, 0x61, 0x87, 0x37, 0x41, 0x8D, 0xE0,
/* 'h' 0x68 */ 0x84, 0x2D, 0x98, 0xC6, 0x31, 0x88,
/* 'i' 0x69 */ 0xBF, 0x80,
/* 'j' 0x6A */ 0x45, 0x55, 0x57,
/* 'k' 0x6B */ 0x84, 0x25, 0x6E, 0x72, 0x52, 0x88,
/* 'l' 0x6C */ 0xFF, 0x80,
/* 'm' 0x6D */ 0xFF, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91,
/* 'n' 0x6E */ 0xB6, 0x63, 0x18, 0xC6, 0x20,
/* 'o' 0x6F */ 0x7B, 0x38, 0x61, 0x87, 0x37, 0x80,
/* 'p' 0x70 */ 0xF6, 0xE3, 0x18, 0xEF, 0xD0, 0x80,
/* 'q' 0x71 */ 0x77, 0x38, 0x61, 0x87, 0x37, 0x41, 0x04,
/* 'r' 0x72 */ 0xBA, 0x49, 0x20,
/* 's' 0x73 */ 0x69, 0x8E, 0x19, 0x60,
/* 't' 0x74 */ 0x5D, 0x24, 0x93,
/* 'u' 0x75 */ 0x8C, 0x63, 0x18, 0xCD, 0xA0,
/* 'v' 0x76 */ 0x85, 0x24, 0x92, 0x30, 0xC3, 0x00,
/* 'w' 0x77 */ 0x89, 0x99, 0x59, 0x55, 0x56, 0x66, 0x26,
/* 'x' 0x78 */ 0x4A, 0x4C, 0x43, 0x27, 0x20,
/* 'y' 0x79 */ 0x85, 0x24, 0x92, 0x30, 0xC3, 0x08, 0x21, 0x80,
/* 'z' 0x7A */ 0x78, 0x44, 0x46, 0x23, 0xE0,
/* '{' 0x7B */ 0x69, 0x25, 0xB2, 0x49, 0x30,
/* '|' 0x7C */ 0xFF, 0xE0,
/* '}' 0x7D */ 0xC9, 0x24, 0xDA, 0x49, 0x60,
/* '~' 0x7E */ 0x66, 0x70,
};
const GFXglyph FreeSans6pt7bGlyphs[] PROGMEM = {{0, 0, 0, 3, 0, 1}, // 0x20 ' '
{0, 2, 9, 4, 1, -8}, // 0x21 '!'
{3, 4, 3, 4, 0, -8}, // 0x22 '"'
{5, 7, 8, 7, 0, -7}, // 0x23 '#'
{12, 6, 11, 7, 0, -9}, // 0x24 '$'
{21, 10, 9, 11, 0, -8}, // 0x25 '%'
{33, 7, 9, 8, 1, -8}, // 0x26 '&'
{41, 1, 3, 2, 1, -8}, // 0x27 '''
{42, 2, 11, 4, 1, -8}, // 0x28 '('
{45, 3, 11, 4, 0, -8}, // 0x29 ')'
{50, 4, 3, 5, 0, -8}, // 0x2A '*'
{52, 5, 5, 7, 1, -4}, // 0x2B '+'
{56, 1, 3, 3, 1, 0}, // 0x2C ','
{57, 2, 1, 4, 1, -3}, // 0x2D '-'
{58, 1, 1, 3, 1, 0}, // 0x2E '.'
{59, 3, 9, 3, 0, -8}, // 0x2F '/'
{63, 5, 9, 7, 1, -8}, // 0x30 '0'
{69, 3, 9, 7, 1, -8}, // 0x31 '1'
{73, 6, 9, 7, 0, -8}, // 0x32 '2'
{80, 6, 9, 7, 0, -8}, // 0x33 '3'
{87, 6, 9, 7, 0, -8}, // 0x34 '4'
{94, 6, 9, 7, 0, -8}, // 0x35 '5'
{101, 5, 9, 7, 1, -8}, // 0x36 '6'
{107, 5, 9, 7, 1, -8}, // 0x37 '7'
{113, 6, 9, 7, 0, -8}, // 0x38 '8'
{120, 6, 9, 7, 0, -8}, // 0x39 '9'
{127, 1, 7, 3, 1, -6}, // 0x3A ':'
{128, 1, 8, 3, 1, -5}, // 0x3B ';'
{129, 5, 6, 7, 1, -5}, // 0x3C '<'
{133, 5, 3, 7, 1, -3}, // 0x3D '='
{135, 5, 6, 7, 1, -5}, // 0x3E '>'
{139, 5, 9, 7, 1, -8}, // 0x3F '?'
{145, 11, 11, 12, 0, -8}, // 0x40 '@'
{161, 8, 9, 8, 0, -8}, // 0x41 'A'
{170, 6, 9, 8, 1, -8}, // 0x42 'B'
{177, 8, 9, 9, 0, -8}, // 0x43 'C'
{186, 7, 9, 8, 1, -8}, // 0x44 'D'
{194, 6, 9, 8, 1, -8}, // 0x45 'E'
{201, 6, 9, 7, 1, -8}, // 0x46 'F'
{208, 8, 9, 9, 0, -8}, // 0x47 'G'
{217, 7, 9, 9, 1, -8}, // 0x48 'H'
{225, 1, 9, 3, 1, -8}, // 0x49 'I'
{227, 5, 9, 6, 0, -8}, // 0x4A 'J'
{233, 7, 9, 8, 1, -8}, // 0x4B 'K'
{241, 5, 9, 7, 1, -8}, // 0x4C 'L'
{247, 8, 9, 10, 1, -8}, // 0x4D 'M'
{256, 7, 9, 9, 1, -8}, // 0x4E 'N'
{264, 9, 9, 9, 0, -8}, // 0x4F 'O'
{275, 6, 9, 8, 1, -8}, // 0x50 'P'
{282, 9, 10, 9, 0, -8}, // 0x51 'Q'
{294, 7, 9, 9, 1, -8}, // 0x52 'R'
{302, 6, 9, 8, 1, -8}, // 0x53 'S'
{309, 7, 9, 8, 0, -8}, // 0x54 'T'
{317, 7, 9, 9, 1, -8}, // 0x55 'U'
{325, 8, 9, 8, 0, -8}, // 0x56 'V'
{334, 11, 9, 11, 0, -8}, // 0x57 'W'
{347, 8, 9, 8, 0, -8}, // 0x58 'X'
{356, 8, 9, 8, 0, -8}, // 0x59 'Y'
{365, 7, 9, 7, 0, -8}, // 0x5A 'Z'
{373, 2, 12, 3, 1, -8}, // 0x5B '['
{376, 3, 9, 3, 0, -8}, // 0x5C '\'
{380, 3, 12, 3, 0, -8}, // 0x5D ']'
{385, 4, 5, 6, 1, -8}, // 0x5E '^'
{388, 7, 1, 7, 0, 2}, // 0x5F '_'
{389, 3, 1, 3, 0, -8}, // 0x60 '`'
{390, 6, 7, 7, 0, -6}, // 0x61 'a'
{396, 5, 9, 7, 1, -8}, // 0x62 'b'
{402, 6, 7, 6, 0, -6}, // 0x63 'c'
{408, 6, 9, 7, 0, -8}, // 0x64 'd'
{415, 6, 7, 6, 0, -6}, // 0x65 'e'
{421, 3, 9, 3, 0, -8}, // 0x66 'f'
{425, 6, 10, 7, 0, -6}, // 0x67 'g'
{433, 5, 9, 6, 1, -8}, // 0x68 'h'
{439, 1, 9, 3, 1, -8}, // 0x69 'i'
{441, 2, 12, 3, 0, -8}, // 0x6A 'j'
{444, 5, 9, 6, 1, -8}, // 0x6B 'k'
{450, 1, 9, 3, 1, -8}, // 0x6C 'l'
{452, 8, 7, 10, 1, -6}, // 0x6D 'm'
{459, 5, 7, 6, 1, -6}, // 0x6E 'n'
{464, 6, 7, 6, 0, -6}, // 0x6F 'o'
{470, 5, 9, 7, 1, -6}, // 0x70 'p'
{476, 6, 9, 7, 0, -6}, // 0x71 'q'
{483, 3, 7, 4, 1, -6}, // 0x72 'r'
{486, 6, 7, 6, 0, -6}, // 0x73 's'
{492, 3, 8, 3, 0, -7}, // 0x74 't'
{495, 5, 7, 6, 1, -6}, // 0x75 'u'
{500, 6, 7, 6, 0, -6}, // 0x76 'v'
{506, 9, 7, 9, 0, -6}, // 0x77 'w'
{514, 6, 7, 6, 0, -6}, // 0x78 'x'
{520, 6, 10, 6, 0, -6}, // 0x79 'y'
{528, 5, 7, 6, 0, -6}, // 0x7A 'z'
{533, 2, 12, 4, 1, -8}, // 0x7B '{'
{536, 1, 11, 3, 1, -8}, // 0x7C '|'
{538, 2, 12, 4, 1, -8}, // 0x7D '}'
{541, 6, 2, 6, 0, -4}}; // 0x7E '~'
const GFXglyph FreeSans6pt7bGlyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 3, 0, 0},
/* '!' 0x21 */ {0, 1, 9, 4, 2, -8},
/* '"' 0x22 */ {2, 3, 3, 4, 0, -8},
/* '#' 0x23 */ {4, 7, 8, 7, 0, -7},
/* '$' 0x24 */ {11, 5, 11, 7, 1, -9},
/* '%' 0x25 */ {18, 10, 9, 11, 0, -8},
/* '&' 0x26 */ {30, 6, 9, 8, 1, -8},
/* ''' 0x27 */ {37, 1, 3, 2, 1, -8},
/* '(' 0x28 */ {38, 2, 11, 4, 1, -8},
/* ')' 0x29 */ {41, 3, 11, 4, 0, -8},
/* '*' 0x2A */ {46, 3, 3, 5, 1, -8},
/* '+' 0x2B */ {48, 5, 5, 7, 1, -4},
/* ',' 0x2C */ {52, 1, 3, 3, 1, 0},
/* '-' 0x2D */ {53, 3, 1, 4, 1, -3},
/* '.' 0x2E */ {54, 1, 1, 3, 1, 0},
/* '/' 0x2F */ {55, 3, 9, 3, 0, -8},
/* '0' 0x30 */ {59, 5, 9, 7, 1, -8},
/* '1' 0x31 */ {65, 2, 9, 7, 2, -8},
/* '2' 0x32 */ {68, 5, 9, 7, 1, -8},
/* '3' 0x33 */ {74, 5, 9, 7, 1, -8},
/* '4' 0x34 */ {80, 5, 9, 7, 1, -8},
/* '5' 0x35 */ {86, 6, 9, 7, 0, -8},
/* '6' 0x36 */ {93, 5, 9, 7, 1, -8},
/* '7' 0x37 */ {99, 5, 9, 7, 1, -8},
/* '8' 0x38 */ {105, 6, 9, 7, 0, -8},
/* '9' 0x39 */ {112, 6, 9, 7, 0, -8},
/* ':' 0x3A */ {119, 1, 7, 3, 1, -6},
/* ';' 0x3B */ {120, 1, 8, 3, 1, -5},
/* '<' 0x3C */ {121, 5, 5, 7, 1, -4},
/* '=' 0x3D */ {125, 5, 3, 7, 1, -3},
/* '>' 0x3E */ {127, 5, 5, 7, 1, -4},
/* '?' 0x3F */ {131, 5, 9, 7, 1, -8},
/* '@' 0x40 */ {137, 11, 11, 12, 0, -8},
/* 'A' 0x41 */ {153, 8, 9, 8, 0, -8},
/* 'B' 0x42 */ {162, 6, 9, 8, 1, -8},
/* 'C' 0x43 */ {169, 8, 9, 9, 0, -8},
/* 'D' 0x44 */ {178, 7, 9, 8, 1, -8},
/* 'E' 0x45 */ {186, 6, 9, 8, 1, -8},
/* 'F' 0x46 */ {193, 5, 9, 7, 1, -8},
/* 'G' 0x47 */ {199, 8, 9, 9, 0, -8},
/* 'H' 0x48 */ {208, 7, 9, 9, 1, -8},
/* 'I' 0x49 */ {216, 1, 9, 3, 1, -8},
/* 'J' 0x4A */ {218, 5, 9, 6, 0, -8},
/* 'K' 0x4B */ {224, 6, 9, 8, 1, -8},
/* 'L' 0x4C */ {231, 5, 9, 7, 1, -8},
/* 'M' 0x4D */ {237, 8, 9, 10, 1, -8},
/* 'N' 0x4E */ {246, 7, 9, 9, 1, -8},
/* 'O' 0x4F */ {254, 9, 9, 9, 0, -8},
/* 'P' 0x50 */ {265, 6, 9, 8, 1, -8},
/* 'Q' 0x51 */ {272, 9, 10, 9, 0, -8},
/* 'R' 0x52 */ {284, 7, 9, 9, 1, -8},
/* 'S' 0x53 */ {292, 6, 9, 8, 1, -8},
/* 'T' 0x54 */ {299, 6, 9, 8, 0, -8},
/* 'U' 0x55 */ {306, 7, 9, 9, 1, -8},
/* 'V' 0x56 */ {314, 7, 9, 8, 0, -8},
/* 'W' 0x57 */ {322, 11, 9, 11, 0, -8},
/* 'X' 0x58 */ {335, 6, 9, 8, 1, -8},
/* 'Y' 0x59 */ {342, 7, 9, 8, 1, -8},
/* 'Z' 0x5A */ {350, 7, 9, 7, 0, -8},
/* '[' 0x5B */ {358, 2, 12, 3, 1, -8},
/* '\' 0x5C */ {361, 3, 9, 3, 0, -8},
/* ']' 0x5D */ {365, 2, 12, 3, 0, -8},
/* '^' 0x5E */ {368, 4, 5, 6, 1, -8},
/* '_' 0x5F */ {371, 7, 1, 7, 0, 2},
/* '`' 0x60 */ {372, 1, 1, 3, 1, -8},
/* 'a' 0x61 */ {373, 7, 7, 7, 0, -6},
/* 'b' 0x62 */ {380, 5, 9, 7, 1, -8},
/* 'c' 0x63 */ {386, 6, 7, 6, 0, -6},
/* 'd' 0x64 */ {392, 6, 9, 7, 0, -8},
/* 'e' 0x65 */ {399, 6, 7, 6, 0, -6},
/* 'f' 0x66 */ {405, 3, 9, 3, 0, -8},
/* 'g' 0x67 */ {409, 6, 10, 7, 0, -6},
/* 'h' 0x68 */ {417, 5, 9, 6, 1, -8},
/* 'i' 0x69 */ {423, 1, 9, 3, 1, -8},
/* 'j' 0x6A */ {425, 2, 12, 3, 0, -8},
/* 'k' 0x6B */ {428, 5, 9, 6, 1, -8},
/* 'l' 0x6C */ {434, 1, 9, 3, 1, -8},
/* 'm' 0x6D */ {436, 8, 7, 10, 1, -6},
/* 'n' 0x6E */ {443, 5, 7, 6, 1, -6},
/* 'o' 0x6F */ {448, 6, 7, 6, 0, -6},
/* 'p' 0x70 */ {454, 5, 9, 7, 1, -6},
/* 'q' 0x71 */ {460, 6, 9, 7, 0, -6},
/* 'r' 0x72 */ {467, 3, 7, 4, 1, -6},
/* 's' 0x73 */ {470, 4, 7, 6, 1, -6},
/* 't' 0x74 */ {474, 3, 8, 3, 0, -7},
/* 'u' 0x75 */ {477, 5, 7, 6, 1, -6},
/* 'v' 0x76 */ {482, 6, 7, 6, 0, -6},
/* 'w' 0x77 */ {488, 8, 7, 9, 0, -6},
/* 'x' 0x78 */ {495, 5, 7, 6, 0, -6},
/* 'y' 0x79 */ {500, 6, 10, 6, 0, -6},
/* 'z' 0x7A */ {508, 5, 7, 6, 0, -6},
/* '{' 0x7B */ {513, 3, 12, 4, 0, -8},
/* '|' 0x7C */ {518, 1, 11, 3, 1, -8},
/* '}' 0x7D */ {520, 3, 12, 4, 1, -8},
/* '~' 0x7E */ {525, 6, 2, 6, 0, -4},
};
const GFXfont FreeSans6pt7b PROGMEM = {(uint8_t *)FreeSans6pt7bBitmaps, (GFXglyph *)FreeSans6pt7bGlyphs, 0x20, 0x7E, 14};
// Approx. 1215 bytes
@@ -1,302 +0,0 @@
/*
Uses Windows-1251 encoding to map translingual Cyrillic characters to range between (uint8_t)127 and (uint8_t)255
https://en.wikipedia.org/wiki/Windows-1251
Cyrillic characters present to the firmware as UTF8.
A NicheGraphics implementation needs to identify these, and substitute the appropriate Windows-1251 char value.
*/
#pragma once
const uint8_t FreeSans6pt8bCyrillicBitmaps[] PROGMEM = {
0xFF, 0xA0, 0xC0, 0xFF, 0xA0, 0xC0, 0xB6, 0x80, 0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, 0x31, 0x75, 0x54, 0x78, 0x79, 0x75,
0x7C, 0x41, 0x00, 0x01, 0x1C, 0x49, 0x22, 0x50, 0x74, 0x02, 0x60, 0xA4, 0x49, 0x11, 0xC0, 0x21, 0x44, 0x94, 0x62, 0x59, 0xE2,
0xF4, 0xE0, 0x6A, 0xAA, 0x90, 0x48, 0x92, 0x49, 0x4A, 0x00, 0x5D, 0x40, 0x21, 0x09, 0xF2, 0x10, 0xE0, 0xC0, 0x80, 0x25, 0x25,
0x24, 0x26, 0xA3, 0x18, 0xC6, 0x31, 0xF0, 0x27, 0x92, 0x49, 0x20, 0x11, 0xB4, 0x41, 0x0C, 0xC6, 0x10, 0xFC, 0x26, 0xA2, 0x13,
0x04, 0x31, 0xF0, 0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, 0xFF, 0xE1, 0x4D, 0x84, 0x31, 0xF0, 0x26, 0xE3, 0x0F, 0x46, 0x31,
0xF0, 0xFF, 0xC4, 0x22, 0x11, 0x08, 0x40, 0x11, 0xA4, 0x51, 0x39, 0x1C, 0x51, 0x78, 0x11, 0xA4, 0x71, 0x45, 0xF0, 0x51, 0x78,
0xC0, 0x30, 0xC0, 0x36, 0x1F, 0x20, 0xE0, 0x80, 0xF8, 0x3E, 0xC1, 0xC2, 0xE8, 0x00, 0x74, 0x62, 0x11, 0x10, 0x80, 0x20, 0x0F,
0x06, 0x18, 0x81, 0xA7, 0xD4, 0x93, 0x22, 0x64, 0x4A, 0x7E, 0x60, 0x06, 0x00, 0x3C, 0x00, 0x18, 0x18, 0x1C, 0x24, 0x24, 0x7E,
0x42, 0x42, 0xC3, 0xFA, 0x38, 0x61, 0xFA, 0x18, 0x61, 0xFC, 0x38, 0x8A, 0x0C, 0x08, 0x10, 0x20, 0xE3, 0x7C, 0xF9, 0x1A, 0x1C,
0x18, 0x30, 0x60, 0xC2, 0xF8, 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, 0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, 0x3C, 0x46,
0x82, 0x80, 0x8F, 0x81, 0x83, 0xC3, 0x7D, 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, 0xFF, 0x80, 0x08, 0x42, 0x10, 0x86,
0x31, 0x78, 0x87, 0x1A, 0x65, 0x8F, 0x1A, 0x22, 0x42, 0x86, 0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, 0xC3, 0xC3, 0xC3, 0xA5, 0xA5,
0xA5, 0x99, 0x99, 0x99, 0x83, 0x87, 0x8D, 0x19, 0x32, 0x62, 0xC3, 0x86, 0x1E, 0x11, 0x90, 0x48, 0x1C, 0x0A, 0x05, 0x06, 0xC2,
0x3E, 0x00, 0xFA, 0x18, 0x61, 0xFE, 0x08, 0x20, 0x80, 0x1E, 0x11, 0x90, 0x48, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x3F, 0x00, 0xFD,
0x0E, 0x0C, 0x1F, 0xD0, 0xA0, 0xC1, 0x82, 0x7A, 0x18, 0x70, 0x78, 0x38, 0x61, 0x7C, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08,
0x10, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC3, 0x7C, 0xC3, 0x42, 0x42, 0x26, 0x24, 0x24, 0x14, 0x18, 0x18, 0xC4, 0x28, 0xC5,
0x39, 0xA5, 0x24, 0xA4, 0x52, 0x8C, 0x71, 0x8C, 0x30, 0x80, 0x87, 0x34, 0x8C, 0x30, 0xC4, 0xB3, 0x84, 0xC3, 0x42, 0x26, 0x24,
0x18, 0x18, 0x08, 0x08, 0x08, 0x7E, 0x0C, 0x10, 0x41, 0x06, 0x08, 0x20, 0xFE, 0xEA, 0xAA, 0xAB, 0x92, 0x24, 0x89, 0x20, 0xED,
0xB6, 0xDB, 0x6D, 0xF0, 0x46, 0xAA, 0x90, 0xFC, 0x90, 0xFC, 0x4F, 0x98, 0xFC, 0x84, 0x21, 0xF8, 0xC6, 0x31, 0xF0, 0x79, 0x18,
0x20, 0x45, 0xE0, 0x04, 0x10, 0x5F, 0xC6, 0x18, 0x51, 0x7C, 0xFC, 0x7F, 0x08, 0xF8, 0x29, 0x74, 0x92, 0x40, 0x7D, 0x18, 0x61,
0x45, 0xF0, 0x52, 0x30, 0x84, 0x21, 0xF8, 0xC6, 0x31, 0x88, 0xDF, 0x80, 0x51, 0x55, 0x56, 0x84, 0x21, 0x2A, 0x72, 0x92, 0x98,
0xFF, 0x80, 0xFF, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFC, 0x63, 0x18, 0xC4, 0x79, 0x18, 0x71, 0x45, 0xE0, 0xFC, 0x63, 0x18, 0xFA,
0x10, 0x80, 0x7D, 0x18, 0x61, 0x45, 0xF0, 0x41, 0x04, 0xF2, 0x49, 0x00, 0x79, 0x07, 0x02, 0xCD, 0xE0, 0x4B, 0xA4, 0x93, 0x8C,
0x63, 0x18, 0xFC, 0xCD, 0x24, 0x94, 0x30, 0xC0, 0x99, 0x59, 0x55, 0x56, 0x66, 0x26, 0x96, 0x66, 0x99, 0xCA, 0x52, 0x63, 0x18,
0x84, 0x40, 0x78, 0xC4, 0x44, 0x7C, 0x6A, 0xAA, 0xA9, 0xFF, 0xF0, 0xC9, 0x24, 0x4A, 0x49, 0x40, 0xE8, 0xC0, 0xFE, 0x18, 0x61,
0x86, 0x18, 0x61, 0xFC, 0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, 0xC0, 0xC0, 0x10, 0x8F, 0xE0, 0x82,
0x08, 0x20, 0x82, 0x08, 0x00, 0x64, 0x0F, 0x88, 0x88, 0x80, 0x3D, 0x0C, 0x2E, 0xF9, 0x04, 0x0F, 0x7C, 0x08, 0x81, 0x10, 0x22,
0x04, 0x7C, 0x88, 0x51, 0x0A, 0x21, 0x87, 0xC0, 0x84, 0x10, 0x82, 0x10, 0x42, 0x0F, 0xFD, 0x08, 0xA1, 0x0C, 0x23, 0x87, 0xC0,
0x10, 0x88, 0xE6, 0xB3, 0x8C, 0x28, 0x92, 0x28, 0xC0, 0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, 0x83,
0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xFE, 0x20, 0x40, 0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, 0x44, 0x11, 0x80, 0x78, 0x24, 0x13,
0xC9, 0x14, 0x8E, 0x7C, 0x88, 0x44, 0x3F, 0xD1, 0x38, 0x8C, 0x78, 0x60, 0x9A, 0xCC, 0xA9, 0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51,
0x44, 0x8C, 0x63, 0x18, 0xFC, 0x80, 0x24, 0x33, 0x0A, 0x36, 0x45, 0x8E, 0x0C, 0x10, 0x60, 0x80, 0x70, 0x22, 0x95, 0xA8, 0xC4,
0x23, 0x10, 0x08, 0x42, 0x10, 0x86, 0x31, 0x78, 0x07, 0xF8, 0x20, 0x82, 0x08, 0x20, 0x82, 0x00, 0x28, 0x0F, 0xE0, 0x82, 0x0F,
0xE0, 0x82, 0x0F, 0xC0, 0x38, 0x8A, 0x0C, 0x0F, 0x90, 0x20, 0xE3, 0x7C, 0x51, 0x55, 0x56, 0xA1, 0x24, 0x92, 0x49, 0x00, 0xFF,
0x80, 0xDF, 0x80, 0x27, 0xC9, 0x24, 0x8A, 0x28, 0xA2, 0x8B, 0xF8, 0x20, 0x80, 0x28, 0xA0, 0x1E, 0x47, 0xFC, 0x11, 0x78, 0x88,
0x44, 0x32, 0x59, 0xDA, 0xCD, 0x66, 0x6B, 0x32, 0x89, 0x80, 0x79, 0x1F, 0x30, 0x45, 0xE0, 0x7A, 0x18, 0x70, 0x78, 0x38, 0x61,
0x7C, 0x79, 0x07, 0x02, 0xCD, 0xE0, 0xB4, 0x24, 0x92, 0x40, 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, 0xFE, 0x08,
0x20, 0xFE, 0x18, 0x61, 0xFC, 0xFA, 0x38, 0x61, 0xFA, 0x18, 0x61, 0xFC, 0xFE, 0x08, 0x20, 0x82, 0x08, 0x20, 0x80, 0x1F, 0x08,
0x84, 0x42, 0x21, 0x10, 0x88, 0x44, 0x42, 0xFF, 0xC0, 0x60, 0x20, 0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, 0x88, 0xA4, 0x9A,
0x87, 0xC1, 0xC1, 0xF1, 0xAD, 0x92, 0x88, 0x80, 0x7A, 0x18, 0x41, 0x38, 0x18, 0x61, 0x7C, 0x87, 0x0E, 0x2C, 0x59, 0x34, 0x68,
0xE1, 0xC2, 0x28, 0x22, 0x1C, 0x38, 0xB1, 0x64, 0xD1, 0xA3, 0x87, 0x08, 0x8E, 0x6B, 0x38, 0xC2, 0x89, 0x22, 0x8C, 0x3E, 0x44,
0x89, 0x12, 0x24, 0x58, 0xA1, 0xC2, 0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, 0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60,
0xC1, 0x82, 0x3C, 0x46, 0x83, 0x81, 0x81, 0x81, 0x81, 0xC2, 0x7C, 0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x82, 0xFA, 0x18,
0x61, 0xFE, 0x08, 0x20, 0x80, 0x38, 0x8A, 0x0C, 0x08, 0x10, 0x20, 0xE3, 0x7C, 0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10,
0xC2, 0x8D, 0x91, 0x63, 0x83, 0x04, 0x18, 0x20, 0x08, 0x1E, 0x32, 0xD1, 0x38, 0x8C, 0x4F, 0x2C, 0xFC, 0x08, 0x00, 0x87, 0x34,
0x8C, 0x30, 0xC4, 0xB3, 0x84, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFF, 0x01, 0x01, 0x8E, 0x38, 0xE3, 0x8D, 0xF0,
0xC3, 0x0C, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFF, 0x99, 0x4C, 0xA6, 0x53, 0x29, 0x94, 0xCA, 0x65, 0x32, 0xFF,
0x80, 0x40, 0x20, 0xF0, 0x04, 0x01, 0x00, 0x40, 0x1F, 0x84, 0x21, 0x0C, 0x42, 0x1F, 0x00, 0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xDC,
0x2E, 0x17, 0x0B, 0xF9, 0x80, 0x82, 0x08, 0x20, 0xFE, 0x18, 0x61, 0xF8, 0x79, 0x8A, 0x18, 0x13, 0xE0, 0x60, 0xC2, 0x7C, 0x87,
0x26, 0x39, 0x06, 0x41, 0xF0, 0x64, 0x19, 0x06, 0x63, 0x8F, 0x80, 0x7E, 0x18, 0x61, 0x7C, 0xD6, 0x71, 0x84, 0x79, 0x11, 0xD9,
0xCD, 0xD0, 0x0D, 0xC4, 0x1E, 0x47, 0x1C, 0x51, 0x78, 0xF4, 0xBD, 0x29, 0xF8, 0xF8, 0x88, 0x88, 0x3C, 0x48, 0x91, 0x22, 0x5F,
0xE0, 0x80, 0x79, 0x1F, 0xF0, 0x45, 0xE0, 0x92, 0x54, 0x38, 0x3C, 0x56, 0x93, 0x78, 0x23, 0x82, 0xCD, 0xE0, 0x9C, 0xEB, 0x5C,
0xC4, 0x70, 0x27, 0x3A, 0xD7, 0x31, 0x9A, 0xCC, 0xA9, 0x7A, 0x52, 0x94, 0xE4, 0x8F, 0x3D, 0x6D, 0xA6, 0x90, 0x8C, 0x7F, 0x18,
0xC4, 0x79, 0x1C, 0x71, 0x45, 0xE0, 0xFC, 0x63, 0x18, 0xC4, 0xFC, 0x63, 0x18, 0xFA, 0x10, 0x80, 0x79, 0x1C, 0x30, 0x45, 0xE0,
0xF9, 0x08, 0x42, 0x10, 0x8A, 0x56, 0xA3, 0x10, 0x8C, 0x40, 0x04, 0x01, 0x07, 0xF9, 0x31, 0xC4, 0x71, 0x14, 0xC5, 0xFE, 0x04,
0x01, 0x00, 0x40, 0x4B, 0x8C, 0x65, 0xE4, 0x8A, 0x28, 0xA2, 0x8B, 0xF0, 0x40, 0x99, 0x97, 0x11, 0x96, 0x59, 0x65, 0x97, 0xF0,
0x95, 0x2A, 0x54, 0xA9, 0x5F, 0xC0, 0x80, 0xF0, 0x20, 0x78, 0x91, 0x23, 0xC0, 0x86, 0x1F, 0x63, 0x8F, 0xD0, 0x84, 0x3D, 0x18,
0xF8, 0xF4, 0xDE, 0x19, 0xF8, 0x9E, 0xA2, 0xE1, 0xA1, 0xA2, 0x9E, 0xFC, 0x7E, 0xD4, 0xC4,
};
const GFXglyph FreeSans6pt8bCyrillicGlyphs[] PROGMEM = {
{0, 0, 0, 3, 0, 0}, // 0x20 ' '
{3, 2, 9, 3, 1, -8}, // 0x21 '!'
{6, 3, 3, 4, 1, -8}, // 0x22 '"'
{8, 7, 8, 7, 0, -7}, // 0x23 '#'
{15, 6, 11, 7, 0, -8}, // 0x24 '$'
{24, 10, 9, 11, 0, -8}, // 0x25 '%'
{36, 6, 9, 8, 1, -8}, // 0x26 '&'
{43, 1, 3, 2, 1, -8}, // 0x27 '''
{44, 2, 10, 4, 1, -7}, // 0x28 '('
{47, 3, 11, 4, 0, -7}, // 0x29 ')'
{52, 3, 4, 5, 1, -8}, // 0x2A '*'
{54, 5, 6, 7, 1, -5}, // 0x2B '+'
{58, 1, 3, 3, 1, 0}, // 0x2C ','
{59, 2, 1, 4, 1, -3}, // 0x2D '-'
{60, 1, 1, 3, 1, 0}, // 0x2E '.'
{61, 3, 8, 3, 0, -7}, // 0x2F '/'
{64, 5, 9, 7, 1, -8}, // 0x30 '0'
{70, 3, 9, 7, 1, -8}, // 0x31 '1'
{74, 6, 9, 7, 0, -8}, // 0x32 '2'
{81, 5, 9, 7, 1, -8}, // 0x33 '3'
{87, 6, 9, 7, 0, -8}, // 0x34 '4'
{94, 5, 9, 7, 1, -8}, // 0x35 '5'
{100, 5, 9, 7, 1, -8}, // 0x36 '6'
{106, 5, 9, 7, 1, -8}, // 0x37 '7'
{112, 6, 9, 7, 0, -8}, // 0x38 '8'
{119, 6, 9, 7, 0, -8}, // 0x39 '9'
{126, 2, 6, 3, 1, -5}, // 0x3A ':'
{128, 2, 8, 3, 1, -5}, // 0x3B ';'
{130, 5, 5, 7, 1, -4}, // 0x3C '<'
{134, 5, 3, 7, 1, -3}, // 0x3D '='
{136, 5, 5, 7, 1, -4}, // 0x3E '>'
{140, 5, 9, 7, 1, -8}, // 0x3F '?'
{146, 11, 11, 12, 0, -8}, // 0x40 '@'
{162, 8, 9, 8, 0, -8}, // 0x41 'A'
{171, 6, 9, 8, 1, -8}, // 0x42 'B'
{178, 7, 9, 9, 1, -8}, // 0x43 'C'
{186, 7, 9, 9, 1, -8}, // 0x44 'D'
{194, 6, 9, 8, 1, -8}, // 0x45 'E'
{201, 6, 9, 7, 1, -8}, // 0x46 'F'
{208, 8, 9, 9, 1, -8}, // 0x47 'G'
{217, 7, 9, 9, 1, -8}, // 0x48 'H'
{225, 1, 9, 3, 1, -8}, // 0x49 'I'
{227, 5, 9, 6, 0, -8}, // 0x4A 'J'
{233, 7, 9, 8, 1, -8}, // 0x4B 'K'
{241, 5, 9, 7, 1, -8}, // 0x4C 'L'
{247, 8, 9, 10, 1, -8}, // 0x4D 'M'
{256, 7, 9, 9, 1, -8}, // 0x4E 'N'
{264, 9, 9, 9, 0, -8}, // 0x4F 'O'
{275, 6, 9, 8, 1, -8}, // 0x50 'P'
{282, 9, 9, 9, 0, -8}, // 0x51 'Q'
{293, 7, 9, 9, 1, -8}, // 0x52 'R'
{301, 6, 9, 8, 1, -8}, // 0x53 'S'
{308, 7, 9, 7, 0, -8}, // 0x54 'T'
{316, 7, 9, 9, 1, -8}, // 0x55 'U'
{324, 8, 9, 8, 0, -8}, // 0x56 'V'
{333, 11, 9, 11, 0, -8}, // 0x57 'W'
{346, 6, 9, 8, 1, -8}, // 0x58 'X'
{353, 8, 9, 8, 0, -8}, // 0x59 'Y'
{362, 7, 9, 7, 0, -8}, // 0x5A 'Z'
{370, 2, 12, 3, 1, -8}, // 0x5B '['
{373, 3, 9, 3, 0, -8}, // 0x5C '\'
{377, 3, 12, 3, 0, -8}, // 0x5D ']'
{382, 4, 5, 6, 1, -8}, // 0x5E '^'
{385, 6, 1, 7, 0, 2}, // 0x5F '_'
{386, 2, 2, 4, 1, -8}, // 0x60 '`'
{387, 5, 6, 7, 1, -5}, // 0x61 'a'
{391, 5, 9, 7, 1, -8}, // 0x62 'b'
{397, 6, 6, 6, 0, -5}, // 0x63 'c'
{402, 6, 9, 7, 0, -8}, // 0x64 'd'
{409, 5, 6, 7, 1, -5}, // 0x65 'e'
{413, 3, 9, 3, 0, -8}, // 0x66 'f'
{417, 6, 9, 7, 0, -5}, // 0x67 'g'
{424, 5, 9, 7, 1, -8}, // 0x68 'h'
{430, 1, 9, 3, 1, -8}, // 0x69 'i'
{432, 2, 12, 3, 0, -8}, // 0x6A 'j'
{435, 5, 9, 6, 1, -8}, // 0x6B 'k'
{441, 1, 9, 3, 1, -8}, // 0x6C 'l'
{443, 8, 6, 10, 1, -5}, // 0x6D 'm'
{449, 5, 6, 7, 1, -5}, // 0x6E 'n'
{453, 6, 6, 7, 0, -5}, // 0x6F 'o'
{458, 5, 9, 7, 1, -5}, // 0x70 'p'
{464, 6, 9, 7, 0, -5}, // 0x71 'q'
{471, 3, 6, 4, 1, -5}, // 0x72 'r'
{474, 6, 6, 6, 0, -5}, // 0x73 's'
{479, 3, 8, 3, 0, -7}, // 0x74 't'
{482, 5, 6, 7, 1, -5}, // 0x75 'u'
{486, 6, 6, 6, 0, -5}, // 0x76 'v'
{491, 8, 6, 9, 0, -5}, // 0x77 'w'
{497, 4, 6, 6, 1, -5}, // 0x78 'x'
{500, 5, 9, 6, 0, -5}, // 0x79 'y'
{506, 5, 6, 6, 0, -5}, // 0x7A 'z'
{510, 2, 12, 4, 1, -8}, // 0x7B '{'
{513, 1, 12, 3, 1, -8}, // 0x7C '|'
{515, 3, 12, 4, 0, -8}, // 0x7D '}'
{520, 5, 2, 7, 1, -4}, // 0x7E '~'
{522, 6, 9, 8, 1, -8}, //
{529, 9, 11, 9, 0, -8}, //
{542, 6, 11, 7, 1, -10}, //
{551, 0, 0, 8, 0, 0}, //
{551, 4, 9, 5, 1, -8}, //
{556, 0, 0, 8, 0, 0}, //
{556, 0, 0, 8, 0, 0}, //
{556, 0, 0, 8, 0, 0}, //
{556, 0, 0, 8, 0, 0}, //
{556, 6, 8, 8, 1, -7}, //
{562, 0, 0, 8, 0, 0}, //
{562, 11, 9, 13, 1, -8}, //
{575, 0, 0, 8, 0, 0}, //
{575, 11, 9, 12, 1, -8}, //
{588, 6, 11, 8, 1, -10}, //
{597, 9, 9, 9, 0, -8}, //
{608, 7, 11, 9, 1, -8}, //
{618, 6, 11, 7, 0, -8}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 0, 0, 8, 0, 0}, //
{627, 9, 6, 10, 0, -5}, //
{634, 0, 0, 8, 0, 0}, //
{634, 9, 6, 10, 1, -5}, //
{641, 4, 8, 6, 1, -7}, //
{645, 6, 9, 7, 0, -8}, //
{652, 5, 7, 7, 1, -5}, //
{657, 0, 0, 8, 0, 0}, //
{657, 7, 11, 7, 0, -10}, //
{667, 5, 11, 6, 0, -7}, //
{674, 5, 9, 6, 0, -8}, //
{680, 0, 0, 8, 0, 0}, //
{680, 6, 10, 7, 1, -9}, //
{688, 0, 0, 8, 0, 0}, //
{688, 0, 0, 8, 0, 0}, //
{688, 6, 11, 8, 1, -10}, //
{697, 7, 9, 9, 1, -8}, //
{705, 0, 0, 8, 0, 0}, //
{705, 0, 0, 8, 0, 0}, //
{705, 2, 12, 3, 0, -8}, //
{708, 0, 0, 8, 0, 0}, //
{708, 0, 0, 8, 0, 0}, //
{708, 3, 11, 3, 0, -10}, //
{713, 0, 0, 8, 0, 0}, //
{713, 0, 0, 8, 0, 0}, //
{713, 1, 9, 3, 1, -8}, //
{715, 1, 9, 3, 1, -8}, //
{717, 3, 8, 5, 1, -7}, //
{720, 6, 9, 7, 1, -5}, //
{727, 0, 0, 8, 0, 0}, //
{727, 0, 0, 8, 0, 0}, //
{727, 6, 9, 7, 0, -8}, //
{734, 9, 9, 11, 1, -8}, //
{745, 6, 6, 6, 0, -5}, //
{750, 0, 0, 8, 0, 0}, //
{750, 0, 0, 8, 0, 0}, //
{750, 6, 9, 8, 1, -8}, //
{757, 6, 6, 6, 0, -5}, //
{762, 3, 9, 3, 0, -8}, //
{766, 8, 9, 8, 0, -8}, //
{775, 6, 9, 8, 1, -8}, //
{782, 6, 9, 8, 1, -8}, //
{789, 6, 9, 7, 1, -8}, //
{796, 9, 11, 10, 0, -8}, //
{809, 6, 9, 8, 1, -8}, //
{816, 9, 9, 11, 1, -8}, //
{827, 6, 9, 8, 1, -8}, //
{834, 7, 9, 9, 1, -8}, //
{842, 7, 11, 9, 1, -10}, //
{852, 6, 9, 8, 1, -8}, //
{859, 7, 9, 8, 0, -8}, //
{867, 8, 9, 10, 1, -8}, //
{876, 7, 9, 9, 1, -8}, //
{884, 8, 9, 10, 1, -8}, //
{893, 7, 9, 9, 1, -8}, //
{901, 6, 9, 8, 1, -8}, //
{908, 7, 9, 9, 1, -8}, //
{916, 7, 9, 7, 0, -8}, //
{924, 7, 9, 7, 0, -8}, //
{932, 9, 9, 10, 1, -8}, //
{943, 6, 9, 8, 1, -8}, //
{950, 8, 11, 9, 1, -8}, //
{961, 6, 9, 8, 1, -8}, //
{968, 8, 9, 10, 1, -8}, //
{977, 9, 11, 10, 1, -8}, //
{990, 10, 9, 10, 0, -8}, //
{1002, 9, 9, 10, 1, -8}, //
{1013, 6, 9, 8, 1, -8}, //
{1020, 7, 9, 9, 1, -8}, //
{1028, 10, 9, 12, 1, -8}, //
{1040, 6, 9, 8, 1, -8}, //
{1047, 6, 6, 7, 0, -5}, //
{1052, 6, 9, 7, 0, -8}, //
{1059, 5, 6, 6, 1, -5}, //
{1063, 4, 6, 5, 1, -5}, //
{1066, 7, 7, 7, 0, -5}, //
{1073, 6, 6, 7, 0, -5}, //
{1078, 8, 6, 9, 1, -5}, //
{1084, 6, 6, 6, 0, -5}, //
{1089, 5, 6, 7, 1, -5}, //
{1093, 5, 8, 7, 1, -7}, //
{1098, 4, 6, 6, 1, -5}, //
{1101, 5, 6, 6, 0, -5}, //
{1105, 6, 6, 7, 1, -5}, //
{1110, 5, 6, 7, 1, -5}, //
{1114, 6, 6, 7, 0, -5}, //
{1119, 5, 6, 7, 1, -5}, //
{1123, 5, 9, 7, 1, -5}, //
{1129, 6, 6, 6, 0, -5}, //
{1134, 5, 6, 5, 0, -5}, //
{1138, 5, 9, 6, 0, -5}, //
{1144, 10, 11, 10, 0, -7}, //
{1158, 5, 6, 6, 0, -5}, //
{1162, 6, 7, 7, 1, -5}, //
{1168, 4, 6, 6, 1, -5}, //
{1171, 6, 6, 8, 1, -5}, //
{1176, 7, 7, 9, 1, -5}, //
{1183, 7, 6, 8, 0, -5}, //
{1189, 6, 6, 8, 1, -5}, //
{1194, 5, 6, 6, 1, -5}, //
{1198, 5, 6, 6, 1, -5}, //
{1202, 8, 6, 9, 1, -5}, //
{1208, 5, 6, 7, 1, -5} //
};
const GFXfont FreeSans6pt8bCyrillic PROGMEM = {(uint8_t *)FreeSans6pt8bCyrillicBitmaps, (GFXglyph *)FreeSans6pt8bCyrillicGlyphs,
0x20, 0xFF, 16};
@@ -0,0 +1,457 @@
#pragma once
const uint8_t FreeSans6pt_Win1250Bitmaps[] PROGMEM = {
/* ' ' 0x20 */
0xFC, 0x80, /* '!' 0x21 */
0xB6, 0x80, /* '"' 0x22 */
0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, /* '#' 0x23 */
0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, /* '$' 0x24 */
0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, /* '%' 0x25 */
0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4, /* '&' 0x26 */
0xE0, /* ''' 0x27 */
0x5A, 0xAA, 0x94, /* '(' 0x28 */
0x89, 0x12, 0x49, 0x29, 0x00, /* ')' 0x29 */
0x5E, 0x80, /* '*' 0x2A */
0x21, 0x3E, 0x42, 0x00, /* '+' 0x2B */
0xE0, /* ',' 0x2C */
0xC0, /* '-' 0x2D */
0x80, /* '.' 0x2E */
0x24, 0xA4, 0xA4, 0x80, /* '/' 0x2F */
0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, /* '0' 0x30 */
0x27, 0x92, 0x49, 0x20, /* '1' 0x31 */
0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, /* '2' 0x32 */
0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78, /* '3' 0x33 */
0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, /* '4' 0x34 */
0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0, /* '5' 0x35 */
0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70, /* '6' 0x36 */
0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, /* '7' 0x37 */
0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, /* '8' 0x38 */
0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78, /* '9' 0x39 */
0x82, /* ':' 0x3A */
0x87, /* ';' 0x3B */
0x3E, 0x30, 0x60, 0x80, /* '<' 0x3C */
0xF8, 0x3E, /* '=' 0x3D */
0xE0, 0xC6, 0xC8, 0x00, /* '>' 0x3E */
0x74, 0x42, 0x11, 0x10, 0x80, 0x20, /* '?' 0x3F */
0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, /* '@' 0x40 */
0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 'A' 0x41 */
0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 'B' 0x42 */
0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, /* 'C' 0x43 */
0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8, /* 'D' 0x44 */
0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 'E' 0x45 */
0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, /* 'F' 0x46 */
0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, /* 'G' 0x47 */
0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 'H' 0x48 */
0xFF, 0x80, /* 'I' 0x49 */
0x08, 0x42, 0x10, 0x87, 0x29, 0x70, /* 'J' 0x4A */
0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, /* 'K' 0x4B */
0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 'L' 0x4C */
0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 'M' 0x4D */
0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, /* 'N' 0x4E */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00, /* 'O' 0x4F */
0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, /* 'P' 0x50 */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40, /* 'Q' 0x51 */
0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, /* 'R' 0x52 */
0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, /* 'S' 0x53 */
0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 'T' 0x54 */
0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, /* 'U' 0x55 */
0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, /* 'V' 0x56 */
0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, /* 'W' 0x57 */
0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, /* 'X' 0x58 */
0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, /* 'Y' 0x59 */
0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, /* 'Z' 0x5A */
0xEA, 0xAA, 0xAB, /* '[' 0x5B */
0x92, 0x24, 0x89, 0x20, /* '\' 0x5C */
0xD5, 0x55, 0x57, /* ']' 0x5D */
0x46, 0xA9, /* '^' 0x5E */
0xFE, /* '_' 0x5F */
0x80, /* '`' 0x60 */
0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, /* 'a' 0x61 */
0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0, /* 'b' 0x62 */
0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, /* 'c' 0x63 */
0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, /* 'd' 0x64 */
0x39, 0x38, 0x7F, 0x81, 0x13, 0x80, /* 'e' 0x65 */
0x6B, 0xA4, 0x92, 0x40, /* 'f' 0x66 */
0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, /* 'g' 0x67 */
0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, /* 'h' 0x68 */
0xBF, 0x80, /* 'i' 0x69 */
0x45, 0x55, 0x57, /* 'j' 0x6A */
0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, /* 'k' 0x6B */
0xFF, 0x80, /* 'l' 0x6C */
0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, /* 'm' 0x6D */
0xF4, 0x63, 0x18, 0xC6, 0x20, /* 'n' 0x6E */
0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, /* 'o' 0x6F */
0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, /* 'p' 0x70 */
0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, /* 'q' 0x71 */
0xF2, 0x49, 0x20, /* 'r' 0x72 */
0x7A, 0x50, 0xE0, 0xE5, 0xE0, /* 's' 0x73 */
0x5D, 0x24, 0x93, /* 't' 0x74 */
0x8C, 0x63, 0x18, 0xCF, 0xA0, /* 'u' 0x75 */
0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, /* 'v' 0x76 */
0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26, /* 'w' 0x77 */
0x4A, 0x4C, 0x43, 0x27, 0x20, /* 'x' 0x78 */
0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00, /* 'y' 0x79 */
0x78, 0x44, 0x46, 0x23, 0xE0, /* 'z' 0x7A */
0x6A, 0xAA, 0xA9, /* '{' 0x7B */
0xFF, 0xE0, /* '|' 0x7C */
0x95, 0x55, 0x56, /* '}' 0x7D */
0x66, 0x60, /* '~' 0x7E */
0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0, /* 0x7F */
0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E, /* 0x80 */
/* 0x81 */
0xE0, /* 0x82 */
/* 0x83 */
0xB6, 0x80, /* 0x84 */
0xA8, /* 0x85 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, /* 0x86 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08, /* 0x87 */
/* 0x88 */
0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60, /* 0x89 */
0x28, 0x47, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80, /* 0x8A */
0x64, /* 0x8B */
0x10, 0x87, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80, /* 0x8C */
0x28, 0x4F, 0xC4, 0x10, 0x41, 0x04, 0x10, 0x40, /* 0x8D */
0x14, 0x11, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0x8E */
0x08, 0x21, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0x8F */
/* 0x90 */
0xE0, /* 0x91 */
0xE0, /* 0x92 */
0xB6, 0x80, /* 0x93 */
0xB6, 0x80, /* 0x94 */
0xFF, 0x80, /* 0x95 */
0xFC, /* 0x96 */
0xFF, 0xF0, /* 0x97 */
/* 0x98 */
0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68, /* 0x99 */
0x52, 0x69, 0x8E, 0x19, 0x60, /* 0x9A */
0x98, /* 0x9B */
0x24, 0x06, 0x98, 0xE1, 0x96, /* 0x9C */
0x15, 0xE4, 0x44, 0x44, 0x60, /* 0x9D */
0x51, 0x00, 0xF0, 0x88, 0x8C, 0x47, 0xC0, /* 0x9E */
0x11, 0x00, 0xF0, 0x88, 0x8C, 0x47, 0xC0, /* 0x9F */
/* 0xA0 */
0xA8, /* 0xA1 */
0x96, /* 0xA2 */
0x41, 0x05, 0x18, 0x43, 0x04, 0x10, 0x7C, /* 0xA3 */
0xFC, 0x63, 0xF0, /* 0xA4 */
0x30, 0x38, 0x28, 0x48, 0x4C, 0x7C, 0x84, 0x86, 0x82, 0x04, 0x07, /* 0xA5 */
0xF9, 0xF0, /* 0xA6 */
0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0, /* 0xA7 */
0xA0, /* 0xA8 */
0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00, /* 0xA9 */
0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, 0xC1, 0x0C, /* 0xAA */
0x5A, 0xA5, /* 0xAB */
0xFC, 0x10, 0x40, /* 0xAC */
/* 0xAD */
0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00, /* 0xAE */
0x18, 0x31, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0xAF */
0x69, 0x96, /* 0xB0 */
0x21, 0x3E, 0x42, 0x03, 0xE0, /* 0xB1 */
0x9C, /* 0xB2 */
0x49, 0x35, 0x92, 0x40, /* 0xB3 */
0x80, /* 0xB4 */
0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80, /* 0xB5 */
0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0, /* 0xB6 */
0x80, /* 0xB7 */
0x67, 0x80, /* 0xB8 */
0x78, 0x84, 0x04, 0x3C, 0xC4, 0x8C, 0x76, 0x04, 0x07, /* 0xB9 */
0x69, 0x8E, 0x19, 0x66, 0x26, /* 0xBA */
0xA5, 0x5A, /* 0xBB */
0xA5, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 0xBC */
0xA0, /* 0xBD */
0xBA, 0x49, 0x24, 0x90, /* 0xBE */
0x31, 0x9E, 0x11, 0x11, 0x88, 0xF8, /* 0xBF */
0x10, 0x43, 0xE4, 0x28, 0x50, 0xBE, 0x42, 0x85, 0x0C, /* 0xC0 */
0x08, 0x10, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC1 */
0x18, 0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC2 */
0x24, 0x18, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC3 */
0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 0xC4 */
0x11, 0x21, 0x08, 0x42, 0x10, 0x87, 0xC0, /* 0xC5 */
0x08, 0x20, 0x01, 0xE4, 0x30, 0x20, 0x40, 0x82, 0x8C, 0xF0, /* 0xC6 */
0x3E, 0x61, 0xC0, 0x80, 0x80, 0x80, 0xC1, 0x63, 0x3E, 0x0C, 0x04, 0x1C, /* 0xC7 */
0x28, 0x20, 0x01, 0xE4, 0x30, 0x20, 0x40, 0x82, 0x8C, 0xF0, /* 0xC8 */
0x08, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xC9 */
0xFD, 0x02, 0x04, 0x0F, 0xD0, 0x20, 0x40, 0xFC, 0x10, 0x38, /* 0xCA */
0x28, 0x0F, 0xE0, 0x83, 0xE8, 0x20, 0x83, 0xF0, /* 0xCB */
0x28, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x82, 0x0F, 0xC0, /* 0xCC */
0x62, 0xAA, 0xA0, /* 0xCD */
0x54, 0x24, 0x92, 0x48, /* 0xCE */
0x50, 0x43, 0xE4, 0x28, 0x30, 0x60, 0xC1, 0x85, 0xF0, /* 0xCF */
0x7C, 0x42, 0x41, 0x41, 0xF1, 0x41, 0x41, 0x42, 0x7C, /* 0xD0 */
0x08, 0x23, 0x0F, 0x1B, 0x32, 0x66, 0xC7, 0x87, 0x04, /* 0xD1 */
0x28, 0x23, 0x0F, 0x1B, 0x32, 0x66, 0xC7, 0x87, 0x04, /* 0xD2 */
0x04, 0x04, 0x0F, 0x8C, 0x6C, 0x1C, 0x06, 0x03, 0x83, 0x63, 0x1F, 0x00, /* 0xD3 */
0x08, 0x0A, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD4 */
0x0A, 0x0A, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD5 */
0x14, 0x00, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD6 */
0x8A, 0x88, 0xA8, 0x80, /* 0xD7 */
0x50, 0x43, 0xE4, 0x28, 0x50, 0xBE, 0x42, 0x85, 0x0C, /* 0xD8 */
0x10, 0x52, 0x4C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xD9 */
0x08, 0x22, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDA */
0x14, 0x52, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDB */
0x29, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDC */
0x09, 0x25, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20, /* 0xDD */
0xFC, 0x41, 0x04, 0x10, 0x41, 0x04, 0x10, 0x60, 0x8E, /* 0xDE */
0x7A, 0x18, 0x61, 0x8A, 0x18, 0x61, 0xB8, /* 0xDF */
0x42, 0xE9, 0x24, 0x80, /* 0xE0 */
0x10, 0x40, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE1 */
0x10, 0x50, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE2 */
0x48, 0x60, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE3 */
0x28, 0x01, 0xE4, 0x20, 0x47, 0xB1, 0x46, 0x76, /* 0xE4 */
0x62, 0xAA, 0xA0, /* 0xE5 */
0x10, 0x80, 0x1E, 0xC6, 0x08, 0x20, 0xC5, 0xE0, /* 0xE6 */
0x7B, 0x18, 0x20, 0x83, 0x17, 0x8C, 0x11, 0xC0, /* 0xE7 */
0x28, 0x40, 0x1E, 0xC6, 0x08, 0x20, 0xC5, 0xE0, /* 0xE8 */
0x10, 0x80, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xE9 */
0x7B, 0x38, 0x7F, 0x83, 0x37, 0x84, 0x1C, /* 0xEA */
0x28, 0x07, 0xB3, 0x87, 0xF8, 0x31, 0x78, /* 0xEB */
0x28, 0x40, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xEC */
0x62, 0xAA, 0xA0, /* 0xED */
0x54, 0x24, 0x92, 0x48, /* 0xEE */
0x02, 0x0C, 0x13, 0xEC, 0xD0, 0xA1, 0x42, 0xCC, 0xE8, /* 0xEF */
0x04, 0x1D, 0xD6, 0x68, 0x50, 0xA1, 0x66, 0x74, /* 0xF0 */
0x11, 0x01, 0x6C, 0xC6, 0x31, 0x8C, 0x40, /* 0xF1 */
0x20, 0x81, 0x6C, 0xC6, 0x31, 0x8C, 0x40, /* 0xF2 */
0x10, 0x80, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF3 */
0x10, 0xA0, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF4 */
0x29, 0x40, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF5 */
0x28, 0x07, 0xB3, 0x86, 0x18, 0x73, 0x78, /* 0xF6 */
0x20, 0x3E, 0x02, 0x00, /* 0xF7 */
0xA8, 0x5D, 0x24, 0x90, /* 0xF8 */
0x22, 0x89, 0x18, 0xC6, 0x31, 0x9B, 0x40, /* 0xF9 */
0x11, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFA */
0x2A, 0x81, 0x18, 0xC6, 0x31, 0x9B, 0x40, /* 0xFB */
0x50, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFC */
0x10, 0x88, 0x52, 0x49, 0x23, 0x0C, 0x30, 0x82, 0x18, /* 0xFD */
0x4E, 0x44, 0x44, 0x46, 0x31, 0x70, /* 0xFE */
0x80, /* 0xFF */
};
const GFXglyph FreeSans6pt_Win1250Glyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 3, 0, 0},
/* '!' 0x21 */ {0, 1, 9, 4, 2, -8},
/* '"' 0x22 */ {2, 3, 3, 4, 0, -8},
/* '#' 0x23 */ {4, 7, 8, 7, 0, -7},
/* '$' 0x24 */ {11, 6, 11, 7, 0, -9},
/* '%' 0x25 */ {20, 10, 9, 11, 0, -8},
/* '&' 0x26 */ {32, 6, 9, 8, 1, -8},
/* ''' 0x27 */ {39, 1, 3, 2, 1, -8},
/* '(' 0x28 */ {40, 2, 11, 4, 1, -8},
/* ')' 0x29 */ {43, 3, 11, 4, 0, -8},
/* '*' 0x2A */ {48, 3, 3, 5, 1, -8},
/* '+' 0x2B */ {50, 5, 5, 7, 1, -4},
/* ',' 0x2C */ {54, 1, 3, 3, 1, 0},
/* '-' 0x2D */ {55, 2, 1, 4, 1, -3},
/* '.' 0x2E */ {56, 1, 1, 3, 1, 0},
/* '/' 0x2F */ {57, 3, 9, 3, 0, -8},
/* '0' 0x30 */ {61, 5, 9, 7, 1, -8},
/* '1' 0x31 */ {67, 3, 9, 7, 1, -8},
/* '2' 0x32 */ {71, 6, 9, 7, 0, -8},
/* '3' 0x33 */ {78, 6, 9, 7, 0, -8},
/* '4' 0x34 */ {85, 6, 9, 7, 0, -8},
/* '5' 0x35 */ {92, 5, 9, 7, 1, -8},
/* '6' 0x36 */ {98, 5, 9, 7, 1, -8},
/* '7' 0x37 */ {104, 5, 9, 7, 1, -8},
/* '8' 0x38 */ {110, 6, 9, 7, 0, -8},
/* '9' 0x39 */ {117, 6, 9, 7, 0, -8},
/* ':' 0x3A */ {124, 1, 7, 3, 1, -6},
/* ';' 0x3B */ {125, 1, 8, 3, 1, -5},
/* '<' 0x3C */ {126, 5, 5, 7, 1, -4},
/* '=' 0x3D */ {130, 5, 3, 7, 1, -3},
/* '>' 0x3E */ {132, 5, 5, 7, 1, -4},
/* '?' 0x3F */ {136, 5, 9, 7, 1, -8},
/* '@' 0x40 */ {142, 11, 11, 12, 0, -8},
/* 'A' 0x41 */ {158, 8, 9, 8, 0, -8},
/* 'B' 0x42 */ {167, 6, 9, 8, 1, -8},
/* 'C' 0x43 */ {174, 8, 9, 9, 0, -8},
/* 'D' 0x44 */ {183, 7, 9, 8, 1, -8},
/* 'E' 0x45 */ {191, 6, 9, 8, 1, -8},
/* 'F' 0x46 */ {198, 6, 9, 7, 1, -8},
/* 'G' 0x47 */ {205, 8, 9, 9, 0, -8},
/* 'H' 0x48 */ {214, 7, 9, 9, 1, -8},
/* 'I' 0x49 */ {222, 1, 9, 3, 1, -8},
/* 'J' 0x4A */ {224, 5, 9, 6, 0, -8},
/* 'K' 0x4B */ {230, 7, 9, 8, 1, -8},
/* 'L' 0x4C */ {238, 5, 9, 7, 1, -8},
/* 'M' 0x4D */ {244, 8, 9, 10, 1, -8},
/* 'N' 0x4E */ {253, 7, 9, 9, 1, -8},
/* 'O' 0x4F */ {261, 9, 9, 9, 0, -8},
/* 'P' 0x50 */ {272, 6, 9, 8, 1, -8},
/* 'Q' 0x51 */ {279, 9, 10, 9, 0, -8},
/* 'R' 0x52 */ {291, 7, 9, 9, 1, -8},
/* 'S' 0x53 */ {299, 6, 9, 8, 1, -8},
/* 'T' 0x54 */ {306, 7, 9, 8, 0, -8},
/* 'U' 0x55 */ {314, 7, 9, 9, 1, -8},
/* 'V' 0x56 */ {322, 7, 9, 8, 0, -8},
/* 'W' 0x57 */ {330, 11, 9, 11, 0, -8},
/* 'X' 0x58 */ {343, 6, 9, 8, 1, -8},
/* 'Y' 0x59 */ {350, 8, 9, 8, 0, -8},
/* 'Z' 0x5A */ {359, 7, 9, 7, 0, -8},
/* '[' 0x5B */ {367, 2, 12, 3, 1, -8},
/* '\' 0x5C */ {370, 3, 9, 3, 0, -8},
/* ']' 0x5D */ {374, 2, 12, 3, 0, -8},
/* '^' 0x5E */ {377, 4, 4, 6, 1, -8},
/* '_' 0x5F */ {379, 7, 1, 7, 0, 2},
/* '`' 0x60 */ {380, 1, 1, 3, 1, -8},
/* 'a' 0x61 */ {381, 6, 7, 7, 0, -6},
/* 'b' 0x62 */ {387, 5, 9, 7, 1, -8},
/* 'c' 0x63 */ {393, 6, 7, 6, 0, -6},
/* 'd' 0x64 */ {399, 6, 9, 7, 0, -8},
/* 'e' 0x65 */ {406, 6, 7, 6, 0, -6},
/* 'f' 0x66 */ {412, 3, 9, 3, 0, -8},
/* 'g' 0x67 */ {416, 6, 10, 7, 0, -6},
/* 'h' 0x68 */ {424, 5, 9, 6, 1, -8},
/* 'i' 0x69 */ {430, 1, 9, 3, 1, -8},
/* 'j' 0x6A */ {432, 2, 12, 3, 0, -8},
/* 'k' 0x6B */ {435, 5, 9, 6, 1, -8},
/* 'l' 0x6C */ {441, 1, 9, 3, 1, -8},
/* 'm' 0x6D */ {443, 8, 7, 10, 1, -6},
/* 'n' 0x6E */ {450, 5, 7, 6, 1, -6},
/* 'o' 0x6F */ {455, 6, 7, 6, 0, -6},
/* 'p' 0x70 */ {461, 5, 9, 7, 1, -6},
/* 'q' 0x71 */ {467, 6, 9, 7, 0, -6},
/* 'r' 0x72 */ {474, 3, 7, 4, 1, -6},
/* 's' 0x73 */ {477, 5, 7, 6, 0, -6},
/* 't' 0x74 */ {482, 3, 8, 3, 0, -7},
/* 'u' 0x75 */ {485, 5, 7, 6, 1, -6},
/* 'v' 0x76 */ {490, 6, 7, 6, 0, -6},
/* 'w' 0x77 */ {496, 8, 7, 9, 0, -6},
/* 'x' 0x78 */ {503, 5, 7, 6, 0, -6},
/* 'y' 0x79 */ {508, 5, 10, 6, 0, -6},
/* 'z' 0x7A */ {515, 5, 7, 6, 0, -6},
/* '{' 0x7B */ {520, 2, 12, 4, 1, -8},
/* '|' 0x7C */ {523, 1, 11, 3, 1, -8},
/* '}' 0x7D */ {525, 2, 12, 4, 1, -8},
/* '~' 0x7E */ {528, 6, 2, 6, 0, -4},
/* 0x7F */ {530, 9, 10, 11, 1, -8},
/* 0x80 */ {542, 7, 9, 8, 0, -8},
/* 0x81 */ {550, 0, 0, 8, 0, 0},
/* 0x82 */ {550, 1, 3, 3, 1, 0},
/* 0x83 */ {551, 0, 0, 8, 0, 0},
/* 0x84 */ {551, 3, 3, 5, 1, 0},
/* 0x85 */ {553, 5, 1, 7, 1, 0},
/* 0x86 */ {554, 5, 11, 7, 1, -8},
/* 0x87 */ {561, 5, 11, 7, 1, -8},
/* 0x88 */ {568, 0, 0, 8, 0, 0},
/* 0x89 */ {568, 12, 9, 12, 0, -8},
/* 0x8A */ {582, 6, 11, 8, 1, -9},
/* 0x8B */ {591, 2, 3, 4, 1, -4},
/* 0x8C */ {592, 6, 11, 8, 1, -10},
/* 0x8D */ {601, 6, 10, 8, 0, -9},
/* 0x8E */ {609, 7, 10, 7, 0, -9},
/* 0x8F */ {618, 7, 10, 7, 0, -9},
/* 0x90 */ {627, 0, 0, 8, 0, 0},
/* 0x91 */ {627, 1, 3, 3, 1, -8},
/* 0x92 */ {628, 1, 3, 2, 1, -8},
/* 0x93 */ {629, 3, 3, 5, 1, -8},
/* 0x94 */ {631, 3, 3, 5, 1, -8},
/* 0x95 */ {633, 3, 3, 5, 1, -5},
/* 0x96 */ {635, 6, 1, 6, 0, -3},
/* 0x97 */ {636, 12, 1, 12, 0, -3},
/* 0x98 */ {638, 0, 0, 8, 0, 0},
/* 0x99 */ {638, 11, 7, 12, 1, -8},
/* 0x9A */ {648, 4, 9, 6, 1, -8},
/* 0x9B */ {653, 2, 3, 3, 1, -4},
/* 0x9C */ {654, 4, 10, 6, 1, -9},
/* 0x9D */ {659, 4, 9, 5, 0, -8},
/* 0x9E */ {664, 5, 10, 6, 0, -9},
/* 0x9F */ {671, 5, 10, 6, 0, -9},
/* 0xA0 */ {678, 0, 0, 3, 0, 0},
/* 0xA1 */ {678, 3, 2, 4, 0, -8},
/* 0xA2 */ {679, 4, 2, 4, 0, -8},
/* 0xA3 */ {680, 6, 9, 7, 0, -8},
/* 0xA4 */ {687, 5, 4, 7, 1, -5},
/* 0xA5 */ {690, 8, 11, 8, 1, -8},
/* 0xA6 */ {701, 1, 12, 3, 1, -8},
/* 0xA7 */ {703, 5, 12, 7, 1, -8},
/* 0xA8 */ {711, 3, 1, 4, 0, -7},
/* 0xA9 */ {712, 9, 9, 10, 0, -8},
/* 0xAA */ {723, 6, 12, 8, 1, -8},
/* 0xAB */ {732, 4, 4, 6, 1, -4},
/* 0xAC */ {734, 6, 3, 7, 1, -4},
/* 0xAD */ {737, 0, 0, 0, 0, 0},
/* 0xAE */ {737, 9, 9, 10, 0, -8},
/* 0xAF */ {748, 7, 10, 7, 0, -9},
/* 0xB0 */ {757, 4, 4, 7, 2, -8},
/* 0xB1 */ {759, 5, 7, 7, 1, -6},
/* 0xB2 */ {764, 3, 2, 4, 1, 1},
/* 0xB3 */ {765, 3, 9, 3, 0, -8},
/* 0xB4 */ {769, 1, 1, 4, 1, -8},
/* 0xB5 */ {770, 6, 9, 7, 1, -6},
/* 0xB6 */ {777, 6, 10, 6, 1, -8},
/* 0xB7 */ {785, 1, 1, 3, 1, -2},
/* 0xB8 */ {786, 3, 3, 4, 1, 1},
/* 0xB9 */ {788, 8, 9, 7, 0, -6},
/* 0xBA */ {797, 4, 10, 6, 1, -6},
/* 0xBB */ {802, 4, 4, 6, 1, -5},
/* 0xBC */ {804, 5, 9, 7, 1, -8},
/* 0xBD */ {810, 3, 1, 4, 0, -8},
/* 0xBE */ {811, 3, 10, 3, 1, -9},
/* 0xBF */ {815, 5, 9, 6, 0, -8},
/* 0xC0 */ {821, 7, 10, 9, 1, -9},
/* 0xC1 */ {830, 8, 10, 8, 0, -9},
/* 0xC2 */ {840, 8, 10, 8, 0, -9},
/* 0xC3 */ {850, 8, 10, 8, 0, -9},
/* 0xC4 */ {860, 8, 10, 8, 0, -9},
/* 0xC5 */ {870, 5, 10, 7, 1, -9},
/* 0xC6 */ {877, 7, 11, 9, 0, -10},
/* 0xC7 */ {887, 8, 12, 9, 0, -8},
/* 0xC8 */ {899, 7, 11, 9, 0, -10},
/* 0xC9 */ {909, 6, 10, 8, 1, -9},
/* 0xCA */ {917, 7, 11, 8, 1, -8},
/* 0xCB */ {927, 6, 10, 8, 1, -9},
/* 0xCC */ {935, 6, 11, 8, 1, -10},
/* 0xCD */ {944, 2, 10, 3, 1, -9},
/* 0xCE */ {947, 3, 10, 4, 0, -9},
/* 0xCF */ {951, 7, 10, 8, 1, -9},
/* 0xD0 */ {960, 8, 9, 8, 0, -8},
/* 0xD1 */ {969, 7, 10, 9, 1, -9},
/* 0xD2 */ {978, 7, 10, 9, 1, -9},
/* 0xD3 */ {987, 9, 10, 9, 0, -9},
/* 0xD4 */ {999, 9, 11, 9, 0, -10},
/* 0xD5 */ {1012, 9, 11, 9, 0, -10},
/* 0xD6 */ {1025, 9, 11, 9, 0, -10},
/* 0xD7 */ {1038, 5, 5, 7, 1, -5},
/* 0xD8 */ {1042, 7, 10, 9, 1, -9},
/* 0xD9 */ {1051, 7, 10, 9, 1, -9},
/* 0xDA */ {1060, 7, 10, 9, 1, -9},
/* 0xDB */ {1069, 7, 10, 9, 1, -9},
/* 0xDC */ {1078, 7, 10, 9, 1, -9},
/* 0xDD */ {1087, 7, 10, 8, 1, -9},
/* 0xDE */ {1096, 6, 12, 7, 0, -8},
/* 0xDF */ {1105, 6, 9, 7, 1, -8},
/* 0xE0 */ {1112, 3, 9, 4, 1, -8},
/* 0xE1 */ {1116, 7, 10, 7, 0, -9},
/* 0xE2 */ {1125, 7, 10, 7, 0, -9},
/* 0xE3 */ {1134, 7, 10, 7, 0, -9},
/* 0xE4 */ {1143, 7, 9, 7, 0, -8},
/* 0xE5 */ {1151, 2, 10, 3, 1, -9},
/* 0xE6 */ {1154, 6, 10, 6, 0, -9},
/* 0xE7 */ {1162, 6, 10, 6, 0, -6},
/* 0xE8 */ {1170, 6, 10, 6, 0, -9},
/* 0xE9 */ {1178, 6, 10, 6, 0, -9},
/* 0xEA */ {1186, 6, 9, 6, 0, -6},
/* 0xEB */ {1193, 6, 9, 6, 0, -8},
/* 0xEC */ {1200, 6, 10, 6, 0, -9},
/* 0xED */ {1208, 2, 10, 3, 1, -9},
/* 0xEE */ {1211, 3, 10, 3, 0, -9},
/* 0xEF */ {1215, 7, 10, 7, 0, -9},
/* 0xF0 */ {1224, 7, 9, 7, 0, -8},
/* 0xF1 */ {1232, 5, 10, 6, 1, -9},
/* 0xF2 */ {1239, 5, 10, 6, 1, -9},
/* 0xF3 */ {1246, 6, 10, 6, 0, -9},
/* 0xF4 */ {1254, 6, 10, 6, 0, -9},
/* 0xF5 */ {1262, 6, 10, 6, 0, -9},
/* 0xF6 */ {1270, 6, 9, 6, 0, -8},
/* 0xF7 */ {1277, 5, 5, 7, 1, -5},
/* 0xF8 */ {1281, 3, 10, 4, 1, -9},
/* 0xF9 */ {1285, 5, 10, 6, 1, -9},
/* 0xFA */ {1292, 5, 9, 6, 1, -8},
/* 0xFB */ {1298, 5, 10, 6, 1, -9},
/* 0xFC */ {1305, 5, 9, 6, 1, -8},
/* 0xFD */ {1311, 6, 12, 6, 0, -8},
/* 0xFE */ {1320, 4, 11, 3, 0, -7},
/* 0xFF */ {1326, 1, 1, 4, 1, -7},
};
const GFXfont FreeSans6pt_Win1250 PROGMEM = {(uint8_t *)FreeSans6pt_Win1250Bitmaps, (GFXglyph *)FreeSans6pt_Win1250Glyphs, 0x20,
0xFF, 14};
@@ -0,0 +1,457 @@
#pragma once
const uint8_t FreeSans6pt_Win1251Bitmaps[] PROGMEM = {
/* ' ' 0x20 */
0xFC, 0x80, /* '!' 0x21 */
0xB6, 0x80, /* '"' 0x22 */
0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, /* '#' 0x23 */
0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, /* '$' 0x24 */
0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, /* '%' 0x25 */
0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4, /* '&' 0x26 */
0xE0, /* ''' 0x27 */
0x5A, 0xAA, 0x94, /* '(' 0x28 */
0x89, 0x12, 0x49, 0x29, 0x00, /* ')' 0x29 */
0x5E, 0x80, /* '*' 0x2A */
0x21, 0x3E, 0x42, 0x00, /* '+' 0x2B */
0xE0, /* ',' 0x2C */
0xC0, /* '-' 0x2D */
0x80, /* '.' 0x2E */
0x24, 0xA4, 0xA4, 0x80, /* '/' 0x2F */
0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, /* '0' 0x30 */
0x27, 0x92, 0x49, 0x20, /* '1' 0x31 */
0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, /* '2' 0x32 */
0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78, /* '3' 0x33 */
0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, /* '4' 0x34 */
0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0, /* '5' 0x35 */
0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70, /* '6' 0x36 */
0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, /* '7' 0x37 */
0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, /* '8' 0x38 */
0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78, /* '9' 0x39 */
0x82, /* ':' 0x3A */
0x87, /* ';' 0x3B */
0x3E, 0x30, 0x60, 0x80, /* '<' 0x3C */
0xF8, 0x3E, /* '=' 0x3D */
0xE0, 0xC6, 0xC8, 0x00, /* '>' 0x3E */
0x74, 0x42, 0x11, 0x10, 0x80, 0x20, /* '?' 0x3F */
0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, /* '@' 0x40 */
0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 'A' 0x41 */
0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 'B' 0x42 */
0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, /* 'C' 0x43 */
0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8, /* 'D' 0x44 */
0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 'E' 0x45 */
0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, /* 'F' 0x46 */
0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, /* 'G' 0x47 */
0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 'H' 0x48 */
0xFF, 0x80, /* 'I' 0x49 */
0x08, 0x42, 0x10, 0x87, 0x29, 0x70, /* 'J' 0x4A */
0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, /* 'K' 0x4B */
0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 'L' 0x4C */
0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 'M' 0x4D */
0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, /* 'N' 0x4E */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00, /* 'O' 0x4F */
0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, /* 'P' 0x50 */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40, /* 'Q' 0x51 */
0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, /* 'R' 0x52 */
0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, /* 'S' 0x53 */
0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 'T' 0x54 */
0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, /* 'U' 0x55 */
0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, /* 'V' 0x56 */
0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, /* 'W' 0x57 */
0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, /* 'X' 0x58 */
0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, /* 'Y' 0x59 */
0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, /* 'Z' 0x5A */
0xEA, 0xAA, 0xAB, /* '[' 0x5B */
0x92, 0x24, 0x89, 0x20, /* '\' 0x5C */
0xD5, 0x55, 0x57, /* ']' 0x5D */
0x46, 0xA9, /* '^' 0x5E */
0xFE, /* '_' 0x5F */
0x80, /* '`' 0x60 */
0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, /* 'a' 0x61 */
0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0, /* 'b' 0x62 */
0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, /* 'c' 0x63 */
0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, /* 'd' 0x64 */
0x39, 0x38, 0x7F, 0x81, 0x13, 0x80, /* 'e' 0x65 */
0x6B, 0xA4, 0x92, 0x40, /* 'f' 0x66 */
0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, /* 'g' 0x67 */
0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, /* 'h' 0x68 */
0xBF, 0x80, /* 'i' 0x69 */
0x45, 0x55, 0x57, /* 'j' 0x6A */
0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, /* 'k' 0x6B */
0xFF, 0x80, /* 'l' 0x6C */
0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, /* 'm' 0x6D */
0xF4, 0x63, 0x18, 0xC6, 0x20, /* 'n' 0x6E */
0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, /* 'o' 0x6F */
0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, /* 'p' 0x70 */
0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, /* 'q' 0x71 */
0xF2, 0x49, 0x20, /* 'r' 0x72 */
0x7A, 0x50, 0xE0, 0xE5, 0xE0, /* 's' 0x73 */
0x5D, 0x24, 0x93, /* 't' 0x74 */
0x8C, 0x63, 0x18, 0xCF, 0xA0, /* 'u' 0x75 */
0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, /* 'v' 0x76 */
0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26, /* 'w' 0x77 */
0x4A, 0x4C, 0x43, 0x27, 0x20, /* 'x' 0x78 */
0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00, /* 'y' 0x79 */
0x78, 0x44, 0x46, 0x23, 0xE0, /* 'z' 0x7A */
0x6A, 0xAA, 0xA9, /* '{' 0x7B */
0xFF, 0xE0, /* '|' 0x7C */
0x95, 0x55, 0x56, /* '}' 0x7D */
0x66, 0x60, /* '~' 0x7E */
0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0, /* 0x7F */
0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, 0xC0, 0xC0, /* 0x80 */
0x10, 0x8F, 0xE0, 0x82, 0x08, 0x20, 0x82, 0x00, /* 0x81 */
0xE0, /* 0x82 */
0x24, 0x0F, 0x88, 0x88, 0x80, /* 0x83 */
0xB6, 0x80, /* 0x84 */
0xA8, /* 0x85 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, /* 0x86 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08, /* 0x87 */
0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E, /* 0x88 */
0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60, /* 0x89 */
0x7C, 0x08, 0x81, 0x10, 0x22, 0x04, 0x7C, 0x88, 0x51, 0x0A, 0x21, 0x87, 0xC0, /* 0x8A */
0x64, /* 0x8B */
0x84, 0x10, 0x82, 0x10, 0x42, 0x0F, 0xFD, 0x08, 0xA1, 0x0C, 0x23, 0x87, 0xC0, /* 0x8C */
0x10, 0x88, 0xE6, 0xB3, 0x8C, 0x28, 0x92, 0x28, 0xC0, /* 0x8D */
0xFC, 0x08, 0x04, 0x02, 0x01, 0xF0, 0x8C, 0x46, 0x23, 0x11, 0x80, /* 0x8E */
0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xFE, 0x20, 0x40, /* 0x8F */
0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, 0x44, 0x11, 0x80, /* 0x90 */
0xE0, /* 0x91 */
0xE0, /* 0x92 */
0xB6, 0x80, /* 0x93 */
0xB6, 0x80, /* 0x94 */
0xFF, 0x80, /* 0x95 */
0xFC, /* 0x96 */
0xFF, 0xF0, /* 0x97 */
/* 0x98 */
0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68, /* 0x99 */
0x78, 0x24, 0x13, 0xC9, 0x14, 0x8E, 0x7C, /* 0x9A */
0x98, /* 0x9B */
0x88, 0x44, 0x3F, 0xD1, 0x38, 0x8C, 0x78, /* 0x9C */
0x24, 0x09, 0xAC, 0xCA, 0x90, /* 0x9D */
0x43, 0xC4, 0x1F, 0x45, 0x14, 0x51, 0x44, /* 0x9E */
0x8C, 0x63, 0x18, 0xFC, 0x80, /* 0x9F */
/* 0xA0 */
0x24, 0x33, 0x0A, 0x36, 0x45, 0x8E, 0x0C, 0x10, 0x60, 0x80, /* 0xA1 */
0x51, 0x22, 0x95, 0xA8, 0xC4, 0x23, 0x10, /* 0xA2 */
0x08, 0x42, 0x10, 0x86, 0x31, 0x78, /* 0xA3 */
0xFC, 0x63, 0xF0, /* 0xA4 */
0x07, 0xF8, 0x20, 0x82, 0x08, 0x20, 0x82, 0x00, /* 0xA5 */
0xF9, 0xF0, /* 0xA6 */
0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0, /* 0xA7 */
0x28, 0x0F, 0xE0, 0x82, 0x0F, 0xE0, 0x82, 0x0F, 0xC0, /* 0xA8 */
0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00, /* 0xA9 */
0x38, 0x8A, 0x0C, 0x0F, 0x90, 0x20, 0xE3, 0x7C, /* 0xAA */
0x5A, 0xA5, /* 0xAB */
0x51, 0x55, 0x56, /* 0xAC */
/* 0xAD */
0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00, /* 0xAE */
0xA1, 0x24, 0x92, 0x49, 0x00, /* 0xAF */
0x69, 0x96, /* 0xB0 */
0x21, 0x3E, 0x42, 0x03, 0xE0, /* 0xB1 */
0xFF, 0x80, /* 0xB2 */
0xDF, 0x80, /* 0xB3 */
0x27, 0xC9, 0x24, /* 0xB4 */
0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80, /* 0xB5 */
0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0, /* 0xB6 */
0x80, /* 0xB7 */
0x28, 0xA0, 0x1E, 0x47, 0xFC, 0x11, 0x78, /* 0xB8 */
0x88, 0x44, 0x32, 0x59, 0xDA, 0xCD, 0x66, 0x6B, 0x32, 0x8B, 0x80, /* 0xB9 */
0x79, 0x1F, 0x30, 0x45, 0xE0, /* 0xBA */
0xA5, 0x5A, /* 0xBB */
0x45, 0x55, 0x57, /* 0xBC */
0x7A, 0x18, 0x70, 0x78, 0x38, 0x61, 0x7C, /* 0xBD */
0x7A, 0x1C, 0x1C, 0xBC, /* 0xBE */
0xB4, 0x24, 0x92, 0x40, /* 0xBF */
0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 0xC0 */
0xFE, 0x08, 0x20, 0xFA, 0x18, 0x61, 0xF8, /* 0xC1 */
0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 0xC2 */
0xFE, 0x08, 0x20, 0x82, 0x08, 0x20, 0x80, /* 0xC3 */
0x1F, 0x08, 0x84, 0x42, 0x21, 0x10, 0x88, 0x44, 0x42, 0xFF, 0xC0, 0x60, 0x20, /* 0xC4 */
0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 0xC5 */
0x88, 0xA4, 0x9A, 0x87, 0xC1, 0xC1, 0xF1, 0xAD, 0x92, 0x88, 0x80, /* 0xC6 */
0x7A, 0x18, 0x41, 0x38, 0x18, 0x61, 0x7C, /* 0xC7 */
0x87, 0x0E, 0x2C, 0x59, 0x34, 0x68, 0xE1, 0xC2, /* 0xC8 */
0x28, 0x22, 0x1C, 0x38, 0xB1, 0x64, 0xD1, 0xA3, 0x87, 0x08, /* 0xC9 */
0x8E, 0x6B, 0x38, 0xC2, 0x89, 0x22, 0x8C, /* 0xCA */
0x3E, 0x44, 0x89, 0x12, 0x24, 0x58, 0xA1, 0xC2, /* 0xCB */
0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 0xCC */
0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 0xCD */
0x3C, 0x42, 0x81, 0x81, 0x81, 0x81, 0x81, 0xC2, 0x7C, /* 0xCE */
0xFF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x82, /* 0xCF */
0xFA, 0x18, 0x61, 0xFE, 0x08, 0x20, 0x80, /* 0xD0 */
0x38, 0x8A, 0x0C, 0x08, 0x10, 0x20, 0xE3, 0x7C, /* 0xD1 */
0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 0xD2 */
0xC2, 0x8D, 0x91, 0x63, 0x83, 0x04, 0x18, 0x20, /* 0xD3 */
0x08, 0x1F, 0x32, 0x71, 0x18, 0x8C, 0x47, 0x26, 0xFE, 0x08, 0x00, /* 0xD4 */
0x87, 0x34, 0x8C, 0x30, 0xC4, 0xB3, 0x84, /* 0xD5 */
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0xFF, 0x01, 0x01, /* 0xD6 */
0x8E, 0x38, 0xE3, 0x8D, 0xF0, 0xC3, 0x0C, /* 0xD7 */
0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xFF, /* 0xD8 */
0x99, 0x4C, 0xA6, 0x53, 0x29, 0x94, 0xCA, 0x65, 0x32, 0xFF, 0x80, 0x40, 0x20, /* 0xD9 */
0xF0, 0x04, 0x01, 0x00, 0x40, 0x1F, 0x84, 0x21, 0x0C, 0x42, 0x1F, 0x00, /* 0xDA */
0x81, 0xC0, 0xE0, 0x70, 0x3F, 0xDC, 0x2E, 0x17, 0x0B, 0xF9, 0x80, /* 0xDB */
0x82, 0x08, 0x20, 0xFE, 0x18, 0x61, 0xF8, /* 0xDC */
0x79, 0x8A, 0x18, 0x13, 0xE0, 0x60, 0xC2, 0x7C, /* 0xDD */
0x87, 0x26, 0x39, 0x06, 0x41, 0xF0, 0x64, 0x19, 0x06, 0x63, 0x8F, 0x80, /* 0xDE */
0x7E, 0x18, 0x61, 0x7C, 0xD6, 0x71, 0x84, /* 0xDF */
0x79, 0x11, 0xD9, 0xCD, 0xD0, /* 0xE0 */
0x0D, 0xC4, 0x1E, 0x47, 0x1C, 0x51, 0x78, /* 0xE1 */
0xF4, 0xBD, 0x29, 0xF8, /* 0xE2 */
0xF8, 0x88, 0x88, /* 0xE3 */
0x3C, 0x48, 0x91, 0x22, 0x5F, 0xE0, 0x80, /* 0xE4 */
0x79, 0x1F, 0xF0, 0x45, 0xE0, /* 0xE5 */
0x92, 0x54, 0x38, 0x3C, 0x56, 0x93, /* 0xE6 */
0x78, 0x23, 0x82, 0xCD, 0xE0, /* 0xE7 */
0x9C, 0xEB, 0x5C, 0xC4, /* 0xE8 */
0x70, 0x27, 0x3A, 0xD7, 0x31, /* 0xE9 */
0x9A, 0xCC, 0xA9, /* 0xEA */
0x7A, 0x52, 0x94, 0xE4, /* 0xEB */
0x8F, 0x3D, 0x6D, 0xA6, 0x90, /* 0xEC */
0x8C, 0x7F, 0x18, 0xC4, /* 0xED */
0x79, 0x1C, 0x71, 0x45, 0xE0, /* 0xEE */
0xFC, 0x63, 0x18, 0xC4, /* 0xEF */
0xFC, 0x63, 0x18, 0xFA, 0x10, 0x80, /* 0xF0 */
0x79, 0x1C, 0x30, 0x45, 0xE0, /* 0xF1 */
0xF9, 0x08, 0x42, 0x10, /* 0xF2 */
0x8A, 0x56, 0xA3, 0x10, 0x8C, 0x40, /* 0xF3 */
0x04, 0x01, 0x07, 0xF9, 0x31, 0xC4, 0x71, 0x14, 0xC5, 0xFE, 0x04, 0x01, 0x00, 0x40, /* 0xF4 */
0x4B, 0x8C, 0x65, 0xE4, /* 0xF5 */
0x8A, 0x28, 0xA2, 0x8B, 0xF0, 0x40, /* 0xF6 */
0x99, 0x97, 0x11, /* 0xF7 */
0x96, 0x59, 0x65, 0x97, 0xF0, /* 0xF8 */
0x95, 0x2A, 0x54, 0xA9, 0x5F, 0xC0, 0x80, /* 0xF9 */
0xF0, 0x20, 0x78, 0x91, 0x23, 0xC0, /* 0xFA */
0x86, 0x1F, 0x63, 0x8F, 0xD0, /* 0xFB */
0x84, 0x3D, 0x18, 0xF8, /* 0xFC */
0xF4, 0xDE, 0x19, 0xF8, /* 0xFD */
0x9E, 0xA2, 0xE1, 0xA1, 0xA2, 0x9E, /* 0xFE */
0xFC, 0x7E, 0xD4, 0xC4, /* 0xFF */
};
const GFXglyph FreeSans6pt_Win1251Glyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 3, 0, 0},
/* '!' 0x21 */ {0, 1, 9, 4, 2, -8},
/* '"' 0x22 */ {2, 3, 3, 4, 0, -8},
/* '#' 0x23 */ {4, 7, 8, 7, 0, -7},
/* '$' 0x24 */ {11, 6, 11, 7, 0, -9},
/* '%' 0x25 */ {20, 10, 9, 11, 0, -8},
/* '&' 0x26 */ {32, 6, 9, 8, 1, -8},
/* ''' 0x27 */ {39, 1, 3, 2, 1, -8},
/* '(' 0x28 */ {40, 2, 11, 4, 1, -8},
/* ')' 0x29 */ {43, 3, 11, 4, 0, -8},
/* '*' 0x2A */ {48, 3, 3, 5, 1, -8},
/* '+' 0x2B */ {50, 5, 5, 7, 1, -4},
/* ',' 0x2C */ {54, 1, 3, 3, 1, 0},
/* '-' 0x2D */ {55, 2, 1, 4, 1, -3},
/* '.' 0x2E */ {56, 1, 1, 3, 1, 0},
/* '/' 0x2F */ {57, 3, 9, 3, 0, -8},
/* '0' 0x30 */ {61, 5, 9, 7, 1, -8},
/* '1' 0x31 */ {67, 3, 9, 7, 1, -8},
/* '2' 0x32 */ {71, 6, 9, 7, 0, -8},
/* '3' 0x33 */ {78, 6, 9, 7, 0, -8},
/* '4' 0x34 */ {85, 6, 9, 7, 0, -8},
/* '5' 0x35 */ {92, 5, 9, 7, 1, -8},
/* '6' 0x36 */ {98, 5, 9, 7, 1, -8},
/* '7' 0x37 */ {104, 5, 9, 7, 1, -8},
/* '8' 0x38 */ {110, 6, 9, 7, 0, -8},
/* '9' 0x39 */ {117, 6, 9, 7, 0, -8},
/* ':' 0x3A */ {124, 1, 7, 3, 1, -6},
/* ';' 0x3B */ {125, 1, 8, 3, 1, -5},
/* '<' 0x3C */ {126, 5, 5, 7, 1, -4},
/* '=' 0x3D */ {130, 5, 3, 7, 1, -3},
/* '>' 0x3E */ {132, 5, 5, 7, 1, -4},
/* '?' 0x3F */ {136, 5, 9, 7, 1, -8},
/* '@' 0x40 */ {142, 11, 11, 12, 0, -8},
/* 'A' 0x41 */ {158, 8, 9, 8, 0, -8},
/* 'B' 0x42 */ {167, 6, 9, 8, 1, -8},
/* 'C' 0x43 */ {174, 8, 9, 9, 0, -8},
/* 'D' 0x44 */ {183, 7, 9, 8, 1, -8},
/* 'E' 0x45 */ {191, 6, 9, 8, 1, -8},
/* 'F' 0x46 */ {198, 6, 9, 7, 1, -8},
/* 'G' 0x47 */ {205, 8, 9, 9, 0, -8},
/* 'H' 0x48 */ {214, 7, 9, 9, 1, -8},
/* 'I' 0x49 */ {222, 1, 9, 3, 1, -8},
/* 'J' 0x4A */ {224, 5, 9, 6, 0, -8},
/* 'K' 0x4B */ {230, 7, 9, 8, 1, -8},
/* 'L' 0x4C */ {238, 5, 9, 7, 1, -8},
/* 'M' 0x4D */ {244, 8, 9, 10, 1, -8},
/* 'N' 0x4E */ {253, 7, 9, 9, 1, -8},
/* 'O' 0x4F */ {261, 9, 9, 9, 0, -8},
/* 'P' 0x50 */ {272, 6, 9, 8, 1, -8},
/* 'Q' 0x51 */ {279, 9, 10, 9, 0, -8},
/* 'R' 0x52 */ {291, 7, 9, 9, 1, -8},
/* 'S' 0x53 */ {299, 6, 9, 8, 1, -8},
/* 'T' 0x54 */ {306, 7, 9, 8, 0, -8},
/* 'U' 0x55 */ {314, 7, 9, 9, 1, -8},
/* 'V' 0x56 */ {322, 7, 9, 8, 0, -8},
/* 'W' 0x57 */ {330, 11, 9, 11, 0, -8},
/* 'X' 0x58 */ {343, 6, 9, 8, 1, -8},
/* 'Y' 0x59 */ {350, 8, 9, 8, 0, -8},
/* 'Z' 0x5A */ {359, 7, 9, 7, 0, -8},
/* '[' 0x5B */ {367, 2, 12, 3, 1, -8},
/* '\' 0x5C */ {370, 3, 9, 3, 0, -8},
/* ']' 0x5D */ {374, 2, 12, 3, 0, -8},
/* '^' 0x5E */ {377, 4, 4, 6, 1, -8},
/* '_' 0x5F */ {379, 7, 1, 7, 0, 2},
/* '`' 0x60 */ {380, 1, 1, 3, 1, -8},
/* 'a' 0x61 */ {381, 6, 7, 7, 0, -6},
/* 'b' 0x62 */ {387, 5, 9, 7, 1, -8},
/* 'c' 0x63 */ {393, 6, 7, 6, 0, -6},
/* 'd' 0x64 */ {399, 6, 9, 7, 0, -8},
/* 'e' 0x65 */ {406, 6, 7, 6, 0, -6},
/* 'f' 0x66 */ {412, 3, 9, 3, 0, -8},
/* 'g' 0x67 */ {416, 6, 10, 7, 0, -6},
/* 'h' 0x68 */ {424, 5, 9, 6, 1, -8},
/* 'i' 0x69 */ {430, 1, 9, 3, 1, -8},
/* 'j' 0x6A */ {432, 2, 12, 3, 0, -8},
/* 'k' 0x6B */ {435, 5, 9, 6, 1, -8},
/* 'l' 0x6C */ {441, 1, 9, 3, 1, -8},
/* 'm' 0x6D */ {443, 8, 7, 10, 1, -6},
/* 'n' 0x6E */ {450, 5, 7, 6, 1, -6},
/* 'o' 0x6F */ {455, 6, 7, 6, 0, -6},
/* 'p' 0x70 */ {461, 5, 9, 7, 1, -6},
/* 'q' 0x71 */ {467, 6, 9, 7, 0, -6},
/* 'r' 0x72 */ {474, 3, 7, 4, 1, -6},
/* 's' 0x73 */ {477, 5, 7, 6, 0, -6},
/* 't' 0x74 */ {482, 3, 8, 3, 0, -7},
/* 'u' 0x75 */ {485, 5, 7, 6, 1, -6},
/* 'v' 0x76 */ {490, 6, 7, 6, 0, -6},
/* 'w' 0x77 */ {496, 8, 7, 9, 0, -6},
/* 'x' 0x78 */ {503, 5, 7, 6, 0, -6},
/* 'y' 0x79 */ {508, 5, 10, 6, 0, -6},
/* 'z' 0x7A */ {515, 5, 7, 6, 0, -6},
/* '{' 0x7B */ {520, 2, 12, 4, 1, -8},
/* '|' 0x7C */ {523, 1, 11, 3, 1, -8},
/* '}' 0x7D */ {525, 2, 12, 4, 1, -8},
/* '~' 0x7E */ {528, 6, 2, 6, 0, -4},
/* 0x7F */ {530, 9, 10, 11, 1, -8},
/* 0x80 */ {542, 9, 11, 9, 0, -8},
/* 0x81 */ {555, 6, 10, 7, 1, -9},
/* 0x82 */ {563, 1, 3, 3, 1, 0},
/* 0x83 */ {564, 4, 9, 5, 1, -8},
/* 0x84 */ {569, 3, 3, 5, 1, 0},
/* 0x85 */ {571, 5, 1, 7, 1, 0},
/* 0x86 */ {572, 5, 11, 7, 1, -8},
/* 0x87 */ {579, 5, 11, 7, 1, -8},
/* 0x88 */ {586, 7, 9, 8, 0, -8},
/* 0x89 */ {594, 12, 9, 12, 0, -8},
/* 0x8A */ {608, 11, 9, 13, 1, -8},
/* 0x8B */ {621, 2, 3, 4, 1, -4},
/* 0x8C */ {622, 11, 9, 12, 1, -8},
/* 0x8D */ {635, 6, 11, 8, 1, -10},
/* 0x8E */ {644, 9, 9, 9, 0, -8},
/* 0x8F */ {655, 7, 11, 9, 1, -8},
/* 0x90 */ {665, 6, 11, 7, 0, -8},
/* 0x91 */ {674, 1, 3, 3, 1, -8},
/* 0x92 */ {675, 1, 3, 2, 1, -8},
/* 0x93 */ {676, 3, 3, 5, 1, -8},
/* 0x94 */ {678, 3, 3, 5, 1, -8},
/* 0x95 */ {680, 3, 3, 5, 1, -5},
/* 0x96 */ {682, 6, 1, 6, 0, -3},
/* 0x97 */ {683, 12, 1, 12, 0, -3},
/* 0x98 */ {685, 0, 0, 8, 0, 0},
/* 0x99 */ {685, 11, 7, 12, 1, -8},
/* 0x9A */ {695, 9, 6, 10, 0, -5},
/* 0x9B */ {702, 2, 3, 3, 1, -4},
/* 0x9C */ {703, 9, 6, 10, 1, -5},
/* 0x9D */ {710, 4, 9, 6, 1, -8},
/* 0x9E */ {715, 6, 9, 7, 0, -8},
/* 0x9F */ {722, 5, 7, 7, 1, -5},
/* 0xA0 */ {727, 0, 0, 3, 0, 0},
/* 0xA1 */ {727, 7, 11, 7, 0, -10},
/* 0xA2 */ {737, 5, 11, 6, 0, -7},
/* 0xA3 */ {744, 5, 9, 6, 0, -8},
/* 0xA4 */ {750, 5, 4, 7, 1, -5},
/* 0xA5 */ {753, 6, 10, 7, 1, -9},
/* 0xA6 */ {761, 1, 12, 3, 1, -8},
/* 0xA7 */ {763, 5, 12, 7, 1, -8},
/* 0xA8 */ {771, 6, 11, 8, 1, -10},
/* 0xA9 */ {780, 9, 9, 10, 0, -8},
/* 0xAA */ {791, 7, 9, 9, 1, -8},
/* 0xAB */ {799, 4, 4, 6, 1, -4},
/* 0xAC */ {801, 2, 12, 3, 0, -8},
/* 0xAD */ {804, 0, 0, 0, 0, 0},
/* 0xAE */ {804, 9, 9, 10, 0, -8},
/* 0xAF */ {815, 3, 11, 3, 0, -10},
/* 0xB0 */ {820, 4, 4, 7, 2, -8},
/* 0xB1 */ {822, 5, 7, 7, 1, -6},
/* 0xB2 */ {827, 1, 9, 3, 1, -8},
/* 0xB3 */ {829, 1, 9, 3, 1, -8},
/* 0xB4 */ {831, 3, 8, 5, 1, -7},
/* 0xB5 */ {834, 6, 9, 7, 1, -6},
/* 0xB6 */ {841, 6, 10, 6, 1, -8},
/* 0xB7 */ {849, 1, 1, 3, 1, -2},
/* 0xB8 */ {850, 6, 9, 7, 0, -8},
/* 0xB9 */ {857, 9, 9, 11, 1, -8},
/* 0xBA */ {868, 6, 6, 6, 0, -5},
/* 0xBB */ {873, 4, 4, 6, 1, -5},
/* 0xBC */ {875, 2, 12, 3, 0, -8},
/* 0xBD */ {878, 6, 9, 8, 1, -8},
/* 0xBE */ {885, 5, 6, 6, 0, -5},
/* 0xBF */ {889, 3, 9, 3, 0, -8},
/* 0xC0 */ {893, 8, 9, 8, 0, -8},
/* 0xC1 */ {902, 6, 9, 8, 1, -8},
/* 0xC2 */ {909, 6, 9, 8, 1, -8},
/* 0xC3 */ {916, 6, 9, 7, 1, -8},
/* 0xC4 */ {923, 9, 11, 10, 0, -8},
/* 0xC5 */ {936, 6, 9, 8, 1, -8},
/* 0xC6 */ {943, 9, 9, 11, 1, -8},
/* 0xC7 */ {954, 6, 9, 8, 1, -8},
/* 0xC8 */ {961, 7, 9, 9, 1, -8},
/* 0xC9 */ {969, 7, 11, 9, 1, -10},
/* 0xCA */ {979, 6, 9, 8, 1, -8},
/* 0xCB */ {986, 7, 9, 8, 0, -8},
/* 0xCC */ {994, 8, 9, 10, 1, -8},
/* 0xCD */ {1003, 7, 9, 9, 1, -8},
/* 0xCE */ {1011, 8, 9, 10, 1, -8},
/* 0xCF */ {1020, 7, 9, 9, 1, -8},
/* 0xD0 */ {1028, 6, 9, 8, 1, -8},
/* 0xD1 */ {1035, 7, 9, 9, 1, -8},
/* 0xD2 */ {1043, 7, 9, 7, 0, -8},
/* 0xD3 */ {1051, 7, 9, 7, 0, -8},
/* 0xD4 */ {1059, 9, 9, 10, 1, -8},
/* 0xD5 */ {1070, 6, 9, 8, 1, -8},
/* 0xD6 */ {1077, 8, 11, 9, 1, -8},
/* 0xD7 */ {1088, 6, 9, 8, 1, -8},
/* 0xD8 */ {1095, 8, 9, 10, 1, -8},
/* 0xD9 */ {1104, 9, 11, 10, 1, -8},
/* 0xDA */ {1117, 10, 9, 10, 0, -8},
/* 0xDB */ {1129, 9, 9, 10, 1, -8},
/* 0xDC */ {1140, 6, 9, 8, 1, -8},
/* 0xDD */ {1147, 7, 9, 9, 1, -8},
/* 0xDE */ {1155, 10, 9, 12, 1, -8},
/* 0xDF */ {1167, 6, 9, 8, 1, -8},
/* 0xE0 */ {1174, 6, 6, 7, 0, -5},
/* 0xE1 */ {1179, 6, 9, 7, 0, -8},
/* 0xE2 */ {1186, 5, 6, 6, 1, -5},
/* 0xE3 */ {1190, 4, 6, 5, 1, -5},
/* 0xE4 */ {1193, 7, 7, 7, 0, -5},
/* 0xE5 */ {1200, 6, 6, 7, 0, -5},
/* 0xE6 */ {1205, 8, 6, 9, 1, -5},
/* 0xE7 */ {1211, 6, 6, 6, 0, -5},
/* 0xE8 */ {1216, 5, 6, 7, 1, -5},
/* 0xE9 */ {1220, 5, 8, 7, 1, -7},
/* 0xEA */ {1225, 4, 6, 6, 1, -5},
/* 0xEB */ {1228, 5, 6, 6, 0, -5},
/* 0xEC */ {1232, 6, 6, 7, 1, -5},
/* 0xED */ {1237, 5, 6, 7, 1, -5},
/* 0xEE */ {1241, 6, 6, 7, 0, -5},
/* 0xEF */ {1246, 5, 6, 7, 1, -5},
/* 0xF0 */ {1250, 5, 9, 7, 1, -5},
/* 0xF1 */ {1256, 6, 6, 6, 0, -5},
/* 0xF2 */ {1261, 5, 6, 5, 0, -5},
/* 0xF3 */ {1265, 5, 9, 6, 0, -5},
/* 0xF4 */ {1271, 10, 11, 10, 0, -7},
/* 0xF5 */ {1285, 5, 6, 6, 0, -5},
/* 0xF6 */ {1289, 6, 7, 7, 1, -5},
/* 0xF7 */ {1295, 4, 6, 6, 1, -5},
/* 0xF8 */ {1298, 6, 6, 8, 1, -5},
/* 0xF9 */ {1303, 7, 7, 9, 1, -5},
/* 0xFA */ {1310, 7, 6, 8, 0, -5},
/* 0xFB */ {1316, 6, 6, 8, 1, -5},
/* 0xFC */ {1321, 5, 6, 6, 1, -5},
/* 0xFD */ {1325, 5, 6, 6, 1, -5},
/* 0xFE */ {1329, 8, 6, 9, 1, -5},
/* 0xFF */ {1335, 5, 6, 7, 1, -5},
};
const GFXfont FreeSans6pt_Win1251 PROGMEM = {(uint8_t *)FreeSans6pt_Win1251Bitmaps, (GFXglyph *)FreeSans6pt_Win1251Glyphs, 0x20,
0xFF, 14};
@@ -0,0 +1,457 @@
#pragma once
const uint8_t FreeSans6pt_Win1252Bitmaps[] PROGMEM = {
/* ' ' 0x20 */
0xFC, 0x80, /* '!' 0x21 */
0xB6, 0x80, /* '"' 0x22 */
0x24, 0x51, 0xF9, 0x42, 0x9F, 0x92, 0x28, /* '#' 0x23 */
0x10, 0xE5, 0x55, 0x50, 0xE1, 0x65, 0x55, 0xE1, 0x00, /* '$' 0x24 */
0x71, 0x24, 0x89, 0x22, 0x50, 0x74, 0x02, 0x70, 0xA4, 0x49, 0x11, 0xC0, /* '%' 0x25 */
0x71, 0x24, 0x9C, 0x62, 0x58, 0xA7, 0xF4, /* '&' 0x26 */
0xE0, /* ''' 0x27 */
0x5A, 0xAA, 0x94, /* '(' 0x28 */
0x89, 0x12, 0x49, 0x29, 0x00, /* ')' 0x29 */
0x5E, 0x80, /* '*' 0x2A */
0x21, 0x3E, 0x42, 0x00, /* '+' 0x2B */
0xE0, /* ',' 0x2C */
0xC0, /* '-' 0x2D */
0x80, /* '.' 0x2E */
0x24, 0xA4, 0xA4, 0x80, /* '/' 0x2F */
0x76, 0xE3, 0x18, 0xC6, 0x3B, 0x70, /* '0' 0x30 */
0x27, 0x92, 0x49, 0x20, /* '1' 0x31 */
0x79, 0x10, 0x41, 0x08, 0xC6, 0x10, 0xFC, /* '2' 0x32 */
0x79, 0x30, 0x43, 0x18, 0x10, 0x71, 0x78, /* '3' 0x33 */
0x08, 0x61, 0x8A, 0x49, 0x2F, 0xC2, 0x08, /* '4' 0x34 */
0xFC, 0x21, 0xE8, 0x84, 0x31, 0xF0, /* '5' 0x35 */
0x74, 0x61, 0xE8, 0xC6, 0x31, 0x70, /* '6' 0x36 */
0xF8, 0x44, 0x22, 0x11, 0x08, 0x40, /* '7' 0x37 */
0x39, 0x34, 0x53, 0x39, 0x1C, 0x51, 0x38, /* '8' 0x38 */
0x39, 0x3C, 0x71, 0x4C, 0xF0, 0x53, 0x78, /* '9' 0x39 */
0x82, /* ':' 0x3A */
0x87, /* ';' 0x3B */
0x3E, 0x30, 0x60, 0x80, /* '<' 0x3C */
0xF8, 0x3E, /* '=' 0x3D */
0xE0, 0xC6, 0xC8, 0x00, /* '>' 0x3E */
0x74, 0x42, 0x11, 0x10, 0x80, 0x20, /* '?' 0x3F */
0x0F, 0x86, 0x19, 0x9A, 0xA4, 0xD9, 0x13, 0x22, 0x56, 0xDA, 0x6E, 0x60, 0x06, 0x00, 0x3C, 0x00, /* '@' 0x40 */
0x18, 0x18, 0x24, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 'A' 0x41 */
0xFA, 0x18, 0x61, 0xFA, 0x18, 0x61, 0xFC, /* 'B' 0x42 */
0x3E, 0x63, 0x40, 0x40, 0xC0, 0x40, 0x41, 0x63, 0x3E, /* 'C' 0x43 */
0xF9, 0x0A, 0x1C, 0x18, 0x30, 0x61, 0xC2, 0xF8, /* 'D' 0x44 */
0xFE, 0x08, 0x20, 0xFE, 0x08, 0x20, 0xFC, /* 'E' 0x45 */
0xFE, 0x08, 0x20, 0xFA, 0x08, 0x20, 0x80, /* 'F' 0x46 */
0x1E, 0x61, 0x40, 0x40, 0xC7, 0x41, 0x41, 0x63, 0x1D, /* 'G' 0x47 */
0x83, 0x06, 0x0C, 0x1F, 0xF0, 0x60, 0xC1, 0x82, /* 'H' 0x48 */
0xFF, 0x80, /* 'I' 0x49 */
0x08, 0x42, 0x10, 0x87, 0x29, 0x70, /* 'J' 0x4A */
0x85, 0x12, 0x45, 0x0D, 0x13, 0x22, 0x42, 0x86, /* 'K' 0x4B */
0x84, 0x21, 0x08, 0x42, 0x10, 0xF8, /* 'L' 0x4C */
0xC3, 0xC3, 0xC3, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, /* 'M' 0x4D */
0x83, 0x86, 0x8D, 0x19, 0x33, 0x62, 0xC3, 0x86, /* 'N' 0x4E */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x06, 0xC6, 0x1E, 0x00, /* 'O' 0x4F */
0xFA, 0x18, 0x61, 0xFA, 0x08, 0x20, 0x80, /* 'P' 0x50 */
0x1E, 0x31, 0x90, 0x68, 0x1C, 0x0A, 0x05, 0x16, 0xC6, 0x1F, 0x00, 0x40, /* 'Q' 0x51 */
0xFD, 0x0E, 0x1C, 0x2F, 0x90, 0xA1, 0x42, 0x86, /* 'R' 0x52 */
0x7A, 0x18, 0x30, 0x78, 0x38, 0x61, 0x78, /* 'S' 0x53 */
0xFE, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, /* 'T' 0x54 */
0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xE2, 0x78, /* 'U' 0x55 */
0xC2, 0x85, 0x0B, 0x22, 0x44, 0x8E, 0x0C, 0x18, /* 'V' 0x56 */
0xC4, 0x28, 0xCD, 0x29, 0x25, 0x24, 0xA4, 0x52, 0x8C, 0x61, 0x8C, 0x31, 0x80, /* 'W' 0x57 */
0x87, 0x34, 0x8C, 0x30, 0xC4, 0xA3, 0x84, /* 'X' 0x58 */
0xC3, 0x42, 0x24, 0x34, 0x18, 0x08, 0x08, 0x08, 0x08, /* 'Y' 0x59 */
0x7E, 0x0C, 0x30, 0x41, 0x06, 0x18, 0x20, 0xFE, /* 'Z' 0x5A */
0xEA, 0xAA, 0xAB, /* '[' 0x5B */
0x92, 0x24, 0x89, 0x20, /* '\' 0x5C */
0xD5, 0x55, 0x57, /* ']' 0x5D */
0x46, 0xA9, /* '^' 0x5E */
0xFE, /* '_' 0x5F */
0x80, /* '`' 0x60 */
0x79, 0x20, 0x4F, 0xC6, 0x37, 0x40, /* 'a' 0x61 */
0x84, 0x3D, 0x18, 0xC6, 0x31, 0xF0, /* 'b' 0x62 */
0x39, 0x3C, 0x20, 0xC1, 0x33, 0x80, /* 'c' 0x63 */
0x04, 0x13, 0xD3, 0xC6, 0x1C, 0x53, 0x3C, /* 'd' 0x64 */
0x39, 0x38, 0x7F, 0x81, 0x13, 0x80, /* 'e' 0x65 */
0x6B, 0xA4, 0x92, 0x40, /* 'f' 0x66 */
0x35, 0x3C, 0x61, 0xC5, 0x33, 0x41, 0x4D, 0xE0, /* 'g' 0x67 */
0x84, 0x3D, 0x38, 0xC6, 0x31, 0x88, /* 'h' 0x68 */
0xBF, 0x80, /* 'i' 0x69 */
0x45, 0x55, 0x57, /* 'j' 0x6A */
0x84, 0x25, 0x4E, 0x52, 0xD2, 0x88, /* 'k' 0x6B */
0xFF, 0x80, /* 'l' 0x6C */
0xF7, 0x99, 0x91, 0x91, 0x91, 0x91, 0x91, /* 'm' 0x6D */
0xF4, 0x63, 0x18, 0xC6, 0x20, /* 'n' 0x6E */
0x39, 0x3C, 0x61, 0xC5, 0x33, 0x80, /* 'o' 0x6F */
0xF4, 0x63, 0x18, 0xC7, 0xD0, 0x80, /* 'p' 0x70 */
0x3D, 0x3C, 0x61, 0xC5, 0x37, 0x41, 0x04, /* 'q' 0x71 */
0xF2, 0x49, 0x20, /* 'r' 0x72 */
0x7A, 0x50, 0xE0, 0xE5, 0xE0, /* 's' 0x73 */
0x5D, 0x24, 0x93, /* 't' 0x74 */
0x8C, 0x63, 0x18, 0xCF, 0xA0, /* 'u' 0x75 */
0x85, 0x24, 0x92, 0x30, 0xC3, 0x00, /* 'v' 0x76 */
0x89, 0x59, 0x59, 0x55, 0x56, 0x26, 0x26, /* 'w' 0x77 */
0x4A, 0x4C, 0x43, 0x27, 0x20, /* 'x' 0x78 */
0x8A, 0x52, 0xA5, 0x18, 0x84, 0x22, 0x00, /* 'y' 0x79 */
0x78, 0x44, 0x46, 0x23, 0xE0, /* 'z' 0x7A */
0x6A, 0xAA, 0xA9, /* '{' 0x7B */
0xFF, 0xE0, /* '|' 0x7C */
0x95, 0x55, 0x56, /* '}' 0x7D */
0x66, 0x60, /* '~' 0x7E */
0xFF, 0xC0, 0x67, 0x34, 0x58, 0x4C, 0x46, 0x03, 0x11, 0x80, 0xFF, 0xC0, /* 0x7F */
0x1C, 0x45, 0x07, 0xE4, 0x1F, 0x10, 0x10, 0x1E, /* 0x80 */
/* 0x81 */
0xE0, /* 0x82 */
0x6B, 0xA4, 0x92, 0x49, 0x60, /* 0x83 */
0xB6, 0x80, /* 0x84 */
0xA8, /* 0x85 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0x21, 0x08, /* 0x86 */
0x21, 0x09, 0xF2, 0x10, 0x84, 0xF9, 0x08, /* 0x87 */
0x54, /* 0x88 */
0x62, 0x09, 0x40, 0x98, 0x06, 0x80, 0x10, 0x01, 0x66, 0x29, 0x92, 0x99, 0x06, 0x60, /* 0x89 */
0x28, 0x47, 0xA1, 0x83, 0x07, 0x83, 0x87, 0x17, 0x80, /* 0x8A */
0x64, /* 0x8B */
0x3B, 0xE8, 0xC2, 0x08, 0x41, 0x08, 0x3F, 0x04, 0x20, 0x82, 0x30, 0x3B, 0xE0, /* 0x8C */
/* 0x8D */
0x14, 0x11, 0xF8, 0x30, 0xC1, 0x04, 0x18, 0x61, 0xFC, /* 0x8E */
/* 0x8F */
/* 0x90 */
0xE0, /* 0x91 */
0xE0, /* 0x92 */
0xB6, 0x80, /* 0x93 */
0xB6, 0x80, /* 0x94 */
0xFF, 0x80, /* 0x95 */
0xFC, /* 0x96 */
0xFF, 0xF0, /* 0x97 */
0xDB, /* 0x98 */
0xE6, 0x28, 0xCD, 0x19, 0xA3, 0x34, 0x6A, 0x8B, 0x51, 0x68, /* 0x99 */
0x52, 0x69, 0x8E, 0x19, 0x60, /* 0x9A */
0x98, /* 0x9B */
0x7B, 0xD9, 0xCE, 0x10, 0xC3, 0xF8, 0x41, 0x9C, 0x5E, 0xF0, /* 0x9C */
/* 0x9D */
0x51, 0x1E, 0x11, 0x11, 0x88, 0xF8, /* 0x9E */
0x29, 0x05, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20, /* 0x9F */
/* 0xA0 */
0xBF, 0x80, /* 0xA1 */
0x23, 0xAB, 0x4A, 0x52, 0xAE, 0x20, /* 0xA2 */
0x39, 0x14, 0x10, 0xF0, 0x82, 0x1C, 0x4C, /* 0xA3 */
0xFC, 0x63, 0xF0, /* 0xA4 */
0x8C, 0x54, 0xAF, 0x93, 0xE4, 0x20, /* 0xA5 */
0xF9, 0xF0, /* 0xA6 */
0x32, 0x91, 0xC9, 0x47, 0x26, 0x14, 0xA4, 0xC0, /* 0xA7 */
0xA0, /* 0xA8 */
0x3E, 0x3F, 0xB8, 0xF4, 0x1A, 0x0D, 0x17, 0x76, 0xC6, 0x3E, 0x00, /* 0xA9 */
0x61, 0x79, 0x60, /* 0xAA */
0x5A, 0xA5, /* 0xAB */
0xFC, 0x10, 0x40, /* 0xAC */
/* 0xAD */
0x3E, 0x31, 0xB7, 0x72, 0x99, 0xCC, 0xC7, 0x56, 0xC6, 0x3E, 0x00, /* 0xAE */
0xE0, /* 0xAF */
0x69, 0x96, /* 0xB0 */
0x21, 0x3E, 0x42, 0x03, 0xE0, /* 0xB1 */
0x69, 0x3C, 0xF0, /* 0xB2 */
0x79, 0x29, 0x70, /* 0xB3 */
0x80, /* 0xB4 */
0x8A, 0x28, 0xA2, 0x8A, 0x6E, 0xE0, 0x80, /* 0xB5 */
0x7F, 0xAE, 0xBA, 0x68, 0xA2, 0x8A, 0x28, 0xA0, /* 0xB6 */
0x80, /* 0xB7 */
0x67, 0x80, /* 0xB8 */
0x75, 0x50, /* 0xB9 */
0x69, 0x96, 0xF0, /* 0xBA */
0xA5, 0x5A, /* 0xBB */
0x42, 0x30, 0x84, 0x41, 0x10, 0x48, 0x82, 0x61, 0x28, 0x8F, 0x20, 0x80, /* 0xBC */
0x40, 0x63, 0x11, 0x09, 0x74, 0xA8, 0x84, 0x44, 0x44, 0x43, 0x80, /* 0xBD */
0x71, 0x24, 0x82, 0x20, 0x50, 0x98, 0x9A, 0x61, 0x28, 0x4F, 0x20, 0x80, /* 0xBE */
0x20, 0x08, 0x44, 0x42, 0x11, 0x70, /* 0xBF */
0x10, 0x08, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC0 */
0x08, 0x10, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC1 */
0x18, 0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC2 */
0x34, 0x2C, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC3 */
0x24, 0x00, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0x42, 0xC3, /* 0xC4 */
0x18, 0x24, 0x18, 0x18, 0x3C, 0x24, 0x24, 0x7E, 0x42, 0xC3, /* 0xC5 */
0x1F, 0xC5, 0x02, 0x40, 0x90, 0x47, 0xDF, 0x04, 0x42, 0x10, 0x87, 0xC0, /* 0xC6 */
0x3E, 0x61, 0xC0, 0x80, 0x80, 0x80, 0xC1, 0x63, 0x3E, 0x0C, 0x04, 0x1C, /* 0xC7 */
0x20, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xC8 */
0x08, 0x40, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xC9 */
0x10, 0xA0, 0x3F, 0x82, 0x0F, 0xA0, 0x83, 0xF0, /* 0xCA */
0x28, 0x0F, 0xE0, 0x83, 0xE8, 0x20, 0x83, 0xF0, /* 0xCB */
0x91, 0x55, 0x50, /* 0xCC */
0x62, 0xAA, 0xA0, /* 0xCD */
0x54, 0x24, 0x92, 0x48, /* 0xCE */
0xA1, 0x24, 0x92, 0x48, /* 0xCF */
0x7C, 0x42, 0x41, 0x41, 0xF1, 0x41, 0x41, 0x42, 0x7C, /* 0xD0 */
0x14, 0x53, 0x0F, 0x1B, 0x32, 0x66, 0xC7, 0x87, 0x04, /* 0xD1 */
0x10, 0x04, 0x0F, 0x8C, 0x6C, 0x1C, 0x06, 0x03, 0x83, 0x63, 0x1F, 0x00, /* 0xD2 */
0x04, 0x04, 0x0F, 0x8C, 0x6C, 0x1C, 0x06, 0x03, 0x83, 0x63, 0x1F, 0x00, /* 0xD3 */
0x08, 0x0A, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD4 */
0x1A, 0x0B, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD5 */
0x14, 0x00, 0x00, 0x07, 0xC6, 0x36, 0x0E, 0x03, 0x01, 0xC1, 0xB1, 0x8F, 0x80, /* 0xD6 */
0x8A, 0x88, 0xA8, 0x80, /* 0xD7 */
0x3E, 0xB1, 0xB0, 0xF0, 0x98, 0x8C, 0x87, 0x86, 0xC6, 0xBE, 0x00, /* 0xD8 */
0x20, 0x22, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xD9 */
0x08, 0x22, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDA */
0x10, 0x52, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDB */
0x29, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0xC6, 0xF8, /* 0xDC */
0x09, 0x25, 0x12, 0x22, 0x87, 0x04, 0x08, 0x10, 0x20, /* 0xDD */
0x83, 0xE8, 0x61, 0x87, 0xE8, 0x20, 0x80, /* 0xDE */
0x7A, 0x18, 0x61, 0x8A, 0x18, 0x61, 0xB8, /* 0xDF */
0x20, 0x20, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE0 */
0x10, 0x40, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE1 */
0x10, 0x50, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE2 */
0x68, 0xB0, 0x03, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE3 */
0x28, 0x01, 0xE4, 0x20, 0x47, 0xB1, 0x46, 0x76, /* 0xE4 */
0x10, 0x50, 0x43, 0xC8, 0x40, 0x8F, 0x62, 0x8C, 0xEC, /* 0xE5 */
0x7B, 0xA1, 0x90, 0x45, 0xFF, 0x84, 0x23, 0x17, 0x38, /* 0xE6 */
0x7B, 0x18, 0x20, 0x83, 0x17, 0x8C, 0x11, 0xC0, /* 0xE7 */
0x20, 0x40, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xE8 */
0x10, 0x80, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xE9 */
0x10, 0xA0, 0x1E, 0xCE, 0x1F, 0xE0, 0xC5, 0xE0, /* 0xEA */
0x28, 0x07, 0xB3, 0x87, 0xF8, 0x31, 0x78, /* 0xEB */
0x91, 0x55, 0x50, /* 0xEC */
0x62, 0xAA, 0xA0, /* 0xED */
0x54, 0x24, 0x92, 0x48, /* 0xEE */
0xA1, 0x24, 0x92, 0x40, /* 0xEF */
0x28, 0x42, 0x8F, 0x46, 0x18, 0x52, 0x30, /* 0xF0 */
0x6A, 0xC1, 0x6C, 0xC6, 0x31, 0x8C, 0x40, /* 0xF1 */
0x20, 0x40, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF2 */
0x10, 0x80, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF3 */
0x10, 0xA0, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF4 */
0x69, 0x60, 0x1E, 0xCE, 0x18, 0x61, 0xCD, 0xE0, /* 0xF5 */
0x28, 0x07, 0xB3, 0x86, 0x18, 0x73, 0x78, /* 0xF6 */
0x20, 0x3E, 0x02, 0x00, /* 0xF7 */
0x7F, 0x39, 0x69, 0xC7, 0x3F, 0x80, /* 0xF8 */
0x41, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xF9 */
0x11, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFA */
0x22, 0x81, 0x18, 0xC6, 0x31, 0x9B, 0x40, /* 0xFB */
0x50, 0x23, 0x18, 0xC6, 0x33, 0x68, /* 0xFC */
0x10, 0x88, 0x52, 0x49, 0x23, 0x0C, 0x30, 0x82, 0x18, /* 0xFD */
0x84, 0x3D, 0xB8, 0xC6, 0x3B, 0xF4, 0x20, /* 0xFE */
0x28, 0x08, 0x52, 0x49, 0x23, 0x0C, 0x30, 0x82, 0x18, /* 0xFF */
};
const GFXglyph FreeSans6pt_Win1252Glyphs[] PROGMEM = {
/* ' ' 0x20 */ {0, 0, 0, 3, 0, 0},
/* '!' 0x21 */ {0, 1, 9, 4, 2, -8},
/* '"' 0x22 */ {2, 3, 3, 4, 0, -8},
/* '#' 0x23 */ {4, 7, 8, 7, 0, -7},
/* '$' 0x24 */ {11, 6, 11, 7, 0, -9},
/* '%' 0x25 */ {20, 10, 9, 11, 0, -8},
/* '&' 0x26 */ {32, 6, 9, 8, 1, -8},
/* ''' 0x27 */ {39, 1, 3, 2, 1, -8},
/* '(' 0x28 */ {40, 2, 11, 4, 1, -8},
/* ')' 0x29 */ {43, 3, 11, 4, 0, -8},
/* '*' 0x2A */ {48, 3, 3, 5, 1, -8},
/* '+' 0x2B */ {50, 5, 5, 7, 1, -4},
/* ',' 0x2C */ {54, 1, 3, 3, 1, 0},
/* '-' 0x2D */ {55, 2, 1, 4, 1, -3},
/* '.' 0x2E */ {56, 1, 1, 3, 1, 0},
/* '/' 0x2F */ {57, 3, 9, 3, 0, -8},
/* '0' 0x30 */ {61, 5, 9, 7, 1, -8},
/* '1' 0x31 */ {67, 3, 9, 7, 1, -8},
/* '2' 0x32 */ {71, 6, 9, 7, 0, -8},
/* '3' 0x33 */ {78, 6, 9, 7, 0, -8},
/* '4' 0x34 */ {85, 6, 9, 7, 0, -8},
/* '5' 0x35 */ {92, 5, 9, 7, 1, -8},
/* '6' 0x36 */ {98, 5, 9, 7, 1, -8},
/* '7' 0x37 */ {104, 5, 9, 7, 1, -8},
/* '8' 0x38 */ {110, 6, 9, 7, 0, -8},
/* '9' 0x39 */ {117, 6, 9, 7, 0, -8},
/* ':' 0x3A */ {124, 1, 7, 3, 1, -6},
/* ';' 0x3B */ {125, 1, 8, 3, 1, -5},
/* '<' 0x3C */ {126, 5, 5, 7, 1, -4},
/* '=' 0x3D */ {130, 5, 3, 7, 1, -3},
/* '>' 0x3E */ {132, 5, 5, 7, 1, -4},
/* '?' 0x3F */ {136, 5, 9, 7, 1, -8},
/* '@' 0x40 */ {142, 11, 11, 12, 0, -8},
/* 'A' 0x41 */ {158, 8, 9, 8, 0, -8},
/* 'B' 0x42 */ {167, 6, 9, 8, 1, -8},
/* 'C' 0x43 */ {174, 8, 9, 9, 0, -8},
/* 'D' 0x44 */ {183, 7, 9, 8, 1, -8},
/* 'E' 0x45 */ {191, 6, 9, 8, 1, -8},
/* 'F' 0x46 */ {198, 6, 9, 7, 1, -8},
/* 'G' 0x47 */ {205, 8, 9, 9, 0, -8},
/* 'H' 0x48 */ {214, 7, 9, 9, 1, -8},
/* 'I' 0x49 */ {222, 1, 9, 3, 1, -8},
/* 'J' 0x4A */ {224, 5, 9, 6, 0, -8},
/* 'K' 0x4B */ {230, 7, 9, 8, 1, -8},
/* 'L' 0x4C */ {238, 5, 9, 7, 1, -8},
/* 'M' 0x4D */ {244, 8, 9, 10, 1, -8},
/* 'N' 0x4E */ {253, 7, 9, 9, 1, -8},
/* 'O' 0x4F */ {261, 9, 9, 9, 0, -8},
/* 'P' 0x50 */ {272, 6, 9, 8, 1, -8},
/* 'Q' 0x51 */ {279, 9, 10, 9, 0, -8},
/* 'R' 0x52 */ {291, 7, 9, 9, 1, -8},
/* 'S' 0x53 */ {299, 6, 9, 8, 1, -8},
/* 'T' 0x54 */ {306, 7, 9, 8, 0, -8},
/* 'U' 0x55 */ {314, 7, 9, 9, 1, -8},
/* 'V' 0x56 */ {322, 7, 9, 8, 0, -8},
/* 'W' 0x57 */ {330, 11, 9, 11, 0, -8},
/* 'X' 0x58 */ {343, 6, 9, 8, 1, -8},
/* 'Y' 0x59 */ {350, 8, 9, 8, 0, -8},
/* 'Z' 0x5A */ {359, 7, 9, 7, 0, -8},
/* '[' 0x5B */ {367, 2, 12, 3, 1, -8},
/* '\' 0x5C */ {370, 3, 9, 3, 0, -8},
/* ']' 0x5D */ {374, 2, 12, 3, 0, -8},
/* '^' 0x5E */ {377, 4, 4, 6, 1, -8},
/* '_' 0x5F */ {379, 7, 1, 7, 0, 2},
/* '`' 0x60 */ {380, 1, 1, 3, 1, -8},
/* 'a' 0x61 */ {381, 6, 7, 7, 0, -6},
/* 'b' 0x62 */ {387, 5, 9, 7, 1, -8},
/* 'c' 0x63 */ {393, 6, 7, 6, 0, -6},
/* 'd' 0x64 */ {399, 6, 9, 7, 0, -8},
/* 'e' 0x65 */ {406, 6, 7, 6, 0, -6},
/* 'f' 0x66 */ {412, 3, 9, 3, 0, -8},
/* 'g' 0x67 */ {416, 6, 10, 7, 0, -6},
/* 'h' 0x68 */ {424, 5, 9, 6, 1, -8},
/* 'i' 0x69 */ {430, 1, 9, 3, 1, -8},
/* 'j' 0x6A */ {432, 2, 12, 3, 0, -8},
/* 'k' 0x6B */ {435, 5, 9, 6, 1, -8},
/* 'l' 0x6C */ {441, 1, 9, 3, 1, -8},
/* 'm' 0x6D */ {443, 8, 7, 10, 1, -6},
/* 'n' 0x6E */ {450, 5, 7, 6, 1, -6},
/* 'o' 0x6F */ {455, 6, 7, 6, 0, -6},
/* 'p' 0x70 */ {461, 5, 9, 7, 1, -6},
/* 'q' 0x71 */ {467, 6, 9, 7, 0, -6},
/* 'r' 0x72 */ {474, 3, 7, 4, 1, -6},
/* 's' 0x73 */ {477, 5, 7, 6, 0, -6},
/* 't' 0x74 */ {482, 3, 8, 3, 0, -7},
/* 'u' 0x75 */ {485, 5, 7, 6, 1, -6},
/* 'v' 0x76 */ {490, 6, 7, 6, 0, -6},
/* 'w' 0x77 */ {496, 8, 7, 9, 0, -6},
/* 'x' 0x78 */ {503, 5, 7, 6, 0, -6},
/* 'y' 0x79 */ {508, 5, 10, 6, 0, -6},
/* 'z' 0x7A */ {515, 5, 7, 6, 0, -6},
/* '{' 0x7B */ {520, 2, 12, 4, 1, -8},
/* '|' 0x7C */ {523, 1, 11, 3, 1, -8},
/* '}' 0x7D */ {525, 2, 12, 4, 1, -8},
/* '~' 0x7E */ {528, 6, 2, 6, 0, -4},
/* 0x7F */ {530, 9, 10, 11, 1, -8},
/* 0x80 */ {542, 7, 9, 8, 0, -8},
/* 0x81 */ {550, 0, 0, 8, 0, 0},
/* 0x82 */ {550, 1, 3, 3, 1, 0},
/* 0x83 */ {551, 3, 12, 3, 0, -8},
/* 0x84 */ {556, 3, 3, 5, 1, 0},
/* 0x85 */ {558, 5, 1, 7, 1, 0},
/* 0x86 */ {559, 5, 11, 7, 1, -8},
/* 0x87 */ {566, 5, 11, 7, 1, -8},
/* 0x88 */ {573, 3, 2, 4, 0, -9},
/* 0x89 */ {574, 12, 9, 12, 0, -8},
/* 0x8A */ {588, 6, 11, 8, 1, -9},
/* 0x8B */ {597, 2, 3, 4, 1, -4},
/* 0x8C */ {598, 11, 9, 12, 0, -8},
/* 0x8D */ {611, 0, 0, 8, 0, 0},
/* 0x8E */ {611, 7, 10, 7, 0, -9},
/* 0x8F */ {620, 0, 0, 8, 0, 0},
/* 0x90 */ {620, 0, 0, 8, 0, 0},
/* 0x91 */ {620, 1, 3, 3, 1, -8},
/* 0x92 */ {621, 1, 3, 2, 1, -8},
/* 0x93 */ {622, 3, 3, 5, 1, -8},
/* 0x94 */ {624, 3, 3, 5, 1, -8},
/* 0x95 */ {626, 3, 3, 5, 1, -5},
/* 0x96 */ {628, 6, 1, 6, 0, -3},
/* 0x97 */ {629, 12, 1, 12, 0, -3},
/* 0x98 */ {631, 4, 2, 4, 0, -8},
/* 0x99 */ {632, 11, 7, 12, 1, -8},
/* 0x9A */ {642, 4, 9, 6, 1, -8},
/* 0x9B */ {647, 2, 3, 3, 1, -4},
/* 0x9C */ {648, 11, 7, 11, 0, -6},
/* 0x9D */ {658, 0, 0, 8, 0, 0},
/* 0x9E */ {658, 5, 9, 6, 0, -8},
/* 0x9F */ {664, 7, 10, 8, 1, -9},
/* 0xA0 */ {673, 0, 0, 3, 0, 0},
/* 0xA1 */ {673, 1, 9, 4, 1, -5},
/* 0xA2 */ {675, 5, 9, 7, 1, -7},
/* 0xA3 */ {681, 6, 9, 7, 0, -8},
/* 0xA4 */ {688, 5, 4, 7, 1, -5},
/* 0xA5 */ {691, 5, 9, 7, 1, -8},
/* 0xA6 */ {697, 1, 12, 3, 1, -8},
/* 0xA7 */ {699, 5, 12, 7, 1, -8},
/* 0xA8 */ {707, 3, 1, 4, 0, -7},
/* 0xA9 */ {708, 9, 9, 10, 0, -8},
/* 0xAA */ {719, 4, 5, 4, 0, -8},
/* 0xAB */ {722, 4, 4, 6, 1, -4},
/* 0xAC */ {724, 6, 3, 7, 1, -4},
/* 0xAD */ {727, 0, 0, 0, 0, 0},
/* 0xAE */ {727, 9, 9, 10, 0, -8},
/* 0xAF */ {738, 3, 1, 4, 0, -8},
/* 0xB0 */ {739, 4, 4, 7, 2, -8},
/* 0xB1 */ {741, 5, 7, 7, 1, -6},
/* 0xB2 */ {746, 4, 5, 4, 0, -9},
/* 0xB3 */ {749, 4, 5, 4, 0, -9},
/* 0xB4 */ {752, 1, 1, 4, 1, -8},
/* 0xB5 */ {753, 6, 9, 7, 1, -6},
/* 0xB6 */ {760, 6, 10, 6, 1, -8},
/* 0xB7 */ {768, 1, 1, 3, 1, -2},
/* 0xB8 */ {769, 3, 3, 4, 1, 1},
/* 0xB9 */ {771, 2, 6, 4, 1, -9},
/* 0xBA */ {773, 4, 5, 4, 0, -8},
/* 0xBB */ {776, 4, 4, 6, 1, -5},
/* 0xBC */ {778, 10, 9, 10, 1, -8},
/* 0xBD */ {790, 9, 9, 10, 1, -8},
/* 0xBE */ {801, 10, 9, 11, 0, -8},
/* 0xBF */ {813, 5, 9, 7, 1, -5},
/* 0xC0 */ {819, 8, 10, 8, 0, -9},
/* 0xC1 */ {829, 8, 10, 8, 0, -9},
/* 0xC2 */ {839, 8, 10, 8, 0, -9},
/* 0xC3 */ {849, 8, 10, 8, 0, -9},
/* 0xC4 */ {859, 8, 10, 8, 0, -9},
/* 0xC5 */ {869, 8, 10, 8, 0, -9},
/* 0xC6 */ {879, 10, 9, 12, 1, -8},
/* 0xC7 */ {891, 8, 12, 9, 0, -8},
/* 0xC8 */ {903, 6, 10, 8, 1, -9},
/* 0xC9 */ {911, 6, 10, 8, 1, -9},
/* 0xCA */ {919, 6, 10, 8, 1, -9},
/* 0xCB */ {927, 6, 10, 8, 1, -9},
/* 0xCC */ {935, 2, 10, 3, 0, -9},
/* 0xCD */ {938, 2, 10, 3, 1, -9},
/* 0xCE */ {941, 3, 10, 4, 0, -9},
/* 0xCF */ {945, 3, 10, 4, 0, -9},
/* 0xD0 */ {949, 8, 9, 8, 0, -8},
/* 0xD1 */ {958, 7, 10, 9, 1, -9},
/* 0xD2 */ {967, 9, 10, 9, 0, -9},
/* 0xD3 */ {979, 9, 10, 9, 0, -9},
/* 0xD4 */ {991, 9, 11, 9, 0, -10},
/* 0xD5 */ {1004, 9, 11, 9, 0, -10},
/* 0xD6 */ {1017, 9, 11, 9, 0, -10},
/* 0xD7 */ {1030, 5, 5, 7, 1, -5},
/* 0xD8 */ {1034, 9, 9, 9, 0, -8},
/* 0xD9 */ {1045, 7, 10, 9, 1, -9},
/* 0xDA */ {1054, 7, 10, 9, 1, -9},
/* 0xDB */ {1063, 7, 10, 9, 1, -9},
/* 0xDC */ {1072, 7, 10, 9, 1, -9},
/* 0xDD */ {1081, 7, 10, 8, 1, -9},
/* 0xDE */ {1090, 6, 9, 8, 1, -8},
/* 0xDF */ {1097, 6, 9, 7, 1, -8},
/* 0xE0 */ {1104, 7, 10, 7, 0, -9},
/* 0xE1 */ {1113, 7, 10, 7, 0, -9},
/* 0xE2 */ {1122, 7, 10, 7, 0, -9},
/* 0xE3 */ {1131, 7, 10, 7, 0, -9},
/* 0xE4 */ {1140, 7, 9, 7, 0, -8},
/* 0xE5 */ {1148, 7, 10, 7, 0, -9},
/* 0xE6 */ {1157, 10, 7, 10, 0, -6},
/* 0xE7 */ {1166, 6, 10, 6, 0, -6},
/* 0xE8 */ {1174, 6, 10, 6, 0, -9},
/* 0xE9 */ {1182, 6, 10, 6, 0, -9},
/* 0xEA */ {1190, 6, 10, 6, 0, -9},
/* 0xEB */ {1198, 6, 9, 6, 0, -8},
/* 0xEC */ {1205, 2, 10, 3, 0, -9},
/* 0xED */ {1208, 2, 10, 3, 1, -9},
/* 0xEE */ {1211, 3, 10, 3, 0, -9},
/* 0xEF */ {1215, 3, 9, 3, 0, -8},
/* 0xF0 */ {1219, 6, 9, 6, 0, -8},
/* 0xF1 */ {1226, 5, 10, 6, 1, -9},
/* 0xF2 */ {1233, 6, 10, 6, 0, -9},
/* 0xF3 */ {1241, 6, 10, 6, 0, -9},
/* 0xF4 */ {1249, 6, 10, 6, 0, -9},
/* 0xF5 */ {1257, 6, 10, 6, 0, -9},
/* 0xF6 */ {1265, 6, 9, 6, 0, -8},
/* 0xF7 */ {1272, 5, 5, 7, 1, -5},
/* 0xF8 */ {1276, 6, 7, 6, 0, -6},
/* 0xF9 */ {1282, 5, 9, 6, 1, -8},
/* 0xFA */ {1288, 5, 9, 6, 1, -8},
/* 0xFB */ {1294, 5, 10, 6, 1, -9},
/* 0xFC */ {1301, 5, 9, 6, 1, -8},
/* 0xFD */ {1307, 6, 12, 6, 0, -8},
/* 0xFE */ {1316, 5, 11, 7, 1, -8},
/* 0xFF */ {1323, 6, 12, 6, 0, -8},
};
const GFXfont FreeSans6pt_Win1252 PROGMEM = {(uint8_t *)FreeSans6pt_Win1252Bitmaps, (GFXglyph *)FreeSans6pt_Win1252Glyphs, 0x20,
0xFF, 14};

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